pi-agent-wait
Interruptible, token-idle wait/yield primitives for Pi agents with aggregated host UI, batched wake coordination, event-driven background-task watches, and pi-subagents integration.
Package details
Install pi-agent-wait from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-agent-wait- Package
pi-agent-wait- Version
0.6.0- Published
- Aug 12, 2026
- Downloads
- 147/mo · 9/wk
- Author
- aledhe
- License
- MIT
- Types
- extension
- Size
- 90.4 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-agent-wait
Wait tools for Pi agents that don't burn tokens while waiting.
The usual way an agent waits for something (dev server booting, background task finishing) is to poll: check status, sleep, check again. Each poll is a model call, so you pay inference cost for doing nothing.
This extension registers two tools that do the waiting on the host side. While a wait is pending, the model is not running at all.
Install
pi install npm:pi-agent-wait
Or for a single session:
pi -e npm:pi-agent-wait
wait_for_background_task requires
pi-background-tasks.
The plain wait tool has no dependencies.
Tools
wait(seconds, reason, mode)
Waits for time to pass. Max 300s per call.
wait_for_background_task(taskId, timeoutSeconds, mode)
Waits for a pi-background-tasks task to reach completed, failed, or
killed. Max 900s per call. This goes through the public EventBus API, not
by reading .pi/tasks internals or polling bg_status.
Both tools take a mode:
block: the tool call stays pending until the wait resolves, then the same agent run continues. No inference happens in between. Use when the result is needed soon.yield: arms a host-side timer/watcher, ends the current turn, and wakes a later turn when done. Use for long waits where there's nothing else to do. Note: call it as a standalone tool call. Pi only honors early termination when every tool in the batch asks for it.
If you type a message while a wait is showing, the foreground wait is interrupted (the background task itself is not killed) and your message goes through normally. The wait moves to a compact footer entry. Esc cancels outright.
UI
All waits in a session share one panel. While Pi is actually idle-waiting,
you get an animated list with progress bars. For wait the bar is real
elapsed time. For task waits it's the fraction of the timeout budget used,
since there's no way to know how far along the task actually is.
⠹ Waiting · 2 host waits · token-idle
1. background task · foreground · npm test (b12ab34c)
[███████░░░░░░░░░░░░░░░░░] 00:31 / 02:00 · event-driven
2. timer · background · allow server to settle
[████████████░░░░░░░░░░░░] 00:31 / 01:00 · host timer
When the agent goes back to doing useful work, the panel collapses to a
one-line footer (background: 2 waits · task 01:29 left +1) with no spinner
and no repaint timer. In headless mode the UI is a no-op.
Wake batching
Completions that arrive while the main agent is busy don't interrupt it. They are held host-side and delivered as one batched follow-up when the run ends. Debounce is 150ms, max window 500ms, deduplicated by wake key.
pi-subagents integration
If pi-subagents is loaded in
the same process, detached/yielded waits show up as background-work provider
items, so a bare subagent_wait() covers subagent runs and these waits
together.
There is no dependency between the two packages. They find each other through
a shared Symbol.for("pi-subagents.background-work.v1") registry, and each
works normally if the other is absent. The registry is process-local on
purpose: a parent can't inspect a child subagent's waits, each process only
sees its own.
Limits
wait: 300s max per call.wait_for_background_task: 900s max.- Blocking waits share a 900s budget per agent run. The budget is reserved up front so sibling tool calls can't double-spend it.
- After 8 unattended yields in a row, further yields are refused until the user says something. This stops a self-waking wait chain from running forever.
- Background timers are
unref'd, so pending waits never keep a Pi process alive on their own. - Task names and errors come from arbitrary subprocess output. They are
flattened, length-bounded, and fenced as
<<untrusted:...>>before the model sees them.
Known issue
Don't put bg_run and wait_for_background_task in the same tool batch.
Sibling calls can run concurrently, so the wait may look up the task id
before it exists. There is a 2-second grace retry that catches near-misses,
but the reliable pattern is: bg_run, get the id, then wait.
Requirements
- Node.js >= 22.19
- A current Pi release with the TypeScript extension API
- pi-background-tasks, for the task wait tool
- Optional: pi-subagents >= 0.47.1
Development
npm run check
This typechecks against hand-written stubs in test-support/, which can
drift from the real API. If you have the actual Pi packages installed, also
run npm run typecheck:real.
License
MIT