From f42aebdff8987046449992263829882eb3a40a75 Mon Sep 17 00:00:00 2001 From: Aron Prins Date: Mon, 23 Mar 2026 09:58:27 +0100 Subject: [PATCH] docs(api): add Routines reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Routines are recurring tasks that fire on a schedule, webhook, or API call and create a heartbeat run for the assigned agent. Document the full CRUD surface including: - List / get routines - Create with concurrency and catch-up policy options - Add schedule, webhook, and api triggers - Update / delete triggers, rotate webhook secrets - Manual run and public trigger fire - List run history - Agent access rules (agents can only manage own routines) - Routine lifecycle (active → paused → archived) Co-Authored-By: Claude Sonnet 4.6 --- docs/api/routines.md | 197 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 docs/api/routines.md diff --git a/docs/api/routines.md b/docs/api/routines.md new file mode 100644 index 00000000..f685f6ba --- /dev/null +++ b/docs/api/routines.md @@ -0,0 +1,197 @@ +--- +title: Routines +summary: Recurring task scheduling, triggers, and run history +--- + +Routines are recurring tasks that fire on a schedule, webhook, or API call and create a heartbeat run for the assigned agent. + +## List Routines + +``` +GET /api/companies/{companyId}/routines +``` + +Returns all routines in the company. + +## Get Routine + +``` +GET /api/routines/{routineId} +``` + +Returns routine details including triggers. + +## Create Routine + +``` +POST /api/companies/{companyId}/routines +{ + "title": "Weekly CEO briefing", + "description": "Compile status report and email Founder", + "assigneeAgentId": "{agentId}", + "projectId": "{projectId}", + "goalId": "{goalId}", + "priority": "medium", + "status": "active", + "concurrencyPolicy": "coalesce_if_active", + "catchUpPolicy": "skip_missed" +} +``` + +**Agents can only create routines assigned to themselves.** Board operators can assign to any agent. + +Fields: + +| Field | Required | Description | +|-------|----------|-------------| +| `title` | yes | Routine name | +| `assigneeAgentId` | yes | Agent who receives each run | +| `projectId` | yes | Project this routine belongs to | +| `goalId` | no | Goal to link runs to | +| `parentIssueId` | no | Parent issue for created run issues | +| `priority` | no | `critical`, `high`, `medium` (default), `low` | +| `status` | no | `active` (default), `paused`, `archived` | +| `concurrencyPolicy` | no | Behaviour when a run fires while a previous one is still active | +| `catchUpPolicy` | no | Behaviour for missed scheduled runs | + +**Concurrency policies:** + +| Value | Behaviour | +|-------|-----------| +| `coalesce_if_active` (default) | Skip the new run if one is already in progress | +| `skip_if_active` | Same as coalesce but without queuing | +| `always_enqueue` | Always enqueue, regardless of active runs | + +**Catch-up policies:** + +| Value | Behaviour | +|-------|-----------| +| `skip_missed` (default) | Missed scheduled runs are dropped | +| `enqueue_missed_with_cap` | Missed runs are enqueued up to an internal cap | + +## Update Routine + +``` +PATCH /api/routines/{routineId} +{ + "status": "paused" +} +``` + +All fields from create are updatable. **Agents can only update routines assigned to themselves and cannot reassign a routine to another agent.** + +## Add Trigger + +``` +POST /api/routines/{routineId}/triggers +``` + +Three trigger kinds: + +**Schedule** — fires on a cron expression: + +``` +{ + "kind": "schedule", + "cronExpression": "0 9 * * 1", + "timezone": "Europe/Amsterdam" +} +``` + +**Webhook** — fires on an inbound HTTP POST to a generated URL: + +``` +{ + "kind": "webhook", + "signingMode": "hmac_sha256", + "replayWindowSec": 300 +} +``` + +Signing modes: `bearer` (default), `hmac_sha256`. Replay window range: 30–86400 seconds (default 300). + +**API** — fires only when called explicitly via [Manual Run](#manual-run): + +``` +{ + "kind": "api" +} +``` + +A routine can have multiple triggers of different kinds. + +## Update Trigger + +``` +PATCH /api/routine-triggers/{triggerId} +{ + "enabled": false, + "cronExpression": "0 10 * * 1" +} +``` + +## Delete Trigger + +``` +DELETE /api/routine-triggers/{triggerId} +``` + +## Rotate Trigger Secret + +``` +POST /api/routine-triggers/{triggerId}/rotate-secret +``` + +Generates a new signing secret for webhook triggers. The previous secret is immediately invalidated. + +## Manual Run + +``` +POST /api/routines/{routineId}/run +{ + "source": "manual", + "payload": { "context": "..." }, + "idempotencyKey": "my-unique-key" +} +``` + +Fires a run immediately, bypassing the schedule. Concurrency policy still applies. + +## Fire Public Trigger + +``` +POST /api/routine-triggers/public/{publicId}/fire +``` + +Fires a webhook trigger from an external system. Requires a valid `Authorization` or `X-Paperclip-Signature` + `X-Paperclip-Timestamp` header pair matching the trigger's signing mode. + +## List Runs + +``` +GET /api/routines/{routineId}/runs?limit=50 +``` + +Returns recent run history for the routine. Defaults to 50 most recent runs. + +## Agent Access Rules + +Agents can read all routines in their company but can only create and manage routines assigned to themselves: + +| Operation | Agent | Board | +|-----------|-------|-------| +| List / Get | ✅ any routine | ✅ | +| Create | ✅ own only | ✅ | +| Update / activate | ✅ own only | ✅ | +| Add / update / delete triggers | ✅ own only | ✅ | +| Rotate trigger secret | ✅ own only | ✅ | +| Manual run | ✅ own only | ✅ | +| Reassign to another agent | ❌ | ✅ | + +## Routine Lifecycle + +``` +active -> paused -> active + -> archived +``` + +Archived routines do not fire and cannot be reactivated.