ap-wait-fanin · git:20260901.0259d5f · 2026-09-01 · sha256 3584c38354fe0329
ap-wait-fanin git:20260901.0259d5fA
Immutable. This exact content never changes and is served at /api/v1/blob/3584c38354fe0329.
---
name: ap-wait-fanin
description: Wait for one or more agentproto sessions to finish a turn (fan-in) without a shell polling loop — multiplex session_monitor across children, or take a session_events_poll cursor before spawning to stay race-free. Triggers — "wait for these agents to finish", "fan in on my children", "wait until turn-end", "block until any session is done", "don't poll in a loop".
---
# Wait For Sessions To Finish (Fan-In)
## When to use
You've spawned one or more agentproto sessions (see ap-spawn-agent) and need
to know the moment any — or all — of them finish a turn, hit
awaiting-input, or exit. This is the fan-in step: block cheaply instead of
burning your own context re-checking output by hand.
## Gotchas — read this before you wait on anything
- **Never write a shell/terminal polling loop** (`for i in ...; do check;
sleep; done`) to wait on children. A watchdog killing you mid-loop
permanently corrupts the underlying session into an "already has an
in-flight prompt" error that survives a restart — this happened in
production on 2026-09-01 and the session never recovered. If you spawn a
supervisor sub-agent that will itself wait on children, brief it
explicitly: `session_monitor` is THE fan-in mechanism, shell poll loops are
forbidden.
- **session_monitor can miss ultra-fast children.** If a trivial child
finishes before you attach the watch, the watch never fires for it. Parry
by taking a `session_events_poll` cursor BEFORE spawning children, or by
confirming completion via `agent_output` once a timeout elapses.
- **Arm the watch at spawn time.** Wakeup timers / scheduled re-checks are a
safety net only — the primary mechanism is the long-poll itself, not a
cron that happens to fire later.
## MCP: session_monitor
Multiplexed long-poll across N sessions. Returns on the FIRST watched
session to fire the requested event — you decide whether to keep waiting on
the rest.
```json
{
"tool": "session_monitor",
"args": {
"sessionIds": ["sess_abc123", "sess_def456"],
"event": "turn-end",
"timeoutMs": 45000
}
}
```
Valid `event` values: `turn-end`, `awaiting-input`, `exited`, `any`.
`timeoutMs` accepts 1000-49000 — it is a long-poll, not an indefinite wait,
so for longer horizons re-issue the call after each timeout. Prefer the CLI
alternative below when a real shell is available to you.
## MCP: session_events_poll
The race-free alternative. Take a cursor before spawning children, then poll
cheaply on your own schedule — an event emitted before your first poll call
is still returned, so nothing is lost to a race with fast children.
```json
{
"tool": "session_events_poll",
"args": { "since": "cursor_9f21" }
}
```
Returns `{ events: [...], nextCursor: "cursor_9f2c" }`. Keep `nextCursor`
and pass it back in as `since` on the next call.
## CLI
```bash
agentproto sessions wait sess_abc123 --until turn-end
```
Exists in v0.16.0 though hidden from `--help`. Defaults to a 15-minute
timeout. This is the preferred mechanism when you have a shell you can
background — see ap-wait-durable for the non-blocking background pattern.
```bash
agentproto sessions --watch
```
Live-tails session state changes to the terminal. Good for interactive
supervision, not for programmatic fan-in — use `session_monitor` or
`session_events_poll` for that.
## Pointers
- ap-wait-durable — get notified without blocking your own turn
- ap-spawn-agent — spawn the sessions you're about to wait on
- supervise-long-missions
- pb-supervise-parallel-mission