fix(interactive-subagents): harden parallel lifecycle delivery

This commit is contained in:
jb
2026-09-03 23:40:14 -04:00
parent d99dbce93d
commit 7a1043e5e0
11 changed files with 848 additions and 131 deletions
+6 -6
View File
@@ -2,7 +2,7 @@
# pi-interactive-subagents
Async subagents for [pi](https://github.com/badlogic/pi-mono), running in Herdr tabs, Orca terminal tabs, or tmux panes. Spawn a sub-agent, keep working in the main session, and get the result steered back when it finishes. Fully non-blocking.
Async subagents for [pi](https://github.com/badlogic/pi-mono), running in Herdr tabs, Orca terminal tabs, or tmux panes. Spawn a sub-agent, keep working in the main session, and get the result as an automatic follow-up when it finishes. Fully non-blocking.
The backend is selected automatically: Herdr is used when Pi runs in a Herdr-managed pane (`HERDR_ENV=1`), then Orca when Pi runs in an Orca-managed terminal (`ORCA_TERMINAL_HANDLE`), otherwise tmux is used when available.
@@ -16,7 +16,7 @@ Subagents 2 running
○ 00:45 scout-2 waiting 2m
```
Spawn several in parallel — they run concurrently and steer results back independently as each finishes.
Spawn several in parallel — they run concurrently and deliver results independently as each finishes.
Running subagents survive a parent `/reload`. Their terminal sessions and completion watchers stay active, then rebind result delivery and the status widget to the fresh Pi extension runtime. Replacing or closing the parent session still cancels its running subagents. This lifecycle behavior requires Pi 0.68 or newer.
@@ -62,8 +62,8 @@ subagent({ agent: "worker", name: "dark-mode", task: "Implement the dark mode to
subagent_message({ name: "scout", message: "Also check the auth middleware" });
```
- **Running** — the message is typed into the live pane (newlines flattened) and picked up at the next turn boundary. The call returns immediately; the eventual completion still arrives as a steer message.
- **Finished** — the session is resumed with the message as the follow-up task, like a fresh spawn: fire-and-forget, always autonomous, result steered back later. The resumed run reclaims its original name.
- **Running** — the message is typed into the live pane (newlines flattened) and picked up at the next turn boundary. The call returns immediately; the eventual completion still arrives as an automatic follow-up.
- **Finished** — a Pi-backed session is resumed with the message as the follow-up task, like a fresh spawn: fire-and-forget, always autonomous, result delivered automatically later. The resumed run reclaims its original name. Claude CLI sessions can be steered while running but cannot currently be resumed after completion.
Every spawn records name → session file in `artifacts/<sessionId>/subagent-registry.json`, so names stay addressable across pi restarts. A nested sub-agent that spawns children gets its own registry keyed by its own session id. Resume is refused with a clear error (listing known names) if the name isn't registered, the session file is gone, or the session predates sandboxed resume.
@@ -116,7 +116,7 @@ You are a specialized agent that does X...
| `skills` | string | Comma-separated skill names to auto-load |
| `session-mode` | string | `standalone` (default), `lineage-only`, or `fork` — see below |
| `system-prompt` | string | `append` or `replace`: pass the body as the child's `--append-system-prompt` / `--system-prompt`. Omit and the body is prepended to the task prompt instead |
| `auto-exit` | boolean | Auto-shutdown when the agent finishes (see below) |
| `auto-exit` | boolean | Auto-shutdown when the agent finishes. Defaults to `true` (see below) |
| `interactive` | boolean | Whether stall/recovery transitions wake the parent (see below) |
| `cwd` | string | Default working directory |
| `disable-model-invocation` | boolean | Hide from `subagents_list`; still spawnable by explicit name |
@@ -130,7 +130,7 @@ You are a specialized agent that does X...
### auto-exit
With `auto-exit: true`, the session shuts down when the agent's turn ends — the agent just writes its final message and stops (there is no "done" tool). The last assistant message becomes the summary returned to the parent. Recommended for all autonomous agents.
`auto-exit` defaults to `true`, matching the fire-and-forget tool contract: the session shuts down when the agent's turn ends, and the parent receives the last assistant message automatically (there is no "done" tool). Set `auto-exit: false` only for a user-driven session that should remain open until the user exits its pane.
Notes: