oh-my-pi · multi-agent

Orchestration prompting, keywords highlighted.

Five config-free ways to run multiple agents in oh-my-pi. For each: what to say, what the agent does, and what you get back — with the load-bearing keywords marked.

aqua = what you say to trigger it teal = what comes back
01

task — declarative fan-out

config-free
Mechanism · task

Spin up parallel subagents in one batch

The primary multi-agent tool. One call, many agents, shared context.

You say

“Do this in parallel — spin up three scouts: read the auth module, the API layer, and the tests, then merge the findings.”

Agent does
task({
  agent: "explore",
  context,
  tasks: [
    { id: "Auth",  role: "explore", assignment: "read src/auth — surface + risks" },
    { id: "API",   role: "explore", assignment: "read src/api — endpoints" },
    { id: "Tests", role: "explore", assignment: "read tests — coverage gaps" },
  ]
})
You get

Three job IDs spawned in one batch, results delivered async as each scout finishes, then a single merged summary. Capped by task.maxConcurrency.

02

eval — code-level DAGs

config-free
Mechanism · eval

pipeline / parallel / agent from one cell

When you want programmatic fan-out and dependency wiring, not a declarative batch.

You say

Pipeline this — fetch five URLs, summarize each, then rank them.”

Agent does
pipeline(
  urls,
  (u)     => agent(`fetch ${u}`,                        { handle: true }),
  (node)  => agent(`summarize: ${output(node.handle)}`, { handle: true }),
  (nodes) => agent(`rank: ${nodes.map(n => n.output).join("\n")}`)
)
You get

Staged waves with a barrier between stages, each step a DAG node carrying a handle you wire into the next stage, and a final ranked list — all from one eval cell.

03

irc — agents that talk to each other

config-free
Mechanism · irc

Ad-hoc peer messaging at runtime

Peers discovered automatically (Main + each task ID). No pre-declaration.

You say

“Spawn two agents and have them negotiate the shared User type instead of guessing.”

Agent does
task([{ id: "AuthLoader" }, { id: "APILoader" }])   // both run
// inside, they talk peer-to-peer:
irc({ op: "send", to: "APILoader", message: "User = email + role?", await: true })
irc({ op: "wait",  from: "AuthLoader" })
You get

A round-trip — one sends, the other waits / replies; parent messages arrive as steering interrupts. A shared contract emerges without you brokering it.

04

job — async lifecycle

config-free
Mechanism · job

Manage work that's already running

Spawn with async; manage (watch / cancel) with job. Results auto-deliver.

You say

“Run the long test suite in the background; tell me when it's done, and cancel it if I say stop.”

Agent does
bash("bun test", { async: true })            // returns a job id
job({ op: "poll",   poll: ["suite"] })       // block only when idle
job({ op: "cancel", cancel: ["suite"] })     // kill mid-run
You get

A job ID immediately, the result auto-delivered on completion; poll to block when you can't do other work, cancel to stop it.

05

omp-swarm — declared YAML pipelines

CLI config-free · TUI needs extension
Mechanism · omp-swarm

A repeatable pipeline file

Agents communicate via the workspace filesystem; state persists under .swarm_<name>/.

You say

“Run the swarm pipeline — research, then draft, then review.”

Agent does
omp-swarm run pipeline.yaml     // CLI: config-free
# /swarm run pipeline.yaml     // TUI: needs the extension loaded
You get

The YAML's waits_for / reports_to edges topologically sorted into waves; agents swap state through the workspace filesystem; a declared, repeatable run. The CLI is config-free; the TUI /swarm needs the extension.

They compose

real orchestration
The pattern

task fans out → irc lets peers coordinate mid-flight → job collects. For explicit dependency graphs, eval parallel / pipeline / agent builds the DAG in code. omp-swarm when you want it declared and repeatable. All five are invocation-only — no .omp/, no models.yml, no settings.