OpenWalrusOpenWalrus

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
  1. Sources (socket, Telegram, Discord, tool calls) send DaemonEvent messages into an mpsc::unbounded channel
  2. The event loop reads events one at a time
  3. Each event is dispatched via tokio::spawn — non-blocking, fully parallel
  4. The spawned task locks the target agent, runs it, and streams results back

Event types

The DaemonEvent enum covers all event sources:

VariantSource
MessageChat message from socket, Telegram, or Discord
ToolCallTool invocation from an agent
ShutdownGraceful 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:

  1. Look up the target agent in the runtime
  2. Lock the agent's mutex
  3. Call agent.run_stream() with tool schemas
  4. Forward AgentEvents back to the transport (socket, bot, etc.)
  5. 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.

On this page