| name | pi-subagents |
| description | Delegate work to builtin or custom subagents with single-agent, chain,
parallel, async, forked-context, and intercom-coordinated workflows. Use
for advisory review, implementation handoffs, and multi-step tasks where a
single agent should stay in control while other agents contribute context,
planning, or execution.
|
Pi Subagents
This skill is for the main parent orchestrator only. Do not inject or follow it inside spawned child subagents. The parent session owns delegation, orchestration, review fanout, and final fix-worker launches; child subagents should receive concrete role-specific tasks. Ordinary children should not run their own subagent workflows; the explicit exception is a delegated fanout child whose resolved builtin tools includes subagent, and that child may use subagent only for the fanout work the parent assigned.
Use this skill when the parent orchestrator needs to launch a specialized subagent, compose multiple agents into a workflow, or create/edit agents and chains on demand.
Capability ceilings
Parent extensions may register a session-scoped, out-of-band ceiling through pi-subagents/capability-ceiling. Child tools are intersected with every active registration and inherited snapshot; denyExtensions removes ambient/provider extension loading while retaining package protocol runtime. Do not add a model-visible ceiling field or rely on role selection for enforcement. Restricted schedules are rejected until their ceiling can be persisted safely.
When to Use
- Complex work orchestration: use Fable mode as the default parent-agent loop for complex work. Complex means the task has multiple moving parts, unclear acceptance, cross-cutting code, meaningful user-visible impact, expensive or irreversible validation, broad review surface, or the user asks for orchestration. Lightweight one-off delegation can stay lightweight.
- Advisory review: use fresh-context
reviewer agents for adversarial code review, or fork to oracle when inherited decisions and drift matter
- Implementation handoff: have
oracle advise, then worker implement only after an approved direction
- Recon and planning: use
scout or context-builder, then planner
- Parallel exploration: run multiple non-conflicting tasks concurrently
- Regular skill specialists: when discovery shows proactive skill subagent suggestions and the current work is broad enough, launch a small fresh-context fanout that asks one subagent per relevant regularly used skill to apply that skill's perspective to the task
- Long-running work: launch async/background runs and inspect them later. For mutation-capable work, bound the delivery slice and elapsed runtime, then request checkpoints after active tool work returns. Reserve hard turn and tool-call caps for explicitly read-only children.
- Subagent control: watch needs-attention signals and soft-interrupt only when a delegated run is genuinely blocked
- Agent authoring: create, update, or override agents and chains for a project
Tool vs Slash Commands
Agents can use the subagent(...) tool directly for execution, management, status, and control.
Humans often use the slash-command layer instead:
/run — launch a single agent
/chain — launch a chain of steps
/parallel — launch top-level parallel tasks
/run-chain — launch a saved .chain.md or .chain.json workflow
/subagents — interactive admin for inspecting agents and editing model, thinking, or system prompt
/subagents-stop [run-id] — stop a current-session top-level async run; opens a selector when no id is given
/subagent-cost — show parent plus child token usage and cost for the session
/subagents-fleet — open the live, inspection-only foreground/async fleet; Ctrl+Alt+F opens it during an active foreground turn, ↑↓/jk selects children, and PgUp/PgDn scrolls transcript detail
/subagents-watchdog — inspect or configure the opt-in adversarial change watchdog (model, on/off, recommend-model, check)
/subagents-doctor — diagnose setup, discovery, async paths, and intercom bridge state
/subagents-models [agent] — show the live runtime-loaded builtin model mapping
/subagents-profiles, /subagents-load-profile, /subagents-refresh-provider-models, /subagents-generate-profiles, /subagents-check-profile — manage model profiles and provider catalogs
/prompt-workflow and /chain-prompts — run prompt templates through native subagent single/chain workflows
Prefer the tool when you are writing agent logic. Prefer the slash commands when
you are guiding a human through an interactive flow.
Packaged prompt shortcuts are also available for repeatable workflows. Treat them as reusable orchestration recipes, not just human slash commands. When the user asks for one of these shapes, or when the workflow clearly fits, apply the same pattern directly with subagent(...) and other tools:
/parallel-review — fresh-context reviewers with distinct review angles, then synthesis
/review-loop — parent-orchestrated worker, fresh-reviewer, and fix-worker cycles until clean or capped
/parallel-research — combine researcher and scout for external evidence plus local code context
/parallel-context-build — parallel context-builder passes that produce planning handoff context and meta-prompts
/parallel-handoff-plan — external-reference research plus local context-builder passes, followed by a synthesis handoff plan and implementation-ready meta-prompt
/gather-context-and-clarify — scout/research first, then ask the user clarifying questions with interview
/parallel-cleanup — two fresh-context reviewers (deslop + verbosity passes) for an adversarial cleanup review of the current diff
Applying Prompt Techniques Without Slash Commands
The prompt templates in prompts/ encode workflows the parent agent can run on demand. If the user provides a URL, issue, PR, plan, local file, screenshot, or freeform target, treat that target as the primary scope: read or fetch it before launching children, then include it explicitly in every child task. Do not depend on the parent conversation history when the recipe calls for fresh context.
Parallel review technique
Use this when the user wants adversarial review of a diff, plan, issue, file, or implemented work. Launch fresh-context reviewer agents with distinct angles generated from the actual target. Common angles are correctness/regressions, tests/validation, and simplicity/maintainability; adapt for TypeScript, UI, security, docs, or large structural changes. Reviewers should inspect files and diffs directly, return concise evidence-backed findings with file/line references, and avoid edits unless the user explicitly asks for a writer pass. The parent synthesizes fixes worth doing now, optional improvements, and feedback to ignore/defer before applying anything.
Proactive skill-specialist technique
Use this when { action: "list" } reports proactive skill subagent suggestions and the user's task would benefit from perspectives the parent regularly uses. These suggestions are conservative: a skill is recommended only when it is available and referenced repeatedly by configured agents or saved chains. Treat the list as an opt-in hint for the current task, not a command to always fan out.
Default guardrails:
- Keep the fanout small: usually one or two skill-specialist children, never more than the listed recommendations or configured cap.
- Prefer
context: "fresh" and include only the files, diff, plan, URL, or request details each child needs. Use forked context only when private/session history is essential and appropriate to share.
- Use read-only agents for analysis/review unless implementation was explicitly requested; do not create several writers in the same worktree.
- Skip proactive skill subagents for tiny questions, direct commands, highly private requests, or when the user asks not to delegate.
- Make cost and concurrency visible by using an ordinary
subagent(...) call rather than hidden/background automation.
Example shape:
subagent({
tasks: [
{ agent: "reviewer", task: "Apply the available 'deslop' skill to review the current diff for concrete cleanup findings only. Do not modify files.", skill: "deslop" },
{ agent: "reviewer", task: "Apply the available 'accessibility' skill to review the UI changes for concrete issues only. Do not modify files.", skill: "accessibility" }
],
context: "fresh",
concurrency: 2
})
Review-loop technique
Use this when the user wants implementation or current diff review to continue until reviewers stop finding fixes worth doing now. Keep the loop in the parent session: one async worker implements or fixes, fresh-context reviewer agents inspect the actual repo and diff, the parent synthesizes accepted fixes, and one async forked worker applies them. The parent can express the sequence up front as an async/background chain when the workflow is known, or continue with explicit follow-up subagent runs after each async completion. For an initial chain, pass async: true so the main chat is unblocked; do not set clarify: true unless the user explicitly wants the foreground clarify UI. Treat an async implementation worker handoff as an intermediate state, not final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Stop when reviewers find no blockers or fixes worth doing now, remaining feedback is optional or deferred, an unapproved product/scope/architecture decision appears, or the max review-round cap is reached. Default to 3 review rounds unless the user sets a different cap. Do not loop for optional polish, and do not let children launch subagents or decide the loop outcome.
As a conservative orchestration policy, do not pass turnBudget or a hard toolBudget to an implementation worker, fix worker, reviewer with edit authority, or other mutation-capable child. The default tool budget blocks read/search tools rather than mutation tools, but count limits still do not measure delivery safety. Use a narrow task plus an outer elapsed deadline with enough margin, then request a checkpoint after the current tool returns. The checkpoint should report changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be used as the checkpoint trigger.
Parallel research technique
Use this when the question needs both external evidence and local implications. Combine researcher for official docs, specs, ecosystem behavior, recent changes, benchmarks, and primary sources with scout for repository files, patterns, constraints, tests, and likely integration points. Give each child a distinct angle: external evidence, local code context, and practical tradeoffs. Ask for source links or file ranges, confidence level, gaps, and decision implications. Do not ask these children to edit unless implementation was explicitly requested.
Parallel context-build technique
Use this before planning or implementation when a stronger handoff is needed. Run a chain with one parallel step of context-builder agents rather than top-level parallel tasks, so relative output files live under the temporary chain directory. Give every task a distinct output path such as context-build/request-and-scope.md, context-build/codebase-and-patterns.md, and context-build/validation-and-risks.md. Choose two or three builders: request/scope, codebase/patterns, and validation/risks. Each builder must read every relevant file needed to understand its slice, follow imports/callers/tests/docs/config, conduct tool-available web research when needed, and include a compact meta-prompt section. The parent synthesizes the outputs into important context, recommended next meta-prompt, open questions, assumptions, and artifact paths.
Example shape:
subagent({
chain: [{
parallel: [
{ agent: "context-builder", task: "Build request/scope context for: ...", output: "context-build/request-and-scope.md" },
{ agent: "context-builder", task: "Build codebase/pattern context for: ...", output: "context-build/codebase-and-patterns.md" },
{ agent: "context-builder", task: "Build validation/risk context for: ...", output: "context-build/validation-and-risks.md" }
]
}],
context: "fresh"
})
Parallel handoff-plan technique
Use this when the user needs a solution brief or implementation-ready handoff from an external reference plus local code context, such as “study this library behavior, inspect our codebase, then produce a worker prompt.” Run a chain with a first parallel group and a second synthesis context-builder step. The first group usually includes researcher for external projects/docs/prompt guidance and context-builder for local code context; add a second context-builder for implementation strategy only when the scope is large enough to benefit. Use distinct output paths under handoff/, then have the synthesis context-builder read those outputs and write handoff/final-handoff-plan.md with the recommended approach, likely files, constraints, non-goals, validation, risks, unresolved questions, and final compact implementation-ready meta-prompt.
Example shape:
subagent({
chain: [
{ parallel: [
{ agent: "researcher", task: "Research the external reference and transferable implementation ideas for: ...", output: "handoff/external-reference.md" },
{ agent: "context-builder", task: "Build local codebase context for: ...", output: "handoff/local-context.md" },
{ agent: "context-builder", task: "Compare evidence and propose implementation strategy for: ...", output: "handoff/implementation-strategy.md" }
] },
{ agent: "context-builder", task: "Read {previous} and synthesize the final handoff plan and implementation-ready meta-prompt.", output: "handoff/final-handoff-plan.md" }
],
context: "fresh"
})
Gather-context-and-clarify technique
Use this at the start of non-trivial work. Launch scout for local context and researcher only when external docs, recent sources, ecosystem context, or primary evidence would materially improve understanding. Ask children for concise findings plus remaining clarification questions. Then synthesize what is known and use interview to ask the unresolved questions needed for shared understanding before planning or implementing.
Parallel cleanup technique
Use this after implementation when the user wants cleanup review or when a final pass would reduce AI-slop. Launch two fresh-context reviewer tasks with output: false and progress: false: one deslop pass and one verbosity pass. If the deslop or verbosity-cleaner skills are available, pass the relevant skill to that reviewer; otherwise inline the criteria. Both reviewers are review-only and should flag concrete issues with severity, file/line references, and smallest safe fixes. Phrase the constraint as “Do not modify project/source files; returning findings through the configured output artifact is allowed” when you use output or outputMode: "file-only". The parent decides what to apply and asks before making changes unless cleanup was already authorized.
Staged fix orchestration technique
Use this when a broad diff has known reviewer findings across several items and the user wants the parent to “orchestrate subagents like a boss.” Keep the active worktree safe with a three-stage chain:
- A parallel read-only planning fanout, one planner/reviewer per issue cluster. Each child inspects the real diff and returns exact files, line refs, proposed fixes, and focused validation. They must not edit.
- One writer worker. It receives the planner summaries through
{previous}, the parent’s accepted scope, stop rules, and verification contract. It is the only child allowed to edit the active worktree.
- A parallel read-only validation fanout. Validators inspect the worker diff from fresh context with distinct angles, report pass/fail, remaining blockers, and missing verification.
Prefer async: true, context: "fresh" for planners/validators, outputMode: "file-only" for large summaries, and per-stage output names that will not collide. Add phase and label to make async status readable, and use as plus {outputs.name} when a later step needs a specific earlier result instead of the whole {previous} blob. Use this pattern instead of launching several writer workers into a dirty worktree. Include non-blocking suggestions in the writer prompt only when they are small, safe, and do not expand product scope; otherwise record them as deferred.
When the first step can return a structured target list, prefer dynamic fanout instead of hand-authoring a static parallel group. Use outputSchema and as on the producer, then an expand step with from: { output, path }, an explicit maxItems, one parallel child template, and collect.as. Item templates may use {item} or a named item such as {target.path}. Do not use dynamic fanout for prose outputs, nested fanout, dynamic agent selection, reducers, when conditions, or arbitrary expressions; .chain.md does not support this syntax, so use direct JSON or a saved .chain.json.
Example shape:
subagent({
async: true,
context: "fresh",
chain: [
{ parallel: [
{ agent: "reviewer", phase: "Planning", label: "Deploy docs", as: "deployPlan", task: "Plan fixes for deploy docs/workflow. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/deploy.md", outputMode: "file-only" },
{ agent: "reviewer", phase: "Planning", label: "Scheduler contract", as: "schedulerPlan", task: "Plan fixes for scheduler contract. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/scheduler.md", outputMode: "file-only" },
{ agent: "reviewer", phase: "Planning", label: "Sandbox/security", as: "sandboxPlan", task: "Plan fixes for sandbox/security. Inspect the current diff. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "plans/sandbox.md", outputMode: "file-only" }
], concurrency: 3 },
{ agent: "worker", phase: "Implementation", label: "Apply accepted fixes", as: "workerResult", task: "Apply only the accepted fixes from these planning summaries. You are the sole writer for the active worktree. Run focused validation and report changed files, commands, failures, and remaining issues.\n\nDeploy plan:\n{outputs.deployPlan}\n\nScheduler plan:\n{outputs.schedulerPlan}\n\nSandbox plan:\n{outputs.sandboxPlan}", output: "worker/fixes.md", outputMode: "file-only", progress: true },
{ parallel: [
{ agent: "reviewer", phase: "Validation", label: "Deploy/scheduler validation", task: "Validate the post-worker diff for deploy and scheduler fixes. Start from the worker result: {outputs.workerResult}. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/deploy-scheduler.md", outputMode: "file-only" },
{ agent: "reviewer", phase: "Validation", label: "Sandbox validation", task: "Validate the post-worker diff for sandbox/security fixes. Start from the worker result: {outputs.workerResult}. Do not modify project/source files; returning findings via the configured output artifact is allowed.", output: "validation/sandbox.md", outputMode: "file-only" }
], concurrency: 2 }
]
})
Builtin Agents
Builtin agents load at the lowest priority. Project agents override user agents,
and user/project agents override builtins with the same name.
| Agent | Purpose | Model | Typical output / role |
|---|
scout | Fast codebase recon | inherits default | Writes context.md handoff material |
planner | Creates implementation plans | inherits default | Writes plan.md |
worker | Implementation and approved oracle handoffs | inherits default | Single-writer implementation with decision escalation |
reviewer | Review specialist | inherits default | Default recipes are review-only; tools include edit/write when a fix pass is explicit |
context-builder | Requirements/codebase handoff builder | inherits default | Writes structured context files |
researcher | Web research brief generator | inherits default | Writes research.md |
delegate | Lightweight generic delegate | inherits default | No fixed output; generic delegated work |
oracle | Decision-consistency advisory review | inherits default | Advisory review, intercom coordination |
advisor | Claude Code-compatible alias for oracle | inherits default | Same advisory role as oracle |
Builtin worker and delegate use strict tool allowlists and do not inherit ambient parent extension tools. To give a child an extension tool, name it in tools and load its provider via extensions, a path-like tools entry, or subagentOnlyExtensions. Custom agents without an extensions field follow subagents.defaultExtensions when set.
Builtin agents inherit the current Pi default model unless a run, user setting, project setting, or subagents.defaultModel overrides model. Set subagents.defaultModel when subagents should use a different default model than the parent session. Override builtin defaults before copying full agent files when a small tweak is enough.
Set subagents.defaultThinking to apply a shared thinking level to builtin, package, user, and project agents whose frontmatter leaves thinking unset. Project settings win over user settings; explicit frontmatter (including thinking: false), agentOverrides.<name>.thinking, and per-run overrides remain more specific. This setting affects child agents only and does not change the parent session's default thinking level.
{
"subagents": {
"defaultThinking": "medium"
}
}
For one run, use inline config:
/run reviewer[model=anthropic/claude-sonnet-4] "Review this diff"
For persistent tweaks, edit subagents.agentOverrides in user or project settings. User overrides apply everywhere. Project overrides apply only in that repo and win over user overrides. Use /subagents-models or subagent({ action: "models" }) to inspect the live mapping after settings and overrides load.
Model ids do not have to be exact. Separator variations (claude-haiku-4.5 vs claude-haiku-4-5), case (Claude-Sonnet-4), and optional trailing date stamps (claude-haiku-4-5-20251001) all resolve to the same registry model. Exact provider/id wins; a qualified provider/model never switches providers. To constrain subagents to a budget or compliance profile, set subagents.modelScope: { enforce: true, allow: ["anthropic/*", "openai/gpt-5-*"] } in user or project settings. Out-of-scope models you pass explicitly error and abort; models inherited from frontmatter, subagents.defaultModel, agent frontmatter, or the parent session only warn.
For model fleets, use the profile commands instead of hand-editing repeated overrides: /subagents-refresh-provider-models <provider>, /subagents-generate-profiles <provider>, /subagents-load-profile <name>, and /subagents-check-profile <name>. Profiles live under ~/.pi/agent/profiles/pi-subagents/ and replace only settings.subagents when loaded.
Prompting role subagents
Builtin role agents inherit the current Pi default model unless you override them. When launching them, write the task prompt as a compact contract, not a long procedural script. Define the destination and let the role choose the efficient path.
A strong subagent prompt usually includes:
- Goal: the concrete outcome the child should produce.
- Context/evidence: relevant plan paths, files, diffs, decisions, or user constraints already approved.
- Success criteria: what must be true before the child can finish.
- Hard constraints: true invariants only, such as no edits for review-only tasks, one writer thread, child must not run subagents unless it is an explicitly assigned
tools: subagent fanout child, or escalation for unapproved decisions.
- Validation: targeted checks to run, or the next-best check when validation is impossible.
- Output: the expected summary shape, artifact path, or finding format.
- Stop rules: when to ask via
intercom, when to stop after enough evidence, and when not to keep searching.
Avoid carrying over old prompt habits that over-specify every step. Use must, always, and never for real invariants; for judgment calls, give decision rules. For example, tell a reviewer to inspect the staged diff directly and report only evidence-backed findings, rather than prescribing every file or command. Tell a researcher the retrieval budget: start with broad targeted searches, fetch only the strongest sources, search again only when a required fact is missing, then stop.
For implementation handoffs, name the approved scope and success criteria more clearly than the process. Good prompts say what to change, what not to change, where the evidence lives, how to validate, and when to escalate. They should not ask the child to create another subagent plan or continue the parent conversation.
Settings locations:
- User scope:
~/.pi/agent/settings.json
- Project scope:
.pi/settings.json
Direct settings example:
{
"subagents": {
"agentOverrides": {
"reviewer": {
"model": "anthropic/claude-sonnet-4",
"thinking": "high",
"fallbackModels": ["openai/gpt-5-mini"],
"acceptanceRole": "read-only"
}
}
}
}
Useful override fields: model, fallbackModels, thinking,
systemPromptMode, inheritProjectContext, inheritSkills, defaultContext,
acceptanceRole, disabled, skills, tools, extensions, and systemPrompt.
Use acceptanceRole: false to clear an override. Create a user or project
agent with the same name only when you want a substantially different agent.
If a provider rejects model IDs with thinking suffixes, use
subagents.disableThinking: true in user or project settings to clear bundled
builtin thinking defaults globally. A higher-precedence per-agent thinking
override can opt one builtin back in. Existing custom-agent frontmatter remains authoritative.
Set subagents.defaultExtensions to give agents without an extensions field a shared child extension allowlist. Omit it to preserve ambient extension discovery, set it to [] to disable ambient extensions by default, or use agentOverrides.<name>.extensions for one agent. Explicit custom-agent frontmatter still wins.
Tool description modes live in ~/.pi/agent/extensions/subagent/config.json, not subagents settings. Set toolDescriptionMode to compact to reduce tool-description prompt cost while keeping the execution, async/subagent_wait, child-safety, one-writer, management/action, and artifact/status guardrails. Set it to custom to read subagent-tool-description.md from the project config dir or agent dir; invalid custom files fall back to full mode and the safety guidance is still appended.
Discovery and Scope Rules
Agent files can live in:
~/.pi/agent/agents/**/*.md — user scope
.pi/agents/**/*.md — canonical project scope
- legacy
.agents/**/*.md — still read for compatibility, but .pi/agents/ wins on conflicts
Chains live in:
~/.pi/agent/chains/**/*.chain.md and ~/.pi/agent/chains/**/*.chain.json — user scope
.pi/chains/**/*.chain.md and .pi/chains/**/*.chain.json — project scope
Discovery is recursive. .chain.md files do not define agents. Use .chain.md for simple saved chains and .chain.json for dynamic fanout or inline schema objects. Agents and chains can set optional frontmatter/package metadata; name: scout plus package: code-analysis registers as runtime name code-analysis.scout while serialization keeps name and package separate.
Precedence is by parsed runtime name:
- project scope
- user scope
- builtin agents
Running Subagents
Single agent
subagent({
agent: "oracle",
task: "Review my current direction and challenge assumptions."
})
Forked context
subagent({
agent: "oracle",
task: "Review my current direction and challenge assumptions.",
context: "fork"
})
context: "fork" creates a branched child session from the current persisted
parent session. It does not create a fresh minimal review context or filter
history down to only the relevant parts. Use it when you want a separate review
or execution thread that can still reference the parent session history.
Foreground results, async status, fleet, and widget surfaces label each child with
its resolved launch context as [fresh] or [fork]. Aggregate headers show
[mixed] when a run uses both modes.
Parallel execution
subagent({
tasks: [
{ agent: "scout", task: "Explore the auth module" },
{ agent: "reviewer", task: "Review the API client" }
]
})
Top-level parallel tasks can override per-task behavior:
subagent({
tasks: [
{ agent: "scout", task: "Map auth", output: "auth-context.md", progress: true },
{ agent: "researcher", task: "Research OAuth best practices", output: "oauth-research.md" },
{ agent: "reviewer", task: "Review auth tests", model: "anthropic/claude-sonnet-4" }
],
concurrency: 3
})
Repeat one parallel task N times with the same settings via count (useful for identical scouts or review angles without hand-duplicating entries):
subagent({
tasks: [
{ agent: "scout", task: "Map a distinct slice of the auth surface and return compressed context.", count: 3 }
],
concurrency: 3,
context: "fresh"
})
Avoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file. For large saved outputs, set outputMode: "file-only" together with an output path. The parent result then contains only a compact reference like Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed. instead of the full saved content. Do not use output: false for this; output: false means no file output. In chains, relative output paths are chain-artifact paths under {chain_dir}, not project CWD paths; use an absolute output path or a persistent chainDir when a saved artifact must outlive the temp chain directory. Read-only children return the complete artifact in their final response and the runtime persists it, so missing write tools are not a supervisor blocker. Mutation-capable children still receive direct-write instructions. Failed runs and save errors still return inline details for debugging.
Chain execution
subagent({
chain: [
{ agent: "scout", task: "Map the auth flow and summarize key files" },
{ agent: "planner", task: "Create an implementation plan from {previous}" },
{ agent: "worker", task: "Implement the approved plan based on {previous}" }
]
})
Chain steps can use templated variables such as {task}, {previous},
{chain_dir}, and {outputs.name}. Use as: "name" on a successful step or
parallel task to make that output available to later steps. Prefer named outputs
when a later step needs one specific result; keep {previous} for simple linear
handoffs or full fan-in summaries. Use phase and label for status readability.
Use outputSchema when later steps need reliable structured data; the child must
call structured_output with schema-valid JSON, or the step fails.
Use agentContract: { version: 1 } when a caller needs generic result projections
instead of acceptance or mutation effects rewriting execution success. V1 adds
execution, acceptance, review, and effects; omitted acceptance means no
acceptance request. Chain steps advance on execution by default under v1. Set
gateOn: "acceptance" only when a rejected explicit acceptance report should stop
the chain.
Async/background
Prefer async mode for every subagent launch. Set async: true no matter the task unless there is a specific reason to opt into a foreground/blocking run. This applies to scouts, researchers, workers, reviewers, validators, oracle checks, one-off delegates, chains, and parallel groups. Keep the write path single-threaded even when the run is async.
Async does not mean parallel writes. Do not edit the same active worktree while an async worker is changing it. Parent-side overlap should be reading, validation prep, synthesis, command planning, or review of unaffected context unless the writer is isolated in a separate worktree.
Do not end your turn immediately after launching an async child if you promised to keep working. Continue the local inspection, synthesis, or validation prep, then check the async run when its result is needed.
In an interactive chat, normally return control when ready to yield and let Pi wake the session on completion; do not call subagent_wait() merely to wait. Override that default and call it when the current request is run-to-completion — for example, the user asked you to report results back before continuing or a skill cannot return before its background work finishes. Headless sessions auto-drain exact current-session work at agent_end; call subagent_wait() when this turn must receive results before it ends. Never substitute sleep or status-polling loops.
subagent_wait() returns when the next initially active async run or registered provider item finishes or a subagent needs attention. Use subagent_wait({ all: true }) for all work active at call time, subagent_wait({ id: "..." }) for one async or remembered detached foreground run, and subagent_wait({ timeoutMs }) to cap the block. If a foreground child detaches for supervisor coordination, reply first, then wait on its id; do not resume or launch a replacement while it remains detached. Headless sessions also auto-drain exact current-session work at agent_end as a final safeguard.
subagent({
agent: "worker",
task: "Run the full test suite",
async: true
})
File-only output mode also works for async single runs, top-level parallel task items, sequential chain steps, and chain parallel task items. In chains, {previous} receives the compact saved-file reference when the prior step used file-only mode. Relative chain output paths are resolved under {chain_dir}; pass a persistent chainDir or an absolute output path when a later human or process needs a stable path outside the temp chain run.
For review fanout where the parent continues a local audit:
const run = subagent({
agent: "reviewer",
task: "Review the current diff for correctness issues. Do not edit files.",
async: true,
context: "fresh"
})
Inspect async runs with subagent({ action: "status", id: "..." }) or subagent({ action: "status" }) for active runs. Use subagent({ action: "status", view: "fleet" }) when supervising several active foreground/background runs and subagent({ action: "status", id: "...", view: "transcript", index: 0 }) when you need the latest child output without digging through artifacts. If a delegated fanout child launches nested runs, the parent status view shows them as a tree and you can target a nested run directly with its nested id.
Stop a current-session top-level async run with stop (or /subagents-stop). Stopped runs finish as stopped/cancelled and are not resumable. Append one more step to the tail of a still-running async chain with append-step (chain must contain exactly one step):
subagent({ action: "stop", id: "run-id" })
subagent({
action: "append-step",
id: "run-id",
chain: [{ agent: "reviewer", task: "Re-check the worker diff after the fix pass. Do not modify files." }]
})
Use steer for top-level live async guidance and resume after a delegated run pauses or finishes. Routed nested runs retain their existing non-destructive live follow-up path:
subagent({ action: "steer", id: "run-id", message: "Focus on the failing test." })
subagent({ action: "resume", id: "run-id", message: "Follow up on this point." })
subagent({ action: "resume", id: "run-id", index: 1, message: "Continue reviewer 2." })
subagent({ action: "resume", id: "nested-run-id", message: "Continue this nested reviewer." })
Resume behavior:
resume revives paused, completed, or failed async/foreground children from persisted session files; stopped runs remain non-resumable, and it does not interrupt live top-level async children.
- Use
steer for acknowledged guidance to a live top-level async child.
- A live nested run can still receive a non-destructive
resume follow-up through its owner route.
- If an async child has completed,
resume revives it by starting a new async child from the persisted child session file.
- Multi-child async runs require
index unless only one running child is selectable.
- Completed foreground single, parallel, and chain runs can also be revived by
index while their run metadata remains in extension state.
- Nested runs can be resumed by nested id when a live route or persisted nested session metadata is available.
- Revive starts a new child process from the old session context; it does not restart the same OS process.
- Direct revival holds an exclusive cross-process lease on the canonical child session file until the new child finishes. Concurrent attempts fail before Pi starts and identify the owning revived run; stale ownership is reclaimed only when the recorded process is demonstrably gone or reused.
- If the chosen child has no persisted
.jsonl session file, resume fails and reports that directly.
Use diagnostics when setup or child startup looks wrong:
subagent({ action: "doctor" })
Scheduled subagent runs
Scheduled runs defer a subagent launch until a future time. They are opt-in and require { "scheduledRuns": { "enabled": true } } in ~/.pi/agent/extensions/subagent/config.json. Only schedule explicit delayed runs the user asked for; do not schedule runs speculatively.
subagent({ action: "schedule", agent: "reviewer", task: "Review the diff for correctness issues.", schedule: "+30m", scheduleName: "evening review" })
subagent({ action: "schedule", tasks: [{ agent: "scout", task: "Map the auth module" }, { agent: "scout", task: "Map the billing module" }], schedule: "+1h" })
subagent({ action: "schedule-list" })
subagent({ action: "schedule-status", id: "ab12" })
subagent({ action: "schedule-cancel", id: "ab12" })
schedule accepts the same execution fields as a normal async run (agent/tasks/chain, cwd, model, output, reads, progress, acceptance, timeoutMs / maxRuntimeMs) plus schedule (a relative delay like +10m/+2h/+1d or a future ISO timestamp with a timezone such as 2030-01-01T09:00:00Z) and an optional scheduleName. Scheduled runs always launch async with fresh context; context: "fork", async: false, and clarify: true are rejected. Once the timer fires, the run becomes a normal tracked async run: it appears in the async widget, is inspectable with subagent({ action: "status" }), can be awaited with subagent_wait(), and delivers the normal completion notification.
Schedules are persisted per session and restored after a Pi restart. A job whose scheduled time passed by more than scheduledRuns.maxLatenessMs (default 5 minutes) while Pi was unavailable is marked missed instead of firing late. scheduledRuns.maxPending (default 20) caps pending or running scheduled jobs per session.
Humans can use /subagents-doctor for the same read-only report. It checks runtime paths, discovery counts, async support, current session context, and intercom bridge state.
Subagent control
Subagent control is the runtime visibility and intervention layer for delegated runs. It is separate from lifecycle status. Lifecycle status says whether a child is queued, running, paused, complete, stopped, or failed. Activity reporting is factual: it tracks the last observed activity time and the current tool when known. It does not pretend to know that a child is truly stuck. Manual top-level async cancellation uses stop / /subagents-stop; a live async chain can gain one more tail step via append-step.
Default behavior is intentionally conservative. When no activity has been observed past the configured threshold, the run emits a needs_attention control event. Foreground runs can push this as a subagent:control-event event, and async runs persist it to events.jsonl so the parent tracker can surface it without constant manual polling. Notification-worthy control events are also inserted into the visible transcript so both the user and the parent agent can see them, with a proactive hint plus concrete nudge, status, and interrupt options. Visible notifications fire once per child run and attention state.
Use soft interrupt when a child is clearly blocked or drifting and the parent needs to regain control:
subagent({ action: "interrupt" })
Pass id when targeting a specific controllable run, including a nested run shown in the parent status tree:
subagent({ action: "interrupt", id: "abc123" })
subagent({ action: "interrupt", id: "nested-run-id" })
A soft interrupt cancels the current child turn and leaves the run paused. It does not mean the delegated task succeeded or failed. Bare interrupt does not target hidden nested descendants; use the explicit nested id. After an interrupt, decide the next explicit action: resume with clearer instructions, replace the task, ask the user, or stop the workflow.
Per-run control thresholds can be overridden when a task legitimately runs without observable output for longer than usual:
subagent({
agent: "worker",
task: "Run the slow migration test suite",
control: {
needsAttentionAfterMs: 300000,
notifyOn: ["needs_attention"]
}
})
If the run already has an active intercom bridge target, needs-attention notifications can also prepare a compact intercom ping for the orchestrator. When a child route is available, the ping tells the orchestrator which agent needs attention and includes the exact intercom({ action: "send", to: "..." }) target for a nudge. Do not invent a target or ask the child to self-report when no bridge exists.
Steering is acknowledged delivery, not a send attempt or model-compliance signal:
subagent({ action: "steer", id: "abc123", message: "Focus on the failing test." })
The action waits up to three seconds for the child Pi session to accept the correlated user input and returns a request id with delivered, scheduled, pending, partial, recovered, or failed plus per-child states. Indexed pending children return scheduled immediately. Only a top-level single-child run may automatically interrupt after a missed acknowledgment and recover after confirmed pause within a further 15 seconds. Recovery preserves the original child contract and only its remaining deadline, turn, and tool budgets. If the session is missing, a budget is exhausted, the pause cannot be confirmed, or replacement launch fails, the source remains paused when pausing succeeded and the action returns the exact failure. Chain, parallel, and nested runs never auto-interrupt; inspect their per-child outcomes and handle failures explicitly. A late acknowledgment is recorded and cannot cancel committed recovery.
Watchdog
The subagent watchdog is an opt-in adversarial change reviewer. It is not the
reviewer subagent and is not configured by subagents.defaultModel or
agentOverrides.reviewer.
When enabled, it reviews actual repo edits at safe agent_end boundaries only if
the final worktree state changed during that turn. Unchanged or reverted diffs and
generated .pi-subagents/ / temp artifacts do not trigger review. Writing children
can review their own worktree; the parent can still review the aggregate diff after
child changes land. Enabled watchdogs also run changed-file TypeScript/JavaScript
LSP diagnostics before the model pass when typescript-language-server is available.
Prefer a strong complementary model (for example Opus 4.8 high paired against a
GPT 5.5 main session, or the reverse). Recommendation and configuration:
/subagents-watchdog recommend-model
/subagents-watchdog session model recommended
/subagents-watchdog on
/subagents-watchdog status
/subagents-watchdog check
subagent({ action: "watchdog.status" })
subagent({ action: "watchdog.recommend-model" })
subagent({ action: "watchdog.configure", model: "recommended", scope: "session" })
subagent({ action: "watchdog.check" })
session scope is temporary. Persistent user/project scopes write settings only
when the user asked. Use ordinary fresh-context reviewer fanout for planned review
waves; enable the watchdog when you want an automatic second pass on real edits.
Clarify TUI
Single and parallel runs support a clarification TUI when you want to preview or
edit parameters before launch:
subagent({
agent: "worker",
task: "Implement feature X",
clarify: true
})
Tool calls launch directly by default. Set clarify: true on single, parallel, or chain runs when you want the clarify UI. Clarify edits affect only the next run; use management actions, settings, or markdown files for persistent changes.
For programmatic background launches, use async: true. clarify: true keeps the run foreground for the clarify UI.
Worktree Isolation
When multiple agents might write concurrently, use worktrees instead of letting
them share one filesystem view.
subagent({
tasks: [
{ agent: "worker", task: "Implement feature A" },
{ agent: "worker", task: "Implement feature B" }
],
worktree: true
})
worktree: true gives each parallel task its own git worktree branched from
HEAD. This requires a clean git state and is mainly for intentionally parallel
write workflows. On completion, use the versioned aggregate handoff at
parallelHandoff.path from foreground details or async status/results instead of scraping the combined
text. Its versioned manifest records child status and output references, full
patch paths and stats, and whether each temporary worktree and branch was
removed. If you want one writer thread and several advisory agents, prefer a
single-writer pattern instead.
The Oracle Workflow
The intended oracle loop is:
- the main agent forks to
oracle
oracle reviews direction, drift, assumptions, and risks
oracle can coordinate back through contact_supervisor when the bridge injects it
- the main agent decides what direction to approve
- only then should
worker implement
subagent({
agent: "oracle",
task: "Review my current direction, challenge assumptions, and propose the best next move."
})
subagent({
agent: "worker",
task: "Implement the approved approach: ..."
})
oracle is not a fresh-context reviewer in the Cognition article sense. It is
a forked advisory thread that inherits the parent session history and uses that
history as a baseline contract.
Use oracle as a smart-friend escalation when the parent needs help with trajectory rather than diff inspection: architectural boundaries, model capability routing, merge conflicts, reviewer disagreement, context drift after long work, a worker about to invent a pattern, or fixes that require product/scope tradeoffs. Ask broad questions when the right concern is unclear, and let oracle point out missing context or files the parent should inspect before asking again. Keep oracle advisory unless it has been explicitly assigned the single writer role.
Subagent + Intercom Coordination
pi-subagents includes native supervisor coordination. Child agents can use contact_supervisor to ask the exact parent session that spawned them; messages are scoped by parent session id and should not appear in other Pi sessions.
Most agents should not call generic intercom directly unless bridge instructions provide a target and contact_supervisor is unavailable. Do not invent a target. Prefer the tool from the injected bridge instructions.
Use contact_supervisor with reason: "need_decision" when:
- a subagent is blocked on a decision
- a child needs clarification instead of guessing
- an approval, product, API, or scope choice is required before continuing safely
Use contact_supervisor with reason: "interview_request" when the child needs structured supervisor input rather than a freeform answer. The request waits for a parent reply, so the child should stay alive and continue only after the reply arrives.
Do not use contact_supervisor just to resolve review-only/no-project-edit versus progress-writing or output-artifact instructions. The child must not modify project/source files, but returning findings through its normal response or configured output artifact is allowed unless the parent explicitly set output: false.
Use contact_supervisor with reason: "progress_update" when:
- a child is explicitly asked for progress
- a meaningful discovery changes the plan
- a long-running child needs to report a blocked/progress checkpoint without waiting for normal tool return flow
Message conventions:
reason: "need_decision" and reason: "interview_request" wait for the parent reply and return it to the child.
reason: "progress_update" is non-blocking and should stay concise.
- Child-side routine completion handoffs are not expected. Native supervisor messages are for decisions, structured input, and meaningful progress updates while a child is still running.
If bridge instructions provide the child-facing tool, a child can ask:
contact_supervisor({
reason: "need_decision",
message: "Should I optimize for readability or performance here?"
})
The parent replies with the native supervisor tool:
subagent_supervisor({ action: "reply", message: "Optimize for readability." })
Or inspects unresolved asks first:
subagent_supervisor({ action: "pending" })
If no external pi-intercom tool owns the intercom name, native supervisor coordination may also expose intercom as a compatibility fallback. Prefer subagent_supervisor for parent replies because it never overrides installed pi-intercom.
If intercom messages do not show up, run subagent({ action: "doctor" }) or /subagents-doctor.
Management Mode
The subagent(...) tool also supports management actions.
List available agents and chains
subagent({ action: "list" })
Create an agent
subagent({
action: "create",
config: {
name: "my-agent",
package: "code-analysis",
description: "Project-specific implementation helper",
systemPrompt: "Your system prompt here.",
systemPromptMode: "replace",
model: "openai-codex/gpt-5.4",
tools: "read,grep,find,ls,bash"
}
})
Update an agent
subagent({
action: "update",
agent: "code-analysis.my-agent",
config: {
thinking: "high"
}
})
Delete an agent
subagent({ action: "delete", agent: "code-analysis.my-agent" })
Eject, disable, enable, and reset
subagent({ action: "eject", agent: "reviewer" })
subagent({ action: "eject", agent: "reviewer", agentScope: "project" })
subagent({ action: "disable", agent: "reviewer" })
subagent({ action: "enable", agent: "reviewer", agentScope: "project" })
subagent({ action: "reset", agent: "reviewer" })
eject copies a builtin or package agent verbatim into the user (default) or project agent dir so it can be customized without hunting package files; the copy shadows the original by runtime name. disable writes a reversible agentOverrides.<name>.disabled: true entry to the user or project settings file. enable removes that disabled field while keeping any other override fields. reset removes the scope's custom file and settings override to restore the bundled default, and refuses if no bundled default exists (use delete for purely custom agents). All four take optional agentScope: "user" | "project"; project overrides win over user ones, so target the project scope to undo a project-scope disable.
Use management actions when the system needs to create or edit subagents on
demand without dropping into raw file editing.
Management actions create or update user/project agent files. config.name is the local frontmatter name; optional config.package registers and looks up the runtime name as {package}.{name}. Use the dotted runtime name for get, update, delete, slash commands, and chain steps. For small builtin changes such as a model swap, prefer subagents.agentOverrides in settings.
Creating and Editing Agents by File
A minimal agent file looks like this:
---
name: my-agent
package: code-analysis
description: What this agent does
model: openai-codex/gpt-5.4
thinking: high
tools: read, grep, find, ls, bash
systemPromptMode: replace
inheritProjectContext: true
inheritSkills: false
skills: safe-bash, review-checklist
skillPath: ./skills, ../shared-skills
---
Your system prompt here.
That is only a starting point. Omit package for the traditional unqualified runtime name. Common optional fields include:
defaultProgress
defaultReads
output
fallbackModels
subagentOnlyExtensions
skills
skillPath
memory
maxSubagentDepth
acceptance
acceptanceRole
async — single-agent default for background launch (true/false); explicit tool-call async wins
timeoutMs — single-agent default run-level max runtime in ms (tool alias maxRuntimeMs also accepted on calls)
turnBudget — single-agent default { maxTurns, graceTurns? } JSON object
acceptance is a single-agent launch default. Use a scalar level such as checked or an inline/block YAML map such as { level: "none", reason: "lightweight lookup" }. An explicit tool-call value wins; chain and parallel acceptance remains configured on the task or step. Management create/update accepts the same policy object, and acceptance: "" clears the frontmatter default (false remains the deprecated disabled-policy shorthand).
acceptanceRole is read-only or writer and controls automatic acceptance inference only. Explicit task mutation or no-edit intent wins; otherwise the role replaces agent-name guessing. Omission preserves the current name heuristics. The field does not grant or revoke tools. Management accepts false or an empty string to clear it.
tools is a strict child allowlist, not an extension loader. For a named extension tool, keep its registered name in tools and load its provider through normal Pi discovery, extensions, a path-like tools entry, or subagentOnlyExtensions. For example, pair tools: read, fixture_search with subagentOnlyExtensions: ./tools/fixture-search.ts when the provider should exist only in that agent's child sessions. The child now fails with the unavailable names and provider-loading guidance instead of silently continuing when a requested tool is absent; internal structured_output is allowed automatically when an output schema requires it.
skillPath adds invocation-private skill files or discovery directories relative to the agent file; it does not select them, so list the desired names under skills. Local matches win, unresolved or unreadable matches use normal discovery, and local candidates never enter the parent/global catalog. Use memory: { scope: "project" | "user", path: "<name>" } for opt-in role-specific durable memory under the dedicated agent-memory/ namespace; it is separate from parent/session project memory.
For many customizations, builtin overrides in settings are lower-friction than
copying a full builtin file.
Prompt Template Integration
The package includes prompt shortcuts for common workflows: /parallel-review,
/review-loop, /parallel-research, /parallel-context-build,
/parallel-handoff-plan, /gather-context-and-clarify, and
/parallel-cleanup. Use them when the user wants repeatable review,
review/fix loops, research, context handoff, implementation handoff,
clarification, or cleanup-review patterns. /parallel-review autofix and
/parallel-cleanup autofix synthesize reviewer feedback and then apply only the
fixes worth doing now. Parent agents can also apply the same recipes directly
with subagent(...) when the user describes the workflow in natural language
instead of invoking a slash command.
Additional user prompt templates can delegate into pi-subagents through the native /prompt-workflow and /chain-prompts commands. This is useful when a slash command should always run through a particular agent or with forked context. Prompt frontmatter can set subagent, model, skill, cwd, worktree, fresh, fork, or inheritContext for the native adapter.
Extension RPC
Other Pi extensions can call pi-subagents through the in-process event bus. The stable v1 channels are subagents:rpc:v1:ready, subagents:rpc:v1:request, and per-request replies at subagents:rpc:v1:reply:<requestId>. Envelopes use { version: 1, requestId, method, params }, and replies use { version: 1, requestId, success, data | error }. ping advertises the exact process-local async completion event as events.asyncComplete for RPC-spawn consumers.
Methods: ping, status, spawn, steer, interrupt, and stop. spawn is async-only and rejects management actions, async: false, or clarify: true; it reuses the normal executor, so discovery, validation, session attribution, configured spawn caps, child-safety depth, artifacts, and async status are shared with the subagent tool. status, acknowledged async steer, and interrupt map to the normal control actions. RPC steer disables pause-and-revive recovery and advertises capabilities.nonRecoveringSteer, preserving the caller's authority over the exact spawned child. stop targets running async runs through the existing timeout control channel. pi.events is process-local, so separate Pi processes and child subagents need lifecycle artifact files or pi-intercom instead.
Important Constraints
- Forking requires a persisted parent session. If the current session does not
have a persisted session file, forked runs fail. Packaged
planner, worker,
oracle, and advisor default to forked context, so use context: "fresh" explicitly
when that is not available or not wanted.
- Forked runs inherit parent history. They are branched threads, not fresh
filtered contexts. Use fresh context for adversarial reviewers unless the user explicitly asks for forked context.
- Default subagent nesting depth is 2. Deeper recursive delegation is blocked
unless configured otherwise.
- Attention signals are not lifecycle state.
needs_attention means no activity has been observed past the configured threshold. paused means the child turn was intentionally interrupted or is awaiting direction; it is not the same as failed.
- Intercom asks are blocking. A session can only maintain one pending outbound
ask wait state at a time.
- Keep conversational authority clear. Advisory subagents should not silently
become second decision-makers.
Runtime config can change orchestration behavior. asyncByDefault and forceTopLevelAsync affect whether launches detach; waitTool can make direct subagent_wait() calls return immediately while headless auto-drain remains active, and its effective value is propagated to child runtimes; globalConcurrencyLimit bounds concurrent fanout, while a positive maxSubagentSpawnsPerSession optionally caps cumulative launches (0 or unset is unlimited). Status and doctor report the budget; static work preflights declared capacity; only the settled root interactive parent can use grant-spawn-budget after native confirmation, with total grants bounded by the original cap. Compaction does not reset usage or grants; singleRunOutputBaseDir and worktreeBaseDir route outputs and worktrees; completionBatch groups async notifications. artifactDir is project (default), session, or temp and chooses where subagent artifacts are stored. Set asyncWidget: false to hide the above-editor background-run widget when a companion footer or dashboard owns that space (fleet inspector remains available). Per-run artifacts: false disables artifact capture for that launch. Async status and result artifacts are versioned with fields such as lifecycleArtifactVersion, workflowGraph, steps, results, totalTokens, totalCost, turnCount, toolCount, and nested children. Child protocol failures expose a structured protocolError; protocol_output_limit means a child emitted a JSONL line above the 4 MiB live-parser cap. Prefer these artifacts and status views over scraping terminal output.
Best Practices
Prefer async orchestration
Launch every subagent asynchronously by default. Use async: true for scouts, researchers, workers, reviewers, validators, oracle checks, one-off delegates, chains, and parallel groups unless you intentionally need a foreground/blocking run. The parent should keep moving: inspect code while scouts run, prepare validation while a worker implements, do a local diff pass while reviewers review, and synthesize or verify while a fix worker applies accepted feedback. Async is the default orchestration posture; foreground runs are the explicit opt-out.
Use subagent_wait() to block until async runs finish
In an interactive chat, do not call subagent_wait() merely to wait after launching background work; return control to the user and Pi will wake the session on completion. Override that default when the current request is run-to-completion — for example, the user asked you to stay with the task and report results back this turn or a skill must finish in one turn. In a headless run, Pi auto-drains exact current-session work at agent_end; call subagent_wait() when this turn must receive results before it ends. In either case, subagent_wait() blocks the current turn until the next run completes or needs attention, keeps the turn alive for normal notification delivery, then returns.
subagent_wait() — return when the next initially active async run or registered provider item finishes, or a subagent needs attention.
subagent_wait({ all: true }) — block until every async run and provider item active at call time finishes, or a subagent needs attention.
subagent_wait({ id: "..." }) — block on one async or remembered detached foreground run (id or prefix). Provider items are not selected through this parameter.
subagent_wait({ timeoutMs }) — cap the block; active work keeps running if it elapses.
Providers are discovered through the versioned pi-subagents/background-work registry and must return stable item IDs with exact owning session IDs. Child agents receive no provider automatically: keep subagent_wait in the child tools allowlist and load provider extensions through extensions or subagentOnlyExtensions.
For non-interactive fleet orchestration, subagent_wait() can keep N workers in flight: launch N, wait for the next completion, react to the result, launch a replacement if needed, then wait again. Use subagent_wait({ all: true }) only when you intentionally want to drain the fleet to zero. If the turn ends first, headless agent_end auto-drain still waits for exact current-session work. In an interactive session, return to the user instead of holding the turn open just to await completion.
If config or PI_SUBAGENT_WAIT_TOOL_ENABLED disables blocking behavior, direct subagent_wait calls return immediately. Headless agent_end auto-drain remains active as a lifecycle safeguard and surfaces provider, reconciliation, or timeout failures.
Keep writes single-threaded by default
A strong pattern is one main decision-maker plus advisory/research/review/validation subagents around it. Use oracle for advice and worker for the actual write path. Parallelize reading, review, validation, and synthesis support, not normal writes, unless you deliberately isolate writers with worktrees. A child that writes should report what changed, what was left undone, commands run with exit codes, validation evidence, surprises, and any decisions that need parent approval.
Use fork for branched advisory or execution threads
Forked runs are useful when the child should reason in a separate thread while
still inheriting the parent’s accumulated context. They are especially useful for
oracle, which audits inherited decisions and drift. For adversarial code review,
prefer fresh-context reviewers that inspect the repo and diff directly unless the
user explicitly requests forked context.
Prefer narrow tasks
Give subagents specific tasks rather than vague mandates.
Review auth.ts for null-check gaps works better than Review everything.
Escalate decisions upward
If a subagent encounters an unapproved product, architecture, or scope choice,
it should use contact_supervisor and wait for the reply instead of deciding alone. Generic intercom is a fallback only when the bridge-provided supervisor tool is unavailable.
Intervene only on clear control signals
Use subagent control proactively when a delegated run emits needs_attention, or when a human asks you to regain control. Do not interrupt just because a child has briefly produced no output. Silence can be normal during long tool calls, test runs, or model reasoning.
Name sessions meaningfully
Use /name so intercom targeting stays stable.
Common Workflows
Recon → Plan → Implement
subagent({
chain: [
{ agent: "scout", task: "Map the auth flow and summarize relevant files" },
{ agent: "planner", task: "Plan the migration from {previous}" },
{ agent: "worker", task: "Implement the approved plan from {previous}" }
]
})
Fable mode for complex work
Fable mode is the default orchestration posture for complex work. It is not a separate runtime mode; it is how the parent session uses subagent, interview, subagent_wait, acceptance contracts, artifacts, and fresh-context review when the work has real complexity. Use it for complex features, broad refactors, migrations, ambiguous goals, multi-system changes, expensive validation, user-visible behavior changes, or any request to plan/orchestrate end to end. Do not force it onto tiny one-shot delegation.
Run the work through seven gated phases:
- Understand — use
scout or context-builder fanout for breadth, but the parent personally reads the load-bearing files and lets direct source reading decide disagreements. Gate: the parent can quote the exact code or behavior being changed and knows the repo's verification harness.
- Decide — separate user-owned decisions from implementation judgments. Use
interview for product, naming, cost, taste, or risk decisions; decide routine engineering details in the parent and state them. Gate: every user-owned decision needed for design is answered.
- Design — use
planner, context-builder, or read-only design/review children for parallel perspectives. Before parallel workstreams, write seam contracts: ownership boundaries, composition points, assumptions, and validation handoffs. Gate: one parent-synthesized plan and written seams for parallel work.
- Implement — capture a baseline first, then launch one async
worker as the sole writer for the active worktree unless isolated worktrees were intentionally requested. Break large work into serial milestones instead of concurrent writes. Gate: build/typecheck is green and every output or diff delta is characterized as intended or fixed.
- Verify — climb the spend ladder: static checks, free end-to-end/dry-run, cheapest live probe, targeted changed-path live test, then full realistic run when warranted. Observe the artifact itself, not only exit codes or scores, and confirm the changed code actually executed. Gate: the highest necessary rung has directly observed evidence matching intent.
- Iterate — when a gate or reviewer finds a defect, the parent names the failure class, searches for siblings, synthesizes fixes, and sends exactly one fix worker for accepted changes. For LLM judges, gates, or detectors, trigger on concrete findings rather than scores, record pass/violations/error verdicts, cache nondeterministic verdicts by input hash, budget enough output tokens, and sanitize judge text before reusing it downstream. Gate: the class is fixed or explicitly bounded, and recurrence detection exists when feasible.
- Ship — run adversarial fresh-context review/validation outside the implementation path, disposition every finding, rerun affected gates, then have the parent inspect the final diff. Commit, push, release, or open PRs only inside user-approved boundaries. Gate: findings are dispositioned, gates re-pass, and the final summary names evidence, artifacts, residual risks, and output paths.
Clarify → Plan → Implement → Review (self-orchestrated workflow)
For straightforward non-trivial work, this sequence is the lightweight version of the parent-owned loop. When the task is complex, use Fable mode above. In either case, factor in the packaged prompt workflows without literally invoking slash commands. Use the same patterns through tools and subagents.
Keep builtin agent defaults unless the user explicitly asks for a different model, thinking level, skills, output behavior, context mode, or other override. Do not add overrides just because you are orchestrating; the defaults encode the intended role behavior. In particular, packaged planner, worker, oracle, and advisor default to forked context.
When the user approves launching a subagent to carry out a plan or workflow, treat that as approval to generate a proper role-specific meta prompt for that subagent. Include the approved plan path or summary, clarified requirements, non-goals, relevant context, role boundaries, files or areas to inspect, acceptance criteria, expected output, and validation expectations. Do not pass vague instructions like “implement the plan fully” or “review this” by themselves.
/gather-context-and-clarify maps to: launch scout and, when needed, researcher; synthesize findings; then use interview to ask every clarification question needed for shared understanding.
/parallel-review maps to: launch fresh-context reviewer agents with distinct review angles; synthesize the feedback before applying anything.
/review-loop maps to: keep the parent in charge of worker → fresh reviewers → synthesized fix worker cycles until no fixes worth doing now remain, an unapproved decision appears, or the review-round cap is reached.
/parallel-research maps to: combine local scout context with external researcher evidence when current docs, ecosystem behavior, or API details matter.
/parallel-context-build maps to: run a chain-mode parallel group of context-builder agents with distinct temp output paths, then synthesize their context and meta-prompt sections.
/parallel-handoff-plan maps to: run external researcher plus local/strategy context-builder passes, then a synthesis context-builder that writes an implementation handoff plan and implementation-ready meta-prompt.
/parallel-cleanup maps to: use review-only cleanup passes after implementation, especially for simplicity, verbosity, and redundant tests.
For feature work, use this sequence as scaffolding for parent-agent behavior:
clarify → validation contract → planner → async worker → parallel async fresh-context reviewers/validators → async fix worker → follow-up review when warranted → parent review
The validation contract defines acceptance before code is written: expected behavior, acceptance checks, commands or user flows to exercise, and evidence the worker should return. Keep it lightweight for small tasks, but make it explicit enough that reviewers and validators are checking the intended outcome rather than the worker’s own assumptions.
Use the structured acceptance field when the run should carry an explicit acceptance contract. If omitted, subagents infer an effective policy from role, mode, and risk. Evidence levels end at verified: use level: "checked" for ordinary writer evidence and level: "verified" when the runtime should run explicit validation commands. Independent review is orthogonal; use review: { required: true, agent: "reviewer" } and orchestrate the reviewer separately. review-required means evidence passed but review is pending, while reviewed means a real independent result found no blockers. For reviewer/read-only calls, omit acceptance. Never explicitly request level: "reviewed"; that value remains recognized only so preflight can return an actionable correction. To disable gates, use { level: "none", reason: "..." }; the bare string "none" is rejected, and false is accepted only as a deprecated shorthand. Child-reported command success is evidence, not runtime verification.
The first worker implements the approved plan. The parent continues with independent inspection or validation prep while it runs, not parallel edits to the same worktree. When the async worker completes, treat its handoff as the transition into review, not as final completion, unless the user explicitly asked for worker-only work, review-only output, or to stop after implementation. Parallel reviewers inspect the resulting diff from fresh context. Validators check behavior with the best available evidence: commands, tests, browser/CLI interaction, screenshots, logs, or manual reproduction notes. The final worker applies synthesized review fixes in forked context, then the parent looks over the final diff before completing. The parent may launch these steps as an initial async chain when the workflow is already clear, or as follow-up subagent runs after each async completion. Initial chains should pass async: true so the main chat is unblocked; avoid clarify: true unless the user asked for foreground clarification. Do not stop after parallel review unless the user explicitly asked for review-only output or the review surfaced a decision that needs approval first.
For complex work, risky changes, broad refactors, or many changed lines, increase review and validation fanout rather than trusting one reviewer. Use distinct angles such as correctness/regressions, tests/validation, simplicity/maintainability, security/privacy, performance, docs/API contracts, and user-flow behavior. When reviewers find non-trivial issues or the fix worker touches many lines, run another focused review round before final validation.
When review has already produced concrete findings across several independent areas, use staged fix orchestration: parallel read-only planners for each issue cluster, one sole writer worker for the active worktree, then parallel fresh-context validators. This is the safest way to handle a dirty worktree with many prior changes because it parallelizes judgment without parallelizing writes. Non-blocking suggestions may go into the writer prompt only if they are small, safe, and inside the approved scope; otherwise defer them explicitly.
For very large work, split into serial milestones instead of launching a swarm of writers. Each milestone gets one writer, a validation contract, fresh-context review/validation, a fix pass, and parent acceptance before the next milestone starts. Use parallel subagents inside a milestone for read-only context, research, review, and validation only.
Keep orchestration authority in the parent session. Child subagents should not launch more subagents, read this skill, or run their own orchestration loops unless the parent intentionally selected a fanout agent whose builtin tools includes subagent. Spawned subagents do not receive the pi-subagents skill, parent-only status/control/slash messages, or prior parent subagent tool-call/tool-result artifacts. Ordinary children also do not receive the subagent extension tool. Child context filtering strips old hidden orchestration-instruction messages when they appear in inherited history. Every child receives a boundary instruction: ordinary children are told the parent owns orchestration and they must not propose or run subagents; explicit fanout children are told to use subagent only for the assigned fanout work, with maxSubagentDepth still enforced. Implementation children must call real edit/write tools instead of printing pseudo tool calls. Pass children concrete role-specific work instead.
- Clarify first. This is mandatory. Gather code context with
scout or context-builder, add researcher only when external evidence matters, then ask the user clarifying questions with interview until scope, acceptance criteria, constraints, and non-goals are clear.
- Define the validation contract. State acceptance before implementation: expected behavior, checks to run, user flows to exercise, and evidence required in the worker handoff. For UI, CLI, integration, or workflow changes, include at least one validator angle that uses the product the way a user would rather than only reading code.
- Plan when useful. For complex work, call
planner or write a plan doc yourself and get approval before implementation. For simple work, confirm shared understanding and explicitly note why planning is skipped.
- Implement with one writer. After approval, launch
worker asynchronously with a proper meta prompt that includes clarified requirements, relevant context, plan path or summary, the validation contract, and output expectations. Packaged worker defaults to forked context; pass context: "fresh" only when you intentionally want a fresh child. While it runs, prepare validation or inspect adjacent code instead of editing the same worktree.
- Require a useful worker handoff. Ask the worker to report changed files, what was implemented, what was left undone, commands run with exit codes, validation evidence, surprises or new risks, decisions made inside approved scope, and decisions needing parent approval.
- Review after implementation. After the worker completes, launch parallel async fresh-context
reviewer agents for correctness/regressions, tests/validation, and simplicity/maintainability. Add security, performance, docs/API, domain-specific, or user-flow validators for complex work, risky changes, broad refactors, or many changed lines. Use output: false unless review artifacts are explicitly needed.