> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ascendgtm.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Scheduled Jobs

> Run agent workflows automatically on daily or weekly cadences

## How scheduling works

Hermes reads `agent_job_schedule:{tenant}` from KV at each CF Cron trigger (06:00 UTC daily). For each enabled schedule entry that matches the current day's cadence, it POSTs a job to Hermes and logs the result.

Schedules are stored in KV — no deploy required to add, modify, or disable them.

## Creating a schedule

Use the Admin API to set the schedule for a tenant:

```bash theme={null}
curl -X PUT https://ascend-gateway-v5.ascendgtm.workers.dev/admin/agent-schedules/kahuna \
  -H "Authorization: Bearer <admin-key>" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "name": "Daily GTM Brief",
      "agent_type": "report_builder",
      "message": "Generate the daily GTM brief: top pipeline movements, ad spend vs plan, and any anomalies. Send via SES to mishaal@ascendgtm.net.",
      "enabled": true,
      "cadence": "daily"
    },
    {
      "name": "Weekly CRM Enrichment",
      "agent_type": "crm_enricher",
      "message": "Enrich all HubSpot contacts created this week with firmographic data. Prioritize ICP accounts (Series A–C, 50–500 employees, B2B SaaS).",
      "enabled": true,
      "cadence": "weekly_monday",
      "callback_url": "https://your-app.com/webhooks/enrichment-done"
    },
    {
      "name": "Weekly Ad Performance Digest",
      "agent_type": "gtm_analyst",
      "message": "Compile Friday ad performance: ROAS by channel, top/bottom campaigns, budget pacing. Email to team.",
      "enabled": true,
      "cadence": "weekly_friday"
    }
  ]'
```

## Schedule fields

| Field          | Type    | Required | Description                                        |
| -------------- | ------- | -------- | -------------------------------------------------- |
| `name`         | string  | Yes      | Human label (logged, not sent to agent)            |
| `agent_type`   | string  | Yes      | Agent config to run                                |
| `message`      | string  | Yes      | The job instruction                                |
| `enabled`      | boolean | Yes      | Set to `false` to pause without deleting           |
| `cadence`      | string  | Yes      | `"daily"`, `"weekly_monday"`, or `"weekly_friday"` |
| `callback_url` | string  | No       | Webhook URL on job completion                      |

## Retrieving the current schedule

```bash theme={null}
curl https://ascend-gateway-v5.ascendgtm.workers.dev/admin/agent-schedules/kahuna \
  -H "Authorization: Bearer <admin-key>"
```

## Pausing a job without deleting it

Set `enabled: false` in the schedule entry and PUT the full array back. The cron runner skips disabled entries.

## Cadence reference

| Cadence         | When it runs           |
| --------------- | ---------------------- |
| `daily`         | Every day at 06:00 UTC |
| `weekly_monday` | Mondays at 06:00 UTC   |
| `weekly_friday` | Fridays at 06:00 UTC   |

All cadences run at 06:00 UTC on the CF Cron trigger. Sub-day cadences (hourly, every-N-minutes) require a separate cron slot — contact support to add one.

## Monitoring

Scheduled job runs appear in:

* **Cloudflare Workers Logs** — filter by `cron: hermes-scheduler`
* **error\_ledger D1 table** — failed runs logged with `action: "hermes_scheduled_job"`
* **Slack alerts** — if `SLACK_WEBHOOK_URL` is set, job failures trigger an alert

## Best practices

* **Write agent messages as complete instructions** — the agent wakes up with no prior context; be explicit
* **Use `callback_url` for enrichment jobs** — so downstream systems know when CRM data is fresh
* **Disable before editing** — set `enabled: false`, update the schedule, re-enable to avoid mid-run changes
* **Test with a job first** — submit the same `message` + `agent_type` as an async job, verify the output, then add to schedule
