Docs

Routines

Consumer-facing guide to /routines — scheduled Chats. A Routine is a cron that fires a Chat on a cadence: each occurrence starts one Master agent turn in a fresh Chat named "{Routine name} — {date}". Use Routines for standing work — refreshing a living document every Monday, a weekly competitive sweep, a daily pipeline pulse — anything you would otherwise re-ask by hand.

The model

code
cron occurrence
   │
   ▼
new Session "Weekly pipeline refresh — 2026-07-13"
   │
   ▼
one Master turn, headless:
   - prompt = the routine's prompt (plus the doc's prior version, when declared)
   - config = the routine's persisted config (write_outputs, actions_allowed, …)
   - on_question is ALWAYS "none": ask_a_human returns no_human_in_loop immediately;
     a routine can never park waiting on a person

Every fire is a normal Chat run: watch it over the same SSE stream / read handles, find it in the Chats list, and read any document it committed in Living Knowledge. A routine that maintains a document commits through the verified write gate (see Outputs below) — promotion to the current version stays human-gated unless every verification check passes.

Create a routine

bash
curl -X POST https://api.amdahl.com/api/platform/v1/routines \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly pipeline refresh",
    "prompt": "Refresh the pipeline health report from current warehouse data.",
    "cron": "0 9 * * 1",
    "timezone": "America/New_York",
    "config": {
      "write_outputs": true,
      "agents": ["pipeline-analyst", "win-loss-analyst"]
    }
  }'

Body fields

FieldRequiredWhat it does
nameyesHuman label. Each fired Session is named "{name} — {date}".
promptyesThe Chat input every fire starts the Master turn with.
cronyesCron expression, validated before the routine is stored.
timezonenoIANA timezone the cron evaluates in. Default UTC.
agentnoLEGACY single-agent pin. Prefer config.agents; passing both rejects.
confignoPer-fire Chat config (below).
enablednoDefault true.

Config

The persisted subset of the Chat config, applied on every fire. on_question is not configurable — routines are headless, so a human ask always fails fast with no_human_in_loop.

KeyDefaultNotes
agentsWho the routine employs: "all" (plain Master, unrestricted delegation), one ref (the Master turn runs AS that agent), or several refs (the Master may delegate ONLY to that roster; other agents and inline prompts are refused). Unset behaves like the legacy agent pin.
write_outputstrueRoutines usually exist to refresh a document; the write gate still verifies.
write_memoryfalseLong-term memory commits.
actions_allowed[]Outbound actions the fired run may invoke.
external_searchfalseMarket fan-outs.
include_divergencefalseDivergence-map fusion on external reads.
evidencetrueCitation/query refs on the answer.
depthstandardquick / standard / deep.

The earlier output_slug / full_regen doc-target knobs are no longer writable — the agent picks its own document slug via outputs.write_doc. Existing routines that carry them keep their behavior (prior-version injection, wrote-no-doc detection) until their config is next replaced.

Manage routines

VerbWhat it does
GET /routinesList (filter ?enabled=, paginate ?limit=&offset=).
GET /routines/:idOne routine, including the last fire's Session + run ids.
PATCH /routines/:idPatch name / prompt / cron / timezone / agent / config / enabled.
DELETE /routines/:idRemove it. Sessions and documents from earlier fires are untouched.
POST /routines/:id/run-nowFire immediately, off-cadence. Returns the Session + run handles.

run-now returns the same { chat_id, run_id, stream_url, read_url, resume_url } envelope a Chat START does, so you can watch the fire live.

Outputs: the document commit gate

A routine that refreshes a living document commits it through outputs.write_doc — the Master's only document-write path — never a raw knowledge-base upload. The gate enforces, in order:

  1. Run policy — the run must have been started with write_outputs: true (the routine's config controls this per fire).
  2. Degraded-read halt — if a theme read (data.cluster_search) FAILED during the run, the commit is blocked entirely. A failed read is not an absence of themes; shipping would silently overwrite the last good version.
  3. Verified promotion — every stated digit is checked against the cells returned by the document's bound query pack (outputs.run_bound_queries, executed earlier in the same run). Auto-promotion to the current version is refused when no pack ran, when any digit fails verification, or when the run's pinned agent is tenant-authored — the new version then lands proposed and a human promotes it in Living Knowledge, which is the normal, safe outcome.

Documents keep their identity across every writer (routine fires, workflows, manual uploads): the slug resolves deterministically to the same per-workspace version family.

Reliability semantics

  • Fresh Session per fire. A routine never appends into an old Session; history is one Session per occurrence.
  • Missed occurrences self-heal. A fire skipped across a deploy/restart is caught up once by the scheduler's reconcile pass (never once per skipped period).
  • No double-fires. A cron tick and a catch-up for the same occurrence collapse to one run.
  • A failed fire is retried by the cadence. If starting the Master turn fails, nothing is recorded and the reconcile catch-up re-fires it; there is no hot retry loop.
  • Roster fires re-validate. Every agent in config.agents re-resolves at fire time; a routine pointing at a deleted agent skips the fire loudly instead of running with a partial roster.
  • Wrote-no-doc detection (legacy doc targets). When a routine still declares output_slug and a fire completes without persisting a version, the next fire logs the gap loudly — and is itself the bounded redelivery.

Canary: validating a routine against a workflow schedule

Before re-pointing a scheduled living document from a Workflow (blueprint schedule) onto a Routine, run both paths in parallel on one internal workspace and compare (this is the program's A9 gate; see the runbook §17):

  1. Pick one (workspace, doc_slug) — e.g. pipeline-health-report on an internal tenant.
  2. Leave the existing blueprint schedule enabled. Create a Routine with the same cadence and a prompt equivalent to the workflow's recipe intent that names the same doc slug (the Master commits it via outputs.write_doc with that slug).
  3. Dry-run first: POST /routines/:id/run-now and watch the run via stream_url. Confirm the fire opened a NEW Session, ran outputs.run_bound_queries before writing, and landed a proposed version (never auto-promoted without a verified pack).
  4. Compare the routine-written proposed version against the blueprint path's version in the doc's Versions tab: section headers present, key metrics match the pack cells, no "empty doc" signals.
  5. Deliberately break a read (or pick a window with a degraded cluster_search) and confirm the routine run REFUSES the doc write (degraded_read) instead of committing a theme-less version.
  6. Run 1–2 real cadences with both paths live, then write a short canary report before any cutover.

Over MCP

Routines ride the Amdahl MCP server's agents tool (one tool covers the Chat lifecycle, the agent library, and its routines): list_routines, get_routine, create_routine (name + prompt + cron, optional timezone / agent / config / enabled), update_routine, delete_routine, and run_routine_now — the last returns the same Chat/run handles a start_chat does, so an MCP agent can fire a routine and watch it via the same tool's chat_status action. Routine reads are also MCP resources: routine://list and routine://<id>. Scopes: routines:read / routines:write (both on the customer-agent key bundle; existing keys were backfilled).

Scopes

ScopeGrantsDefault role
routines:readGET /routines, GET /routines/:idviewer
routines:writecreate / update / delete / run-noweditor
outputs:writeoutputs.write_doc, outputs.run_bound_queries (agent gate)editor