All docs

Docs / API & CLI

Runs

A run is the second shape: you hand Amolfi a goal instead of a tool call. Amo triages it, delegates to the specialists that own the work, and follows it against your real workspace — the same work you would watch happen in chat.

Start one

Starting a run returns 202, never 200. A run is asynchronous by nature, and a run id must never read as finished work.

POST /v1/runs
{ "goal": "draft the october email from what actually shipped" }

202 { "status": "queued", "run_id": "…" }

Follow it

GET  /v1/runs/{run_id}           → status, specialists, activity, any pending approval
POST /v1/runs/{run_id}/guidance  → steer it mid-flight
POST /v1/runs/{run_id}/cancel    → stop it

Poll the run rather than holding a connection open. Each snapshot carries the run’s status, the specialists working on it, and the recent activity lines.

The status vocabulary

A run reports one of six statuses. This is a deliberately narrow public vocabulary — the internal lifecycle is richer, and it stays internal so it can change without breaking you.

  • queued — accepted, not started.
  • working — in progress.
  • pending_approval — stopped, waiting on a person. Not an error.
  • completed · failed · cancelled — terminal.

Activity lines are also a projection, not raw internals: they read as amo:…, specialist:…, tool:…, approval:…, or run:…. A tool line can carry the hostname it called. Render that as plain text and never as a link — it is influenced by whatever the tool was pointed at.

When a run needs an owner

A run that reaches something outward — sending, spending, signing, publishing — does not execute it and does not fail. It files an approval card and waits. The run surfaces as pending_approval with the decision’s id, and a workspace owner approves or declines in the app.

Machines propose. Owners approve. A run is a goal, not an authorisation.

There is deliberately no approve endpoint. Guidance is guidance — it maps to steering a run that is already yours to steer — and adding an approve verb would be the bypass this whole design exists to prevent, wearing a different noun. The scope vocabulary makes it unrepresentable: propose is the ceiling.

What bounds a run

A run’s reach is bounded by the token’s scopes, not by the goal’s ambition. A goal that needs a capability the token lacks stops with a 403 rather than returning a partial result and calling it done. Running a goal needs runs.runs.write; polling one needs runs.runs.read.

Read how it actually works. Setup, security, and the model underneath — in plain language, no marketing in the way.