Skip to main content

Pi Orchestration Architecture

Design of a human-gated multi-agent coding system using Claude Code or OpenCode as orchestrator, pi workers dispatched via pueue, and the pi-diff-review extension as the review gate. All design decisions derived from a structured grill session.

System Overview


Key Design Decisions

Orchestrator choice

Claude Code or OpenCode — contextual or manual. No automated routing between them. Both dispatch pi workers identically. Orchestrator choice is about what model family runs the planning layer (Claude judgment vs GPT-5.x), not about task type.

Dispatch mechanism

pueue — background task queue. Orchestrator fires N workers simultaneously, each as an independent pi -p "..." process. pueue wait <id> blocks until completion; pueue log <id> captures stdout for debugging.

Task prompt format

Structured spec, not free text:
Scope enforcement is prompt-level only — no filesystem isolation (no worktrees). Non-overlapping scope assignments prevent parallel workers from conflicting.

File isolation

Task scoping (not git worktrees). Orchestrator assigns non-overlapping file/module scopes per worker. Worktrees add overhead not justified for ≤5 parallel tasks with clean module boundaries. See Shared Task Queue (Cross-Worktree) for when worktree pools are needed instead.

Model routing

Workers self-route via ~/.pi/agent/AGENTS.md difficulty-tier routing. Orchestrator passes the task; worker picks the model. OpenCode Go subscription ($10/mo) provides the model pool: DeepSeek V4 Pro (high), Flash (medium/low). See Pi Agent (pi-mono) for the full routing table.

Worker subagents

Scouts only (read-only, Haiku-class, depth-limited). Write-capable sub-workers not enabled — creates nested task-scope coordination problem the architecture doesn’t solve. See Pi Agent (pi-mono) for Scout/Researcher/Worker tier definitions.

Review modes — two distinct paths

Interactive pi sessions (human runs pi with TUI):
  • pi-diff-review fires per write/edit
  • Human reviews line-by-line: accept/deny/edit per changed row
  • Model self-corrects within session when lines are denied
  • After session: manual git review + commit
Headless pueue workers (pi -p "..."):
  • ctx.hasUI = false → extension auto-accepts, writes audit log only
  • Human gate happens post-completion at orchestrator level
  • Orchestrator reads git diff + status-<id>.json and presents to human
  • Human commits manually after review

Status artifact

Written on session_shutdown. Named status-<PUEUE_TASK_ID>.json (falls back to status.json). Fields:
  • resolved: all files’ last decision was "accepted"
  • unresolvedFiles: files whose last applyReview action ≠ "accepted"
  • retryCount: value of DIFF_REVIEW_RETRY_COUNT env var at time of write
  • needsHuman: !resolved && retryCount >= 2 — orchestrator stops retrying
“Last decision” = last decisions.jsonl entry per file path. Earlier denials followed by a final acceptance = resolved. See apply-decisions.ts:writeStatusArtifact.

Retry strategy

Orchestrator re-runs failed workers with added context, up to 3 total attempts (retry counts 0, 1, 2). On attempt 2 with unresolved files: needsHuman=true in status artifact → orchestrator halts, human takes over manually. Re-run prompt pattern:

Commit strategy

No auto-commit. Orchestrator presents full git diff after all workers complete. Human reviews and commits manually. Per Pi Building In World Of Slop: “critical code, read every line.”

Extension loading

pi-diff-review installed globally via pi install. Orchestrator verifies extension presence at startup (fail-fast gate) before firing any workers. Silent absence of the review gate is worse than a loud startup failure.

Artifact Layout


Orchestrator Dispatch Snippet