Event Loop
How OpenWalrus routes events through a single mpsc channel — zero bottlenecks, fully async.
The event loop is the core of the OpenWalrus daemon. All events from all sources flow through a single channel, and each is dispatched as its own async task.
How it works
[Sources] ──→ mpsc::unbounded ──→ [Event Loop] ──→ tokio::spawn- Sources (socket, Telegram, Discord, tool calls) send
DaemonEventmessages into anmpsc::unboundedchannel - The event loop reads events one at a time
- Each event is dispatched via
tokio::spawn— non-blocking, fully parallel - The spawned task locks the target agent, runs it, and streams results back
Event types
The DaemonEvent enum covers all event sources:
| Variant | Source |
|---|---|
Message | Chat message from socket, Telegram, or Discord |
ToolCall | Tool invocation from an agent |
Shutdown | Graceful shutdown signal |
Why a single channel
A single mpsc::unbounded channel provides:
- Ordering — events arrive in the order they're sent
- Backpressure — unbounded means no sender blocks (the event loop is always fast enough to keep up)
- Simplicity — one place to observe all activity
The parallelism comes from tokio::spawn, not from multiple channels. Each event gets its own async task, so agents run concurrently even though events are dispatched sequentially.
Agent execution within the loop
When a message event arrives:
- Look up the target agent in the runtime
- Lock the agent's mutex
- Call
agent.run_stream()with tool schemas - Forward
AgentEvents back to the transport (socket, bot, etc.) - Release the lock
Tool call events from the agent are sent back into the same channel, creating a natural feedback loop.
Starting the event loop
The daemon starts the event loop automatically when you run walrus daemon. See configuration for setup, and agents for how agents are configured.