DEV Community

Lakshmi Sravya Vedantham
Lakshmi Sravya Vedantham

Posted on

I Built a Coordination System for Multiple Claude AI Agents — So They Stop Overwriting Each Other

I Built a Coordination System for Multiple Claude AI Agents — So They Stop Overwriting Each Other

Here's a problem nobody talks about yet but everyone will hit as AI-assisted development scales up: what happens when two Claude agents are working in the same codebase at the same time?

They overwrite each other. Silently. No warnings, no errors — just lost work.

I built a skill to fix this. It's called agent-comms, and it gives Claude agents a shared communication channel so they can coordinate before conflicts happen.


The Problem

I've been running multiple Claude Code sessions simultaneously on a project — one handling frontend UI work, another fixing the backend pipeline. Both intelligent, both fast, both completely unaware the other exists.

The result: one agent refactors a file, the other overwrites it ten seconds later with a different version. Neither agent knows. The work is gone.

The root issue: Claude agents have no shared awareness. Each terminal is its own isolated context. There's no built-in coordination layer.


The Solution: File-Based Agent Communication

The only channel multiple Claude agents share is the filesystem. So that's where I built the communication layer.

agent-comms creates a .agent-comms/ directory in your project root with three JSON files:

.agent-comms/
  registry.json       — who is active right now
  announcements.json  — what files each agent plans to edit (and why)
  messages.json       — direct agent-to-agent messages
Enter fullscreen mode Exit fullscreen mode

A Python script (comms.py) handles all reads and writes — atomic, stale-safe, zero dependencies.


The Protocol

Every agent follows the same lifecycle:

1. Register

python3 $COMMS register researchUI "building dashboard UI components"
python3 $COMMS register Worker1 "fixing backend data pipeline"
Enter fullscreen mode Exit fullscreen mode

2. Announce upfront — before touching any file

python3 $COMMS announce researchUI \
  "src/lib/api.ts|adding stream endpoint" \
  "src/pages/dashboard.tsx|adding real-time chart"

python3 $COMMS announce Worker1 \
  "src/lib/api.ts|fixing broken API call" \
  "src/pages/dashboard.tsx|removing hardcoded mock data"
Enter fullscreen mode Exit fullscreen mode

3. Check for conflicts

python3 $COMMS check-conflicts Worker1
Enter fullscreen mode Exit fullscreen mode

Output:

CONFLICT: researchUI also needs src/lib/api.ts — their reason: adding stream endpoint
CONFLICT: researchUI also needs src/pages/dashboard.tsx — their reason: adding real-time chart component
Enter fullscreen mode Exit fullscreen mode

Two conflicts detected. Before a single file was touched.

4. Negotiate

Worker1 (the later announcer) initiates:

python3 $COMMS send Worker1 researchUI \
  "CONFLICT on api.ts — my change: fixing broken endpoint call on line 34. I should go first since it's a bug fix."

python3 $COMMS send Worker1 researchUI \
  "CONFLICT on dashboard.tsx — removing 3 hardcoded mock arrays. Safe to do before your chart work. Suggest: I go first."
Enter fullscreen mode Exit fullscreen mode

researchUI reads and replies:

python3 $COMMS read-messages researchUI
# FROM [Worker1]: CONFLICT on api.ts...
# FROM [Worker1]: CONFLICT on dashboard.tsx...

python3 $COMMS send researchUI Worker1 \
  "Agreed — go first on both. I'll wait for your DONE broadcast."
Enter fullscreen mode Exit fullscreen mode

5. Worker1 finishes and broadcasts

python3 $COMMS done Worker1 \
  "src/backend/classifier.py" \
  "src/lib/api.ts" \
  "src/pages/dashboard.tsx"
Enter fullscreen mode Exit fullscreen mode

6. researchUI gets the all-clear

python3 $COMMS read-messages researchUI
# FROM [Worker1]: [DONE] Worker1 finished. Modified: src/lib/api.ts, src/pages/dashboard.tsx
Enter fullscreen mode Exit fullscreen mode

researchUI now knows exactly which files were modified and can proceed safely.


Full Terminal Output

Here's the actual output from a real test run:

=== researchUI announces its files ===
[agent-comms] Announced 3 file(s) for 'researchUI'

=== Worker1 announces its files ===
[agent-comms] Announced 3 file(s) for 'Worker1'

=== researchUI checks for conflicts ===
CONFLICT: Worker1 also needs src/lib/api.ts — their reason: fixing broken API call
CONFLICT: Worker1 also needs src/pages/dashboard.tsx — their reason: removing hardcoded mock data

=== Worker1 negotiates ===
[agent-comms] Sent from 'Worker1' to 'researchUI'
[agent-comms] Sent from 'Worker1' to 'researchUI'

=== researchUI reads messages ===
  FROM [Worker1] @ 2026-03-27T19:14:27: CONFLICT on api.ts — fixing broken endpoint call on line 34. I should go first.
  FROM [Worker1] @ 2026-03-27T19:14:27: CONFLICT on dashboard.tsx — removing 3 hardcoded mocks. Suggest: I go first.

=== researchUI agrees ===
[agent-comms] Sent from 'researchUI' to 'Worker1'

=== Worker1 finishes ===
[agent-comms] 'Worker1' done. Broadcast sent to 1 agent(s).

=== researchUI gets the all-clear ===
  FROM [Worker1]: [DONE] Worker1 finished. Modified: src/backend/classifier.py, src/lib/api.ts, src/pages/dashboard.tsx

=== Final status ===
[agent-comms] Active agents: 1 | Unread messages: 0
  [researchUI] building dashboard UI components
    planned files: dashboard.tsx, Chart.tsx, api.ts
Enter fullscreen mode Exit fullscreen mode

Zero overwrites. Zero lost work.


How It's Designed as a Claude Code Skill

The system ships as a SKILL.md — a Claude Code skill file that instructs Claude to follow the agent lifecycle automatically. When you invoke superpowers:agent-comms in a Claude Code session, Claude:

  1. Runs status to see who's active
  2. Auto-assigns itself a name (or asks you to rename it)
  3. Registers itself with its task description
  4. Before any edit session — announces files and checks conflicts
  5. If conflict detected — initiates or responds to negotiation
  6. Every ~10 tool calls — sends a heartbeat
  7. When done — deregisters and broadcasts to all other agents

The SKILL.md protocol:

## Step 2: Announce Upfront (BEFORE any file edit)

Before touching ANY file this session, list every file you plan to edit and why:

python3 $COMMS announce agent-N \
  "path/to/file.ts|reason for editing"

Then immediately check for conflicts:
python3 $COMMS check-conflicts agent-N

If output is CLEAR → proceed.
If output contains CONFLICT → go to Step 3 (negotiation).
Enter fullscreen mode Exit fullscreen mode

Design Decisions

Why file-based?
Claude agents in different terminals share nothing except the filesystem. No sockets, no shared memory, no APIs between them. Files are the only viable channel.

Why upfront announcements instead of locks?
Locks only catch conflicts at the moment of editing — after you've already started work. Announcements catch them before any work begins, when the cost of changing course is zero.

Why negotiation instead of blocking?
Blocking wastes time. Negotiation lets agents make intelligent decisions: "include my change," "I'll go first," or "let's split the file." The agents have context about what they need — use it.

Stale agent cleanup:
Agents that haven't sent a heartbeat in 5 minutes are auto-removed from the registry. If an agent crashes without deregistering, it won't block others indefinitely.

Project-scoped:
.agent-comms/ lives in the project root and is added to .gitignore automatically. Coordination state doesn't belong in git history.


Install

SKILL_DIR="$HOME/.claude/plugins/cache/claude-plugins-official/superpowers/5.0.5/skills/agent-comms"
mkdir -p "$SKILL_DIR/tests"
curl -o "$SKILL_DIR/comms.py" https://raw.githubusercontent.com/LakshmiSravyaVedantham/agent-comms/main/comms.py
curl -o "$SKILL_DIR/SKILL.md" https://raw.githubusercontent.com/LakshmiSravyaVedantham/agent-comms/main/SKILL.md
Enter fullscreen mode Exit fullscreen mode

Then in any Claude Code session working in a shared project:

superpowers:agent-comms
Enter fullscreen mode Exit fullscreen mode

Tests

19 tests covering the full lifecycle:

python3 -m pytest tests/ -v
# 19 passed in 1.83s
Enter fullscreen mode Exit fullscreen mode

What's Next

  • Three-agent coordination — tested with 2, curious how negotiation chains work at 3+
  • File section locks — "I own lines 1–80 of this file, you take 81–160"
  • Integration with Claude Code hooks — auto-register/deregister via session hooks

GitHub

github.com/LakshmiSravyaVedantham/agent-comms

Python 3.8+, stdlib only, MIT license. Drop it into your superpowers skill directory and your agents start coordinating immediately.

If you're running multiple Claude sessions simultaneously, this will save you from the silent overwrite problem sooner or later.

Top comments (2)

Collapse
 
klement_gunndu profile image
klement Gunndu

The upfront announcement pattern is smart — catching file conflicts before work starts is way cheaper than merging after. Worth watching: the 5-minute stale cleanup might be too aggressive if an agent is stuck in a long tool call.

Collapse
 
lakshmisravyavedantham profile image
Lakshmi Sravya Vedantham

Thanks for the thoughtful feedback. You're absolutely right — catching conflicts upfront saves a lot of headaches. On the 5-minute stale cleanup: valid concern. The tradeoff was not leaving stale locks hanging indefinitely vs. prematurely cancelling a busy agent. A more adaptive timeout or a heartbeat system where the agent pings to say 'still working' would be the cleaner fix. Definitely something to explore in a future version.