Skip to main content

scheduler Agent

Run ensembles on a schedule. Cron syntax, distributed execution.

Basic Usage

agents:
  - name: schedule
    agent: scheduler
    inputs:
      cron: "0 0 * * *"  # Daily at midnight
      ensemble: daily-report
      inputs:
        date: ${new Date().toISOString()}

Inputs

inputs:
  cron:
    type: string
    required: true
    description: Cron expression

  ensemble:
    type: string
    required: true
    description: Ensemble to execute

  inputs:
    type: object
    description: Inputs for ensemble

  timezone:
    type: string
    default: UTC
    description: Timezone for cron

  enabled:
    type: boolean
    default: true
    description: Enable/disable schedule

Cron Syntax

Standard cron format:
 minute (0 - 59)
  hour (0 - 23)
   day of month (1 - 31)
    month (1 - 12)
     day of week (0 - 6) (Sunday to Saturday)
    
    
* * * * *

Common Patterns

# Every minute
cron: "* * * * *"

# Every 5 minutes
cron: "*/5 * * * *"

# Every hour
cron: "0 * * * *"

# Daily at midnight
cron: "0 0 * * *"

# Daily at 3 AM
cron: "0 3 * * *"

# Weekdays at 9 AM
cron: "0 9 * * 1-5"

# First day of month
cron: "0 0 1 * *"

# Every Sunday at noon
cron: "0 12 * * 0"

Configuration

Daily Report

agents:
  - name: schedule-report
    agent: scheduler
    inputs:
      cron: "0 8 * * *"  # 8 AM daily
      ensemble: generate-report
      timezone: America/New_York
      inputs:
        recipients: [${env.REPORT_EMAILS}]

Hourly Sync

agents:
  - name: schedule-sync
    agent: scheduler
    inputs:
      cron: "0 * * * *"  # Every hour
      ensemble: sync-data
      inputs:
        source: ${env.SOURCE_DB}
        target: ${env.TARGET_DB}

Weekly Cleanup

agents:
  - name: schedule-cleanup
    agent: scheduler
    inputs:
      cron: "0 2 * * 0"  # Sunday 2 AM
      ensemble: cleanup-old-data
      inputs:
        days_old: 90

Advanced Patterns

Multiple Schedules

ensemble: scheduled-tasks

agents:
  # Daily report
  - name: daily-report
    agent: scheduler
    inputs:
      cron: "0 8 * * *"
      ensemble: generate-report

  # Hourly sync
  - name: hourly-sync
    agent: scheduler
    inputs:
      cron: "0 * * * *"
      ensemble: sync-data

  # Weekly backup
  - name: weekly-backup
    agent: scheduler
    inputs:
      cron: "0 3 * * 0"
      ensemble: backup-database

Conditional Execution

agents:
  - name: check-config
    operation: storage
    config:
      type: kv
      action: get
      key: schedule-enabled

  - name: schedule
    condition: ${check-config.output.enabled}
    agent: scheduler
    inputs:
      cron: "0 0 * * *"
      ensemble: daily-task

Dynamic Scheduling

agents:
  - name: get-schedule
    operation: storage
    config:
      type: d1
      query: SELECT cron, ensemble, inputs FROM schedules WHERE active = 1

  - name: create-schedules
    operation: code
    config:
      code: |
        const schedules = ${get-schedule.output};

        return {
          schedules: schedules.map(s => ({
            cron: s.cron,
            ensemble: s.ensemble,
            inputs: JSON.parse(s.inputs)
          }))
        };

With Error Handling

ensemble: scheduled-task

agents:
  - name: execute
    operation: code
    config:
      code: |
        try {
          // Task logic
          return { success: true };
        } catch (error) {
          return { success: false, error: error.message };
        }

  - name: notify-failure
    condition: ${!execute.output.success}
    operation: email
    config:
      to: ${env.ADMIN_EMAIL}
      subject: "Scheduled task failed"
      body: |
        Task: ${input.task_name}
        Error: ${execute.output.error}
        Time: ${new Date().toISOString()}

Complete Examples

Daily Data Pipeline

ensemble: daily-pipeline

agents:
  # 1. Extract from source
  - name: extract
    operation: http
    config:
      url: ${env.SOURCE_API}/data
      headers:
        Authorization: Bearer ${env.API_KEY}

  # 2. Transform
  - name: transform
    agent: transformer
    inputs:
      data: ${extract.output.body}
      template: ${component.transform-template@v1.0.0}

  # 3. Load to database
  - name: load
    operation: storage
    config:
      type: d1
      query: INSERT INTO daily_data (date, data) VALUES (?, ?)
      params:
        - ${new Date().toISOString()}
        - ${JSON.stringify(transform.output)}

  # 4. Send report
  - name: report
    operation: email
    config:
      to: [${env.REPORT_EMAILS}]
      subject: "Daily Data Pipeline - ${new Date().toISOString()}"
      body: |
        Pipeline completed successfully.
        Records processed: ${transform.output.length}

# Schedule it
---
ensemble: scheduler-config

agents:
  - name: schedule-pipeline
    agent: scheduler
    inputs:
      cron: "0 1 * * *"  # 1 AM daily
      ensemble: daily-pipeline
      timezone: UTC

Hourly Health Check

ensemble: health-check

agents:
  # Check services
  - name: check-api
    agent: fetcher
    inputs:
      url: ${env.API_URL}/health
      timeout: 5000

  - name: check-database
    operation: storage
    config:
      type: d1
      query: SELECT 1

  # Alert on failure
  - name: alert
    condition: ${check-api.failed || check-database.failed}
    operation: sms
    config:
      to: ${env.ON_CALL_PHONE}
      body: |
        Health check failed!
        API: ${check-api.failed ? 'DOWN' : 'UP'}
        DB: ${check-database.failed ? 'DOWN' : 'UP'}

# Schedule it
---
ensemble: scheduler-config

agents:
  - name: schedule-health-check
    agent: scheduler
    inputs:
      cron: "*/15 * * * *"  # Every 15 minutes
      ensemble: health-check

Monthly Cleanup

ensemble: monthly-cleanup

agents:
  # Delete old records
  - name: cleanup-logs
    operation: storage
    config:
      type: d1
      query: DELETE FROM logs WHERE created_at < date('now', '-90 days')

  - name: cleanup-cache
    operation: storage
    config:
      type: kv
      action: delete
      key: ${input.stale_keys}

  # Vacuum database
  - name: vacuum
    operation: storage
    config:
      type: d1
      query: VACUUM

  # Report
  - name: report
    operation: email
    config:
      to: [${env.ADMIN_EMAIL}]
      subject: "Monthly Cleanup Complete"
      body: |
        Logs deleted: ${cleanup-logs.output.changes}
        Cache cleared: ${cleanup-cache.output.count}
        Database vacuumed

# Schedule it
---
ensemble: scheduler-config

agents:
  - name: schedule-cleanup
    agent: scheduler
    inputs:
      cron: "0 3 1 * *"  # 1st of month at 3 AM
      ensemble: monthly-cleanup

Best Practices

1. Use UTC for Consistency
timezone: UTC  # Avoid DST issues
2. Add Idempotency
ensemble: scheduled-task
agents:
  - name: check-already-run
    operation: storage
    config:
      type: kv
      action: get
      key: task-${new Date().toISOString().split('T')[0]}

  - name: execute
    condition: ${!check-already-run.output}
3. Monitor Executions
agents:
  - name: log-execution
    operation: storage
    config:
      type: d1
      query: INSERT INTO execution_log (task, timestamp, status) VALUES (?, ?, ?)
      params:
        - ${input.task_name}
        - ${Date.now()}
        - success
4. Handle Failures Gracefully
agents:
  - name: execute
    operation: code

  - name: retry-on-failure
    condition: ${execute.failed}
    agent: scheduler
    inputs:
      cron: "*/5 * * * *"  # Retry in 5 minutes
      ensemble: ${input.ensemble}
      enabled: ${execute.error.retryable}
5. Test Schedules
# Use short intervals for testing
cron: "* * * * *"  # Every minute

# Then switch to production
cron: "0 0 * * *"  # Daily

Monitoring

Track scheduled executions:
ensemble: monitor-schedules

agents:
  - name: query-executions
    operation: storage
    config:
      type: d1
      query: |
        SELECT task, COUNT(*) as count, MAX(timestamp) as last_run
        FROM execution_log
        WHERE timestamp > datetime('now', '-24 hours')
        GROUP BY task

  - name: check-missing
    operation: code
    config:
      code: |
        const executions = ${query-executions.output};
        const expected = ['daily-report', 'hourly-sync'];

        const missing = expected.filter(task =>
          !executions.find(e => e.task === task)
        );

        return { missing };

  - name: alert
    condition: ${check-missing.output.missing.length > 0}
    operation: email
    config:
      to: ${env.ADMIN_EMAIL}
      subject: "Missing scheduled executions"
      body: |
        These tasks haven't run in 24 hours:
        ${check-missing.output.missing.join(', ')}

Limitations

  • Minimum interval: 1 minute
  • Maximum concurrent: 100 schedules per account
  • Execution timeout: 30 minutes per run
  • No guaranteed ordering: Concurrent executions may overlap

Next Steps