--- name: pi-subagent description: >- Delegates work to one or more headless `pi` subagents on any provider/model, run in the background, and collects each one's final answer plus its actual billed cost. Covers a single delegated task, the same task fanned out to several models for independent answers, or a job split into separate tasks run in parallel, followed by verifying what came back; a run saved as a session can be followed up, resumed after a timeout, or forked. Use when the user asks for subagents, to hand something to another model, to get several models' takes, or to parallelize work across pi runs — and when another skill (such as pi-review-panel) builds on it. Spawning costs money: never start subagents on your own initiative without the user asking. --- # pi subagents Run `pi` headless as a subagent: a fresh process, a written brief, no memory of this conversation, one final answer. You stay the orchestrator. Subagents produce raw material; you check it before it reaches the user. The fiddly parts (hang avoidance, output extraction, cost accounting, keeping failed attempts) are solved in `run-agent.sh` next to this file. Use it. Don't hand-roll `pi -p` invocations — the flag set and the redirection shape are load-bearing, and the failure modes are silent hangs. The reasons are at the top of the script. `$SK` below is this skill's directory. ## 0. Shape the job Pick one of three shapes, and say which to the user if it isn't obvious: | shape | what | when | |---|---|---| | **delegate** | one task, one model | a self-contained job worth running elsewhere: a long investigation, a second opinion from a specific model, work you want off your own context | | **fan-out** | one brief, N models | you want independent answers to compare: reviews, designs, hard questions. Disagreement is the signal | | **split** | N briefs, one model each | a job that divides cleanly into parts that don't depend on each other's results | A subagent knows nothing you don't write down, can't ask you anything, and can't see your other subagents. If the parts of a split need each other's output, it's a sequence, not a split — run it in stages. **Models.** Use exactly the provider/model pairs the user names; don't add others. If they named none, ask — or, for a fan-out, offer the default panel in the pi-review-panel skill. Check a name resolves first: `pi --offline --list-models `. Credentials are already configured in `pi`. ## 1. Set up a workdir ```bash P="$(mktemp -d -t pi-subagent)"; mkdir -p "$P/out" ``` `$P` is scratch. One workdir per job; several briefs can live in it (`$P/brief-.md`), and every run writes `$P/out/.*`. **Snapshot the inputs.** If the subagents will read files someone else may be editing — including you — record their content hash now and re-check before you use the answers. Input that changes mid-run invalidates parts of their reasoning, and you need to know that happened. ## 2. Write the brief The brief is the whole interface. Write it as if for a capable contractor who has never seen the project and will not get to ask questions: - **The task, first sentence.** What you actually want. "Find bugs in this diff" and "propose a better design than this one" produce very different work; don't leave it to be guessed. - **Context.** One paragraph on the project (from its README) and on why this task exists. - **The material, inline** in fenced blocks, even if you also give paths — the subagent should not have to go looking for the thing it's about. - **Absolute paths** of relevant files and directories, so it can read the surroundings with its tools. - **Criteria**, as hard requirements. If the user gave criteria, quote them verbatim. - **Evidence rules.** Verify empirically before asserting, and say which command, interpreter, or version produced each claim. Distinguish what was run from what was reasoned. - **What it may touch** — see §3 — stated plainly. `pi` has edit and write tools and will use them unless told, or prevented. - **The deliverable**: format, sections, length. End with a **fixed final line** where answers will be compared — `VERDICT: SHIP` / `VERDICT: DO NOT SHIP`, `ANSWER: `, `STATUS: DONE` / `STATUS: BLOCKED — `. Fixed strings make the tally and the success check mechanical. - **No questions, no follow-ups.** Deliver the full result as the final answer; don't ask for confirmation, don't offer further work. ## 3. Decide what it may touch Subagents share this machine and its filesystem. Constrain them in this order of preference: 1. **Read-only by construction**: `--tools read,grep,find,ls`. No shell, so it can't run or change anything. Right for pure reading and reasoning. 2. **Read-only by instruction**: default tools (bash included), with the brief saying everything is read-only. Needed when the subagent must run things to verify claims — tests, interpreters, measurements. Tell it to put scratch files under its own `$P/scratch-/` and nowhere else. 3. **Writes, isolated**: give each writing subagent its own git worktree and pass it as `--cwd`; never let two writers share a tree, and never point one at the user's working copy. Worktrees go under `~/x/worktrees//`. You review and bring over the result; the subagent doesn't commit, push or post anything — say so in the brief. Context files (AGENTS.md/CLAUDE.md) are off by default, so the brief is the only instruction a subagent gets. Pass `--context-files` when it works inside a repo whose conventions it must follow. ## 4. Launch Always in the background, so you can keep working: ```bash "$SK/run-agent.sh" "$P" "" > "$P/out/_.log" 2>&1 & ``` Options go before the positionals: `--brief FILE` (default `$P/brief.md`), `--timeout SECS` (default 1800), `--thinking LEVEL` (default `high`), `--tools LIST`, `--cwd DIR`, `--context-files`, `--deliver TEXT`, and `--session` to keep the conversation for a follow-up (§10). Names must be unique within a workdir; a natural scheme is `-` for a fan-out and `` for a split. A fan-out of one brief to three models: ```bash "$SK/run-agent.sh" "$P" fireworks "accounts/fireworks/models/kimi-k3" fw-kimi-k3 > "$P/out/_fw-kimi-k3.log" 2>&1 & "$SK/run-agent.sh" "$P" openrouter "z-ai/glm-5.3" or-glm-5.3 > "$P/out/_or-glm-5.3.log" 2>&1 & "$SK/run-agent.sh" "$P" openrouter "google/gemini-3.7-flash" or-gemini > "$P/out/_or-gemini.log" 2>&1 & ``` A split, each part with its own brief: ```bash for part in parser cli docs; do "$SK/run-agent.sh" --brief "$P/brief-$part.md" "$P" openrouter "z-ai/glm-5.3" "$part" \ > "$P/out/_$part.log" 2>&1 & done ``` ## 5. Monitor — and work meanwhile Expect minutes to tens of minutes per run. Check progress with: ```bash "$SK/status.sh" "$P" # once: running names, then the table so far "$SK/status.sh" --wait 60 "$P" # block until all are done (exit 0) ``` `status.sh` exits 3 while anything is still running, and also prints free disk space — the event streams are big while runs are in flight. **Get woken instead of waiting.** In an interactive pi, the `alarm` tool can fire when processes exit. Launch, set one alarm on all the runs' PIDs, and end your turn: when the last run exits, the alarm starts a new turn, or arrives after the tool call in progress if you're busy by then. For the PIDs, print `$!` after each launch in the same bash call, or read `"$P"/out/*.running`, which holds each run's PID while it's in flight. ``` alarm action=set when_exits=[] in_minutes= note="pi-subagent runs in <$P> have ended. Run <$SK>/status.sh <$P>, handle failures (§6), verify (§7), report with the cost table (§8)." ``` - Write the note with absolute paths. By the time it fires, this context may have been compacted away. - One alarm per PID wakes you as each run ends instead. That's worth it for a long split whose parts you can check as they come; for a fan-out, one alarm for all is the point. - The alarm sees no exit status. `status.sh` has it. - The deadline is a backstop, in case a run hangs past its own timeout. - In Claude Code, which has no `alarm` but wakes you when a background Bash task exits: launch the whole job as one `run_in_background` command that starts the runs with `&` and ends with `wait`, and end your turn. - Without either (pi in print or RPC mode), monitor with `status.sh`. **Don't sit on the wait loop.** With an alarm set, there's nothing to wait for. Otherwise, launching early is only worth it if you use the time: do your own investigation of the same question, build whatever harness you'll need to check the answers, establish baselines. You need your own evidence in §7 regardless. When you do block, give the shell call a timeout and loop, rather than one unbounded wait. ## 6. Handle failures A run succeeded if `$P/out/.md` is non-empty and (when you asked for one) ends with the fixed final line. Exit 124 is the timeout firing. `.err` and `.jsonl` say what happened otherwise. Retry a failure once, under the same name: `run-agent.sh` moves the failed run's files to `.attempt.*` first, cost included. A run started with `--session` that timed out after real progress is often better continued than retried: `--followup` it (§10), and it picks up with everything it had read and run. If it fails twice, report it with its cost and carry on — one dead provider must not sink the job. For a split, a failed part is a gap you either fill yourself or report. ## 7. Verify, then use What comes back is raw material, not results: - **Reproduce every substantive claim** before passing it on. Models hallucinate line numbers, APIs, file contents and measurements, with confidence. - **Disagreement is where the answer is.** When answers conflict, run the experiment that decides it and say who was right. With sessions (§10) you can also put each side's claim to the other first — but a subagent conceding or holding firm is not evidence either; the experiment is. - **Ask for the evidence.** With a session, a vague or surprising claim can be followed up: "show the exact command and output behind X". - **Consensus is weak evidence.** Several models agreeing can all be making the same mistake, or testing the same wrong version. One claim you confirmed outranks four you didn't. - **Check what was actually tested.** Watch for a claim true of a variant but not of the thing written — a subagent "verifying" code it silently fixed first. - **Distrust your own harness too.** A test extracted to run standalone can fail for reasons of its own (a missing import, a swallowed exception) that look exactly like the bug under discussion. Check the baseline passes what it should. - **Written work**, from a worktree: read the whole diff and run the tests yourself before bringing any of it over. Never merge it unseen. Say what you dropped and why, alongside what you kept — that's what makes the kept part trustworthy. ## 8. Report cost Every report that used subagents ends with the cost table; the user should never have to ask. `status.sh` prints it: per run, from the provider's own per-message `usage.cost` — billed figures, not estimates — failed attempts as their own rows, then the total. A timed-out run bills for every token it generated and can be the most expensive line. When cost per useful result varies a lot across models, say so: it informs who to use next time. ## 9. Keep what matters `$P` won't survive the session. If the answers matter, copy the `.md` outputs, the cost files, and any verification scripts somewhere durable in the project, and link those instead of `$P`. ## 10. Follow up, resume, fork Off by default: a run saves nothing, and once it ends it can't be talked to again. Pass `--session` at launch when you expect to come back to it — a long run that may time out, a fan-out whose disagreements you'll want to put back to the subagents, anything you may need to question. It costs nothing extra until used. The session is kept as `$P/sessions/_.jsonl`. Then, once that run has finished: ```bash # Continue the same conversation. Provider and model may differ from before. "$SK/run-agent.sh" --followup "" "$P" "" # Branch it into a new name; the original session is left as it was. "$SK/run-agent.sh" --fork --followup "" "$P" "" ``` - **Uses.** Continue a run that timed out ("You were cut off. Carry on from where you stopped and deliver the full result"). Ask for the evidence behind a claim. Put another subagent's contradicting finding to it ("Another reviewer says X, because Y. Check it and say who is right, with evidence"). Fork to ask several different questions of the same context without them seeing each other, or to hand a whole investigation to a different model — it reads the full history, whoever produced it. - **The message is sent as written.** No brief, no `--deliver` wrapper, so say what to deliver and end with the same fixed final line if you'll tally it. - **What carries over.** A follow-up or fork inherits `--tools`, `--thinking`, `--cwd` and `--context-files` from the run it continues, so a read-only subagent stays read-only; pass one again to change it. - **Outputs.** The earlier round's files move to `.round.*`, so every answer is kept and every round is its own row in the cost table. Each follow-up resends the whole conversation as input: a short question to a long session is not cheap. - **Limits.** A run killed mid-step loses that step; everything before it is in the session. `run-agent.sh` refuses to follow up or fork a run still in flight. A fresh retry under the same name (no `--followup`) starts a new conversation and moves the old session aside. - **Don't hand-roll the resume.** By id, pi looks only among sessions started in the current directory, and where it finds none it silently starts a new, empty one under that id — exit 0, and an answer from a model that remembers nothing. `run-agent.sh` opens the session by its file path instead.