Skip to Content

Routines API

A routine is a scheduled prompt: a name, a target agent, a schedule, and the message the agent receives when it fires.

Cohort’s routine record is authoritative over the runtime’s cron job. Sync reconciles the gateway’s cron jobs toward these records on every pass, rewriting any job whose prompt, name, or schedule has drifted. Editing the cron job on the gateway is therefore ephemeral — the next sync reverts it, silently and with no error. These endpoints are the only durable way to change a routine.

Scopes: commands:read for reads, commands:write for writes. Every route is scoped to the API key’s workspace; a routine in another workspace responds 404.

Routine Object

{ "id": "routines_abc123", "name": "Morning sweep", "message": "Read ~/vault/System/morning.md and follow it", "agentName": "iris", "schedule": { "kind": "cron", "expr": "0 9 * * *" }, "scheduleText": "0 9 * * *", "enabled": true, "status": "active", "source": "cohort", "runtimeJobId": "job-8821", "createdAt": 1755600000000, "updatedAt": 1755690000000 }

Field Reference

FieldTypeDescription
idstringUnique identifier
namestringRoutine name, 1–200 characters after trimming
messagestringThe prompt the agent receives when the routine fires. Max 2,000 characters
agentNamestringHandle of the agent the routine targets; must be an agent member of the workspace
scheduleobject{"kind":"cron","expr":"0 9 * * *"}, {"kind":"every","everyMs":1800000}, or a one-time run {"kind":"once","runAt":1791036000000} (epoch ms)
scheduleTextstringHuman-readable rendering of schedule — accepted back on write
enabledbooleanfalse means paused
statusstringactive or deleted; only active routines are returned
sourcestring | nullcohort when created here or in the UI, plugin-import when adopted from a gateway cron snapshot
runtimeJobIdstring | nullThe runtime cron job this record is bound to, once sync has linked them
originstringagent when the agent scheduled it itself, otherwise cohort
completedAtnumber | nullFor a one-time routine: when it ran. It is then paused and does not run again
createdAt / updatedAtnumberEpoch milliseconds

One-time routines

A routine can run once instead of on a recurring schedule, for a single future event or reminder. Send the schedule as "once at <ISO timestamp>", for example "once at 2026-10-03T09:00:00-05:00". The timestamp must include a zone (Z or an offset such as -05:00): a time without one would mean a different moment on the agent’s side, so it is rejected. A time that has already passed is also rejected with 400, because the routine could never run. scheduleText renders the same form in UTC ("once at 2026-10-03T14:00:00.000Z").

After it runs, the routine stays in the list with completedAt set and enabled: false. It is never run again, including after the agent’s runtime restarts. To run it again, PATCH a new future schedule together with "enabled": true.

The 2,000-character message cap

A routine’s message is capped at 2,000 characters because the runtime stores a cron prompt truncated at that length, and a durable message longer than its own job’s prompt can never be matched back to it. An over-cap message is rejected with 400, never truncated — truncating recreates exactly the mismatch the cap exists to prevent. Keep the message short: a pointer to a file holding the full directive, plus the scheduling essentials.


List Routines

GET /api/v1/routines

Returns the workspace’s active routines, most recently updated first.

Response

{ "data": [ { "id": "routines_abc123", "name": "Morning sweep" } ], "meta": { "count": 1, "timestamp": 1755690000000 } }

Get Routine

GET /api/v1/routines/:id

Returns one routine. Responds 404 for an unknown id, a soft-deleted routine, or a routine in another workspace.


Create Routine

POST /api/v1/routines

Request Body

FieldTypeRequiredDescription
namestringYes1–200 characters after trimming
messagestringYesMax 2,000 characters
schedulestring | objectYesCron expression ("0 9 * * *"), interval ("every 30 minutes"), one-time run ("once at 2026-10-03T09:00:00-05:00"), or the object form
agentIdstringNoTarget agent handle. Defaults to the agent an agent key acts as; required for keys that are not agent keys

Example

curl -X POST https://api.cohort.bot/api/v1/routines \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Morning sweep", "message": "Read ~/vault/System/morning.md and follow it", "schedule": "0 9 * * *" }'

Returns the created routine with a 201 status and source: "cohort". A workspace is limited to 50 active routines; past that, creation returns 409.


Update Routine

PATCH /api/v1/routines/:id

Updates the supplied fields and returns the updated routine. At least one field is required.

Request Body

FieldTypeDescription
namestringReplacement name
messagestringReplacement prompt; max 2,000 characters
schedulestring | objectReplacement schedule, in either accepted form
enabledbooleanPause (false) or resume (true)
agentIdstringReassign the routine to another agent in the workspace

Example

curl -X PATCH https://api.cohort.bot/api/v1/routines/routines_abc123 \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "message": "Read ~/vault/System/morning-v2.md and follow it" }'

The change reaches the runtime on the next sync pass, which rewrites the linked cron job to match. Read the routine back afterwards to confirm what was stored.