8.6 KiB
Generic subagents design
Date: 2026-04-12 Status: approved for planning
Summary
Simplify pi-subagents from named, specialized child agents into a single generic subagent concept.
A subagent run should be a normal Pi child session that receives:
- a delegated
task - a selected
model - an optional
cwd
It should not receive a role-specific system prompt, role-specific tool restrictions, built-in role behavior, or markdown-discovered agent definitions.
This is an intentional breaking API cleanup, not a compatibility shim.
Current state
Today the package supports:
- built-in named roles in
src/builtin-agents.ts(scout,planner,reviewer,worker) - optional markdown-discovered user/project agents in
src/agents.ts - role-derived
systemPrompt,tools, and optional defaultmodel - prompt templates in
prompts/that explicitly chain those named roles
That surface no longer matches the desired product behavior.
Goals
- Make every child run a generic Pi agent.
- Remove named/specialized agent concepts from the package API and runtime.
- Preserve the existing runner, wrapper, model-registration, and artifact mechanics where they are still valid.
- Keep parallel and chain execution modes.
- Keep explicit model selection and validation.
Non-goals
- No compatibility layer that silently accepts old role names.
- No replacement specialization layer.
- No change to process-vs-tmux runner selection.
- No change to package identity or env names (
PI_SUBAGENTS_*).
Chosen approach
Use a hard simplification:
- remove named agent definitions entirely
- remove markdown agent discovery entirely
- make child runs task/model/cwd only
- rewrite workflow prompts so they describe generic multi-step delegation rather than named roles
This matches the intended behavior exactly and removes misleading concepts instead of preserving dead abstractions.
Public API design
Tool modes
Single mode
Required:
taskmodel
Optional:
cwd
Parallel mode
Required:
- top-level
model tasks: Array<{ task: string; model?: string; cwd?: string }>
The top-level model remains the default for tasks that do not specify model.
Chain mode
Required:
- top-level
model chain: Array<{ task: string; model?: string; cwd?: string }>
{previous} substitution remains supported.
Removed fields
Remove from the tool schema:
agenttasks[].agentchain[].agentagentScopeconfirmProjectAgents
Model fields
Keep:
- required top-level
model - optional per-task/per-step
model - optional per-task/per-step
cwd
Keep the current schema descriptions that explain models must come from the currently available models.
Runtime design
Tool execution
src/tool.ts should stop discovering agents entirely.
Instead, each run is built directly from the requested task item:
- resolve the effective model from
task.model ?? params.model - pass generic run metadata to the configured runner
- do not attach
systemPrompt - do not attach
tools
Parallel and chain execution semantics stay the same apart from the simplified payload shape.
Child wrapper
src/wrapper/cli.mjs remains a generic Pi launcher.
Keep:
pi --mode json --session ... --model ... <task>- effective model selection based on resolved model when present
PI_SUBAGENTS_CHILD=1on every child run- GitHub Copilot initiator behavior only for effective models under
github-copilot/* - best-effort artifact appends that must never block writing
result.json
Remove:
--append-system-prompt- any dependence on agent-role metadata
Runner behavior
Keep process runner and tmux runner behavior unchanged except for the smaller metadata payload.
No change to:
- process runner as default
- tmux as opt-in
- tmux requiring
tmuxonPATHonly when the tmux runner is selected - result monitoring and artifact paths
Metadata and artifact design
Keep stable run bookkeeping fields such as:
runIdmodetaskIndexsteptaskcwdrequestedModelresolvedModelsessionPath- artifact paths
- exit status and stop-reason fields
Remove role-derived fields from runtime payloads and outputs:
agentagentSourcesystemPromptsystemPromptPath- any role-only transcript rendering
Transcript headers should stay generic and continue to show useful run metadata, but should no longer print Agent: ....
Artifact directory structure should stay stable under .pi/subagents/runs/<runId>/ unless a removed role-specific file is no longer needed.
Extension registration behavior
Keep the current model-registration behavior exactly:
- do not register the tool when no models are available
- preserve original available-model order for schema enums
- dedupe registration using an order-insensitive lowercase-sorted copy for the cache key
- re-register when the model set changes
- do not re-register when the model set is the same in a different order
- if the first observed set is empty, a later non-empty set must still register
Keep the child-session guard in index.ts:
- provider override may still register first
- subagent tool registration must still be skipped when
PI_SUBAGENTS_CHILD=1
Prompt and documentation design
Keep the shipped workflow prompt templates, but rewrite them as generic orchestration helpers.
They must no longer reference:
scoutplannerreviewerworker
Instead, they should instruct the parent agent to run generic subagents whose tasks describe the intended step, for example:
- inspect
- plan
- implement
- review
- revise
README and package-facing docs should describe:
- generic child Pi sessions
- the unchanged runner options
- the simplified subagent concept
They should stop describing specialized built-in roles or markdown agent discovery.
File-level impact
Expected primary runtime changes:
- modify
src/schema.ts - modify
src/tool.ts - modify
src/artifacts.ts - modify
src/process-runner.ts - modify
src/wrapper/cli.mjs - modify
src/wrapper/render.mjs - modify
README.md - modify
prompts/*.md
Expected removals if implementation chooses the full cleanup path:
src/builtin-agents.tssrc/agents.ts- agent-discovery-specific tests
index.ts, src/process-runner.ts, and src/tmux-runner.ts should otherwise keep the smallest possible runner-specific changes.
Testing plan
Implementation should follow TDD:
- write or update the failing tests first
- verify the failures are for the intended reason
- implement the minimal runtime changes
- re-run targeted tests
- run full
npm test
Tests to preserve
Keep dedicated coverage for:
- every child run setting
PI_SUBAGENTS_CHILD=1 - non-copilot models not receiving the copilot initiator flag
- the effective model using the resolved model when requested/resolved differ
- best-effort artifact logging never preventing
result.jsonfrom being written - no registration on empty model lists
- later registration on a non-empty model list
- no re-registration for the same model set in different orders
- re-registration when the model set changes
Tests to rewrite
src/tool.test.ts: generic task payloads, no named agentssrc/wrapper/render.test.ts: noAgent: scoutassertionsrc/artifacts.test.tsandsrc/process-runner.test.ts: no role/system-prompt assumptionssrc/prompts.test.ts: prompts still ship but no longer rely on named roles- README/package tests: documentation still accurate after the simplification
Tests to remove if modules are removed
src/agents.test.ts
Risks and mitigations
Risk: breaking downstream callers
Mitigation:
- treat the change as explicit API breakage
- update shipped prompts/docs/tests in the same change
- avoid a fake compatibility layer that hides the break
Risk: over-editing runner code
Mitigation:
- keep changes focused on schema, tool execution, prompt handling, and artifact metadata
- preserve shared runner behavior unless role metadata is the only reason a field exists
Risk: stale role wording in tests/docs
Mitigation:
- explicitly scrub
scout,planner,reviewer, andworkerfrom prompts and user-facing tests - update transcript/header expectations to generic wording
Acceptance criteria
The design is satisfied when:
- the
subagenttool no longer requires or accepts agent names - child runs are launched as normal Pi sessions with task/model/cwd only
- no custom system prompt is injected into child runs
- no agent discovery logic remains in the runtime path
- model validation and registration behavior still passes all existing regressions
- shipped prompts/docs describe generic subagents only
- tests no longer rely on the removed role names or prompt files for behavior