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
| Behavior | Detail |
|---|---|
| Connect | Lazy on first publish/subscribe |
| Reconnect | Automatic via NATS client |
| Idle cleanup | 500ms after last active subscription |
| Unavailable | Silent no-op (NATS is optional) |
| URL | GENIE_NATS_URL or nats://localhost:4222 |
Subject Hierarchy
Hook handlers emit events to structured NATS subjects:| Subject Pattern | Event Source | Data |
|---|---|---|
genie.tool.{agent}.call | PreToolUse (all tools) | Tool name, input, agent, team |
genie.msg.{recipient} | PostToolUse:SendMessage | From, to, message content |
genie.user.{agent}.prompt | UserPromptSubmit | Agent name, prompt text |
genie.agent.{agent}.response | Stop | Agent name, response summary |
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 workers 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 worker 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/worker system with Claude Code’s internal teammate IPC protocol.
What Native Teams Provide
| Feature | Mechanism |
|---|---|
| Inbox polling | Filesystem-based — agents auto-poll ~/.claude/teams/<team>/inbox/<agent>/ |
| Member registry | config.json in team directory lists all members |
| Shutdown protocol | Structured JSON messages for graceful teardown |
| Plan approval | Structured JSON messages for plan review flow |
| Direct messages | File drops to inbox directories |
Directory Structure
Member Registration
When a worker joins a team with native teams enabled, it is registered in the team’sconfig.json:
Dual Delivery
When native teams are enabled, the protocol router attempts both delivery mechanisms:- Native inbox — file drop to
~/.claude/teams/<team>/inbox/<agent>/ - tmux send-keys — direct pane injection (traditional path)
Event Aggregator
The event aggregator (event-aggregator.ts) subscribes to the normalized event stream and maintains per-worker dashboard state: