# agent-relay
[](https://crates.io/crates/agent-relay)
[](https://docs.rs/agent-relay)
[](LICENSE)
**Agent-to-agent messaging for AI coding tools.** Let Claude, Gemini, GPT, and human devs coordinate in real time.
No server. No database. No config. Just the filesystem.
```toml
[dependencies]
agent-relay = "0.1"
```
## The problem
You have 3 Claude sessions, a Gemini agent, and a human all editing the same repo. Claude #1 starts refactoring `auth.rs`. Claude #2 has no idea and starts editing the same file. Gemini rewrites a function that Claude #1 just deleted. The human comes back to merge conflicts everywhere.
## The fix
```bash
# Install
cargo install agent-relay
# Claude session 1
agent-relay register --agent claude --session claude-1
agent-relay send "refactoring auth module, stay away from src/auth/"
# Claude session 2 checks before editing
agent-relay inbox --session claude-2
# [NEW] claude (claude-1): refactoring auth module, stay away from src/auth/
# Gemini replies
agent-relay send -f gemini-1 -a gemini --to claude-1 "got it, working on tests instead"
# Human checks what's happening
agent-relay agents
# SESSION AGENT PID HEARTBEAT
# claude-1 claude 12345 08:31:20
# claude-2 claude 12346 08:31:22
# gemini-1 gemini 12400 08:31:25
```
## Library API
```rust
use std::path::PathBuf;
use agent_relay::Relay;
let relay = Relay::new(PathBuf::from(".relay"));
// Register
relay.register("claude-opus", "session-1", std::process::id());
// Send (None = broadcast to all)
relay.send("session-1", "claude-opus", None, "refactoring auth");
// DM a specific agent
relay.send("session-1", "claude-opus", Some("session-2"), "can you review?");
// Check inbox (marks messages as read)
let msgs = relay.inbox("session-2", 10);
for (msg, is_new) in &msgs {
println!("[{}] {}: {}", if *is_new { "NEW" } else { "read" }, msg.from_agent, msg.content);
}
// Poll for new messages (for integration into loops)
let count = relay.poll("session-2");
if count > 0 {
// trigger action — spawn agent, send notification, etc.
}
```
## CLI Commands
| `register --agent NAME --session ID` | Register an agent |
| `unregister --session ID` | Remove an agent |
| `send MESSAGE` | Broadcast a message |
| `send --to SESSION MESSAGE` | DM a specific agent |
| `inbox --session ID` | Read messages (marks as read) |
| `unread --session ID` | Count unread messages |
| `agents` | List active agents |
| `cleanup` | Remove dead agents + old messages |
| `watch --session ID --exec CMD` | Poll for new messages, optionally run a command |
## Watch mode
Auto-trigger a command when messages arrive:
```bash
# Spawn Claude to respond when new messages come in
agent-relay watch --session my-agent --exec "claude -p 'check agent-relay inbox and respond'"
# Or just get notified
agent-relay watch --session my-agent --interval 5
```
## How it works
- One JSON file per message in `.relay/messages/`
- One JSON file per agent in `.relay/agents/`
- Read tracking: each message has a `read_by` array
- Dead agents cleaned up by PID check
- Old messages cleaned up by timestamp
- Atomic writes (tmp + rename) prevent corruption
All agents that point to the same `.relay` directory see each other. That's the entire protocol.
## Integration with AI tools
### Claude Code (CLAUDE.md)
```markdown
Before editing any file, check for team messages:
$ agent-relay inbox --session $SESSION_ID
```
### Gemini / Cursor / Windsurf
Same pattern — add relay commands to your agent's system prompt or MCP tool definitions.
### MCP Server
Wrap agent-relay as an MCP tool server so AI agents can call `relay_send`, `relay_inbox`, etc. natively. (Coming in v0.2)
## Origin
Extracted from [Aura](https://auravcs.com) — the semantic version control engine for AI-generated code. Aura uses agent-relay's messaging protocol to coordinate multiple Claude Code agents editing the same repository.
## License
Apache-2.0