Skip to main content

Messaging & Routing

Genie’s messaging layer routes messages between agents regardless of their backing provider (Claude Code or Codex). Three systems work together: NATS for real-time pub/sub, the protocol router for delivery, and the Claude native teams bridge for IPC.

NATS Pub/Sub

NATS provides real-time observability across the entire agent fleet. The client is a lazy singleton that connects on first use and auto-closes after 500ms idle when there are no active subscriptions.

Connection Behavior

Subject Hierarchy

Hook handlers emit events to structured NATS subjects: All NATS emissions are fire-and-forget — they never block execution. If NATS is unavailable, events are silently dropped.

Hook Integration

Four hook handlers power the NATS event stream:

Protocol Router

The protocol router (protocol-router.ts) is provider-agnostic. It routes messages between agents regardless of whether they are backed by Claude or Codex.

Resolution Order

When a message is sent to a recipient, the router resolves the target through a strict tiered search:

Delivery Flow

Auto-Spawn

When a message targets an offline agent that exists in the directory or has a saved spawn template, the router automatically spawns a new instance:
  • Spawn from saved template (provider, team, role, skill, cwd)
  • Wait up to 15 seconds for the agent to reach idle state
  • Poll every 1 second for pane readiness
  • Deliver message once idle, or queue if timeout expires

Claude Code Native Teams

The native teams bridge (claude-native-teams.ts) connects Genie’s team/agent system with Claude Code’s internal teammate IPC protocol.

What Native Teams Provide

Directory Structure

Member Registration

When an agent joins a team with native teams enabled, it is registered in the team’s config.json:

Dual Delivery

When native teams are enabled, the protocol router attempts both delivery mechanisms:
  1. Native inbox — file drop to ~/.claude/teams/<team>/inbox/<agent>/
  2. tmux send-keys — direct pane injection (traditional path)
This ensures messages arrive even if one delivery mechanism is unavailable.

Event Aggregator

The event aggregator (event-aggregator.ts) subscribes to the normalized event stream and maintains per-agent dashboard state:
When the event stream is unavailable, the aggregator falls back to building state from the agent registry.