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).
  • /agents or Alt+A is the control center; watch the fleet run.
  • Up to task.maxConcurrency run 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 output schema 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), a concern, or a blocker (both interrupt).
  • Own model, own context β€” catches what the doer rushed past. It advises only; it cannot approve or change state.
DialDefaultEffect
advisor.enabledoffturns the advisor on
advisor.syncBacklogoffprimary waits up to 30s when the advisor falls behind
advisor.immuneTurns3throttles repeat interruptions
  • WATCHDOG.yml defines a roster of named advisors with different lenses and models; a sibling WATCHDOG.md holds guidance only the advisors see.
  • Cost: a second bill, roughly one review stream per turn. omp stats -s reports the advisor:main request ratio β€” decide from that.

Vibe: direct long-lived workers

  • task fires and forgets; /vibe keeps workers alive and makes you the director.
  • Your session drops to read-only plus five vibe_* controls.
  • fast workers (the sonic agent on @smol) grind mechanical volume; a good worker (the task agent) reviews what they produce.
  • vibe_send steers 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 ps lists 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.