Schedules API
Agent-scoped cron schedules — a schedule fires a fixed prompt to a specific agent on a cron cadence. Fully live (not a stub). Backed by the kernel's CronJob records (crates/kernel/hoziron-kernel-types/src/scheduler.rs). See also cron.md for the equivalent daemon-wide /cron/jobs surface, which manages the exact same underlying records (they share the same in-memory store — a schedule created via one surface is visible/manageable via the other).
Endpoints
| Method | Path | Action | Description |
|---|---|---|---|
| GET | /agents/{id}/schedules | AgentStatus | List schedules for an agent |
| POST | /agents/{id}/schedules | ScheduleCreate | Create a schedule for an agent |
| POST | /schedules/{id}/pause | ScheduleUpdate | Pause a schedule |
| POST | /schedules/{id}/resume | ScheduleUpdate | Resume a schedule |
| DELETE | /schedules/{id} | ScheduleDelete | Delete a schedule |
ScheduleCreate/ScheduleUpdate/ScheduleDelete are admin/operator only. AgentStatus (read) is broadly readable (admin/operator/developer/viewer/service/auditor).
GET /agents/{id}/schedules
curl -H "Api-Version: v1" -H "Authorization: Bearer hzn_sk_..." \
http://localhost:4200/agents/550e8400-e29b-41d4-a716-446655440000/schedules
Response (200) — CronJob[]
{
"schedules": [
{
"id": "a1b2c3d4-e29b-41d4-a716-446655440000",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "schedule",
"enabled": true,
"schedule": {"kind": "cron", "expr": "0 */6 * * *", "tz": null},
"action": {"kind": "agent_turn", "message": "Check for overdue claims and escalate any past SLA.", "model_override": null, "timeout_secs": null},
"created_at": "2026-05-20T00:00:00Z",
"last_run": "2026-06-04T06:00:00Z",
"next_run": "2026-06-04T12:00:00Z"
}
]
}
id is a plain UUID (CronJobId's Display prints the inner UUID with no prefix). name defaults to "schedule" for jobs created through this route — there is no name field on the create request. enabled is a plain boolean, not a state string enum. schedule and action are internally-tagged enums ("kind" field): schedule.kind is "cron" (with expr/tz), "every" (with every_secs), or "at" (with at); action.kind is always "agent_turn" (with message/model_override/timeout_secs) — it's the only variant.
POST /agents/{id}/schedules
curl -X POST -H "Api-Version: v1" -H "Authorization: Bearer hzn_sk_..." \
-H "Content-Type: application/json" \
-d '{"expression": "0 */6 * * *", "prompt": "Check for overdue claims."}' \
http://localhost:4200/agents/550e8400-e29b-41d4-a716-446655440000/schedules
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
expression | string | Yes | Cron expression |
prompt | string | Yes | Prompt delivered to the agent when the schedule fires |
(agent_id is also a valid field on the underlying request struct but is ignored on this route — the path param {id} takes precedence. It's required, not ignored, on the /cron/jobs variant — see cron.md.)
Response (201)
{"id": "a1b2c3d4-e29b-41d4-a716-446655440000"}
Error (400 — invalid cron expression)
{"error": {"category": "ValidationError", "message": "..."}}
POST /schedules/{id}/pause
curl -X POST -H "Api-Version: v1" -H "Authorization: Bearer hzn_sk_..." \
http://localhost:4200/schedules/a1b2c3d4-e29b-41d4-a716-446655440000/pause
Response (200)
{"status": "paused"}
POST /schedules/{id}/resume
{"status": "active"}
DELETE /schedules/{id}
Response (204 No Content)
Error (404 — unknown schedule)
{"error": {"category": "NotFound", "message": "Schedule not found: a1b2c3d4-...", "details": {"schedule_id": "a1b2c3d4-..."}}}