English · 简体中文
Multi-agent orchestration, as code. Works anywhere coding agents run — Orca is
the first supported host. A coordinator writes a plan in
plain JavaScript, runs it with orcast run, and gets a JSON result back. Under the hood
the plan spawns worker agent terminals in the active worktree, delegates tasks
to them, validates their structured replies, and collects everything into one
return value.
orcast is driven by a coordinator agent — itself an LLM. When it faces a task that needs several agents, it does not run a fixed, pre-built pipeline. It writes the orchestration as code, on the spot, in plain JavaScript, then runs it. The workers it spawns are themselves LLM agents. So there are two levels of LLM — one that authors the plan, and many that execute the delegated work — and the plan is a program tailored to the task, not a static config.
a task that needs several agents
│
▼
┌─────────────────────────────────────────────────┐
│ COORDINATOR ── an LLM agent │
│ │
│ reads SKILL.md, then WRITES a plan in JS — │
│ the orchestration itself is LLM-authored code: │
│ │
│ export default async function plan({ agent, │
│ parallel, pipeline }) { ... } │
└────────────────────────┬────────────────────────┘
│ orcast run review
▼
┌─────────────────────────────────────────────────┐
│ PLAN PROCESS ── runs the JavaScript │
│ agent() · parallel() · pipeline() │
└────┬───────────────────┬───────────────────┬─────┘
│ spawn │ spawn │ spawn
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ WORKER │ │ WORKER │ │ WORKER │ ← each is an
│ (LLM) │ │ (LLM) │ │ (LLM) │ LLM agent
│ do task │ │ do task │ │ do task │ (codex/pi/omp/
│ report │ │ report │ │ report │ claude/kimi)
└────┬────┘ └────┬────┘ └────┬────┘
│ worker_done (JSON, schema-checked) │
└───────────────────┼───────────────────┬────┘
▼
plan collects + validates + returns
│
▼
JSON result → stdout
What each side outputs: the coordinator LLM outputs the plan (the orchestration program); each worker LLM outputs a structured JSON result. orcast is the glue that runs the plan, spawns the workers, and routes results back.
SKILL.mdis what triggers this — it teaches the coordinator agent to author and run a plan instead of doing the work sequentially itself. It is loaded into the model's context when the skill is used (keep it lean). This README,install.mjs, andtests/are for humans/tooling and never enter that context.
1. Install (Node-only, cross-platform — installs into Claude Code, Cline, codex, Kimi Code, pi):
node skills/orcast/install.mjs
2. Create a project Plan (or pass --global for ~/.orcast/plans):
orcast plan init review
Edit .orcast/plans/review.plan.mjs:
export const manifest = { apiVersion: 1 }
export default async function plan({ agent, parallel, input }) {
const findings = await parallel(
['auth', 'db', 'api'].map((area) => () =>
agent(
`GOAL: review the ${area} layer for boundary bugs.
CONTEXT: repo is the current worktree; read-only.
CONSTRAINTS: do not edit files.
DONE-CRITERIA: return JSON { area, findings: [] }`,
{ agentType: 'codex', schema: { required: ['area', 'findings'] } },
),
),
)
return { task: input.task, findings: findings.filter(Boolean) }
}3. Run it and read the JSON it prints:
orcast run review "review current changes"
That's the whole loop: write a Plan → orcast run it → the Plan's return value is
printed to stdout as JSON. That JSON is your result.
Plans may be project-local, global, or stored in named custom sources:
orcast plan source add team /srv/team/plans --global
orcast plan init team:security-review
orcast plan list
orcast run team:security-reviewUnqualified names resolve project first, then global. Every invocation gets a
unique run ID; use orcast runs --active and control persistent Actor Plans by
that ID.
A Plan is just JavaScript — loops, conditionals, whatever. orcast run injects
the primitives, input, project context, run identity, and workflow helpers;
aggregate however you like and return one value.
agent(brief, opts)= one worker. The brief must be self-contained: a fresh worker has none of your context, so always spell out GOAL / CONTEXT / CONSTRAINTS / DONE-CRITERIA. The report-back instruction is appended for you.schema: { required: [...] }validates the worker's JSON reply. A reply that omits a key is bounced back to the worker with the reason so it can fix and resend — you never get a malformed result.agentType—codex|pi|omp|claude|kimi(defaultcodex).effortandtimeoutMsare optional per call.- Aggregate and return one value — that is what gets printed. Multiple workers
→ collect with
parallel/pipelineand return the array. - Pass artifacts, not bulk prompts. Every worker's complete result is retained
under
<project>/.orcast/artifacts/<run-id>/nodes/<node-id>/result.json. Useartifacts.input(name, result)in downstream briefs instead of stringifying a previous worker result. - Waiting is your job, not the skill's. Run a short plan in the foreground and read its output; run a long one in the background with your own harness and read the output when it finishes. While a plan runs, don't interact with the worker terminals — their prompts and reports are owned by the plan.
| Primitive | Meaning |
|---|---|
agent(brief, { schema?, agentType?, effort?, timeoutMs? }) |
one worker; resolves to its validated JSON payload |
parallel(thunks) |
barrier — awaits all; a failed child becomes null |
pipeline(items, ...stages) |
each item flows through the stages independently (no barrier between stages) |
phase(title) / log(msg) |
progress bookkeeping + a status broadcast |
budget |
count-based .workers() / .rounds() (token budget is out of scope) |
workflow(subPlan, args) |
run a sub-plan inline (one level of nesting) |
artifacts |
format prompt-safe references to durable worker results |
Full API: references/api.md.
Ready-made patterns in references/plan-recipes.md:
- Fan-out review —
parallel(dims.map(d => () => agent(...))). - Adversarial verify — pipeline each finding into N refuters; keep it only if the majority fail to refute.
- Judge panel —
parallelproposers → score → synthesize the winner. - Loop-until-dry — a real
whileloop that spawns finder rounds, dedups against a seen-set, stops after K empty rounds, bounded bybudget.
- Spawn —
agent()launches the worker with a bare command (codex, notENV=x codex) so Orca recognizes the agent and applies its own launch preset. Concurrency is capped per plan bybudget.maxWorkers(default 3). Every Run has its own runtime, so concurrent plans keep independent limits and failure domains. - Route — how the worker learns where to report, chosen by probing the
orcaCLI once: env (ORCAST_REPORT_TO/ORCAST_NODEviaterminal create --env, preferred) or, as a fallback,--to <coordinator> --node <n>pre-filled into the report command. - Deliver the brief — wait for Orca's public
tui-idlecondition and a stable terminal surface; a fresh terminal that times out may be closed and recreated before any input is sent. After composing and sending Enter separately, OrCast must observe the agent leave idle (or receive a real report) before recordingbrief_dispatched. API acceptance without a started turn recordsbrief_unconfirmedand fails without resending a possibly submitted prompt. - Report — the worker writes its complete JSON to its project-local run/node
artifact directory.
orcast report --result-file <file>sends only a path, byte count, and checksum through the broker socket. - Collect — the broker verifies the owned path and checksum, reads and validates
the JSON against the node's
schema, and resolvesagent(). Route/Actor prompts receive only small summaries and artifact references. The plan'sreturnis printed as JSON, then the process exits.
Durability & safety: every Run owns an append-only journal (journal.jsonl)
that records each event. Managed Runs receive reports through their private socket and
do not create or consume a coordinator terminal. A single-instance lock guarantees
one broker per Run runtime. A worker whose terminal is gone fails its node
(→ null in parallel) so the plan never hangs. Immutable,
content-addressed releases let active Runs finish on their original code while newly
installed code serves new Runs.
There is no default time limit — pass timeoutMs on an agent() to opt in.
| Module | Role |
|---|---|
plan-registry.mjs |
project/global/custom Plan source discovery, init, and resolution |
plan-runner.mjs |
portable Plan loader and injected API/runtime context |
flow.mjs |
coordinator entry: run(plan) — lock, journal, engine+daemon, print JSON, exit |
engine.mjs |
scheduler + router + worker lifecycle (spawn, deliver, schema feedback, liveness) |
daemon.mjs |
worker liveness loop + optional legacy coordinator-inbox adapter |
primitives.mjs |
the six primitives over the engine |
orca.mjs |
thin, injectable wrapper over the orca CLI (spawn, send, terminal I/O, --env probe) |
report.mjs |
worker-side helper: resolve routing (env or flags) and send worker_done |
journal.mjs |
append-only event log — single source of truth + message de-dup |
lock.mjs |
atomic single-instance lock (mkdir-based, steals stale holders by pid) |
paths.mjs |
shared on-disk locations, keyed off ORCA_WORKTREE_ID |
self.mjs |
resolve the coordinator's own terminal handle from ORCA_TERMINAL_HANDLE |
Node-only, cross-platform (macOS / Linux / Windows — no shell required):
node skills/orcast/install.mjs # install into every detected runtime (claude, cline, codex, kimi, pi)
node skills/orcast/install.mjs --claude # only Claude Code (~/.claude/skills)
node skills/orcast/install.mjs --cline # only Cline (~/.cline/skills)
node skills/orcast/install.mjs --codex # only codex (~/.agents/skills)
node skills/orcast/install.mjs --kimi # only Kimi Code ($KIMI_CODE_HOME/skills or ~/.kimi-code/skills)
node skills/orcast/install.mjs --pi # only pi (~/.pi/agent/skills)
node skills/orcast/install.mjs --to <dir> # install into <dir>/orcast
It copies SKILL.md, lib/, and references/ into <skills>/orcast/ (not the
tests, READMEs, or installer) and removes any previous install under the old
orca-flow name. Re-run after editing the source to push the update.
node skills/orcast/tests/run-tests.mjs # unit tests plus real Codex CLI + isolated local mock-model E2E
orcast/ repo root
README.md English docs (this file)
README.zh-CN.md Chinese docs
skills/
orcast/ the skill
SKILL.md agent-facing instructions (loaded into model context)
install.mjs cross-platform installer
lib/ the implementation (see module map)
references/ api.md, plan-recipes.md (loaded on demand by the agent)
tests/ unit tests + run-tests.mjs runner
- Node — present wherever the Orca runtime runs.
- Orca's orchestration experimental feature enabled.