Documentation Index
Fetch the complete documentation index at: https://docs.orq.ai/llms.txt
Use this file to discover all available pages before exploring further.
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
| Type | Expression | Example | Fires |
|---|
interval | @every <duration> | @every 6h | Every 6 hours after creation |
cron | 6-field cron (seconds required) | 0 0 9 * * mon-fri | 9:00:00 UTC Mon–Fri |
once | @at <RFC3339-UTC> | @at 2026-05-01T09:00:00Z | Exactly 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.
| Field | Type | Description |
|---|
input | string or array | Same shape as the Responses API input — text or items. |
variables | object | Template variable substitution. Supports secret values {"secret": true, "value": "..."}. |
memory_entity_id | string | Memory store entity to attach, see Memory. |
metadata | object | Opaque 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 reschedules the job, bumps generation, and resets trigger_count to 0.
is_active — false stops future firings; 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. Permanently removes the schedule in a single call.
Trigger on demand
POST /v3/agents/{agent_key}/schedules/{schedule_id}/execution
Runs the schedule’s payload immediately (≈10 seconds after the request, the minimum dispatch 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 flips is_active to false. 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 removes all schedules attached to it. You don’t need to clean up schedules before deleting the agent.
Inactive schedules don’t fire
When is_active is false, the schedule stops firing entirely. You can still PATCH its fields (payload, expression) while inactive; the new values take effect on the next is_active: true transition.
Missed firings are not replayed
If orq.ai is unavailable when a schedule would fire, that firing is lost. There’s no catch-up. Cron and interval schedules resume on their next scheduled time once service is restored.
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 — the record is preserved, just won't fire.
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
| Status | Code | Cause |
|---|
| 400 | invalid_expression | Malformed cron, interval, or @at timestamp; or fires more often than once per hour. |
| 400 | invalid_request | Unknown type; missing required field. |
| 400 | schedule_inactive | POST /execution on an inactive schedule. |
| 404 | agent_not_found | agent_key (or agent_tag) doesn’t exist in the workspace. |
| 404 | schedule_not_found | Schedule 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).