Contents

Developers

Relays

A Relay is a fixed chain of agents you run from anywhere: JSON in, agents and scripts do the work, JSON out. You describe what you want in a Builder chat, test the draft, then publish versioned releases (v1, v2, …) that stay stable while you keep editing.

How one call flows

1. CallPOST your function, input JSON, and an idempotency key. Empty version means the active release.
→
2. Run pinnedThe run executes that release's frozen snapshot — later publishes can't change it mid-flight.
→
3. Poll resultGET the run until it completes. The response carries the JSON result plus the version that ran.

Repeat an idempotency key and you get the original run back (duplicate: true), even after newer releases publish. Reuse a key with different input and the API refuses with 409 — keys are promises, not suggestions.

Drafts vs releases

Draft Release (v1, v2, …)
Lives in Your editable workspace A frozen, checksummed snapshot
Changes when You edit in the Builder Never — publish mints a new one
Runs via Builder tests API calls (active, or a pinned older one)
On failure You see it in chat and fix it Fails visibly with the step and reason

Publishing requires a valid graph: a final output agent producing JSON, at least one enabled function with a required object INPUT, and saved code for every script step. Only owners and editors can publish or call.

What's inside a Relay

Agents

Authored prompts that read the caller's JSON ({{input}}), use tools and skills, and must return valid JSON.

Scripts

Strict Python steps with saved code. A script failure stops the run — no retries, no repairs.

Branches

Deterministic routes on JSON values. Every route must reach the output agent; no loops or joins.

Schedules can fire a Relay on a timer with a fixed JSON payload. Slack notifications are supported; WhatsApp, bot chats, and Auto-improve are not.

API reference

All calls are authenticated the same way as the rest of the API.

Start a run — POST /api/relays/{id}/runs

{
  "function": "greet",
  "input": { "name": "Ada" },
  "idempotency_key": "order-8842-attempt-1",
  "version": "v1"
}

version is optional and defaults to the active release. Returns 202:

{
  "run_id": "b28e48e9-…",
  "status": "running",
  "version": "v1",
  "duplicate": false,
  "poll_url": "/api/relays/wf_bb882752/runs/b28e48e9-…"
}

Poll a run — GET /api/relays/{id}/runs/{run}

Returns the run status while it works, and the output agent's JSON plus version once complete. Unknown runs and other people's runs both answer 404 — the API never confirms what you may not see.

List releases — GET /api/relays/{id}/releases

Returns the active version and every published release with its content hash.

Limits to know

  • Snapshots hold UTF-8 text only (50 MiB / 5000 files). Binary assets are outside the release contract.
  • Schedules execute the draft, not a pinned release.
  • A crashed run ends honestly as interrupted and stays pollable — but it never resumes mid-chain. Don't describe Relays as resumable.
  • A release whose files change after publishing fails its checksum and stops serving until you republish. Runs should only write inside their run folder.

Related: Security overview, Sharing and slots.