summaryrefslogtreecommitdiff
path: root/skills/pi-subagent/SKILL.md
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-10-21 12:23:28 +0100
committerIgor Soarez <igor@soarez.org>2026-10-21 12:23:28 +0100
commit32123f167dd5a7cdcbdaf6e5c144f40654d236fc (patch)
treeeb2b2585d2f7cb14b03d5a895f17a962821ade52 /skills/pi-subagent/SKILL.md
parent485aec099b56f2e24fa04600e85d7aba8d66f3fd (diff)
skills: pi-subagent, extracted from pi-review-panel, which now runs on it
The panel's mechanics -- headless pi runs that don't hang, answer extraction, billed cost, retries, verifying what comes back -- are not review-specific. pi-subagent covers one delegated task, one brief fanned out to several models, or a job split into parallel parts; pi-review-panel keeps only what a review adds. run-agent.sh replaces run-member.sh and fixes what it got wrong: - `timeout` is not on a Mac without coreutils, which failed every member with exit 127; it falls back to gtimeout, then perl's alarm (142 -> 124). - pi exits 0 when the provider refuses the request, or the answer is empty; both are now exit 1, with stopReason and error in the cost file. - a retry moves the earlier attempt to <name>.attempt<N>.* instead of overwriting its cost file. New options: --tools (an allowlist; read,grep,find,ls is read-only by construction), --cwd, --context-files, --brief, --deliver. status.sh replaces the `pgrep -f run-member.sh` loop, which counted every panel on the machine, and prints the cost table. From dot request 20261021-114826-work-laptop-2b868c.
Diffstat (limited to 'skills/pi-subagent/SKILL.md')
-rw-r--r--skills/pi-subagent/SKILL.md209
1 files changed, 209 insertions, 0 deletions
diff --git a/skills/pi-subagent/SKILL.md b/skills/pi-subagent/SKILL.md
new file mode 100644
index 0000000..c5f1bfb
--- /dev/null
+++ b/skills/pi-subagent/SKILL.md
@@ -0,0 +1,209 @@
+---
+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. 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 <search>`. 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-<part>.md`), and every run writes `$P/out/<name>.*`.
+
+**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: <x>`, `STATUS: DONE` /
+ `STATUS: BLOCKED — <why>`. 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-<name>/` 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/<repo>/<name>`. 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" <provider> "<model>" <name> > "$P/out/_<name>.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`. Names must be
+unique within a workdir; a natural scheme is `<provider-abbrev>-<model>` for a
+fan-out and `<part>` 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.
+
+**Don't sit on the wait loop.** 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/<name>.md` is non-empty and (when you asked for one)
+ends with the fixed final line. Exit 124 is the timeout firing. `<name>.err`
+and `<name>.jsonl` say what happened otherwise.
+
+Retry a failure once, under the same name: `run-agent.sh` moves the failed
+run's files to `<name>.attempt<N>.*` first, cost included. 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.
+- **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`.