Docs

Routines

Scheduled Chats. A cron fires a fresh Chat on a cadence - a weekly refresh, a daily pipeline pulse, a standing competitive sweep - with no human in the loop.

Put a recurring question on a schedule — /routines is scheduled Chats. A Routine is a cron that fires a Chat on a cadence: each occurrence starts one turn of Master — the platform's general-purpose agent — 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

One occurrence
  1. The cron fires

    One occurrence of the schedule, in the timezone you set.

    your cadence

  2. A fresh Chat opens

    Never appended to an old one - history is one Chat per occurrence.

    named by date

  3. One Master turn runs

    on_question is always none, so a routine can never park waiting on a person.

    headless

  4. Outputs commit

    A living document lands as a new version; promotion stays human-gated.

    verified write gate

code
cron occurrence
   │
   ▼
new Chat "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://app.amdahl.ai/api/platform/v1/routines \
  -H "X-API-Key: $AMDAHL_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(absent = all)Outbound actions each fired run may invoke. Absent = every cataloged action is allowed (the default); pass a list to narrow, or [] to disable actions entirely.
external_searchfalseMarket fan-outs.
include_divergencefalseDivergence-map fusion on external reads.
depthdeepquick / standard / deep. Unset fires at deep, same as a Chat.

There is no evidence knob — citations and the query refs behind every data-backed block are unconditional on every fired run.

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, 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.

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