Vibe Async Patterns
Conventions for async and concurrent code in Vibe. Apply when touching the agent loop, Textual event loop, HTTP clients, streaming, or any async code.
Runtime
asynciois the orchestration runtime in the agent loop and tool execution. Useasyncio.create_task+ queues for concurrent work, not blanketgather.
Blocking work
- Never run CPU-heavy or I/O-bound code on the UI thread. The Textual TUI and the agent loop share one event loop, so anything blocking (large JSON/Pydantic serialization,
os.fsync, subprocess calls, recursive globs) freezes the UI — offload it withasyncio.to_thread. - Async file wrappers don't make blocking syscalls non-blocking.
- Use
anyio.Pathfor file I/O on async paths.
Streaming
- Streaming surfaces return
AsyncGenerator[Event, None], not coroutines.
Core-to-TUI communication
- Route core-to-TUI communication through
vibe.app_server. Server requests such as approvals and user input become canonical Vibe events; neither the TUI nor app server may register callbacks, listeners, or message observers directly on the agent loop.
HTTP clients
- When Vibe owns an HTTP client, use
VibeAsyncHTTPClientfromvibe.utils.httpinstead ofhttpx.AsyncClientso proxy env vars are handled consistently. - Its CIDR
NO_PROXYmatching applies only to IP-literal request hosts; do not resolve DNS before proxy selection. - Mock outbound HTTP with
respxin tests.