Fanning one session out into parallel subagents: isolation, dispatch, advisors, vibe, hub, and orchestration from code.
Read Traps before your first fan-out.
Isolation first
omp config set task.isolation.mode auto # ships as "none"
none(default): parallel workers share one working tree and clobber each other.auto: each isolated worker gets its own workspace (CoW clone, overlayfs, or git worktree, whatever the filesystem supports) and returns patches instead of raw edits.- Requirements: a git repo, and plan mode off.
The task tool: batch-shaped fan-out
One call, one shared context, one entry per worker:
{
"context": "Monorepo, Bun + TypeScript. Target: drop the legacy utils/date.ts helper.",
"tasks": [
{ "name": "Callers", "agent": "scout", "task": "List every import of utils/date.ts with file:line." },
{ "name": "Migrate", "task": "Replace date.ts helpers with Temporal API in packages/api.", "isolated": true },
{ "name": "Migrate2", "task": "Same migration in packages/web.", "isolated": true }
]
}
The agent writes this JSON; you supply the vocabulary:
orchestrateβ standalone, lowercase in your prompt: delegate independent work to parallel subagents and verify each phase.workflowzβ ask for a deterministic multi-subagent workflow.- Results are paths, not prose:
read agent://Callers(output),read agent://Callers/findings.0.path(one field),read history://Migrate(transcript). /agentsorAlt+Ais the control center; watch the fleet run.- Up to
task.maxConcurrencyrun at once (default 32) β cap your providers first, see Settings.
Bundled agents: scout, reviewer, security-reviewer, designer, librarian, sonic, task.
Custom agent = one markdown file
.omp/agents/dep-auditor.md:
---
name: dep-auditor
description: Audits one package's dependencies for unused and outdated entries.
model: "@smol"
tools: read, grep, glob, bash
thinkingLevel: low
output:
type: object
properties:
unused: { type: array, items: { type: string } }
outdated: { type: array, items: { type: string } }
required: [unused, outdated]
---
You audit dependencies for exactly one package directory.
Read its package.json, grep the source for each dependency, and run
`bun outdated` there. Report only what you verified. Never edit files.
- The
outputschema is the point: the workerβs result is validated against it, so the parent reads a real object instead of parsing text. model: "@smol"keeps a fleet of these cheap.
Advisor: a second model on every turn
# ~/.omp/agent/config.yml
modelRoles:
advisor: anthropic/claude-sonnet-5:medium
advisor:
enabled: true
- Reads the primary agentβs transcript after each turn, inspects the workspace with its own read-only tools.
- Injects a
nit(batched quietly), aconcern, or ablocker(both interrupt). - Own model, own context β catches what the doer rushed past. It advises only; it cannot approve or change state.
| Dial | Default | Effect |
|---|---|---|
advisor.enabled | off | turns the advisor on |
advisor.syncBacklog | off | primary waits up to 30s when the advisor falls behind |
advisor.immuneTurns | 3 | throttles repeat interruptions |
WATCHDOG.ymldefines a roster of named advisors with different lenses and models; a siblingWATCHDOG.mdholds guidance only the advisors see.- Cost: a second bill, roughly one review stream per turn.
omp stats -sreports the advisor:main request ratio β decide from that.
Vibe: direct long-lived workers
taskfires and forgets;/vibekeeps workers alive and makes you the director.- Your session drops to read-only plus five
vibe_*controls. fastworkers (thesonicagent on@smol) grind mechanical volume; agoodworker (thetaskagent) reviews what they produce.vibe_sendsteers any of them mid-flight.- Exclusive with plan and goal modes; leaving vibe kills every worker β land the work first.
Hub: switchboard and process supervisor
Peer messaging between live agents plus real process supervision:
hub { "op": "start", "name": "dev", "application": "bun", "args": ["run", "dev"],
"ready": { "port": 3000, "timeout": 30 }, "restart": "on-failure" }
hub { "op": "logs", "name": "dev", "grep": "error|warn", "follow": true }
hub { "op": "send", "to": "Migrate2", "message": "api patch landed, rebase before you yield" }
- Launch with a readiness gate so nobody races the server.
- Grep logs instead of tailing; send keys or signals when a process wedges.
omp pslists supervised processes from outside the session.
Orchestration under real control flow
When fan-out must be a loop with a budget, the eval toolβs bridge calls back into the agentβs own tools from a Python or JS cell:
import json
pkg = json.loads(read("package.json"))
results = parallel([
lambda d=d: agent(f"Audit {d} for CVEs", agent="dep-auditor", label=d)
for d in pkg["dependencies"]
])
display([r for r in results if r["unused"]])
- Bridge surface:
tool.<name>(args),read/write,agent(...),parallel(...),pipeline(...),completion(...),budget.remaining(). - Recursion respects
task.maxRecursionDepth(default 2).
See also: Cheat sheet, Tips, Getting started, Guide.
Condensed from the omp guide by Hugo Lopes (MIT). Verify against your install:
omp config list.