@ferris1225/pi-subagents 0.28.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +270 -597
- package/agents/explore.md +1 -0
- package/agents/reviewer.md +1 -0
- package/agents/worker.md +1 -1
- package/package.json +1 -1
- package/src/completion.ts +28 -0
- package/src/config.ts +25 -0
- package/src/dispatch.ts +845 -0
- package/src/format.ts +149 -0
- package/src/index.ts +90 -1386
- package/src/models.ts +13 -0
- package/src/monitor.ts +27 -0
- package/src/prompt.ts +10 -0
- package/src/runtime.ts +145 -0
- package/src/setup.ts +50 -0
- package/src/spawn.ts +189 -68
- package/src/tools.ts +409 -0
- package/src/ui.ts +8 -3
- package/src/widget.ts +182 -0
package/README.md
CHANGED
|
@@ -1,597 +1,270 @@
|
|
|
1
|
-
# pi-subagents
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
4
|
-
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
5
|
-
[](./LICENSE)
|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- **
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- **
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- **
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- **
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
##
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
### 3. Proposed solutions
|
|
273
|
-
Evaluate a suggested approach: correctness and tradeoffs, fit with existing codebase patterns, simpler alternatives, edge cases the proposal may miss.
|
|
274
|
-
|
|
275
|
-
### 4. Codebase health
|
|
276
|
-
Assess key files, tests, and structure: architecture drift or tech debt, inconsistent patterns, untested or undocumented areas, obvious bugs, fragile code.
|
|
277
|
-
|
|
278
|
-
### 5. Specific PR or issue
|
|
279
|
-
Understand the context first, then verify: the fix addresses the root cause, changes are minimal and focused, no regressions, tests and docs updated as needed.
|
|
280
|
-
|
|
281
|
-
## Hunt across these categories
|
|
282
|
-
- Logic bugs, off-by-one, wrong edge-case handling.
|
|
283
|
-
- Error handling gaps; swallowed failures; unreported unrun checks.
|
|
284
|
-
- Security: injection, path traversal, secrets in code/logs, trusting untrusted input.
|
|
285
|
-
- Concurrency: shared mutable state, locks held across await, races.
|
|
286
|
-
- Encoding/Unicode: assuming `char*`/files/CLI text is UTF-8; wrong `A` vs `W` Win32 APIs; boundary conversions.
|
|
287
|
-
- Resource leaks; violations of the project's stated conventions.
|
|
288
|
-
- Classify severity honestly. Distinguish blockers from nits; do not pad with style preferences.
|
|
289
|
-
|
|
290
|
-
## Collaboration
|
|
291
|
-
- Independent of `worker` by design — your verdict is the gate before commit. Fix nothing yourself; report so the caller can dispatch a worker.
|
|
292
|
-
|
|
293
|
-
## Output format
|
|
294
|
-
## Files Reviewed
|
|
295
|
-
- `path/to/file.ts`
|
|
296
|
-
## Critical (must fix)
|
|
297
|
-
- `file.ts:42` — concrete issue and why it breaks.
|
|
298
|
-
## Warnings (should fix)
|
|
299
|
-
- `file.ts:10` — issue and suggested direction.
|
|
300
|
-
## Suggestions (consider)
|
|
301
|
-
- Optional improvements.
|
|
302
|
-
## Verdict
|
|
303
|
-
One of: APPROVE / APPROVE_WITH_NITS / REQUEST_CHANGES, plus a 2-3 sentence rationale.
|
|
304
|
-
End with exactly one machine-readable line: `VERDICT: REVIEW_PASS` for APPROVE or APPROVE_WITH_NITS; `VERDICT: REVIEW_FAIL` for REQUEST_CHANGES.
|
|
305
|
-
|
|
306
|
-
## Quality standards
|
|
307
|
-
Specific file paths and line numbers. No vague feedback. A clean report means you looked hard, not that you found nothing to say.
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
</details>
|
|
311
|
-
|
|
312
|
-
## Workflow
|
|
313
|
-
|
|
314
|
-
```text
|
|
315
|
-
main agent
|
|
316
|
-
│
|
|
317
|
-
├─ subagent(explore / worker / reviewer)
|
|
318
|
-
│ └─ isolated pi child process
|
|
319
|
-
│ └─ result message
|
|
320
|
-
│
|
|
321
|
-
└─ automatic follow-up turn with the result
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
1. The main agent calls `subagent` with a self-contained brief.
|
|
325
|
-
2. The tool returns immediately, so the editor stays usable while the child works.
|
|
326
|
-
3. Up to `maxConcurrency` sub-agents run at once (default 4); a parallel call accepts at
|
|
327
|
-
most that many tasks, and anything beyond waits in the queue.
|
|
328
|
-
4. When a run finishes (successfully or not), the extension sends a result message to the
|
|
329
|
-
main session. The result is delivered as soon as the current tool call finishes — even
|
|
330
|
-
mid-turn — or starts a new turn when the agent is idle. A run that ended with failed
|
|
331
|
-
tool calls (e.g. a broken build) is reported as such, never as a plain success.
|
|
332
|
-
5. The main agent uses the result to continue. No extra user prompt is needed.
|
|
333
|
-
|
|
334
|
-
### Waiting, inspecting, and stopping runs
|
|
335
|
-
|
|
336
|
-
The extension registers three companion tools so the main agent never has to
|
|
337
|
-
`sleep`/poll for a background run:
|
|
338
|
-
|
|
339
|
-
- `subagent_wait` — looks up a run's result in-turn. It does **not block by
|
|
340
|
-
default**: a settled run returns its result immediately; a still-active run
|
|
341
|
-
returns a note telling the model to end its turn (the completion message then
|
|
342
|
-
wakes it). Pass `timeoutMs` to block inside the tool call (event-driven, wakes
|
|
343
|
-
on the run's completion) — only when the current turn must receive the result
|
|
344
|
-
right now (sequential dependent steps). Otherwise end the turn and the
|
|
345
|
-
completion message wakes you.
|
|
346
|
-
- `subagent_status` — lists active runs (id, agent, model, usage, elapsed, activity)
|
|
347
|
-
and finished results; pass an id to read a finished run's full result.
|
|
348
|
-
- `subagent_stop` — cancels an active run (or `all: true`); the child is terminated
|
|
349
|
-
and an aborted result with its partial output is delivered, so the main agent
|
|
350
|
-
always knows the run did not complete.
|
|
351
|
-
|
|
352
|
-
Switching sessions, reloading, or shutting down cancels remaining background runs. A
|
|
353
|
-
crashed or aborted agent returns whatever partial output it produced, clearly labelled,
|
|
354
|
-
so the main agent can decide whether to retry.
|
|
355
|
-
|
|
356
|
-
## Usage
|
|
357
|
-
|
|
358
|
-
The main agent is encouraged to delegate automatically, but you can also ask directly:
|
|
359
|
-
|
|
360
|
-
```text
|
|
361
|
-
Use explore to map how authentication is wired up.
|
|
362
|
-
Ask worker to implement the API change after the exploration is complete.
|
|
363
|
-
Run reviewer on the final diff before reporting completion.
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### Single task
|
|
367
|
-
|
|
368
|
-
```json
|
|
369
|
-
{
|
|
370
|
-
"agent": "worker",
|
|
371
|
-
"task": "Implement the requested change. Inspect the existing conventions, update tests, and report the files changed and checks run."
|
|
372
|
-
}
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
Optional `cwd` selects the working directory for that child.
|
|
376
|
-
|
|
377
|
-
### Parallel tasks
|
|
378
|
-
|
|
379
|
-
Use parallel mode only for independent work:
|
|
380
|
-
|
|
381
|
-
```json
|
|
382
|
-
{
|
|
383
|
-
"tasks": [
|
|
384
|
-
{ "agent": "explore", "task": "Map the API layer and its tests." },
|
|
385
|
-
{ "agent": "explore", "task": "Map the database layer and its tests." }
|
|
386
|
-
]
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
Start dependent work only after the relevant result has been delivered.
|
|
391
|
-
|
|
392
|
-
### Waiting for a result in-turn
|
|
393
|
-
|
|
394
|
-
Results arrive as messages that wake the main agent automatically, so waiting is
|
|
395
|
-
usually unnecessary: end your turn and the result resumes you. When a result must
|
|
396
|
-
be fetched in-turn, `subagent_wait` is a **non-blocking lookup by default** — a
|
|
397
|
-
settled run returns its result immediately, a still-active run returns a note
|
|
398
|
-
telling the model to end its turn:
|
|
399
|
-
|
|
400
|
-
```json
|
|
401
|
-
{
|
|
402
|
-
"id": "3"
|
|
403
|
-
}
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
Only when the turn must not end AND the result is needed right now (e.g. the user
|
|
407
|
-
asked for it) pass `timeoutMs` to block; on timeout it reports the still-running
|
|
408
|
-
runs and the model ends the turn (the completion message then wakes it) or
|
|
409
|
-
re-invokes with a longer timeout.
|
|
410
|
-
|
|
411
|
-
### Inspecting runs
|
|
412
|
-
|
|
413
|
-
`subagent_status` returns an overview of active and finished runs with their ids:
|
|
414
|
-
|
|
415
|
-
```json
|
|
416
|
-
{}
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
Pass a run id to read that run's full result:
|
|
420
|
-
|
|
421
|
-
```json
|
|
422
|
-
{
|
|
423
|
-
"id": "3"
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Stopping a run
|
|
428
|
-
|
|
429
|
-
`subagent_stop` cancels a run that is obsolete, stuck, or superseded — the child is
|
|
430
|
-
terminated and an aborted result (with partial output) is delivered:
|
|
431
|
-
|
|
432
|
-
```json
|
|
433
|
-
{
|
|
434
|
-
"id": "3"
|
|
435
|
-
}
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
Or stop everything with `{ "all": true }`.
|
|
439
|
-
|
|
440
|
-
## Configuration
|
|
441
|
-
|
|
442
|
-
Configuration is stored at `~/.pi/agent/pi-subagents.json`. The location follows
|
|
443
|
-
`PI_CODING_AGENT_DIR` when set.
|
|
444
|
-
|
|
445
|
-
The `/subagents-setup` wizard drives the main fields interactively: for each agent, picking
|
|
446
|
-
a model is immediately followed by picking that agent's thinking strength (or inheriting the
|
|
447
|
-
agent's default — its frontmatter `thinking`, else the global default). The global
|
|
448
|
-
`thinkingLevel` is set first and applies as the final fallback. `notifyOnReviewPass` and
|
|
449
|
-
`maxResultLines` are edited directly in `pi-subagents.json`.
|
|
450
|
-
|
|
451
|
-
When the config already exists, re-running `/subagents-setup` opens a menu whose
|
|
452
|
-
**Configure an agent (model + thinking)** entry lets you pick one agent and set just its
|
|
453
|
-
model and thinking strength — so changing a single agent no longer walks every enabled
|
|
454
|
-
agent. After one agent's model + strength picks, the wizard returns to the agent picker
|
|
455
|
-
so several agents can be configured in one pass; Esc at any step ends the pass and keeps
|
|
456
|
-
every agent already configured. The rest of the menu toggles injection, scope, concurrency,
|
|
457
|
-
fix rounds, and idle timeout; **Full re-setup** re-runs the whole first-time wizard.
|
|
458
|
-
|
|
459
|
-
```json
|
|
460
|
-
{
|
|
461
|
-
"enabledAgents": ["explore", "worker", "reviewer"],
|
|
462
|
-
"agentModels": {
|
|
463
|
-
"explore": "anthropic/claude-haiku-4-5"
|
|
464
|
-
},
|
|
465
|
-
"agentThinkingLevels": {
|
|
466
|
-
"explore": "low",
|
|
467
|
-
"worker": "high"
|
|
468
|
-
},
|
|
469
|
-
"thinkingLevel": "high",
|
|
470
|
-
"notifyOnReviewPass": false,
|
|
471
|
-
"maxResultLines": 80,
|
|
472
|
-
"proactiveInjection": true,
|
|
473
|
-
"agentScope": "user",
|
|
474
|
-
"maxConcurrency": 4,
|
|
475
|
-
"maxFixRounds": 2,
|
|
476
|
-
"idleTimeoutSec": 90
|
|
477
|
-
}
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
| Field | Description |
|
|
481
|
-
| --- | --- |
|
|
482
|
-
| `enabledAgents` | Agent names exposed to discovery and prompt injection. An empty array disables all agents. |
|
|
483
|
-
| `agentModels` | Optional `provider/model-id` override per agent. |
|
|
484
|
-
| `agentThinkingLevels` | Optional thinking level per agent; agents without an entry use the agent's frontmatter `thinking`, then `thinkingLevel`. |
|
|
485
|
-
| `thinkingLevel` | Default thinking level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` (default `high`). |
|
|
486
|
-
| `notifyOnReviewPass` | When `true`, a passing reviewer result is delivered without waking the main agent (default `false`). |
|
|
487
|
-
| `maxResultLines` | Max lines of a sub-agent result carried in the completion message (default `80`). Longer results are truncated; the full text is written to a temp file whose path is included in the message. |
|
|
488
|
-
| `proactiveInjection` | Whether to add the delegation directive to the main system prompt. |
|
|
489
|
-
| `agentScope` | `user`, `project`, or `both`; controls which user/project agent directories are discovered. |
|
|
490
|
-
| `maxConcurrency` | Max sub-agent processes running at once (1–16, default 4), and the max tasks one parallel `subagent` call accepts. Extra work waits in the queue. |
|
|
491
|
-
| `maxFixRounds` | Auto-fix rounds when a reviewer returns `REVIEW_FAIL`: the extension dispatches a `worker` (briefed with the review's findings) then a `reviewer` re-review, repeating up to this many times before waking the main agent with the full chain. `0` disables it (the main agent handles fixes itself). Default 2. |
|
|
492
|
-
| `idleTimeoutSec` | Idle timeout in seconds: a sub-agent whose stdout goes silent for this long is terminated and retried (same model first, then the main-window fallback, like any transient provider failure). `0` disables the idle watchdog. Default 90. A long but active run is never interrupted. |
|
|
493
|
-
|
|
494
|
-
### Configuration migration
|
|
495
|
-
|
|
496
|
-
The config file migrates itself on load — no manual steps after an upgrade:
|
|
497
|
-
|
|
498
|
-
- **Schema upgrades** — a config written by an older version (missing newer keys or
|
|
499
|
-
holding invalid values) is normalized and saved back with the new fields filled in.
|
|
500
|
-
- **Removed agents** — agents no longer shipped are stripped from `enabledAgents`,
|
|
501
|
-
`agentModels`, and `agentThinkingLevels` automatically.
|
|
502
|
-
- **Merged limits** — the pre-0.13 `maxParallelTasks` key is folded into `maxConcurrency`
|
|
503
|
-
(the larger of the two wins) and dropped on the next save.
|
|
504
|
-
- **Removed keys** — `maxSubagentDepth` (0.14) is dropped on load: sub-agent children are
|
|
505
|
-
always leaf processes. To disable delegation entirely, use `"enabledAgents": []`.
|
|
506
|
-
- **New fields** — `idleTimeoutSec` (0.16) is filled in on load with its default (90)
|
|
507
|
-
when missing from an older config.
|
|
508
|
-
|
|
509
|
-
Model selection uses this precedence:
|
|
510
|
-
|
|
511
|
-
```text
|
|
512
|
-
configured agent model → current main-session model → agent frontmatter model
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
Unavailable configured models are replaced with a usable current-session model when
|
|
516
|
-
possible, and the repaired configuration is saved.
|
|
517
|
-
|
|
518
|
-
At runtime, if an agent's model fails at the provider level before producing any output
|
|
519
|
-
(bad model id, auth, thinking level, quota, ...), the run is retried **once** with the
|
|
520
|
-
main window's current model. This degradation is per-run only and never persisted; it
|
|
521
|
-
does not apply to task-level failures (the model worked, the task failed) or aborts.
|
|
522
|
-
Idle timeouts count as model-level failures and do trigger the fallback, since a stalled
|
|
523
|
-
stream is usually a provider-side issue. Results carry a `model fell back from …` note
|
|
524
|
-
when it happened.
|
|
525
|
-
|
|
526
|
-
If the model is unavailable or broken and the fallback retry also fails (or no fallback
|
|
527
|
-
model is available), the task is **handed back to the main window**: the completion
|
|
528
|
-
message tells the main agent to execute the task itself with its own tools. A background
|
|
529
|
-
task that crashes with an exception is also surfaced — the user gets a `✗ dispatch
|
|
530
|
-
failed` notification and the failure is delivered to the main agent, which can
|
|
531
|
-
re-dispatch it.
|
|
532
|
-
|
|
533
|
-
Thinking strength uses this precedence: `agentThinkingLevels` entry → agent frontmatter `thinking` → `thinkingLevel` default.
|
|
534
|
-
|
|
535
|
-
## Agent discovery and overrides
|
|
536
|
-
|
|
537
|
-
- Built-in agents are shipped with the package.
|
|
538
|
-
- User agents live in `~/.pi/agent/agents/`.
|
|
539
|
-
- Project agents live in the nearest `.pi/agents/` directory.
|
|
540
|
-
- For duplicate names, project overrides user and user overrides built-in.
|
|
541
|
-
|
|
542
|
-
Use a matching Markdown filename and `name` field to replace a built-in agent. Keep the
|
|
543
|
-
task brief explicit: include the goal, relevant paths, constraints, and expected handoff.
|
|
544
|
-
|
|
545
|
-
Optional frontmatter fields: `model` (default model reference) and `thinking` (default
|
|
546
|
-
thinking strength). Both are overridden by `agentModels` / `agentThinkingLevels` in
|
|
547
|
-
`pi-subagents.json` when set.
|
|
548
|
-
|
|
549
|
-
## Development
|
|
550
|
-
|
|
551
|
-
```bash
|
|
552
|
-
npm install
|
|
553
|
-
npm run check
|
|
554
|
-
npm test
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
The package has no runtime dependencies beyond pi peer dependencies.
|
|
558
|
-
|
|
559
|
-
## Acknowledgments
|
|
560
|
-
|
|
561
|
-
- The official [pi subagent example](https://github.com/earendil-works/pi)
|
|
562
|
-
(`examples/extensions/subagent`) — the child-process dispatch and
|
|
563
|
-
event-stream handling build on it.
|
|
564
|
-
- [tintinweb/pi-subagents](https://github.com/tintinweb/pi-subagents) — the
|
|
565
|
-
live widget (two lines per run: header + quiet gray activity row) and
|
|
566
|
-
parallel fan-out follow its design.
|
|
567
|
-
- [nicobailon/pi-subagents](https://github.com/nicobailon/pi-subagents) — the
|
|
568
|
-
result-delivery design is learned from it: prompt **steer** delivery (a
|
|
569
|
-
completion is injected right after the current tool call instead of waiting
|
|
570
|
-
for the turn to end), a blocking `subagent_wait` tool that returns the result
|
|
571
|
-
in-turn, status inspection and stop/interrupt management, and the rule that
|
|
572
|
-
an agent should never `sleep`/poll for a background run. Its status-file and
|
|
573
|
-
workflow-script orchestration (JS chains, checkpoints, scheduling, missions)
|
|
574
|
-
are deliberately out of scope here: this extension stays a focused 3-agent
|
|
575
|
-
delegation tool with a configuration wizard instead of a full orchestrator.
|
|
576
|
-
- The sub-agent pattern itself, popularized by
|
|
577
|
-
[Claude Code](https://github.com/anthropics/claude-code): role-specialized
|
|
578
|
-
agents that receive self-contained briefs.
|
|
579
|
-
|
|
580
|
-
The agent prompts and extension code are written independently for this
|
|
581
|
-
project; the projects above served as design references.
|
|
582
|
-
|
|
583
|
-
### What stays ours
|
|
584
|
-
|
|
585
|
-
- **Exactly three focused agents** (`explore` / `worker` / `reviewer`) with
|
|
586
|
-
hand-tuned prompts, not a generic orchestration surface.
|
|
587
|
-
- **`/subagents-setup` wizard** — per-agent model + thinking selection,
|
|
588
|
-
concurrency, fix rounds, idle watchdog, scope, injection — with config
|
|
589
|
-
migration and unavailable-model repair, all interactive.
|
|
590
|
-
- **The auto-fix loop** — a `REVIEW_FAIL` reviewer automatically drives
|
|
591
|
-
worker → re-review rounds before waking anyone.
|
|
592
|
-
- **Zero runtime dependencies**: agents are plain Markdown files; override or
|
|
593
|
-
add one by writing a file.
|
|
594
|
-
|
|
595
|
-
## License
|
|
596
|
-
|
|
597
|
-
MIT
|
|
1
|
+
# pi-subagents
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
4
|
+
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
Focused background delegation for [pi](https://pi.dev): `explore` / `worker` /
|
|
10
|
+
`reviewer` agents run in **isolated child processes** and hand their results back
|
|
11
|
+
to the main agent automatically. Install it, and the main model starts using it
|
|
12
|
+
on its own — no prompt engineering, no babysitting.
|
|
13
|
+
|
|
14
|
+
## Highlights
|
|
15
|
+
|
|
16
|
+
- **Zero-setup proactive dispatch** — the extension injects a delegation directive
|
|
17
|
+
into the main system prompt, so the main model automatically sends broad searches
|
|
18
|
+
to `explore`, self-contained implementations to `worker`, and pre-commit reviews
|
|
19
|
+
to `reviewer`. You just use pi; delegation happens by itself.
|
|
20
|
+
- **Vision-capable image tasks** — a task that may need to view screenshots,
|
|
21
|
+
mockups, or design files is flagged `vision: true`; the sub-agent then runs on
|
|
22
|
+
the vision model you configure in `/subagents-setup`. Not configured? It falls
|
|
23
|
+
back to the main session's current model. Configured model unavailable? You are
|
|
24
|
+
asked to pick a replacement, which is persisted. The agents know they can `read`
|
|
25
|
+
image files when the brief asks.
|
|
26
|
+
- **Results come back on their own** — completions are delivered as messages that
|
|
27
|
+
wake the main agent automatically, even mid-turn. No polling, no `sleep`, no
|
|
28
|
+
"go check" step. `subagent_wait` is a **non-blocking** in-turn lookup by default
|
|
29
|
+
(pass `timeoutMs` to block); `subagent_status` inspects runs; `subagent_stop`
|
|
30
|
+
cancels one and delivers its partial output.
|
|
31
|
+
- **Results are not re-narrated** — a sub-agent's completion is shown to you
|
|
32
|
+
verbatim, and the main agent is told not to paraphrase it back. It replies with
|
|
33
|
+
only its own conclusion or next step, so the same findings are never paid for
|
|
34
|
+
twice in tokens.
|
|
35
|
+
- **A quality gate that closes the loop** — when a reviewer returns `REVIEW_FAIL`,
|
|
36
|
+
the extension dispatches a worker briefed with the concrete findings, then a
|
|
37
|
+
re-review, up to `maxFixRounds` times — and only then wakes the main agent.
|
|
38
|
+
- **Self-healing model management** — unavailable configured models are repaired
|
|
39
|
+
and persisted automatically; a provider hiccup retries the same model up to 5×
|
|
40
|
+
with backoff, then falls back once to the main window's model; terminal errors
|
|
41
|
+
(quota/auth) short-circuit straight to the main agent; an idle watchdog kills
|
|
42
|
+
runs that go silent; startup races are retried with backoff.
|
|
43
|
+
- **Resumes, not restarts, on a model switch** — every run is session-backed, so
|
|
44
|
+
a model quota/auth failure resumes on another model with its earlier searches,
|
|
45
|
+
reads, and edits intact (no re-scanning). When every model is out, the run is
|
|
46
|
+
handed back with its session preserved for a one-call `subagent({ resume })`.
|
|
47
|
+
- **Honest completions** — a run that ended with failed tool calls (e.g. a broken
|
|
48
|
+
build) is reported as `completed with N failed tool call(s)` with the errors
|
|
49
|
+
attached — a cheerful final text can never hide a failure.
|
|
50
|
+
- **Parallel fan-out** — independent tasks run concurrently up to a configurable
|
|
51
|
+
limit (default 4).
|
|
52
|
+
- **Live progress widget** — each run's status, current activity, model, token
|
|
53
|
+
usage, and elapsed time; auto-fix chain rounds hang under their triggering
|
|
54
|
+
review as a tree, each finished round keeping a one-line outcome.
|
|
55
|
+
- **Recursion is structurally impossible** — children are leaf processes; the
|
|
56
|
+
`subagent` tool is excluded from their toolset.
|
|
57
|
+
- **Zero runtime dependencies** — agents are plain Markdown files; overriding or
|
|
58
|
+
adding one is writing a file.
|
|
59
|
+
- **Update announcements** — when a new configurable feature ships, you are told
|
|
60
|
+
about it once (a persisted marker stops the notice from nagging).
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pi install npm:@ferris1225/pi-subagents
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Requires pi **>= 0.80.6**. After installation, open the setup wizard in an
|
|
69
|
+
interactive TUI session:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
/subagents-setup
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The default configuration enables `explore`, `worker`, and `reviewer` — you can
|
|
76
|
+
start delegating immediately.
|
|
77
|
+
|
|
78
|
+
## The agents
|
|
79
|
+
|
|
80
|
+
| Agent | Access | Purpose |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `explore` | Read-only | Fast codebase reconnaissance: broad/open-ended search, multi-file lookups, mapping unfamiliar code. Returns compressed, structured findings. |
|
|
83
|
+
| `worker` | Full | Implements, fixes, refactors, and tests a self-contained task end to end, then reports honest verification. |
|
|
84
|
+
| `reviewer` | Read-only | Adversarial pre-commit quality gate: diff review, plus plans, proposed solutions, codebase health, and PR/issue validation. |
|
|
85
|
+
|
|
86
|
+
Each agent runs in its own isolated `pi` process with a clean context window; it
|
|
87
|
+
has no memory of your conversation, so briefs must be self-contained (goal, exact
|
|
88
|
+
paths, constraints, expected output).
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
### Single task
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
subagent({ agent: "explore", task: "Map the test setup: which files run what, and how is CI wired? Report exact paths." });
|
|
96
|
+
subagent({ agent: "worker", task: "Implement X in src/foo.ts, add tests, run npm test." });
|
|
97
|
+
subagent({ agent: "reviewer", task: "Review the diff of src/index.ts and tests/load.test.ts for correctness and edge cases." });
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Parallel tasks
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
subagent({
|
|
104
|
+
tasks: [
|
|
105
|
+
{ agent: "explore", task: "Where is the model fallback logic?" },
|
|
106
|
+
{ agent: "worker", task: "Add unit tests for models.ts." },
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Vision tasks (screenshots / mockups / designs)
|
|
112
|
+
|
|
113
|
+
When a task may require viewing images — frontend work, UI review, design
|
|
114
|
+
comparisons — set `vision: true` and give the sub-agent the exact image paths:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
subagent({
|
|
118
|
+
agent: "reviewer",
|
|
119
|
+
task: "Compare the UI in screenshots/settings.png against the mockup design.png; list every visual mismatch.",
|
|
120
|
+
vision: true,
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The sub-agent reads the images with its `read` tool. Model selection for
|
|
125
|
+
vision-flagged runs: configured `visionModel` → main session's current model →
|
|
126
|
+
agent's own model. When a configured vision model is no longer available, the
|
|
127
|
+
TUI asks you to pick a replacement (persisted); outside the TUI it warns and
|
|
128
|
+
falls back. A vision-flagged auto-fix chain keeps its worker/re-review rounds on
|
|
129
|
+
the vision model too, since they re-read the same images.
|
|
130
|
+
|
|
131
|
+
### Waiting, inspecting, stopping
|
|
132
|
+
|
|
133
|
+
- `subagent_wait` — in-turn result lookup. **Non-blocking by default**: a settled
|
|
134
|
+
run returns its result immediately; a still-active run tells the model to end
|
|
135
|
+
its turn (the wake-up message arrives on its own). Pass `timeoutMs` only when
|
|
136
|
+
you must stay in the turn.
|
|
137
|
+
- `subagent_status` — what is running now, what finished this session, full
|
|
138
|
+
result by run id.
|
|
139
|
+
- `subagent_stop` — cancel a run (or all); the child is terminated and an aborted
|
|
140
|
+
result with partial output is delivered.
|
|
141
|
+
|
|
142
|
+
## Configuration
|
|
143
|
+
|
|
144
|
+
Stored at `~/.pi/agent/pi-subagents.json` (follows `PI_CODING_AGENT_DIR` when
|
|
145
|
+
set). The `/subagents-setup` wizard drives every field interactively — models,
|
|
146
|
+
thinking levels, the vision model, concurrency, fix rounds, idle timeout, scope,
|
|
147
|
+
and injection — with a per-agent "configure one" menu when the config already
|
|
148
|
+
exists. `notifyOnReviewPass` and `maxResultLines` are edited directly in the
|
|
149
|
+
file.
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"enabledAgents": ["explore", "worker", "reviewer"],
|
|
154
|
+
"agentModels": {
|
|
155
|
+
"explore": "anthropic/claude-haiku-4-5"
|
|
156
|
+
},
|
|
157
|
+
"agentThinkingLevels": {
|
|
158
|
+
"explore": "low"
|
|
159
|
+
},
|
|
160
|
+
"thinkingLevel": "high",
|
|
161
|
+
"visionModel": "anthropic/claude-sonnet-4-5",
|
|
162
|
+
"notifyOnReviewPass": false,
|
|
163
|
+
"maxResultLines": 80,
|
|
164
|
+
"proactiveInjection": true,
|
|
165
|
+
"agentScope": "user",
|
|
166
|
+
"maxConcurrency": 4,
|
|
167
|
+
"maxFixRounds": 2,
|
|
168
|
+
"idleTimeoutSec": 90
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
| Field | Description |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| `enabledAgents` | Agent names exposed to discovery and prompt injection. An empty array disables all agents. |
|
|
175
|
+
| `agentModels` | Optional `provider/model-id` override per agent. |
|
|
176
|
+
| `agentThinkingLevels` | Optional thinking level per agent; agents without an entry use the agent's frontmatter `thinking`, then `thinkingLevel`. |
|
|
177
|
+
| `thinkingLevel` | Default thinking level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` (default `high`). |
|
|
178
|
+
| `visionModel` | Optional vision-capable model for `vision: true` tasks (screenshots/mockups/designs). Unset = falls back to the main session's current model. |
|
|
179
|
+
| `notifyOnReviewPass` | When `true`, a passing reviewer result is delivered without waking the main agent (default `false`). |
|
|
180
|
+
| `maxResultLines` | Max lines of a sub-agent result carried in the completion message (default `80`). Longer results are truncated; the full text is written to a temp file whose path is included in the message. |
|
|
181
|
+
| `proactiveInjection` | Whether to add the delegation directive to the main system prompt. |
|
|
182
|
+
| `agentScope` | `user`, `project`, or `both`; controls which user/project agent directories are discovered. |
|
|
183
|
+
| `maxConcurrency` | Max sub-agent processes running at once (1–16, default 4), and the max tasks one parallel `subagent` call accepts. Extra work waits in the queue. |
|
|
184
|
+
| `maxFixRounds` | Auto-fix rounds when a reviewer returns `REVIEW_FAIL` (default 2; `0` disables the loop). |
|
|
185
|
+
| `idleTimeoutSec` | Idle watchdog: a sub-agent whose stdout goes silent for this long is terminated and retried. `0` disables it. Default 90. |
|
|
186
|
+
|
|
187
|
+
### Model precedence
|
|
188
|
+
|
|
189
|
+
```text
|
|
190
|
+
per-agent override → current main-session model → agent frontmatter model
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
For vision-flagged runs:
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
visionModel (configured) → current main-session model → agent model
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Unavailable configured models are replaced with a usable current-session model
|
|
200
|
+
and the repaired config is saved. At runtime, a model that fails at the provider
|
|
201
|
+
level before producing output is retried (same model up to 5× on transient
|
|
202
|
+
errors, then once with the main window's model — per-run only, never persisted);
|
|
203
|
+
if everything fails, the task is handed back to the main window with
|
|
204
|
+
instructions to execute it directly.
|
|
205
|
+
|
|
206
|
+
### Resuming after a model quota/auth failure
|
|
207
|
+
|
|
208
|
+
Every sub-agent run is **session-backed**: its pi session is persisted to a
|
|
209
|
+
temp dir for the run. When a model fails at the provider level, the retry and
|
|
210
|
+
the fallback **resume that session** instead of starting over — so a model
|
|
211
|
+
switch inherits the sub-agent's earlier searches, reads, and edits and never
|
|
212
|
+
re-scans. If every available model is exhausted (e.g. the account is out of
|
|
213
|
+
quota), the run is handed back with its session preserved; once you have a
|
|
214
|
+
working model again, resume it in-context:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
subagent({ resume: 7 }); // continue run #7 from where its model stopped
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The session is reclaimed once the resume succeeds (or when the session ends).
|
|
221
|
+
|
|
222
|
+
### Configuration migration
|
|
223
|
+
|
|
224
|
+
The config file migrates itself on load — no manual steps after an upgrade:
|
|
225
|
+
schema upgrades are normalized and saved back, removed agents are stripped,
|
|
226
|
+
legacy keys (`maxParallelTasks`, `maxSubagentDepth`) are folded in or dropped,
|
|
227
|
+
and new fields are filled with defaults. New features are announced to you once
|
|
228
|
+
after an update via a toast (marker persisted in `announcedFeatures`).
|
|
229
|
+
|
|
230
|
+
## Agent discovery and overrides
|
|
231
|
+
|
|
232
|
+
- Built-in agents ship with the package; user agents live in `~/.pi/agent/agents/`;
|
|
233
|
+
project agents in the nearest `.pi/agents/` directory.
|
|
234
|
+
- For duplicate names: project overrides user overrides built-in. Keep the
|
|
235
|
+
matching filename and `name` field to replace a built-in agent.
|
|
236
|
+
- Optional frontmatter: `model` (default model reference), `thinking` (default
|
|
237
|
+
thinking strength), `tools` (comma-separated tool allow-list; absent = all
|
|
238
|
+
tools). Config overrides win at spawn.
|
|
239
|
+
|
|
240
|
+
## How it stays reliable
|
|
241
|
+
|
|
242
|
+
- **Three-layer model resilience** — same-model retry with backoff on transient
|
|
243
|
+
provider errors (503/429/timeout/network), then a one-shot fallback to the main
|
|
244
|
+
window's model. Terminal errors (quota/billing/invalid key/auth) never retry.
|
|
245
|
+
- **Startup-race retries** — a silent zero-activity child exit (concurrent pi
|
|
246
|
+
startup lock contention) is relaunched with backoff; only clean silent exits
|
|
247
|
+
qualify, so real work is never duplicated.
|
|
248
|
+
- **Idle watchdog** — a stalled provider stream (no output for `idleTimeoutSec`)
|
|
249
|
+
terminates the child and retries via the normal fallback path.
|
|
250
|
+
- **Dispatch crashes surface** — an exception in the dispatch layer produces a
|
|
251
|
+
failed result with a notification, never a silent hang.
|
|
252
|
+
- **Leaf children** — no nested delegation, no runaway trees.
|
|
253
|
+
|
|
254
|
+
## Development
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npm install
|
|
258
|
+
npm run check
|
|
259
|
+
npm test
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
The source is modular: `dispatch.ts` (subagent tool + auto-fix chain + vision
|
|
263
|
+
model), `tools.ts` (wait/status/stop), `widget.ts` (widget + announcements),
|
|
264
|
+
`runtime.ts` (shared session state), `spawn.ts` (child process layer),
|
|
265
|
+
`monitor.ts` (run tracking), `setup.ts` (wizard), `prompt.ts` (delegation
|
|
266
|
+
directive). No runtime dependencies beyond pi peer dependencies.
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|