# Research Findings: Robust Pi subagent workflow for Nimrod

## Phase Contract

Allowed reads:
- `tickets/artifacts/2026-06-03-robust-pi-subagents/01-questions.md`
- Pi extension/SDK docs and relevant examples
- Existing Nimrod QRSPI docs

Do not read:
- design or plan artifacts for this ticket

Will write:
- `tickets/artifacts/2026-06-03-robust-pi-subagents/02-research.md`

## Q1: How does Pi's example `subagent` extension create isolated agent contexts, configure tools/models/prompts, stream results, and return compressed output?

### Findings

- The example explicitly describes itself as spawning a separate `pi` process per subagent invocation, giving an isolated context window: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:1-12`.
- It supports three invocation modes: single agent, parallel task array, and sequential chain with `{previous}` handoff: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:7-10` and `:442-451`.
- It caps parallel tasks at 8, concurrency at 4, collapsed display items at 10, and per-task parent-visible output at 50 KB: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:27-30`.
- Agent prompts are written to temporary `0600` markdown files and passed via `--append-system-prompt`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:233-240` and `:316-322`.
- Child agents are launched as `pi --mode json -p --no-session`, with optional `--model` and `--tools` derived from agent frontmatter: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:288-290`.
- Child processes are spawned with inherited/selected cwd and stdout/stderr pipes: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:327-333`.
- The parent parses JSON lines from child stdout and captures `message_end` and `tool_result_end` events: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:336-370`.
- Usage data is accumulated from assistant messages: turns, input, output, cache read/write, cost, and context tokens: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:349-363`.
- Abort signals kill the subprocess with `SIGTERM`, then `SIGKILL` after 5 seconds if needed: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:393-402`.
- Chain mode runs steps sequentially and replaces `{previous}` with prior output: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:524-570`.
- Parallel mode initializes placeholder results, streams progress, limits concurrency, and returns a markdown summary for each task: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:577-657`.
- Single mode runs one agent and returns the final assistant text or an error summary: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:660-684`.

## Q2: What extension APIs are needed for a Nimrod-specific subagent workflow?

### Findings

- Extensions can register custom tools, intercept events, prompt users, add commands, persist state, and customize rendering: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:5-16`.
- Project-local extension locations are `.pi/extensions/*.ts` and `.pi/extensions/*/index.ts`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:112-119`.
- Extensions can register tools with `pi.registerTool()`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:76-90`.
- Extensions can register commands with `pi.registerCommand()`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:92-99`.
- Extensions can execute shell commands via `pi.exec(command, args, options)`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:1477-1484`.
- Extensions can manage active tools with `pi.getActiveTools()`, `pi.getAllTools()`, and `pi.setActiveTools(names)`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:1486-1506`.
- The example subagent extension uses custom rendering through `renderCall` and `renderResult`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:694-760`.
- The example uses a custom tool named `subagent` registered with a TypeBox parameter schema: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:454-464`.

## Q3: What security/safety boundaries does Pi's subagent example use for user-level vs project-local agents, and what should Nimrod require?

### Findings

- The example README states that the tool executes a separate `pi` subprocess with delegated system prompt and tool/model configuration: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/README.md` under “Security Model”.
- Agent definitions can live in user-level `~/.pi/agent/agents/*.md` or project-level `.pi/agents/*.md`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents.ts:85-99` and `:97-115`.
- Default scope is user-level agents only. Project agents are loaded only when `agentScope` is `project` or `both`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:437-451` and `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents.ts:101-115`.
- Project-local agents override user agents with the same name when scope is `both`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents.ts:106-109`.
- The tool prompts for confirmation before running project-local agents in interactive UI when `confirmProjectAgents` is true: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:499-521`.
- Extension docs warn that extensions run with full system permissions and should only be installed from trusted sources: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:108-110`.
- Tool restrictions are agent-frontmatter driven. Agent definitions can specify `tools`, and the runner passes them via `--tools`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents.ts:58-68` and `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:288-290`.

## Q4: How should QRSPI artifacts integrate with subagents so each subagent reads narrow inputs and writes bounded markdown outputs?

### Findings

- Nimrod QRSPI already defines artifact files `00-context.md` through `06-review.md`: `docs/qrspi-adaptation.md` under “Artifact Layout”.
- Nimrod QRSPI states each phase writes an artifact and later phases read only the listed artifacts: `docs/qrspi-adaptation.md` under “Core Context-Management Rule”.
- Nimrod QRSPI already defines standard sub-agent/role passes: Locator, Researcher, Analyzer, Pattern Finder, Designer, Structurer, Planner, Implementer, Reviewer: `docs/qrspi-adaptation.md` under “Standard Sub-Agent / Role Passes”.
- The Pi subagent example returns final assistant text to the parent, while preserving full per-agent results in tool details: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:641-657` and `:681-684`.
- The example does not directly write subagent output to project artifact files; it returns output to the parent model/tool result. Artifact writing would need to be performed by parent agent or added as Nimrod-specific wrapper behavior.
- The example supports chained handoff through `{previous}` but does not define QRSPI phase contracts itself: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:524-570`.

## Q5: Should the MVP copy/adapt Pi's example extension directly, wrap it, or build a simpler project-local extension from scratch?

### Findings

- The example already provides the hard parts: subprocess spawning, JSON mode parsing, usage collection, abort handling, single/parallel/chain execution, project/user agent discovery, and TUI rendering: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:261-423`, `:454-684`, and `:694-760`.
- The example is a standalone extension directory with `index.ts` and `agents.ts`; Pi supports project-local extension directories with `index.ts`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md:112-119`.
- Agent discovery is generic and already searches nearest `.pi/agents`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents.ts:85-99`.
- A direct copy into `.pi/extensions/subagent/` plus project-local `.pi/agents/*.md` would likely be the shortest path to an MVP.
- A Nimrod-specific wrapper or fork would be needed for artifact-aware commands such as “run researcher and write/update `02-research.md`”. The generic example currently has no artifact-path parameter or file-writing behavior.

## Q6: Which agent roles are needed first for Nimrod?

### Findings

- Nimrod QRSPI lists Locator, Researcher, Analyzer, Pattern Finder, Designer, Structurer, Planner, Implementer, Reviewer roles: `docs/qrspi-adaptation.md` under “Standard Sub-Agent / Role Passes”.
- Pi's sample agents are Scout, Planner, Reviewer, Worker: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/README.md` under “Sample Agents”.
- Sample `scout` is optimized for codebase recon and compressed handoff: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents/scout.md`.
- Sample `planner` is read-only and creates implementation plans: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents/planner.md`.
- Sample `reviewer` is read-only except for read-only bash commands by instruction: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents/reviewer.md`.
- Sample `worker` is general-purpose with full capabilities: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/agents/worker.md`.
- For a safe MVP, roles that can use read-only tools map cleanly to the subagent model: locator/scout, researcher, analyzer, pattern-finder, planner, reviewer.

## Q7: What verification steps can prove the subagent system actually reduces main-context load and remains safe?

### Findings

- The example reports per-agent usage stats, including turns, input/output tokens, cost, and context tokens: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:39-63` and `:349-363`.
- The example caps parallel output returned to the parent at 50 KB per task, preserving full output in details: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:187-195` and `:641-657`.
- The example has explicit failure handling for child exit code, model stop reason `error`, and `aborted`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:176-184` and `:560-567`.
- Project-local agent confirmation can verify safety prompts appear before repo-controlled agents run: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:499-521`.
- Tool restriction can be verified by creating agents with read-only `tools` frontmatter and confirming subprocess invocation includes `--tools`: `/usr/local/lib/node_modules/@earendil-works/pi-coding-agent/examples/extensions/subagent/index.ts:288-290`.

## Cross-Cutting Observations

- The Pi example is not just conceptual; it already implements true isolated child contexts through separate `pi` processes.
- The generic example is close to a Nimrod MVP, but it is not artifact-aware.
- The most important missing Nimrod-specific layer is QRSPI command/workflow glue: choose the phase, construct the narrow subagent prompt, pass the relevant artifact path, and write/merge the output into the correct markdown artifact.
- Read-only agents can be safely introduced before any write-capable worker agent.
- The project-local agent prompt mechanism is powerful but requires trust controls because repo-controlled prompts can instruct the model to use available tools.

## Open Areas

- The exact installed Pi CLI invocation may need testing after copying the extension locally.
- The docs/examples do not show an artifact-writing subagent wrapper; that part would be new Nimrod-specific code.
- The best UX for phase commands is undecided: one generic `subagent` tool, separate `/qrspi-*` commands, or both.
- The model names in sample agents (`claude-haiku-4-5`, `claude-sonnet-4-5`) may need adjustment to whatever models are configured in this environment.
