Skip to content

YousefShereen1/agent-bus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

agentbus

File-based inter-agent communication for AI coding agents.

No server. No SDK. No vendor lock-in. Just bash + JSON + filesystem.

What it does

agentbus lets AI coding agents (Claude Code, Codex, Cursor, etc.) communicate with each other through a shared filesystem. Agents register, send messages, and a lightweight daemon delivers them by injecting text directly into agent terminals — waking turn-based LLM agents from their idle state.

The entire protocol is JSON files on disk. Any language that can read and write files can participate. The daemon uses inotifywait for zero-latency filesystem watching and kitty/tmux terminal injection for real-time delivery.

Requirements

  • Linux (uses inotifywait from inotify-tools)
  • Python 3 (for JSON manipulation)
  • One of: Kitty terminal (recommended), tmux, or poll-based fallback

Quick Start

# 1. Initialize in your project
.agents/agentbus/bus init

# 2. Start the daemon (once per team)
.agents/agentbus/bus daemon-start

# 3. Register agents (from each agent's terminal)
.agents/agentbus/bus join agent-a --role reviewer --runtime claude-code
.agents/agentbus/bus join agent-b --role implementer --runtime codex

# 4. Start heartbeats (background)
.agents/agentbus/bus alive agent-a &
.agents/agentbus/bus alive agent-b &

# 5. Send a message
.agents/agentbus/bus msg agent-b "Review this PR" --from agent-a --type request

# 6. Check health
.agents/agentbus/bus doctor

How it Works

Agent A terminal          Filesystem           Agent B terminal
     |                       |                       |
     |-- agentbus msg ------>|                       |
     |                  [write JSON]                 |
     |                       |                       |
     |                  [inotifywait]                |
     |                       |                       |
     |                  [daemon reads]               |
     |                       |                       |
     |                       |--- kitty send-text -->|
     |                       |--- kitty send-key --->|
     |                       |                  [agent wakes]
  1. Agent A sends a message — JSON file written to Agent B's mailbox
  2. The daemon watches all mailboxes via inotifywait
  3. On new file, daemon reads the message and looks up Agent B's terminal
  4. Daemon injects the message text + presses Enter via kitty/tmux
  5. Agent B wakes up and processes the message

Terminal Setup

Kitty (recommended)

Add to your kitty.conf:

allow_remote_control yes
listen_on unix:/tmp/kitty-{kitty_pid}

agentbus auto-detects Kitty sockets via $KITTY_PID and $KITTY_WINDOW_ID.

tmux

Register with a pane target:

.agents/agentbus/bus join agent-a --role worker --runtime claude-code --pane mysession:0.0

Polling fallback

For terminals without injection support, agents can poll:

.agents/agentbus/bus poll agent-a  # non-blocking check for new messages

Commands

Agent Lifecycle

Command Description
join <id> [--role <r>] [--runtime <r>] Register an agent
leave <id> Deregister an agent
alive <id> [--interval <s>] Background heartbeat loop (default 30s)
who Show online/stale/offline agents
status Show all agents and tasks

Daemon

Command Description
daemon-start [--log <path>] Start daemon in background
daemon-stop Stop running daemon
daemon-status Check if daemon is running (exit: 0=running, 1=stopped, 2=dead)

Messaging

Command Description
msg <target> <body> [--from <id>] [--type <t>] Send a message
inbox <id> [--unread] Check inbox
read <id> Mark all messages as read
poll <id> Non-blocking check for new notifications

Message types: info, review, question, answer, warning, request

Tasks

Command Description
task create <subject> [--by <id>] [--desc <d>] Create a task
task claim <task_id> <agent_id> Claim a task (atomic via mkdir)
task done <task_id> [--note <n>] Complete a task
task list List all tasks

Maintenance

Command Description
init [<dir>] Initialize agentbus in a project
doctor Check system health
gc [subcommand] [--dry-run] [--days <N>] Clean up stale state
version Show version

GC subcommands: agents, messages, tasks, locks, notify, log, all (default)

Directory Layout

.agents/agentbus/
├── bus                   # Entry point
├── lib/                  # Modules
│   ├── core.sh           # Shared helpers (timestamp, log_event)
│   ├── agent.sh          # Agent lifecycle (join, leave, heartbeat, alive, who)
│   ├── task.sh           # Task management (create, claim, done, list)
│   ├── msg.sh            # Messaging (msg, inbox, read)
│   ├── daemon.sh         # Daemon + notifications (start, stop, listen, poll)
│   ├── gc.sh             # Garbage collection
│   └── setup.sh          # Init, doctor, file coordination
├── PROTOCOL.md           # Protocol specification
├── README.md             # This file
├── registry/             # Agent registrations + heartbeats
│   ├── <id>.json         # Agent config
│   ├── <id>.notify       # Notification log
│   └── <id>.cursor       # Poll cursor
├── mailbox/              # Per-agent message inboxes
│   └── <id>/
│       └── msg-<ts>-<rand>.json
├── tasks/                # Shared task board
│   └── <id>.json
├── locks/                # Atomic task claiming (mkdir-based)
│   └── <id>.lock/
├── filelocks/            # Advisory file editing locks
├── log/
│   └── events.jsonl      # Append-only audit trail
└── daemon.pid            # Daemon PID file

Design Decisions

  • Why bash: Universal on Linux, no compilation, agents just need file I/O
  • Why inotifywait: Zero-latency filesystem watching, no polling overhead
  • Why PID files: Reliable process detection, no false matches from grep
  • Why JSON: Human-readable, debuggable with cat/jq, any language reads it
  • Why mkdir for locks: POSIX-atomic, no external lock manager needed
  • Why terminal injection: LLM agents are turn-based — they idle until input arrives. Injecting text + Enter wakes them instantly

Troubleshooting

Daemon not running:

bus doctor          # Check overall health
bus daemon-start    # Start it

Messages not delivering:

  • Check daemon: bus daemon-status
  • Check agent registration: bus who
  • Check Kitty socket exists: ls /tmp/kitty-*

Stale state accumulating:

bus gc --dry-run    # Preview what would be cleaned
bus gc              # Clean up

Double daemon:

bus daemon-stop     # Stop via PID file
bus daemon-start    # Start fresh

About

File-based inter-agent communication for AI coding agents. No server, no SDK, no vendor lock-in — just bash + JSON + filesystem.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages