# Agent orchestration

> Multi-agent coordination: messaging (`send`/`check`/`reply`), task DAGs, dispatch/inject, coordinator `run`, decision gates, and group addresses—requires experimental feature and running runtime.

- Repository: stablyai/orca
- GitHub: https://github.com/stablyai/orca
- Human docs: https://grok-wiki.com/public/docs/stablyai-orca-2036d532bf1c
- Complete Markdown: https://grok-wiki.com/public/docs/stablyai-orca-2036d532bf1c/llms-full.txt

## Source Files

- `src/cli/specs/orchestration.ts`
- `src/cli/handlers/orchestration.ts`
- `src/main/runtime/orchestration/db.ts`
- `src/main/runtime/orchestration/formatter.ts`
- `skills/orchestration/SKILL.md`
- `src/cli/help.ts`

---

---
title: "Agent orchestration"
description: "Multi-agent coordination: messaging (`send`/`check`/`reply`), task DAGs, dispatch/inject, coordinator `run`, decision gates, and group addresses—requires experimental feature and running runtime."
---

Orca’s `orca orchestration` command group talks to the running desktop or headless runtime over RPC. The runtime persists mail, tasks, dispatch contexts, decision gates, and coordinator runs in SQLite (`orchestration.db` under Electron `userData`), injects unread mail into agent terminals on TUI idle, and runs an optional background coordinator loop. Enable **Agent Orchestration** in **Settings → Orchestration** (`orca.orchestration.enabled` in `localStorage`) and keep Orca running (`orca status --json` with `runtime: true`) before using these commands.

## Architecture

```mermaid
flowchart TB
  subgraph cli["CLI handlers"]
    OC[orca orchestration *]
  end
  subgraph rpc["Runtime RPC (`orchestration.*` methods)"]
    SEND[send / check / reply / inbox / ask]
    TASK[taskCreate / taskList / taskUpdate]
    DISP[dispatch / dispatchShow]
    RUN[run / runStop]
    GATE[gateCreate / gateResolve / gateList]
    RESET[reset]
  end
  subgraph store["SQLite (`OrchestrationDb`)"]
    MSG[(messages)]
    TSK[(tasks)]
    CTX[(dispatch_contexts)]
    GAT[(decision_gates)]
    CRN[(coordinator_runs)]
  end
  subgraph runtime["Orca runtime"]
    PTY[PTY inject on idle]
    COORD[Coordinator loop]
  end
  OC --> rpc
  SEND --> MSG
  TASK --> TSK
  DISP --> CTX
  DISP --> PTY
  RUN --> COORD
  COORD --> TSK
  COORD --> CTX
  COORD --> MSG
  GATE --> GAT
  RESET --> store
  PTY --> MSG
```

| Layer | Responsibility |
| --- | --- |
| CLI | Parses flags, resolves `--from` / `--terminal` via `ORCA_TERMINAL_HANDLE` or active terminal selector, calls RPC |
| RPC (`orchestration.*`) | Validation, group fan-out, long-poll `check --wait`, dispatch preamble build/inject |
| `OrchestrationDb` | WAL SQLite schema, DAG promotion, dispatch circuit breaker, gate blocking |
| `Coordinator` | Poll loop: read coordinator inbox, dispatch ready tasks, stale-heartbeat warnings |
| PTY path | Push-on-idle delivery of undelivered banners (`formatMessagesForInjection`) |

<Note>
Orchestration is for **agent-to-agent** coordination. Use `orca terminal` (see [CLI scripting workflow](/cli-scripting-workflow)) for shell I/O, `orca worktree` for git workspaces, and `orca orchestration` only when messaging tasks between agent terminals.
</Note>

## Prerequisites

<Steps>
<Step title="Runtime reachable">
Confirm the Orca app or `orca serve` runtime is up: `orca status --json` should report a ready runtime.
</Step>
<Step title="Enable orchestration">
In **Settings → Orchestration**, turn on **Agent Orchestration**. Optionally install the bundled `orchestration` agent skill from the same pane so workers know the CLI contract.
</Step>
<Step title="CLI on PATH">
Register the CLI from **Settings → Browser → Enable Orca CLI** (or use `orca-dev` when developing against a dev user-data directory).
</Step>
<Step title="Agent terminals">
Create terminals with a recognized agent CLI (`claude`, `codex`, etc.) before `dispatch --inject`. Each Orca-managed PTY receives `ORCA_TERMINAL_HANDLE` for default `--from` / `--terminal` resolution.
</Step>
</Steps>

## Terminal handle resolution

Handlers resolve the sending or checking terminal in this order:

1. Explicit `--from` or `--terminal`
2. `ORCA_TERMINAL_HANDLE` in the process environment (injected at PTY spawn)
3. Active terminal for the current worktree via CLI selectors

`orchestration ask` extends the RPC client timeout to `timeoutMs + 5000` so the default 60s transport limit does not abort a long question wait.

## Messaging

Inter-agent mail is stored per recipient with independent `read` and `delivered_at` tracking. Unread rows returned by `check` (default) are marked read; push-on-idle injection uses `delivered_at` so the same message is not re-injected on every idle transition.

### Commands

| Command | Purpose |
| --- | --- |
| `orca orchestration send` | Point-to-point or group fan-out |
| `orca orchestration check` | Read inbox for a handle; optional inject, wait, type filter |
| `orca orchestration reply` | Reply in-thread to a message id |
| `orca orchestration inbox` | Global or per-handle history (`--full` includes body/payload) |
| `orca orchestration ask` | Send `decision_gate`, block until reply (not in `orca help` summary yet) |

```bash
orca orchestration send --to <handle|@group> --subject "<text>" \
  [--from <handle>] [--body <text>] [--type <type>] [--priority <level>] \
  [--thread-id <id>] [--payload <json>] [--json]

orca orchestration check [--terminal <handle>] [--unread | --all] \
  [--types <type,...>] [--inject] [--wait] [--timeout-ms <n>] [--json]

orca orchestration reply --id <msg_id> --body "<text>" [--from <handle>] [--json]
```

### Message types and priority

| `type` values | Typical use |
| --- | --- |
| `status` | General updates (default) |
| `dispatch` | Work assignment metadata |
| `worker_done` | Structured task completion |
| `merge_ready` | Branch ready to merge |
| `escalation` | Blocker before completion |
| `handoff` | Pass work to another agent |
| `decision_gate` | Human or coordinator decision |
| `heartbeat` | Liveness during long tasks |

Priority: `normal`, `high`, `urgent` (banner tags `[HIGH]` / `[URGENT]` when injected).

### `check` behavior

| Flag | Behavior |
| --- | --- |
| *(default)* | Unread only; marks returned rows read |
| `--all` | All messages for handle; does not mark read |
| `--inject` | Adds `formatted` banner text for prompt injection |
| `--wait` | Blocks until a matching message or timeout (default inner wait **2 minutes** when `--timeout-ms` omitted) |
| `--types` | Comma-separated filter (e.g. `worker_done,escalation`) |

With `--wait`, the CLI emits JSON heartbeat objects on **stderr** every 15s (`_heartbeat: true`) so parent processes know the subprocess is alive. Filter with `jq 'select(._heartbeat|not)'` when merging streams.

### Group addresses

Addresses starting with `@` fan out to one `messages` row per recipient, sharing `thread_id`, with per-recipient read state. Resolution happens at send time in the runtime group resolver.

| Address | Recipients |
| --- | --- |
| `@all` | All terminal handles except sender |
| `@idle` | Handles whose agent TUI status is `idle` |
| `@claude`, `@codex`, `@opencode`, `@gemini` | Handles whose title contains the agent name (case-insensitive group token) |
| `@worktree:<id>` | Handles in the given worktree, except sender |

Empty resolution throws `No recipients resolved for group address`. `orchestration ask` **rejects** group addresses; use `send --type decision_gate` for fan-out questions.

### `ask`

```bash
orca orchestration ask --to <handle> --question "<text>" \
  [--options <csv>] [--timeout-ms <n>] [--from <handle>] [--json]
```

Default wait **600000 ms** (10 minutes). On timeout, exit code is **1**. With `--json`, stdout is a **bare** JSON object (`answer`, `messageId`, `threadId`, `timedOut`) — not the usual RPC envelope — so `jq -r .answer` works directly.

## Task DAG

Tasks live in `tasks` with a JSON `deps` array of task ids. Tasks without deps start as `ready`; tasks with deps start as `pending` until every dependency is `completed`, then promotion runs synchronously inside `updateTaskStatus`.

### Task statuses

```mermaid
stateDiagram-v2
  [*] --> pending: deps non-empty
  [*] --> ready: no deps
  pending --> ready: all deps completed
  ready --> dispatched: dispatch
  dispatched --> completed: worker_done / task-update
  dispatched --> ready: dispatch failed (< 3 failures)
  dispatched --> failed: circuit_broken
  ready --> blocked: gate-create
  blocked --> ready: gate-resolve
  ready --> failed: task-update / circuit
```

| Status | Meaning |
| --- | --- |
| `pending` | Waiting on dependencies |
| `ready` | Dispatchable |
| `dispatched` | Active dispatch context |
| `completed` | Done; promotes dependents |
| `failed` | Terminal failure (including circuit breaker) |
| `blocked` | Held by a pending decision gate |

### Commands

```bash
orca orchestration task-create --spec "<text>" \
  [--deps '["task_a","task_b"]'] [--parent <task_id>] [--json]

orca orchestration task-list [--status <status>] [--ready] [--json]

orca orchestration task-update --id <task_id> --status <status> \
  [--result <json>] [--json]
```

`task-list` joins active dispatch metadata (`assignee_handle`, `dispatch_id`) for `dispatched` rows. `task-create` records `ORCA_TERMINAL_HANDLE` as `created_by_terminal_handle` when set (used for worktree lineage).

## Dispatch and preamble

Dispatch uses a **sling** pattern: the `tasks` row stays canonical; `dispatch_contexts` track each assignment, failures, and heartbeats. A terminal may hold only one active dispatch (`pending` or `dispatched`).

```bash
orca orchestration dispatch --task <task_id> --to <handle> \
  [--from <handle>] [--inject] [--dry-run] [--return-preamble] [--json]

orca orchestration dispatch-show --task <task_id> [--preamble] [--from <handle>] [--json]
```

| Flag | Behavior |
| --- | --- |
| `--inject` | Sends built preamble + task spec into the PTY (`enter: true`). Requires a recognized agent in the target terminal |
| `--dry-run` | Returns preamble only; no state change; `--to` optional |
| `--return-preamble` | Includes preamble text in the RPC result for auditing |

The dispatch preamble documents required `worker_done` and periodic `heartbeat` payloads (5-minute cadence; coordinator stale warning at ~10 minutes without heartbeat). In dev user-data paths, preamble uses `orca-dev` instead of `orca`.

**Circuit breaker:** after **3** consecutive dispatch failures for a task, the context becomes `circuit_broken` and the task moves to `failed`. Failed dispatches otherwise return the task to `ready` for retry.

**Stale base guard (coordinator):** when `orchestration run --worktree` is set, dispatch may skip tasks whose worktree is more than **20** commits behind tracking branch unless the task spec includes a final line `allow-stale-base: true` (stripped from the worker-facing spec).

## Decision gates

Gates block a task and complete its active dispatch until resolved.

```bash
orca orchestration gate-create --task <task_id> --question "<text>" \
  [--options '["A","B"]'] [--json]

orca orchestration gate-resolve --id <gate_id> --resolution "<text>" [--json]

orca orchestration gate-list [--task <task_id>] [--status <status>] [--json]
```

| Gate status | Meaning |
| --- | --- |
| `pending` | Awaiting resolution |
| `resolved` | `gate-resolve` applied; task set back to `ready` |
| `timeout` | Timed out (DB supports; coordinator does not auto-resolve) |

Workers can also send `--type decision_gate` messages; the coordinator creates gates from structured payloads.

## Coordinator loop

```bash
orca orchestration run --spec "<text>" \
  [--from <handle>] [--poll-interval-ms <n>] [--max-concurrent <n>] \
  [--worktree <selector>] [--json]

orca orchestration run-stop [--json]
```

| Behavior | Detail |
| --- | --- |
| Concurrency | Default **4** simultaneous `dispatched` tasks (`--max-concurrent`) |
| Poll interval | Default **2000 ms** (`--poll-interval-ms` on run record) |
| Single flier | Second `run` throws if a coordinator run is already `running` |
| Return | `run` returns immediately with `runId`; loop runs in the background |
| Task creation | **Does not** decompose `--spec` into tasks; create tasks with `task-create` first |
| Stop | `run-stop` signals the in-process `Coordinator` to stop; may mark run `failed` if tasks remain incomplete |

Coordinator phases (in-memory): `decomposing` → `dispatching` → `monitoring` → `merging` → `done`. Progress is observed via `task-list`, coordinator logs, and message traffic—not a blocking RPC on `run`.

```mermaid
sequenceDiagram
  participant C as Coordinator terminal
  participant R as Runtime RPC
  participant W as Worker terminal
  C->>R: task-create (DAG)
  C->>R: run (background)
  R->>W: dispatch --inject (preamble)
  W->>R: send --type worker_done
  R->>C: check / coordinator inbox
  R->>R: promote dependent tasks to ready
```

## Reset

```bash
orca orchestration reset [--all] [--tasks] [--messages] [--json]
```

If no scope flag is passed, **`--all`** is assumed (messages, tasks, dispatches, gates, coordinator runs). `--tasks` clears orchestration state but keeps messages.

## JSON and errors

Pass `--json` on any orchestration verb for structured RPC results (except `ask`, noted above). Invalid task status values are rejected client-side with an enum list before RPC. Common runtime errors include unknown task/message ids, dispatch to busy terminal, `inject` without agent, and `Coordinator already running`.

Remote runtimes follow the same RPC names; use global `--environment` / `--pairing-code` as documented on [Selectors and JSON output](/selectors-json-output).

## Verification

```bash
orca status --json
orca terminal list --json
orca orchestration task-create --spec "Smoke task" --json
orca orchestration task-list --ready --json
orca orchestration send --to <peer_handle> --subject "ping" --json
orca orchestration check --wait --timeout-ms 5000 --json
```

Expect `runtime: true`, stable terminal handles for the session, and message/task ids prefixed with `msg_`, `task_`, `ctx_`, `gate_`, `run_`.

## Related pages

<CardGroup>
<Card title="Terminals and agents" href="/terminals-and-agents">
PTY handles, `ORCA_*` env, TUI idle detection, and when to use terminal CLI vs orchestration mail.
</Card>
<Card title="CLI scripting workflow" href="/cli-scripting-workflow">
`orca terminal` read/send/wait for shell automation alongside orchestration messaging.
</Card>
<Card title="CLI core reference" href="/cli-core-reference">
Global flags, selectors, and command groups including orchestration entry points.
</Card>
<Card title="Runtime environments" href="/runtime-environments">
Headless `orca serve` and targeting remote runtimes from the CLI.
</Card>
<Card title="Troubleshooting" href="/troubleshooting">
Runtime unreachable, orchestration timeouts, and stale terminal handles after restart.
</Card>
</CardGroup>
