oira666_pi-subagent 0.4.0 → 0.4.2
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 +54 -640
- package/agents/code-architect.md +1 -1
- package/agents/code-reviwer.md +1 -1
- package/agents/code-writer.md +1 -1
- package/agents/team-lead.md +1 -1
- package/agents.ts +163 -181
- package/budget.ts +91 -142
- package/config.ts +8 -7
- package/create-subagent/SKILL.md +83 -0
- package/detail.ts +4 -673
- package/docs/configuration.md +117 -0
- package/docs/sessions.md +73 -0
- package/docs/usage.md +56 -0
- package/extension/broadcast.ts +231 -0
- package/extension/contracts.ts +15 -0
- package/extension/details.ts +17 -0
- package/extension/events.ts +103 -0
- package/extension/execution.ts +157 -0
- package/extension/expand-command.ts +138 -0
- package/extension/launch-tool.ts +295 -0
- package/extension/models.ts +87 -0
- package/extension/policy.ts +287 -0
- package/extension/progress.ts +82 -0
- package/extension/prompt-hook.ts +73 -0
- package/extension/prompts.ts +20 -0
- package/extension/provider.ts +171 -0
- package/extension/resume-offer.ts +102 -0
- package/extension/resume-tool.ts +283 -0
- package/extension/runtime.ts +131 -0
- package/extension/schemas.ts +115 -0
- package/extension/session-start.ts +209 -0
- package/extension/state.ts +70 -0
- package/extension/tool-registration.ts +26 -0
- package/extension/usage.ts +202 -0
- package/index.ts +30 -2714
- package/names.ts +12 -435
- package/overlay.ts +4 -574
- package/package.json +29 -14
- package/render.ts +188 -285
- package/resume.ts +50 -43
- package/runner/arguments.ts +263 -0
- package/runner/attempt-state.ts +14 -0
- package/runner/attempt.ts +343 -0
- package/runner/constants.ts +37 -0
- package/runner/events.ts +172 -0
- package/runner/files.ts +28 -0
- package/runner/launch.ts +148 -0
- package/runner/options.ts +72 -0
- package/runner/parallel.ts +183 -0
- package/runner/protocol.ts +131 -0
- package/runner/result.ts +47 -0
- package/runner/single.ts +204 -0
- package/runner.ts +8 -1509
- package/shared.ts +38 -38
- package/storage/budget-ledger.ts +135 -0
- package/storage/budget-state.ts +34 -0
- package/storage/name-records.ts +42 -0
- package/storage/names-identity.ts +143 -0
- package/storage/names-lock.ts +75 -0
- package/storage/names-registry.ts +93 -0
- package/storage/session-fork.ts +73 -0
- package/storage/values.ts +8 -0
- package/tree.ts +5 -704
- package/types/contracts.ts +165 -0
- package/types/details.ts +166 -0
- package/types/messages.ts +104 -0
- package/types/outcomes.ts +53 -0
- package/types/records.ts +8 -0
- package/types/transcript.ts +45 -0
- package/types/usage.ts +138 -0
- package/types.ts +6 -610
- package/ui/detail-lines.ts +242 -0
- package/ui/detail-model.ts +44 -0
- package/ui/detail-selectors.ts +60 -0
- package/ui/detail-transcript.ts +237 -0
- package/ui/frame.ts +21 -0
- package/ui/overlay-input.ts +54 -0
- package/ui/pager-view.ts +237 -0
- package/ui/pager.ts +208 -0
- package/ui/picker.ts +109 -0
- package/ui/session.ts +40 -0
- package/ui/tree-build.ts +302 -0
- package/ui/tree-format.ts +126 -0
- package/ui/tree-lines.ts +54 -0
- package/ui/tree-live.ts +98 -0
- package/ui/tree-model.ts +22 -0
- package/ui/value.ts +11 -0
- package/shims.d.ts +0 -148
package/README.md
CHANGED
|
@@ -1,703 +1,117 @@
|
|
|
1
|
-
# Pi
|
|
1
|
+
# Pi subagent
|
|
2
2
|
|
|
3
|
-
Delegate tasks to
|
|
3
|
+
Delegate tasks to agents running in separate Pi processes. Each worker has its own context and saved session. The parent receives its final text and usage statistics, not its reasoning or tool transcript.
|
|
4
|
+
|
|
5
|
+
Requires Pi 0.85.1 or newer, using the `@earendil-works` SDK packages.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
pi install npm:oira666_pi-subagent
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Or via git:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
11
|
+
# Or install from Git:
|
|
14
12
|
pi install git:github.com/gee666/pi-subagent.git
|
|
15
13
|
```
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
To remove it:
|
|
18
16
|
|
|
19
17
|
```bash
|
|
20
18
|
pi remove npm:oira666_pi-subagent
|
|
21
19
|
```
|
|
22
20
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
Each subagent runs as a **separate `pi` process** — fully isolated memory, its own model/tool loop.
|
|
26
|
-
Processes are spawned via the operating system and communicate through JSON-line stdout.
|
|
27
|
-
Subagent sessions are persisted separately under a `sessions-subagents` directory (a sibling of Pi's normal `sessions` directory), so they can be resumed without mixing into the main session list.
|
|
28
|
-
|
|
29
|
-
- Full OS-level isolation — a crashed subagent cannot affect the parent
|
|
30
|
-
- True parallel execution across all CPU cores
|
|
31
|
-
- Each subprocess boots a fresh Node.js runtime
|
|
32
|
-
- Uses the same Pi CLI entrypoint as the parent process when available
|
|
33
|
-
|
|
34
|
-
Each subagent receives only the task string. The main agent in turn receives
|
|
35
|
-
only the **final text output** from subagents (no tool calls, no reasoning).
|
|
36
|
-
|
|
37
|
-
## Tool Call Shape
|
|
38
|
-
|
|
39
|
-
The delegation tool is called `subagents` (older sessions may contain the
|
|
40
|
-
legacy name `subagent`, which is still recognized when reading history):
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{ "tasks": [{ "agent": "code-writer", "task": "Implement the API", "max_agents_allowed": 1 }] }
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Multiple tasks run in parallel:
|
|
21
|
+
## Launch and resume
|
|
47
22
|
|
|
48
23
|
```json
|
|
49
24
|
{
|
|
50
25
|
"tasks": [
|
|
51
|
-
{ "agent": "code-writer", "task": "
|
|
52
|
-
{ "agent": "code-reviwer", "task": "Review the
|
|
26
|
+
{ "agent": "code-writer", "task": "Implement the API", "max_subagents_allowed": 0 },
|
|
27
|
+
{ "agent": "code-reviwer", "task": "Review the design", "max_subagents_allowed": 0 }
|
|
53
28
|
]
|
|
54
29
|
}
|
|
55
30
|
```
|
|
56
31
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
## Delegation policy
|
|
60
|
-
|
|
61
|
-
Before launching new agents, the default prompts require a concrete time or context saving that outweighs startup, discovery, and coordination costs.
|
|
62
|
-
|
|
63
|
-
- Default to direct work rather than launching new agents. Use a small, flat set of specialists for substantial independent slices.
|
|
64
|
-
- Choose the fewest agents the task needs. Plan for the whole task, including nested workers and later phases, and respect any limit the user sets.
|
|
65
|
-
- Nested workers share the same budget. Each delegated task gets an explicit allowance.
|
|
66
|
-
- Another management layer must save enough attention to pay for itself. Prefer direct workers and count all nested agents in the same budget.
|
|
67
|
-
- Delegate before deep discovery, or pass existing findings directly or through a handoff file under the project's `tmp/` directory.
|
|
68
|
-
|
|
69
|
-
The efficiency guidance is a model instruction. Agent budgets and depth restrictions are enforced at runtime, but neither limits dollar spending. Use `pi --subagent-max-depth 1` to block nested delegation.
|
|
70
|
-
|
|
71
|
-
## Agent budgets
|
|
72
|
-
|
|
73
|
-
A main session starts with a budget of 50 new agents for its entire delegation tree. Set `PI_SUBAGENT_MAX_TOTAL_AGENTS` before starting a new session to change it. `0` blocks new launches but still permits named resumes. Invalid values block launches rather than silently removing the limit.
|
|
74
|
-
|
|
75
|
-
The main agent sees its remaining count only when it is below 30. Larger counts stay out of automatic prompts and budget-rejection messages so they do not suggest a target to spend. Enforcement is unchanged. Delegated workers always receive their own remaining allowance.
|
|
76
|
-
|
|
77
|
-
Each task reserves exactly `max_agents_allowed` slots from its caller. A value of `10` means ten agents total, including the assigned worker. The worker's automatic prompt says it may launch at most nine more subagents, including nested launches. Two tasks with budgets of `4` and `1` reserve five slots in total.
|
|
32
|
+
Call `subagents` with one or more tasks. Tasks run in parallel, subject to the concurrency limit. Every task requires an agent type, task text, and a descendant allowance. Use `0` for a worker that will not delegate, or `1` to let it launch one subagent. The caller reserves one slot for the worker plus its descendant allowance.
|
|
78
33
|
|
|
79
|
-
|
|
80
|
-
- Every nested call must specify allowances too. If a batch would exceed its caller's remaining slots, the extension rejects the whole batch before launching or naming any workers. The error explains the requested and remaining amounts.
|
|
81
|
-
- Siblings cannot borrow each other's slots. The extension commits reservations atomically across processes, so concurrent calls cannot spend the same slots.
|
|
82
|
-
- Unused allowances stay reserved for later resumes. Finished, failed, or canceled branches do not return slots to their parent. Interrupted calls reuse their original reservations when recovered.
|
|
83
|
-
- Named resumes do not consume new slots. The resumed worker, including any private session forks, keeps its current budget unless `max_agents_allowed` overrides it. Past launches and assigned slots still count.
|
|
84
|
-
- The extension adds the remaining allowance and explains inclusive branch sizes in the worker's prompt automatically. No hand-written budget instructions are needed.
|
|
34
|
+
Workers with zero descendant allowance receive neither active delegation tools nor added delegation guidance. Raising `max_subagents_allowed` on resume restores the tools, subject to the depth limit. This uses Pi's documented `getActiveTools()` and `setActiveTools()` APIs during `session_start`. Workers that spent a positive allowance keep their tools so they can resume existing children.
|
|
85
35
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Recorded calls and budgets from the older, exclusive argument remain resumable. The extension converts them without changing their reserved slots or remaining allowance.
|
|
89
|
-
|
|
90
|
-
Budget state is stored alongside subagent sessions using immutable files and atomic hard links. Missing or corrupt saved state blocks new launches instead of resetting the allowance. The session filesystem must support hard links. This is an agent-count limit, not a spending limit or a security sandbox.
|
|
91
|
-
|
|
92
|
-
## Tool Prompt Overrides
|
|
93
|
-
|
|
94
|
-
The complete LLM-facing description of each extension tool can be replaced in
|
|
95
|
-
`pi-subagents.json`. Supported locations, from lowest to highest priority:
|
|
96
|
-
|
|
97
|
-
1. `~/.pi/pi-subagents.json`
|
|
98
|
-
2. `$PI_CODING_AGENT_DIR/pi-subagents.json` (normally `~/.pi/agent/pi-subagents.json`)
|
|
99
|
-
3. The nearest trusted project `.pi/pi-subagents.json`, walking up from the current directory
|
|
100
|
-
|
|
101
|
-
Project values override global values per tool. Missing prompts keep their
|
|
102
|
-
built-in defaults. Overrides replace the written delegation guidance, not the required budget argument or runtime enforcement. Keep estimation guidance in custom descriptions. Use a JSON object for `tool-prompts`:
|
|
36
|
+
Workers receive durable human names. Call `resume_subagents` to continue one with its previous context:
|
|
103
37
|
|
|
104
38
|
```json
|
|
105
|
-
{
|
|
106
|
-
"tool-prompts": {
|
|
107
|
-
"subagents": "Your complete replacement prompt for the subagents tool.",
|
|
108
|
-
"resume_subagents": "Your complete replacement prompt for the resume tool."
|
|
109
|
-
}
|
|
110
|
-
}
|
|
39
|
+
{ "resumes": [{ "subagent": "John", "task": "Now update the tests." }] }
|
|
111
40
|
```
|
|
112
41
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Four built-in agents ship with the extension and remain available alongside custom agents by default:
|
|
42
|
+
`agent` selects a definition; `subagent` identifies an existing worker. Resumes do not consume new slots. See [sessions and budgets](docs/sessions.md) for budget overrides, forks, and crash recovery.
|
|
116
43
|
|
|
117
|
-
|
|
118
|
-
- `code-reviwer` — code review and risk finding
|
|
119
|
-
- `code-architect` — technical design and approach selection
|
|
120
|
-
- `team-lead`: rare coordination of one large subproject. Its bundled `first-layer: only` setting limits launches to the main agent.
|
|
44
|
+
Delegate only when parallel work or context isolation saves enough effort to cover worker startup and coordination. Pass existing findings with the task so workers do not repeat your research.
|
|
121
45
|
|
|
122
|
-
##
|
|
46
|
+
## Agent definitions
|
|
123
47
|
|
|
124
|
-
|
|
48
|
+
Bundled agents:
|
|
125
49
|
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
50
|
+
- `code-writer`: implementation and refactoring.
|
|
51
|
+
- `code-reviwer`: code review. The spelling is retained for compatibility.
|
|
52
|
+
- `code-architect`: technical design.
|
|
53
|
+
- `team-lead`: coordination of a large subproject, launchable only by the main agent.
|
|
129
54
|
|
|
130
|
-
|
|
131
|
-
Built-in agents remain available alongside custom agents unless
|
|
132
|
-
`PI_SUBAGENT_HIDE_BUILTIN_AGENTS=true`. A custom definition with the same name
|
|
133
|
-
as a built-in agent overrides that built-in definition, including its delegation instructions. Update custom copies separately to adopt the bundled policy.
|
|
55
|
+
Create Markdown files in `~/.pi/agent/agents/`, `$PI_CODING_AGENT_DIR/agents/`, or the project's `.pi/agents/` directory:
|
|
134
56
|
|
|
135
57
|
```markdown
|
|
136
58
|
---
|
|
137
59
|
name: writer
|
|
138
|
-
description:
|
|
60
|
+
description: Writes technical documentation
|
|
139
61
|
thinking: low
|
|
140
62
|
first-layer: enabled
|
|
141
63
|
last-layer: disabled
|
|
142
64
|
tools: read,write
|
|
143
65
|
---
|
|
144
66
|
|
|
145
|
-
|
|
67
|
+
Write clear, concise technical documentation.
|
|
146
68
|
```
|
|
147
69
|
|
|
148
|
-
|
|
70
|
+
The body is appended to Pi's system prompt. Project definitions override user/environment definitions, which override bundled definitions of the same name. Custom definitions replace the bundled instructions too.
|
|
149
71
|
|
|
150
|
-
|
|
151
|
-
| ------------- | -------- | -------------------- | -------------------------------------------------------- |
|
|
152
|
-
| `name` | Yes | — | Agent identifier used in tool calls |
|
|
153
|
-
| `description` | Yes | — | What the agent does (shown to the main agent) |
|
|
154
|
-
| `model` | No | Current parent model | Legacy fallback only when live parent model context is unavailable |
|
|
155
|
-
| `thinking` | No | Pi default | `off`, `minimal`, `low`, `medium`, `high`, `xhigh` |
|
|
156
|
-
| `tools` | No | `read,bash,edit,write` | Comma-separated built-in tools |
|
|
157
|
-
| `first-layer` | No | `enabled` | Rule for depth 1, launched by the main agent |
|
|
158
|
-
| `second-layer` | No | `enabled` | Rule for depth 2 |
|
|
159
|
-
| `last-layer` | No | `enabled` | Rule for the configured maximum depth |
|
|
160
|
-
| `nth-layer(1,2,-1)` | No | `enabled` | Rule for a comma-separated list of layer numbers |
|
|
72
|
+
See [configuration](docs/configuration.md) for frontmatter, layer restrictions, prompt overrides, and environment settings. The optional [create-subagent skill](create-subagent/SKILL.md) teaches Pi to write definitions.
|
|
161
73
|
|
|
162
|
-
|
|
74
|
+
## Interactive controls
|
|
163
75
|
|
|
164
|
-
|
|
165
|
-
- `disabled` blocks the selected layers.
|
|
166
|
-
- `only` restricts the agent to the selected layers. Multiple `only` rules combine their selections. A matching `disabled` rule still wins, regardless of order.
|
|
76
|
+
Collapsed results show each child's name, task, status, and most recent activity anywhere in its subtree. `Ctrl+O` expands the newest call from memory without reading historical transcripts.
|
|
167
77
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
```yaml
|
|
171
|
-
# Only the main agent can launch this agent.
|
|
172
|
-
first-layer: only
|
|
173
|
-
```
|
|
78
|
+
`/subagent-expand <name>` opens a saved worker transcript. With no name, it opens a searchable picker. Name completion is fuzzy.
|
|
174
79
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
The Markdown body becomes the agent's system prompt (appended to Pi's default, not replacing it).
|
|
186
|
-
|
|
187
|
-
## Delegation Guards
|
|
80
|
+
| Key | Action |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| Left / Right | Previous / next turn |
|
|
83
|
+
| T | Current turn's tool list |
|
|
84
|
+
| Up / Down, Enter | Select and open a tool or nested child |
|
|
85
|
+
| C | Children across all turns |
|
|
86
|
+
| Esc | Return to the parent view |
|
|
87
|
+
| /, n, N | Search, next match, previous match |
|
|
88
|
+
| q | Close |
|
|
188
89
|
|
|
189
|
-
|
|
90
|
+
While workers run, steering input can be broadcast to selected names, including nested paths such as `John > Maria`. Only inputs marked as streaming `steer` open the routing prompt. Idle prompts and queued follow-ups remain with the parent.
|
|
190
91
|
|
|
191
|
-
|
|
92
|
+
The `WITH SUBS` footer includes recursive worker usage. Resuming or privately forking a named worker adds usage without increasing the unique-worker count. See [usage accounting](docs/usage.md) for programmatic results.
|
|
192
93
|
|
|
193
|
-
|
|
194
|
-
| ------------------------------ | ------- | ------------------------------------------------ |
|
|
195
|
-
| `--subagent-max-depth` / `PI_SUBAGENT_MAX_DEPTH` | `3` | Max delegation depth (0 disables delegation) |
|
|
196
|
-
| `--subagent-prevent-cycles` / `PI_SUBAGENT_PREVENT_CYCLES` | `true` | Block same agent in delegation chain |
|
|
94
|
+
## Development
|
|
197
95
|
|
|
198
96
|
```bash
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
pi --no-subagent-prevent-cycles # allow cycles (not recommended)
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Parallel Limits
|
|
205
|
-
|
|
206
|
-
| Env Var | Default | Description |
|
|
207
|
-
| -------------------------------- | ------- | ---------------------------------------- |
|
|
208
|
-
| `PI_SUBAGENT_MAX_TOTAL_AGENTS` | `50` | Total new-agent budget for a new main session's tree |
|
|
209
|
-
| `PI_SUBAGENT_MAX_PARALLEL_TASKS` | `30` | Max tasks per single call |
|
|
210
|
-
| `PI_SUBAGENT_MAX_CONCURRENCY` | `8` | Max subagents running simultaneously |
|
|
211
|
-
|
|
212
|
-
## Child Process Environment
|
|
213
|
-
|
|
214
|
-
Children inherit all provider, authentication, proxy, home, temp, and Pi
|
|
215
|
-
environment variables. The runner also repairs the executable search path for
|
|
216
|
-
elevated Windows PowerShell and pnpm installations: it normalizes duplicate
|
|
217
|
-
`Path`/`PATH` keys and adds the Node directory, `PNPM_HOME`, npm's user bin,
|
|
218
|
-
`%LOCALAPPDATA%\\pnpm`, and `%SystemRoot%\\System32`. This also applies to every
|
|
219
|
-
nested child, so tools and sub-subagents use the same working environment.
|
|
220
|
-
|
|
221
|
-
Pi itself is relaunched with the current runtime and entrypoint
|
|
222
|
-
(`process.execPath process.argv[1]`). The extension does not inspect npm/pnpm
|
|
223
|
-
shims or assume package names, `node_modules` locations, or Pi `dist` layouts.
|
|
224
|
-
This also supports Bun and other Node-compatible runtimes with the same process
|
|
225
|
-
semantics. Embedded hosts without a script entrypoint can use
|
|
226
|
-
`PI_SUBAGENT_PI_COMMAND` and `PI_SUBAGENT_PI_ARGS_PREFIX` explicitly.
|
|
227
|
-
|
|
228
|
-
## Subagent Liveness Timeouts
|
|
229
|
-
|
|
230
|
-
A delegated process cannot block its parents forever. The runner applies a
|
|
231
|
-
startup timeout before the first model turn and an agent-inactivity timeout
|
|
232
|
-
after startup. The inactivity watchdog is paused while any tool call is in
|
|
233
|
-
progress, so tool executions can run for unlimited time; a fresh full idle
|
|
234
|
-
window starts after the last concurrent tool finishes. Agent/turn events and
|
|
235
|
-
changed nested-agent state reset the idle timer; repeated unchanged progress
|
|
236
|
-
heartbeats do not. On timeout or cancellation, the runner terminates the child
|
|
237
|
-
process tree and bounds cleanup; even if a wedged OS process never reports
|
|
238
|
-
`close`, the tool returns an error result so every waiting parent can settle.
|
|
239
|
-
|
|
240
|
-
RPC completion is based on Pi's `agent_settled` event—not `agent_end`.
|
|
241
|
-
`agent_end` is only a low-level run boundary and may be followed by Pi's normal
|
|
242
|
-
provider retry, overflow compaction, or queued continuation. Rejected prompt
|
|
243
|
-
commands, signal exits, and processes that exit before `agent_settled` are
|
|
244
|
-
reported immediately as failures.
|
|
245
|
-
|
|
246
|
-
| Env Var | Default | Description |
|
|
247
|
-
| --- | --- | --- |
|
|
248
|
-
| `PI_SUBAGENT_STARTUP_TIMEOUT` | `120000` | Milliseconds allowed to reach the first model turn; `0` disables |
|
|
249
|
-
| `PI_SUBAGENT_STARTUP_RETRIES` | `2` | Fresh retries after a startup timeout |
|
|
250
|
-
| `PI_SUBAGENT_IDLE_TIMEOUT` | `1200000` | Milliseconds without agent activity after startup, excluding time spent in ongoing tool calls; `0` disables |
|
|
251
|
-
|
|
252
|
-
## Timestamps & Status Footer
|
|
253
|
-
|
|
254
|
-
Subagent tool calls and live activity lines render a dim `hh:mm:ss` timestamp.
|
|
255
|
-
The collapsed view shows every direct child as `Name (agent-type)`, two prompt
|
|
256
|
-
lines, its current status, and `last action`. That timestamp is the newest
|
|
257
|
-
activity anywhere in the child's recursive subtree, so active grandchildren
|
|
258
|
-
keep their ancestor visibly alive. Press `Ctrl+O` for an instant in-memory
|
|
259
|
-
view: the newest subagent tool call is shown verbosely, while older calls stay
|
|
260
|
-
as lightweight trees. Ctrl+O never reads historical child session transcripts.
|
|
261
|
-
|
|
262
|
-
Use `/subagent-expand <name>` (for example `/subagent-expand Olga`) to open a
|
|
263
|
-
centered, turn-oriented popup. It starts on the latest turn and shows only that
|
|
264
|
-
turn's task/resume prompt, final response, compact tool summary, and collapsed
|
|
265
|
-
named children. Use Left/Right to change turns and `T` to open that turn's tool
|
|
266
|
-
list; delegation tool rows include a minimal tree of their named children.
|
|
267
|
-
Select a tool with Up/Down and press Enter to inspect its full arguments and
|
|
268
|
-
result. Every overview also shows its distinct direct children across all turns;
|
|
269
|
-
press `C`, select a child, and press Enter to open that child's same expanded
|
|
270
|
-
view. `Esc` returns to the parent. `/` opens visible search, `n`/`N` moves
|
|
271
|
-
through matches, and `q` closes from anywhere. The command offers fuzzy name
|
|
272
|
-
completion, and running `/subagent-expand` with no argument opens a searchable
|
|
273
|
-
picker (type to filter hundreds of names by name, agent type, or task). It is
|
|
274
|
-
available only in the interactive TUI.
|
|
275
|
-
|
|
276
|
-
In the tool list, delegation rows expand into their named children, and those
|
|
277
|
-
child rows are selectable: press Enter on one to open that subagent's own view.
|
|
278
|
-
|
|
279
|
-
The count in `WITH SUBS: (N)` is the number of unique subagents, including nested workers. Resuming a subagent or continuing its private session fork does not increase this count. Resume costs and tokens still contribute to the usage totals. Older compact history uses the name registry to recover identities that are no longer stored in the chat.
|
|
280
|
-
|
|
281
|
-
The `WITH SUBS` status line aggregates `ctx.sessionManager.getEntries()`, which
|
|
282
|
-
is the approach Pi documents for extension-side token stats. It applies Pi's own
|
|
283
|
-
rules (`AgentSession.getSessionStats`): every billed entry counts, including
|
|
284
|
-
off-branch retries, history compacted away, branch summaries, and tool-reported
|
|
285
|
-
usage. Delegated cost is added once, from the durable subagent usage summary, so
|
|
286
|
-
the combined line can never be lower than Pi's parent-only cost.
|
|
287
|
-
|
|
288
|
-
In the interactive TUI the extension publishes the combined `total` usage line
|
|
289
|
-
(parent + all subagents, recursively) via Pi's normal `ctx.ui.setStatus()`
|
|
290
|
-
status line. Pi renders all extension statuses on the same footer status line.
|
|
291
|
-
|
|
292
|
-
## Steering Running Subagents
|
|
293
|
-
|
|
294
|
-
While a `subagents` tool call is running, mid-stream steering input can be broadcast to one or more child agents. Targets are selected by human name; nested targets use paths such as `John > Maria > Elena`. The extension uses Pi's `InputEvent.streamingBehavior` metadata when available, so idle prompts and queued follow-ups continue to the parent normally; only true `steer` inputs open the broadcast routing prompt.
|
|
295
|
-
|
|
296
|
-
## Subagent Session Resume
|
|
297
|
-
|
|
298
|
-
> Requires Pi **0.81.0 or newer**. Crash recovery uses Pi's public full Provider SDK and session-replacement lifecycle.
|
|
299
|
-
|
|
300
|
-
Subagent subprocesses save sessions in `sessions-subagents`. When a main Pi session is resumed and its latest branch contains an unfinished `subagents` tool call (aborted, errored, or closed by Pi's synthetic unfinished-tool error), the extension can resume that delegation from the saved subagent sessions.
|
|
301
|
-
|
|
302
|
-
The same detection also runs after navigating the session tree in the TUI (Esc navigation): if you jump back to a point whose branch ends in an unfinished `subagents` call, the extension offers to resume those subagents from their saved sessions.
|
|
303
|
-
|
|
304
|
-
- TUI mode asks: **Resume subagents?**
|
|
305
|
-
- Non-UI modes (`pi -p`, JSON/RPC) resume automatically.
|
|
306
|
-
- Already-finished subagents are reused as completed; unfinished ones continue from their own saved sessions.
|
|
307
|
-
- Durable child refs retain final output, own usage, model, and tool counts, so completed siblings survive a JSON/session restart without becoming `(no output)` or losing accounting.
|
|
308
|
-
- Nested subagents use the same mechanism recursively.
|
|
309
|
-
- Provider fallback goes through the selected model's effective Pi provider, so custom providers, custom APIs, auth-derived endpoints, headers, and provider-scoped environment are preserved.
|
|
310
|
-
- Pending resume state and delayed callbacks are discarded on `/resume`, `/new`, `/fork`, and `/reload`, preventing stale work from an old runtime from leaking into the replacement session.
|
|
311
|
-
|
|
312
|
-
| Env Var | Default | Description |
|
|
313
|
-
| --- | --- | --- |
|
|
314
|
-
| `PI_SUBAGENT_RESUME_PROMPT` | `true` | Set to `false` to suppress the TUI yes/no prompt and auto-resume. |
|
|
315
|
-
| `PI_SUBAGENT_DISABLE_RESUME` | `false` | Set to `true` to disable automatic subagent resume detection entirely. |
|
|
316
|
-
|
|
317
|
-
Note: crash-resume covers `subagents` calls only. An interrupted `resume_subagents` call is not replayed automatically — the model can simply issue it again, since names stay valid (see below).
|
|
318
|
-
|
|
319
|
-
## Resumable Subagents by Name (`resume_subagents`)
|
|
320
|
-
|
|
321
|
-
Every subagent run is assigned a random, durable human first name from a bundled
|
|
322
|
-
list of 1000 culturally diverse names — for example `John`, `Octavian`, or `Vishnu`.
|
|
323
|
-
Names are never reused anywhere in the same delegation tree. The name is
|
|
324
|
-
returned together with the agent type and shown in every TUI view.
|
|
325
|
-
|
|
326
|
-
The `resume_subagents` tool continues named subagents with a new task while
|
|
327
|
-
preserving their full previous context:
|
|
328
|
-
|
|
329
|
-
```json
|
|
330
|
-
{ "resumes": [{ "subagent": "John", "task": "Now also update the tests." }] }
|
|
97
|
+
npm ci
|
|
98
|
+
npm run check
|
|
331
99
|
```
|
|
332
100
|
|
|
333
|
-
|
|
101
|
+
Tests use the real SDK packages installed as development dependencies. No host loader or permissive type shims are needed. Run tests outside a delegated worker environment, or unset inherited `PI_SUBAGENT_*` storage and budget variables first.
|
|
334
102
|
|
|
335
|
-
|
|
336
|
-
{ "resumes": [{ "subagent": "John", "task": "Continue the implementation", "max_agents_allowed": 10 }] }
|
|
337
|
-
```
|
|
103
|
+
Source organization:
|
|
338
104
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
- Increases reserve only the extra capacity from the original launcher's remaining budget. The full-tree cap still applies.
|
|
342
|
-
- A decrease cannot remove slots already spent or assigned to nested workers. It also does not return reserved capacity to the parent. Raising the cap back to a previously funded value needs no extra slots.
|
|
343
|
-
- A caller can override workers in its own delegation tree. For nested workers, increases use their immediate launcher's allowance. Increase that launcher's cap first if necessary.
|
|
344
|
-
- Overrides in one call must share an original launcher. Split overrides for different launchers into separate calls.
|
|
345
|
-
- Recorded reservations are required for overrides. Older workers without them can still resume without the optional field.
|
|
346
|
-
- Budget changes persist across resumes and forks. If interrupted after funding an increase, the extra capacity stays reserved and a retry does not charge it again.
|
|
347
|
-
|
|
348
|
-
Naming is deliberately unambiguous: `agent` (in `subagents`) selects an agent
|
|
349
|
-
*type* to spawn; `subagent` (in `resume_subagents`) addresses an already-run
|
|
350
|
-
subagent *instance* by its unique name.
|
|
351
|
-
|
|
352
|
-
- All resumes in one call run **in parallel**.
|
|
353
|
-
- The preferred shape is `{"resumes":[...]}`. For compatibility, the common single-item shorthand `{"subagent":"name","task":"..."}` is normalized automatically before validation.
|
|
354
|
-
- Names are unique within one delegation tree (everything spawned from one
|
|
355
|
-
top-level session) and are persisted in a registry file under the subagent
|
|
356
|
-
session root, so they survive restarts: you can resume a subagent in a later
|
|
357
|
-
session of the same conversation.
|
|
358
|
-
- The registry location and the session's ownership identity are stored in the
|
|
359
|
-
session itself (a custom metadata entry). Pi assigns resumed/branched
|
|
360
|
-
sessions a new internal session id, but the persisted identity (plus a
|
|
361
|
-
`parentSession` ancestor-walk fallback for sessions created before it
|
|
362
|
-
existed) keeps the whole tree's names alive across process restarts — for
|
|
363
|
-
the top-level session and every nested subagent alike.
|
|
364
|
-
- **Ownership & forks**: the agent that spawned a subagent (its *owner*)
|
|
365
|
-
resumes the original session. A parent may pass names to its own subagents
|
|
366
|
-
(in their task text); when a child resumes a name created by an ancestor, it
|
|
367
|
-
transparently gets a **private fork** of that subagent (a copy of its
|
|
368
|
-
session), so the owner's copy is never polluted by the child's continuation.
|
|
369
|
-
Each child gets exactly **one fork per name** and keeps reusing it on
|
|
370
|
-
subsequent resumes. Fork session locations are persisted too.
|
|
371
|
-
- Concurrent resumes of the same target are rejected (in-process and
|
|
372
|
-
cross-process via crash-tolerant registry markers), because two processes
|
|
373
|
-
continuing the same session file would corrupt it.
|
|
374
|
-
- If the original agent definition file has been removed, the resume still
|
|
375
|
-
works: the registry remembers the agent's model/tool restrictions and the
|
|
376
|
-
session itself carries the context.
|
|
377
|
-
|
|
378
|
-
| Env Var | Default | Description |
|
|
379
|
-
| --- | --- | --- |
|
|
380
|
-
| `DISABLE_RESUMABLE_SUBAGENTS` | `false` | Set to `true`/`on`/`1` to disable resumable subagents entirely: no names are allocated, the `resume_subagents` tool is not registered, and the system prompt omits the feature. |
|
|
381
|
-
| `PI_SUBAGENT_NAMES_FILE` | (internal) | Path of the shared name registry, propagated to child processes so the whole delegation tree allocates unique names. |
|
|
382
|
-
| `PI_SUBAGENT_BUDGET_DIR` | internal | Child's reserved branch ledger. Passed through the process environment and persisted in session metadata. |
|
|
383
|
-
|
|
384
|
-
## Agent Discovery
|
|
385
|
-
|
|
386
|
-
| Env Var | Description |
|
|
387
|
-
| ----------------------- | ------------------------------------------------------------ |
|
|
388
|
-
| `PI_CODING_AGENT_DIR` | Override Pi's agent config directory. Agents are read from `$PI_CODING_AGENT_DIR/agents/*.md`, and tool prompts from `$PI_CODING_AGENT_DIR/pi-subagents.json`. |
|
|
389
|
-
| `PI_SUBAGENT_HIDE_BUILTIN_AGENTS` | Set to `true`/`on`/`yes`/`1` to hide all bundled agents. By default they are available alongside custom agents. |
|
|
390
|
-
|
|
391
|
-
## CLI Argument Proxying
|
|
392
|
-
|
|
393
|
-
Flags passed to the parent `pi` process are forwarded to subagent child
|
|
394
|
-
processes, so they inherit the same provider, API key, and other runtime settings. At every new launch, the extension explicitly passes the parent's currently active model; changing `/model` mid-conversation therefore affects all subsequently started subagents. Flags the extension manages itself are blocked from being forwarded.
|
|
395
|
-
|
|
396
|
-
**Always forwarded verbatim:**
|
|
397
|
-
|
|
398
|
-
| Flag(s) | Purpose |
|
|
399
|
-
| --- | --- |
|
|
400
|
-
| `--provider` | AI provider |
|
|
401
|
-
| `--api-key` | API key |
|
|
402
|
-
| `--system-prompt` | Base system prompt override |
|
|
403
|
-
| `--session-dir` | Session storage directory |
|
|
404
|
-
| `--models` | Model cycling list |
|
|
405
|
-
| `--skill`, `--no-skills`/`-ns` | Skill loading |
|
|
406
|
-
| `--prompt-template`, `--no-prompt-templates`/`-np` | Prompt templates |
|
|
407
|
-
| `--theme`, `--no-themes` | Themes |
|
|
408
|
-
| `--verbose` | Verbose startup output |
|
|
409
|
-
| Unknown/custom flags | Forwarded with heuristic value detection |
|
|
410
|
-
|
|
411
|
-
**Forwarded as fallback** (agent frontmatter overrides if set):
|
|
412
|
-
|
|
413
|
-
| Flag | Overridden by |
|
|
105
|
+
| Directory | Responsibility |
|
|
414
106
|
| --- | --- |
|
|
415
|
-
|
|
|
416
|
-
|
|
|
417
|
-
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
`--mode`, `-p`/`--print`, `--session`/`--no-session`, `--continue`, `--resume`,
|
|
421
|
-
`--append-system-prompt`, `--offline`, `--extension`/`-e`, `--no-extensions`/`-ne`,
|
|
422
|
-
`--subagent-max-depth`, `--subagent-prevent-cycles`, `--export`, `--list-models`,
|
|
423
|
-
`--help`, `--version`.
|
|
424
|
-
|
|
425
|
-
---
|
|
426
|
-
|
|
427
|
-
## Programmatic Usage (JSON RPC)
|
|
428
|
-
|
|
429
|
-
When running `pi` programmatically with `--mode rpc` (or `--mode json`), the stream contains
|
|
430
|
-
`tool_result_end` events whenever the agent completes a `subagents` tool call. The `details` field
|
|
431
|
-
of these events carries the full stats for that delegation — including recursive usage and tool
|
|
432
|
-
call counts from all subagents in the tree.
|
|
433
|
-
|
|
434
|
-
### Stream event shape
|
|
435
|
-
|
|
436
|
-
```
|
|
437
|
-
tool_result_end
|
|
438
|
-
└── message
|
|
439
|
-
├── role: "toolResult"
|
|
440
|
-
├── toolName: "subagents"
|
|
441
|
-
├── toolCallId: string
|
|
442
|
-
├── isError: boolean
|
|
443
|
-
├── content: [{ type: "text", text: "<final output>" }]
|
|
444
|
-
└── details: SubagentDetails
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
### `SubagentDetails` object
|
|
448
|
-
|
|
449
|
-
```ts
|
|
450
|
-
interface SubagentDetails {
|
|
451
|
-
// Execution metadata
|
|
452
|
-
mode: "single" | "parallel"; // one task vs multiple parallel tasks
|
|
453
|
-
delegationMode: "spawn"; // always "spawn" (kept for backward-compatible serialization)
|
|
454
|
-
projectAgentsDir: string | null; // path to .pi/agents/ dir if used
|
|
455
|
-
|
|
456
|
-
// Individual agent results (one per task)
|
|
457
|
-
results: SingleResult[];
|
|
458
|
-
|
|
459
|
-
// ── Stats summary (own + all descendants, recursively) ──────────────────
|
|
460
|
-
aggregatedUsage: UsageStats; // token counts and cost, full tree
|
|
461
|
-
aggregatedToolCalls: ToolCallCounts; // { toolName: callCount }, full tree
|
|
462
|
-
|
|
463
|
-
// ── Per-agent breakdown ──────────────────────────────────────────────────
|
|
464
|
-
usageTree: UsageTreeNode[]; // one root node per result
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
interface SingleResult {
|
|
468
|
-
agent: string; // agent name
|
|
469
|
-
agentSource: "user" | "project" | "builtin" | "unknown";
|
|
470
|
-
task: string; // task string passed to this agent
|
|
471
|
-
exitCode: number; // 0 = process success, >0 = error, -1 = still running
|
|
472
|
-
messages: Message[]; // full conversation history of the subagent
|
|
473
|
-
stderr: string;
|
|
474
|
-
usage: UsageStats; // this agent's OWN token usage only
|
|
475
|
-
toolCalls: ToolCallCounts; // this agent's OWN tool calls only
|
|
476
|
-
model?: string;
|
|
477
|
-
stopReason?: string; // "end_turn" | "error" | "aborted" | ...
|
|
478
|
-
errorMessage?: string;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
interface UsageStats {
|
|
482
|
-
input: number; // input tokens
|
|
483
|
-
output: number; // output tokens
|
|
484
|
-
cacheRead: number; // cache read tokens
|
|
485
|
-
cacheWrite: number; // cache write tokens
|
|
486
|
-
cost: number; // total cost in USD
|
|
487
|
-
contextTokens: number; // snapshot: last context window size (not summed in aggregates)
|
|
488
|
-
turns: number; // number of assistant turns
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// toolName → call count, e.g. { "bash": 5, "read": 3, "subagents": 1 }
|
|
492
|
-
type ToolCallCounts = Record<string, number>;
|
|
493
|
-
|
|
494
|
-
interface UsageTreeNode {
|
|
495
|
-
agent: string;
|
|
496
|
-
task: string;
|
|
497
|
-
ownUsage: UsageStats; // only this agent's turns
|
|
498
|
-
ownToolCalls: ToolCallCounts; // only this agent's tool calls
|
|
499
|
-
aggregatedUsage: UsageStats; // ownUsage + all children recursively
|
|
500
|
-
aggregatedToolCalls: ToolCallCounts; // ownToolCalls + all children recursively
|
|
501
|
-
children: UsageTreeNode[]; // one node per nested subagent invocation
|
|
502
|
-
}
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
### Important notes on stats
|
|
506
|
-
|
|
507
|
-
- **`SingleResult.usage`** and **`SingleResult.toolCalls`** cover **only that one agent's own work** —
|
|
508
|
-
not its children. Children run in separate processes; their tokens never appear in the parent's usage.
|
|
509
|
-
- **`aggregatedUsage`** / **`aggregatedToolCalls`** on `SubagentDetails` (and on each `UsageTreeNode`)
|
|
510
|
-
are the correct totals to use when you want the cost or tool call count for an entire delegation
|
|
511
|
-
subtree.
|
|
512
|
-
- **`contextTokens`** is a point-in-time snapshot of the context window size at the last turn of that
|
|
513
|
-
agent. It is **not** summed in aggregated stats (it would be meaningless as a cross-process sum).
|
|
514
|
-
- **`toolCalls`** includes **all** tool calls an agent made, including the `"subagents"` call itself.
|
|
515
|
-
You can use the `"subagents"` count to see how many nested delegations an agent spawned.
|
|
516
|
-
|
|
517
|
-
### Annotated example JSON
|
|
518
|
-
|
|
519
|
-
The scenario below: main agent delegates to `code-writer`, which does some file work and then
|
|
520
|
-
delegates to `code-reviwer` before finishing.
|
|
521
|
-
|
|
522
|
-
```json
|
|
523
|
-
{
|
|
524
|
-
"type": "tool_result_end",
|
|
525
|
-
"message": {
|
|
526
|
-
"role": "toolResult",
|
|
527
|
-
"toolName": "subagents",
|
|
528
|
-
"toolCallId": "toolu_01XYZ",
|
|
529
|
-
"isError": false,
|
|
530
|
-
"content": [
|
|
531
|
-
{
|
|
532
|
-
"type": "text",
|
|
533
|
-
"text": "Feature implemented and reviewed. Added validation logic in auth.ts and updated the test suite."
|
|
534
|
-
}
|
|
535
|
-
],
|
|
536
|
-
"details": {
|
|
537
|
-
"mode": "single",
|
|
538
|
-
"delegationMode": "spawn",
|
|
539
|
-
"projectAgentsDir": null,
|
|
540
|
-
|
|
541
|
-
"aggregatedUsage": {
|
|
542
|
-
"input": 2180,
|
|
543
|
-
"output": 615,
|
|
544
|
-
"cacheRead": 940,
|
|
545
|
-
"cacheWrite": 120,
|
|
546
|
-
"cost": 0.0079,
|
|
547
|
-
"contextTokens": 0,
|
|
548
|
-
"turns": 3
|
|
549
|
-
},
|
|
550
|
-
"aggregatedToolCalls": {
|
|
551
|
-
"read": 3,
|
|
552
|
-
"bash": 2,
|
|
553
|
-
"edit": 1,
|
|
554
|
-
"subagents": 1
|
|
555
|
-
},
|
|
556
|
-
|
|
557
|
-
"usageTree": [
|
|
558
|
-
{
|
|
559
|
-
"agent": "code-writer",
|
|
560
|
-
"task": "Implement the auth feature and have it reviewed",
|
|
561
|
-
"ownUsage": {
|
|
562
|
-
"input": 1380,
|
|
563
|
-
"output": 365,
|
|
564
|
-
"cacheRead": 540,
|
|
565
|
-
"cacheWrite": 120,
|
|
566
|
-
"cost": 0.0058,
|
|
567
|
-
"contextTokens": 2840,
|
|
568
|
-
"turns": 2
|
|
569
|
-
},
|
|
570
|
-
"ownToolCalls": {
|
|
571
|
-
"read": 1,
|
|
572
|
-
"bash": 1,
|
|
573
|
-
"edit": 1,
|
|
574
|
-
"subagents": 1
|
|
575
|
-
},
|
|
576
|
-
"aggregatedUsage": {
|
|
577
|
-
"input": 2180,
|
|
578
|
-
"output": 615,
|
|
579
|
-
"cacheRead": 940,
|
|
580
|
-
"cacheWrite": 120,
|
|
581
|
-
"cost": 0.0079,
|
|
582
|
-
"contextTokens": 0,
|
|
583
|
-
"turns": 3
|
|
584
|
-
},
|
|
585
|
-
"aggregatedToolCalls": {
|
|
586
|
-
"read": 3,
|
|
587
|
-
"bash": 2,
|
|
588
|
-
"edit": 1,
|
|
589
|
-
"subagents": 1
|
|
590
|
-
},
|
|
591
|
-
"children": [
|
|
592
|
-
{
|
|
593
|
-
"agent": "code-reviwer",
|
|
594
|
-
"task": "Review the auth implementation in auth.ts",
|
|
595
|
-
"ownUsage": {
|
|
596
|
-
"input": 800,
|
|
597
|
-
"output": 250,
|
|
598
|
-
"cacheRead": 400,
|
|
599
|
-
"cacheWrite": 0,
|
|
600
|
-
"cost": 0.0021,
|
|
601
|
-
"contextTokens": 1450,
|
|
602
|
-
"turns": 1
|
|
603
|
-
},
|
|
604
|
-
"ownToolCalls": {
|
|
605
|
-
"read": 2,
|
|
606
|
-
"bash": 1
|
|
607
|
-
},
|
|
608
|
-
"aggregatedUsage": {
|
|
609
|
-
"input": 800,
|
|
610
|
-
"output": 250,
|
|
611
|
-
"cacheRead": 400,
|
|
612
|
-
"cacheWrite": 0,
|
|
613
|
-
"cost": 0.0021,
|
|
614
|
-
"contextTokens": 0,
|
|
615
|
-
"turns": 1
|
|
616
|
-
},
|
|
617
|
-
"aggregatedToolCalls": {
|
|
618
|
-
"read": 2,
|
|
619
|
-
"bash": 1
|
|
620
|
-
},
|
|
621
|
-
"children": []
|
|
622
|
-
}
|
|
623
|
-
]
|
|
624
|
-
}
|
|
625
|
-
],
|
|
626
|
-
|
|
627
|
-
"results": [
|
|
628
|
-
{
|
|
629
|
-
"agent": "code-writer",
|
|
630
|
-
"agentSource": "builtin",
|
|
631
|
-
"task": "Implement the auth feature and have it reviewed",
|
|
632
|
-
"exitCode": 0,
|
|
633
|
-
"stopReason": "end_turn",
|
|
634
|
-
"model": "claude-opus-4-5",
|
|
635
|
-
"stderr": "",
|
|
636
|
-
"usage": {
|
|
637
|
-
"input": 1380,
|
|
638
|
-
"output": 365,
|
|
639
|
-
"cacheRead": 540,
|
|
640
|
-
"cacheWrite": 120,
|
|
641
|
-
"cost": 0.0058,
|
|
642
|
-
"contextTokens": 2840,
|
|
643
|
-
"turns": 2
|
|
644
|
-
},
|
|
645
|
-
"toolCalls": {
|
|
646
|
-
"read": 1,
|
|
647
|
-
"bash": 1,
|
|
648
|
-
"edit": 1,
|
|
649
|
-
"subagents": 1
|
|
650
|
-
},
|
|
651
|
-
"messages": [
|
|
652
|
-
"... full conversation history of code-writer (includes the nested subagent tool_result) ..."
|
|
653
|
-
]
|
|
654
|
-
}
|
|
655
|
-
]
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
### Collecting stats across an entire session
|
|
662
|
-
|
|
663
|
-
If you are consuming the JSON stream programmatically and want to track the total cost and tool
|
|
664
|
-
usage across all subagent work in a session, listen for every `tool_result_end` event where
|
|
665
|
-
`message.toolName === "subagents"` (or the legacy `"subagent"` in old sessions) and sum `message.details.aggregatedUsage` across them.
|
|
666
|
-
|
|
667
|
-
```js
|
|
668
|
-
let totalCost = 0;
|
|
669
|
-
const totalToolCalls = {};
|
|
670
|
-
|
|
671
|
-
for await (const line of jsonLines) {
|
|
672
|
-
const event = JSON.parse(line);
|
|
673
|
-
if (
|
|
674
|
-
event.type === "tool_result_end" &&
|
|
675
|
-
["subagents", "subagent", "resume_subagents"].includes(event.message?.toolName) &&
|
|
676
|
-
event.message?.details
|
|
677
|
-
) {
|
|
678
|
-
const { aggregatedUsage, aggregatedToolCalls } = event.message.details;
|
|
679
|
-
totalCost += aggregatedUsage.cost;
|
|
680
|
-
for (const [tool, count] of Object.entries(aggregatedToolCalls)) {
|
|
681
|
-
totalToolCalls[tool] = (totalToolCalls[tool] ?? 0) + count;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
Note: if you also track the main agent's own usage from `message_end` events, make sure **not** to
|
|
688
|
-
double-count the subagent costs there — the main agent's own token usage (from its own `message_end`
|
|
689
|
-
events) does not include subagent work.
|
|
690
|
-
|
|
691
|
-
---
|
|
692
|
-
|
|
693
|
-
## create-subagent Skill
|
|
694
|
-
|
|
695
|
-
If you want the agent to **create new subagent definition files** for itself, install the [`create-subagent` skill](https://github.com/gee666/pi-subagent/tree/main/create-subagent). Once installed, the agent will know how to scaffold new `.md` agent files in the right location with correct frontmatter.
|
|
696
|
-
|
|
697
|
-
## Attribution
|
|
107
|
+
| `extension/` | Tool registration, session lifecycle, policy, recovery provider, steering |
|
|
108
|
+
| `runner/` | Child launch, RPC events, watchdogs, process cleanup |
|
|
109
|
+
| `storage/` | Budget ledger, name registry, session files and validation |
|
|
110
|
+
| `types/` | Runtime contracts, transcript parsing, outcomes, usage aggregation |
|
|
111
|
+
| `ui/` | Transcript views, trees, navigation and overlays |
|
|
698
112
|
|
|
699
|
-
|
|
113
|
+
Root entry points preserve existing imports. `config.ts` and `agents.ts` discover configuration and definitions. Runtime and test files stay below 350 lines; the name list is static data.
|
|
700
114
|
|
|
701
|
-
##
|
|
115
|
+
## Attribution and license
|
|
702
116
|
|
|
703
|
-
MIT
|
|
117
|
+
Inspired by [vaayne/agent-kit](https://github.com/vaayne/agent-kit) and [pi-mono](https://github.com/badlogic/pi-mono). MIT licensed.
|