Skip to main content
Agent schedules let you execute an agent on a recurring or one-off cadence. A scheduled run is equivalent to calling POST /v3/router/responses with model: agent/<key> — same execution path, same tracing, same billing — just fired by the scheduler rather than by a client request. Use them for:
  • Nightly briefings, hourly summaries, daily digests
  • One-off follow-ups at a specific time
  • Background agents that don’t need to be driven by user traffic

Schedule types

TypeExpressionExampleFires
interval@every <duration>@every 6hEvery 6 hours after creation
cron6-field cron (seconds required)0 0 9 * * mon-fri9:00:00 UTC Mon–Fri
once@at <RFC3339-UTC>@at 2026-05-01T09:00:00ZExactly once at that moment
Predefined cron descriptors also work: @hourly, @daily, @weekly, @monthly, @yearly.
Minimum interval is 1 hour. Any schedule that would fire more frequently than once per hour is rejected at validation time — including cron expressions like */5 * * * * * (every 5 seconds) or @every 30m. once schedules are exempt. If you need to run an agent in response to an event rather than on a clock, call the Responses API directly from your trigger.
All timestamps are UTC. Expressions in any other timezone are rejected.

Quick start

Create an hourly schedule for an existing agent:
curl -X POST https://api.orq.ai/v3/agents/customer_digest/schedules \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "interval",
    "expression": "@every 1h",
    "payload": {
      "input": "Summarize new tickets from the last hour"
    }
  }'
Response:
{
  "_id": "01KPN29WWKSK0VDPJNTKZPVNRB",
  "workspace_id": "...",
  "agent_key": "customer_digest",
  "type": "interval",
  "expression": "@every 1h",
  "is_active": true,
  "generation": 1,
  "payload": { "input": "Summarize new tickets from the last hour" },
  "trigger_count": 0,
  "created": "2026-04-20T10:00:00Z",
  "updated": "2026-04-20T10:00:00Z"
}
The agent will now run every hour with the provided input. Each run appears in your traces as a schedule.<agent_key> leading span — identical structure to an HTTP-invoked agent run.

Payload

The payload object is what the agent receives on each firing. All fields are optional.
FieldTypeDescription
inputstring or arraySame shape as the Responses API input — text or items.
variablesobjectTemplate variable substitution. Supports secret values {"secret": true, "value": "..."}.
memory_entity_idstringMemory store entity to attach, see Memory.
metadataobjectOpaque key/value pairs attached to every response generated by this schedule.
{
  "type": "cron",
  "expression": "0 0 9 * * mon-fri",
  "agent_tag": "v2",
  "payload": {
    "input": "Generate the morning briefing for {{region}}",
    "variables": { "region": "EMEA" },
    "memory_entity_id": "mem_entity_123",
    "metadata": { "run_source": "daily-briefing" }
  }
}
agent_tag pins the schedule to a specific agent version. Omit it to always run the agent’s current active version.

CRUD

All endpoints are workspace-scoped via the API key. Each schedule belongs to exactly one agent (identified by agent_key in the URL).

Create

POST /v3/agents/{agent_key}/schedules Required: type, expression, payload. Returns 201 Created with the stored schedule, or 400 for invalid expressions, 404 if the agent doesn’t exist.

List

GET /v3/agents/{agent_key}/schedules Returns { "schedules": [...] }. Schedules are listed in creation order, most recent first.

Get

GET /v3/agents/{agent_key}/schedules/{schedule_id} Returns the full schedule document, including trigger_count, last_triggered_at, and generation.

Update

PATCH /v3/agents/{agent_key}/schedules/{schedule_id} Partial update. Any omitted field is left unchanged. Fields you can patch:
  • type, expression — changing either re-publishes the NATS schedule, bumps generation, and resets trigger_count to 0.
  • is_activefalse stops future firings (NATS entry is removed); true resumes or reactivates.
  • agent_tag — change the pinned version.
  • payload — update the input, variables, memory, or metadata.
Payload-only and agent_tag-only changes do not reset the firing cadence — they apply to the next regularly-scheduled run. Expression/type changes shift the cadence starting from the PATCH time.

Delete

DELETE /v3/agents/{agent_key}/schedules/{schedule_id} Returns 204 No Content. Removes the schedule from NATS, the Mongo record, and the Redis cache in one call.

Trigger on demand

POST /v3/agents/{agent_key}/schedules/{schedule_id}/execution Runs the schedule’s payload immediately (≈10 seconds after the request, to stay above the NATS scheduler’s minimum deliver-at margin). The schedule itself is unaffected — its regular cadence continues. Useful for:
  • Smoke-testing a new schedule without waiting for its next firing
  • Manually re-running a missed execution
  • UI “Run now” buttons
Returns 202 Accepted with { "status": "triggered", "schedule_id": "..." }. Inactive schedules return 400.

Lifecycle semantics

is_active flips automatically for once schedules

After a once schedule fires, the scheduler records the trigger and sets is_active: false on the Mongo document. The record stays available via GET so you can inspect what ran and when. To re-run it, either create a new schedule or PATCH is_active: true with a fresh @at timestamp in the future.

Agent deletion cascades

Deleting an agent (DELETE /v2/agents/{agent_key}) asynchronously purges all schedules attached to it — from NATS, Mongo, and the Redis cache. You don’t need to clean up schedules before deleting the agent.

Inactive schedules don’t fire

When is_active is false, the NATS message is removed. Mongo fields (payload, expression) can still be updated while inactive; the values take effect on the next is_active: true transition.

Missed firings are not replayed

If the responses-api is down when a schedule would fire, that firing is lost. There’s no catch-up. Cron and interval schedules resume on the next scheduled time after the service is healthy.

Observability

Every scheduled run emits:
  • A trace with a schedule.<agent_key> leading span. The span carries orq.schedule_id, the full agent execution chain as children, and the same gen_ai.* / openresponses.* attributes you get from HTTP-invoked runs. Searchable by schedule_id in the traces UI.
  • An entity event with action triggered when execution starts, then one of completed, errored, or skipped when it ends. skipped covers inactive schedules, stale generations (the schedule was updated between the trigger being published and consumed), and deleted agents.
  • Field updates on the schedule document: last_triggered_at (UTC timestamp) and trigger_count (monotonic counter, reset on expression/type change).
Cost, tokens, and model are attached to the leading span the same way they appear for HTTP runs, so schedule-driven spend shows up in your usage reports automatically.

Worked examples

Daily morning digest (weekdays at 9am UTC)

curl -X POST https://api.orq.ai/v3/agents/ops_digest/schedules \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "cron",
    "expression": "0 0 9 * * mon-fri",
    "agent_tag": "v2",
    "payload": {
      "input": "Generate the morning briefing for {{region}}",
      "variables": { "region": "EMEA" },
      "metadata": { "run_source": "daily-briefing" }
    }
  }'

Follow-up in 24 hours

curl -X POST https://api.orq.ai/v3/agents/support_bot/schedules \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "once",
    "expression": "@at 2026-04-21T09:00:00Z",
    "payload": {
      "input": "Check in on ticket TICKET-123 and post a status update."
    }
  }'

Hourly background summarizer (minimum allowed cadence)

curl -X POST https://api.orq.ai/v3/agents/knowledge_indexer/schedules \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "interval",
    "expression": "@every 1h",
    "payload": {
      "input": "Fetch new entries and update the knowledge base",
      "memory_entity_id": "mem_entity_123"
    }
  }'

Scheduled run with secret variables

curl -X POST https://api.orq.ai/v3/agents/daily_sync/schedules \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "cron",
    "expression": "0 0 3 * * *",
    "payload": {
      "input": "Sync new rows from {{table}} to the analytics warehouse",
      "variables": {
        "table": "orders",
        "warehouse_token": { "secret": true, "value": "sk-secret-123" }
      }
    }
  }'
Secrets are redacted from traces and stripped from the stored payload’s observable form, same as the Responses API.

Update only the payload (cadence unchanged)

curl -X PATCH https://api.orq.ai/v3/agents/ops_digest/schedules/01KPN29WWKSK0VDPJNTKZPVNRB \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payload": {
      "input": "Generate the morning briefing for {{region}} — include active incidents",
      "variables": { "region": "EMEA" }
    }
  }'

Deactivate and reactivate

# Stop future firings — NATS entry is removed, Mongo state preserved.
curl -X PATCH https://api.orq.ai/v3/agents/ops_digest/schedules/01KPN29WWKSK0VDPJNTKZPVNRB \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

# Resume with the current (possibly-updated) values.
curl -X PATCH https://api.orq.ai/v3/agents/ops_digest/schedules/01KPN29WWKSK0VDPJNTKZPVNRB \
  -H "Authorization: Bearer $ORQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": true }'

List all schedules for an agent

curl https://api.orq.ai/v3/agents/ops_digest/schedules \
  -H "Authorization: Bearer $ORQ_API_KEY"
{
  "schedules": [
    {
      "_id": "01KPN29WWKSK0VDPJNTKZPVNRB",
      "type": "cron",
      "expression": "0 0 9 * * mon-fri",
      "is_active": true,
      "trigger_count": 12,
      "last_triggered_at": "2026-04-20T09:00:02Z"
    }
  ]
}

Run now (smoke test or retry)

curl -X POST https://api.orq.ai/v3/agents/ops_digest/schedules/01KPN29WWKSK0VDPJNTKZPVNRB/execution \
  -H "Authorization: Bearer $ORQ_API_KEY"
Returns 202 Accepted. The run appears in traces ~10 seconds later as schedule.ops_digest. Regular cadence is unaffected.

Delete

curl -X DELETE https://api.orq.ai/v3/agents/ops_digest/schedules/01KPN29WWKSK0VDPJNTKZPVNRB \
  -H "Authorization: Bearer $ORQ_API_KEY"
Returns 204 No Content.

Error reference

StatusCodeCause
400invalid_expressionMalformed cron, interval, or @at timestamp; or fires more often than once per hour.
400invalid_requestUnknown type; missing required field.
400schedule_inactivePOST /execution on an inactive schedule.
404agent_not_foundagent_key (or agent_tag) doesn’t exist in the workspace.
404schedule_not_foundSchedule ID doesn’t exist, or belongs to a different agent.

Limits

  • Minimum firing interval: 1 hour (interval + cron). once schedules have no minimum.
  • Maximum schedules per agent: unlimited.
  • Maximum payload size: same as the Responses API request body (1 MB).