docsorchestration

Chain headless agents, step by step

Define an ordered chain of Claude or Codex steps that run headless in a grid slot. Each step's final output flows into the next, and the run pauses at a checkpoint whenever you want it to.

overview

Relay runs a sequence of AI-agent steps as terminating child processes — no interactive terminal, no typing. Each step picks its own agent, model, permissions and budget, and its final output flows into the next step's prompt through a {prev} placeholder. The whole chain is spawned, parsed and persisted by the backend, so it survives an app restart. It's how you orchestrate multi-stage work — plan, then implement, then review — deterministically.

  • No relay server, no cloud, no telemetry — only the agent CLIs talk to their providers
  • Definitions and runs live under the project's own .13x/relays/ directory
  • Done/Failed decided by exit code + parsed result event — never a timer or output silence
  • run.json rewritten atomically (tmp + rename) and repaired to Failed if interrupted
  • Headless steps never prompt — the permission preset is enforced up front
  • On Windows, each step's process tree is job-isolated — no leftover background processes
why it matters

Completion is decided, not guessed

Done vs failed comes only from the child's exit code, enriched by the parsed JSONL result event. Exit 0 always wins. There is no timer and no output-silence heuristic — a stream that claims is_error but exits 0 stays Done with a warning.

Manual checkpoints between steps

In manual mode the run pauses at a checkpoint after every successful step and waits for you to press Continue. Auto mode chains straight through while exit codes are 0. A failure always halts the chain, in either mode.

Crash-safe local persistence

Every structural change rewrites run.json atomically (tmp + rename) under .13x/relays/runs/. After a restart, runs hydrate back into their panes, and any orphaned 'running' record is repaired to Failed('interrupted') on next read — run.json never lies running forever.

Per-step model, permissions and a budget cap

Each step picks its agent and model (Claude Opus / Sonnet / Fable / Haiku presets, Codex, or a custom override), a permission preset (readonly, workspace, full) that pre-authorizes the headless run, and — for Claude — a hard --max-budget-usd cost ceiling.

Structured hand-off, never scrollback

The {prev} placeholder substitutes the previous step's structured result — the Claude result event, or Codex's -o output file (falling back to the last agent_message) — never raw terminal scrollback. The extracted text is written to step-NN-output.txt as the source of truth.

Reusable saved relays per project

Definitions persist to .13x/relays/definitions/<id>.json and appear in a saved-relay library you can pick, duplicate, edit and delete. Author them in the dedicated Relay view or in the per-slot builder modal.

how it works
01

Build the chain

Open the Relay view from the sidebar (needs an open project), name the relay, and add ordered steps. Per step, set the agent, model, permission preset, optional Claude budget cap, and the prompt. On non-first steps, insert the +{prev} chip to reference the previous step's output.

02

Start it on a slot

From an empty grid slot click RELAY to open the builder, then START. The definition is always persisted first, then the chain launches headless on the managed slot. A slot rejects a second start while a run is Running or Paused — one active run per slot, enforced.

03

Steps run headless

The runner builds the CLI invocation (claude -p --output-format stream-json, or codex exec --json), spawns the child with stdin closed, tees raw JSONL to disk, and feeds it to the parser. Completion is pipe EOF plus the wait() exit code plus the parsed result.

04

Watch and checkpoint

The pane shows a live step counter, turns, cost, exit code, an activity line and the extracted final output. In manual mode it pauses at a checkpoint — press CONTINUE to release the next step, or ABORT to tree-kill the current child and settle the run as aborted.

05

Restart-safe by default

On rig launch or workspace switch, runs hydrate from .13x/relays/runs/ and the newest run per slot rebinds to its pane. RESET drops the slot binding without deleting the run — the history stays on disk.

faq

How does Relay know a step finished?

By the child process exiting. Completion is pipe EOF plus the wait() exit code, enriched by the parsed JSONL result event. Exit 0 always wins; there is no timer and no output-silence guessing. A stream that claims is_error but exits 0 stays Done with a warning.

What can a headless step do?

Only what its permission preset pre-authorizes — readonly, workspace (default), or full. A headless step never prompts; anything the preset disallows is denied and surfaced at the checkpoint. This maps to Claude's --permission-mode / --dangerously-skip-permissions and Codex's sandbox flags.

Does a relay survive an app restart?

Yes. Every structural change rewrites run.json atomically under .13x/relays/runs/. On the next launch, runs hydrate back into their panes, and any orphaned 'running' record is auto-repaired to Failed('interrupted').

Can steps loop, or hand off an interactive session?

Not yet. Loops aren't implemented — next_step is simply the next step in the list (instances are stored chronologically to allow loops later). And the interactive 'takeover' (claude --resume / codex resume) is reserved: session ids are captured and stored but not used this round.

get started

one project. many shells. zero noise.

13x is local-first and free of telemetry — your code, commands and shells never leave the machine. Join the waitlist for the next build.