A run is one execution of a routine version. Runs are jobs, so you can wait on them, stream them or get a webhook.

Start a run

bash
curl -s "https://beta-api.b3os.org/v1/routines/nightly-digest/runs?wait=30" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"input": {"topic": "pricing"}, "durability": "ephemeral"}'
FieldMeaning
inputValidated against the routine's inputs schema; its defaults are applied
versionRun this version (ver_ ID or number) instead of the active one
durabilityOverride the routine's default: ephemeral, standard or strict
webhookWhere to post the run's events

With ?wait= the response is the finished run if it ends in time. An ephemeral run that finishes within the wait never touches the disk, which suits a routine an agent calls like a tool. Send Accept: text/event-stream to follow it live instead.

The run

json
{ "id": "run_01m5t5fr06dx6azc42f4wbzf5s", "object": "routine_run", "status": "succeeded", "routine_id": "rtn_01m5t6vhkw4a8fa4tb5w4ffz37", "version_number": 2, "durability": "ephemeral", "trigger": { "type": "api" }, "input": { "topic": "pricing" }, "result": { "summary": "Prices did not change today." }, "steps": [ { "id": "page", "uses": "vision/scrape@1", "status": "succeeded", "attempt": 1, "duration_ms": 91.2 }, { "id": "summary", "uses": "infer/chat@1", "status": "succeeded", "attempt": 1, "duration_ms": 1218.4 } ], "progress": { "completed": 2, "total": 2, "unit": "steps" }}

This example is abridged and its values are illustrative. trigger says how the run started: api, cron, interval, webhook, action, or routine for a run started by another routine. steps covers the top-level steps; GET /v1/routines/runs/{run_id}/steps lists every step execution in start order, with each map item (item_index), each retry (attempt), and their outputs and errors.

Follow it live

GET /v1/routines/runs/{run_id}/events streams the lifecycle events plus:

EventWhen
step.startedA step begins
step.retryingA step failed and will try again
step.waitingA wait step is waiting for a signal or a time
step.succeeded, step.failed, step.skippedA step ends
run.logA core/log@1 step wrote a line

Events are kept with the run's history, so you can reconnect with Last-Event-ID and pick up where you left off.

Signals

A wait step with a signal name waits for you to send that signal:

bash
curl -s "https://beta-api.b3os.org/v1/routines/runs/$RUN_ID/signal" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "approval", "payload": {"approved": true, "by": "ops@example.com"}}'

The waiting step completes with the payload as its outputs. A signal sent before its step starts waiting is buffered, up to 16 per name, and consumed in order. Signaling a run that already finished, or whose buffer for that name is full, fails with run_not_waiting.

Cancel

POST /v1/routines/runs/{run_id}/cancel tells in-flight steps to stop. Steps whose effects already happened are not undone. The run ends canceled, and steps that have not started are skipped unless their if calls always(), which is how a cleanup step still runs.

History and versions

Runs are kept for 30 days. GET /v1/routines/{routine}/runs lists a routine's runs, newest first, filterable by status. Each run pins the version it started with, so publishing a new version or rolling back never changes a run in progress. GET /v1/routines/{routine}/versions lists the versions, and GET .../versions/{version} returns one with its full definition.

Pause a routine

PATCH /v1/routines/{routine} with {"paused": true} stops all of its triggers; runs you start through the API still work. {"paused": false} resumes them, except for a routine paused because its publishing key was revoked, which needs a new version published with a valid key.

Ask a question... ⌘I