[FEATURE] Multi-agent collaboration across machines (Agent-to-Agent protocol)

Open 💬 35 comments Opened Feb 24, 2026 by MarioK1975

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Modern software is rarely a single codebase. Microservices, headless CMS + consumer apps, IoT platforms — real-world systems consist of multiple repositories on multiple machines that must work together through shared APIs, webhooks, and data contracts.

Claude Code is excellent at working within one codebase. But it has no concept of "the other side."

When two Claude Code instances work on interconnected systems simultaneously, they are completely blind to each other. Every interface change, every schema decision, every API contract must be manually relayed by the developer — who becomes a slow, error-prone message broker between two AI agents that could otherwise coordinate at machine speed.

This isn't an edge case. It's the reality for:

  • Microservice architectures (each service = separate repo, separate machine)
  • Headless CMS + frontend apps (CMS on server A, consumer apps on server B)
  • IoT/embedded + cloud (device firmware on one machine, cloud backend on another)
  • Platform teams (API team + multiple consumer teams working in parallel)

The irony: we use Claude Code because it's fast and autonomous. But the moment a project spans two machines, the human becomes the bottleneck again.

Proposed Solution

An Agent-to-Agent protocol built on top of MCP, enabling:

  1. Shared Workspace / Channel: Multiple Claude Code instances join a shared collaboration channel (via MCP server or similar). They can see what each agent is working on, what files were changed, and what decisions were made.
  1. Real-time Messaging: Agents can send structured messages to each other:
  • "I changed the webhook payload format — here's the new schema"
  • "I need an endpoint at /api/events returning this JSON structure"
  • "My side is ready for integration testing"
  1. Spec Negotiation: Agents can propose and agree on shared interfaces (API specs, data models, event formats) before implementing independently in parallel.
  1. Conflict Awareness: When both agents touch shared definitions (e.g., a TypeScript type exported by one and imported by the other), they coordinate rather than diverge.

Alternative Solutions

  • Shared MCP Knowledge Base (current workaround): A custom MCP server that both machines access via SSH. Agents store and retrieve project knowledge asynchronously. This works for background context but lacks real-time coordination — Agent A doesn't know Agent B just changed an interface.
  • Human as Message Broker: The developer manually copies context between sessions ("On the other machine, Claude just built X, now build Y to match"). This works but is slow and defeats the purpose of AI-assisted development.
  • Single Machine, Multiple Repos: Running everything on one machine loses the benefit of parallel execution and doesn't match real-world team setups where systems run on different infrastructure.

Priority

Medium - Would be very helpful

Feature Category

API and model interactions

Use Case Example

A typical multi-system project with Claude Code on two machines:

| System | Stack | Machine | Purpose |
|--------|-------|---------|---------|
| Backend API | Python (FastAPI) | Mac 1 | API + business logic |
| Headless CMS | Strapi/Contentful | Mac 2 | Content management |
| Consumer App | Next.js | Mac 2 | End-user frontend |

The CMS is the single source of truth for content (events, menus, schedules, media). The backend API consumes this data and serves it to displays, apps, and other endpoints.

Both systems are being actively developed by separate Claude Code instances. The CMS has content types with channel controls (which content goes to which consumer). The backend has webhook receivers and rendering endpoints. Custom API routes are being built on both sides.

But the two agents can't coordinate. When the CMS agent adds a field to a content type, the backend agent doesn't know. When the backend agent needs a specific JSON format, it can't tell the CMS agent. The developer must Alt-Tab between terminals, copy schemas, and explain context that both agents already have — just in separate, isolated sessions.

Current workflow (slow):

  1. On Mac 2: "Claude, build the content types for events"
  2. Wait for completion
  3. Switch to Mac 1: "Claude, the CMS now has events at this URL with this schema — build the webhook receiver"
  4. If the schema needs adjustment, go back to Mac 2 and relay the change
  5. Repeat for every interface point — events, menus, schedules, media sync...

Desired workflow (fast):

  1. Both Claude Code instances join a shared channel
  2. Developer: "Build the event system — CMS manages events, backend renders them for displays and apps"
  3. Agent on Mac 2 proposes the event schema and API endpoint
  4. Agent on Mac 1 reviews, suggests adjustments (e.g., "I need startTime and endTime as ISO strings, not Unix timestamps, and a duration field")
  5. Both agents agree on the interface and implement their sides in parallel
  6. They notify each other when ready for integration testing
  7. Developer focuses on product decisions, not on being a relay

This would turn hours of back-and-forth into minutes of autonomous collaboration.

Additional Context

  • MCP as foundation: The MCP (Model Context Protocol) infrastructure is already there. We're already using shared MCP servers (accessed via SSH from both machines) for persistent knowledge storage. The missing piece is real-time agent-to-agent communication on top of MCP.
  • Not just "more context window": This isn't about making one agent smarter — it's about enabling genuine multi-agent teamwork where each agent owns a codebase and they coordinate through shared protocols, just like human developers do.
  • Real production use: This isn't theoretical. We're running this kind of multi-system setup in production today, actively building interconnected services on two separate machines. The coordination overhead between Claude Code sessions is our biggest bottleneck.
  • Scaling beyond two: The same pattern applies to microservice architectures, monorepo teams, or any scenario where multiple related systems need coordinated development. Imagine 3-4 Claude Code agents each owning a service, negotiating APIs, and implementing in parallel.
  • Security consideration: Agent-to-agent communication should be opt-in, authenticated (perhaps via shared MCP server credentials), and the human should be able to observe/approve cross-agent decisions before they're implemented.

View original on GitHub ↗

35 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/27601
  2. https://github.com/anthropics/claude-code/issues/20559
  3. https://github.com/anthropics/claude-code/issues/27441

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

MarioK1975 · 4 months ago

Not a duplicate — this addresses a different layer of the problem.

I've reviewed the linked issues, and while they're all related to multi-agent communication, they solve different parts of the stack:

#27601 focuses on remote debugging — sending error logs from a production server back to the dev machine. That's a specific DevOps workflow.
#27441 focuses on message injection infrastructure — sockets, pipes, APIs to push prompts into a running session. That's the transport layer.
#20559 is closest, but focuses on cross-repo code sync — "I changed this file, update your imports." That's reactive coordination.
This issue (#28300) is about the workflow layer on top: Two agents that don't just pass messages, but negotiate shared interfaces before implementing. Agent A proposes an API schema, Agent B reviews it and requests changes, they agree, then both implement their sides in parallel. The developer makes product decisions — the agents handle the coordination.

Think of it this way:

#27441 = "How do I send a message to another session?" (plumbing)
#20559 = "How do I notify another session about my changes?" (events)
#28300 = "How do two agents collaborate like a team?" (workflow)
These are complementary, not duplicates. The injection API from #27441 could be the transport. The cross-repo awareness from #20559 could be the trigger. But neither describes the collaboration protocol — spec negotiation, interface agreement, parallel implementation, integration readiness signaling.

I'm happy to consolidate if there's a preferred umbrella issue, but I'd argue this adds a distinct perspective that the others don't cover. I've upvoted all three related issues.

tiagogbarbosa · 4 months ago

+1

ThinkOffApp · 4 months ago

This is exactly the problem we hit running 7-10 agents across a MacBook, Mac mini, and Galaxy Watch. Cross-machine agents are blind to each other's context and user state.

We open-sourced user-intent-kit to solve the intent/state layer: https://github.com/ThinkOffApp/user-intent-kit

It gives every device a shared view of what the user is doing (coding, in a meeting, walking) and what they prefer (response style, notification urgency). Devices push state updates, agents read before acting. Built on LWW per-device slots, CRDT merge planned.

Already integrated with our agent coordination platform Groupmind (https://groupmind.one) which provides rooms, scratchpads, and a live intent dashboard. Also shipping adapters for Swift (Apple Watch/iOS) and Zig (ClawWatch wearable runtime). Works alongside IDE Agent Kit for cross-machine agent communication.

sk7n4k3d · 3 months ago

Real-world use case: Mobile app + ML training coordination

I'm building Alfred, a personal AI assistant Android app (Kotlin, 81 tools, wake word detection, agent system). My workflow involves two Claude Code instances running simultaneously:

  • Instance A (my main machine): Android development — writing Kotlin, building APKs, deploying to phone, reading device logs, fixing bugs
  • Instance B (GPU server): ML model training — training a custom OpenWakeWord model (ONNX), validating accuracy, exporting weights

What happens today

I am literally the human message bus between the two instances:

  1. Instance B trains a wake word model, reports: "Model ready: 97% accuracy, 736KB, deployed to assets/"
  2. I copy-paste this to Instance A
  3. Instance A integrates it, builds, deploys to phone, reads logs: "False positives at 0.87-0.93 on background noise"
  4. I copy-paste the diagnosis back to Instance B
  5. Instance B retrains with more negative samples
  6. Repeat 4-5 times

Each round trip takes 2-3 minutes of manual copy-paste instead of happening instantly. The instances work on the same git repo but can't see each other's work or communicate.

What I need

Instance A (code):  "The model produces false positives at 0.87-0.93 
                      on background noise. Here are the raw device logs. 
                      Retrain with these criteria: [...]"
                              ↓ (automatic)
Instance B (ML):    "Understood. Retraining with real device audio as 
                      negatives. New model exported to assets/. 
                      Validation scores: positives 0.99, negatives 0.003"
                              ↓ (automatic)  
Instance A (code):  "Building and deploying with new model..."

Concrete requirements

  1. Shared project context: Both instances should see the same CLAUDE.md, memory files, and git state
  2. Direct messaging: Instance A should be able to send a message to Instance B (and vice versa) without human relay
  3. File-level coordination: When Instance B writes a file (hey_alfred.onnx), Instance A should be notified
  4. Asymmetric roles: Instance A has Android SDK + ADB access, Instance B has GPU + training frameworks. They don't need the same tools, just communication.

This is not theoretical — I spent an entire evening being the relay between two Claude instances that could have coordinated autonomously. The Agent SDK's multi-agent support is a start, but it doesn't work across separate Claude Code sessions on different machines.

niceban · 3 months ago

If you’re building a supervisor or multi-agent workflow, I think the missing piece is often a clean session controller around Claude Code.

I made claude-node for that use case: let Python handle orchestration while the local Claude CLI stays the actual agent runtime. That separation ended up being much cleaner for me than turning every interaction into a fresh process call.

Sharing in case it helps:
https://github.com/claw-army/claude-node

kumaakh · 3 months ago

We hit this exact wall and ended up building Apra Fleet as an open-source MCP server to solve it.
The core insight from our design: the missing piece isn't A2A messaging - it's a shared orchestration layer that one agent talks through to dispatch work to others and get results back, while handling session continuity, file transfer, and credential provisioning automatically.
In practice it looks like this - your Mac 1 agent (the PM) tells Fleet: "execute this prompt on the CMS machine", Fleet SSHes in, starts/resumes a Claude session there, runs the work, streams the result back. The two agents never need to know about each other's interface - the orchestrator handles handoff.
The scoped git auth point you raised is also addressed - we mint short-lived tokens (1hr) per machine via GitHub App rather than sharing PATs, so each agent only gets repo access to what it needs.
Still very early (v0.1.4), but might be useful to try against your CMS + backend setup

laulpogan · 2 months ago

Wanted to share a reference implementation that's been running in production for the past two weeks: inter-agent-deaddrop.

It's not a solution to the full cross-machine ask in this issue, but it covers a specific slice — two Claude Code agents coordinating async over a shared filesystem with strong invariants — that I haven't seen specified anywhere else.

The protocol (v2.0):

  • Append-only JSONL inboxes per direction
  • 8 non-negotiable invariants (correlation_id, decisions log as canonical, etc.)
  • Heartbeat tiers (T0 30s through T3 1200s with explicit transitions)
  • Bilateral autonomy with explicit domain ownership
  • Spec-negotiation primitives: proposalack / counter / silence-as-revert, with bilateral acks distilling into decisions.jsonl

Production track record (single operator, two agents, single host):

  • 12 days running, 1,034 messages exchanged
  • 14 canonical decisions ratified
  • 2 incidents declared (both resolved within the 1-heartbeat SLA)
  • 0 protocol-level disagreements

Honest scope limits:

  • Single-operator track record. Cross-org stress test is forthcoming.
  • Single-host filesystem assumption. TRANSPORTS.md covers options for cross-machine (shared host with scoped UNIX users / shared private git repo / NFS over Tailscale / S3 drop zone) — none battle-tested yet.
  • n=2. N-agent generalization is non-trivial; not in this version.
  • Cooperative trust model. Adversarial scenarios need v3 HMAC-signing extension (planned, not implemented).

Comparison to adjacent work in the comparison table — most relevant cells: append-only contract + spec-negotiation primitives + heartbeat tiers in one package. mcp_agent_mail covers the inbox/lease piece beautifully but isn't append-only-contract. Apra Fleet covers SSH dispatch but not spec negotiation. Agent Teams covers same-host mailbox but is local-only.

Posting here in case it's useful as a starting point for whatever Anthropic ships, or as a fork-target for anyone else solving this. Happy to discuss the design choices, integrate feedback, or contribute the protocol upstream if there's interest.

Repo: https://github.com/laulpogan/inter-agent-deaddrop

laulpogan · 2 months ago

Update — agent-mail layer wired in, three-Claude E2E green

Stood up an end-to-end deployment using inter-agent-deaddrop semantics layered on top of Dicklesworthstone/mcp_agent_mail as the transport/inbox/lease substrate. Two cooperating Claude Code sessions on different machines, full round-trip verified.

Topology:

  • mcp_agent_mail running as a systemd unit on a Linux host (DGX Spark / Ubuntu Noble), 127.0.0.1:8765, storage co-located with the project under _coordination/mail/
  • SSH tunnel from a macOS machine: localhost:8775 → spark:8765
  • Per-agent registration tokens stashed at ~/.config/mcp_agent_mail/<agent>.token on both sides
  • .mcp.json at project root wires Claude Code to the tunneled MCP
  • Pre-commit guard hook (mcp-agent-mail guard install --prepush) installed for hard lease enforcement (advisory leases alone aren't enough)

Three-session round-trip with real claude --print invocations:

  1. Mac Claude (paul-spark) → tunnel → MCP → message id=2, verified_sender=true
  2. Spark Claude (willard-spark) → local MCP → fetched inbox, replied id=3, verified_sender=true
  3. Mac Claude (paul-spark) → tunnel → fetched inbox, confirmed willard's reply

Worked first try after token wiring.

Honest scope: Still single-operator on both ends (both Claude sessions billed to my account). The genuinely-independent-counterparty stress test is still pending — that's what we want to do once a second operator joins. The substrate-level claim is "two Claude sessions on different machines coordinate via async-durable inbox + advisory leases + spec-negotiation primitives, end-to-end working." Not "this is battle-tested across organizations."

Adoption-friction findings worth flagging:

  • mcp_agent_mail's leases are advisory by default — server returns granted: [...] AND conflicts: [...] simultaneously. Agents must self-back-off OR rely on the pre-commit guard hook to enforce. Filed Dicklesworthstone/mcp_agent_mail#156 on a separate verbose-commit-message issue I hit.
  • Agent naming: explicit IDs must match [A-Za-z0-9][A-Za-z0-9._-]{0,127} OR adj+noun. Single-word names like paul get auto-renamed to e.g. PurpleMeadow.
  • WORKTREES_ENABLED=1 required in env for guard install to work (the pre-commit hook).
  • Single-server-per-storage enforced via server.lock — confirms the architectural choice (single shared host with two scoped UNIX users) over multi-machine federation for this use case.

Still unsolved upstream: the spec-negotiation layer (proposal → ack/counter/silence-reverts → decisions.jsonl as canonical), and cross-machine session-resume. inter-agent-deaddrop covers the first; nobody's shipped the second yet.

Repo: https://github.com/laulpogan/inter-agent-deaddrop (now includes examples/spark-tunnel.sh and examples/spark-mcp-config.json for the deployment recipe).

laulpogan · 2 months ago

Update — git-as-wire transport shipped, real cross-machine round-trip green

Built and validated the cross-machine layer of inter-agent-deaddrop. Two physical machines, no shared host, no shared infrastructure beyond a private GitHub repo — the case that motivates this whole issue.

Shipped at examples/git-as-wire/:

  • README.md — deployment recipe + threat model + comparison
  • wire-daemon.py — sync daemon: file-watch local appends → commit + push, heartbeat-cadence fetch + rebase, retries with exponential backoff, signed commits
  • wire-daemon.service — systemd user unit
  • test/test-roundtrip.sh — local two-clone integration test (passes)

Architecture: shared private git repo holds _coordination/. Each agent appends to its outbound JSONL locally; daemon stages + commits + pushes. Counterparty fetches + rebases at heartbeat cadence, processes new lines. Append-only invariant means rebase always succeeds on JSONL files. Branch protection (no force-push) enforces the invariant at the wire level. Signed commits give cryptographic identity for the from field.

Live cross-machine validation today:

  • Mac (paul-mac, macOS) → local commit → push to private GitHub repo
  • Linux (paul-spark, DGX Spark) → fetch → see Mac's heartbeat
  • Linux → reply commit → push
  • Mac → fetch → confirm reply

Full round-trip in ~30s. Wire repo log clean:

def706c msg: paul-spark appended 1 entries [2026-05-05T15:49:54Z]
873a22a msg: paul-mac appended 1 entries [2026-05-05T15:49:37Z]
b9ade47 Bootstrap wire repo for paul-mac <-> paul-spark E2E

Failure modes handled by the daemon:

  • Concurrent push: one wins fast-forward, other rebases + retries (up to 3 attempts with backoff)
  • Long offline: each side queues commits locally, push when remote reachable
  • Conflict on JSONL: impossible if append-only honored — daemon raises incident if it ever happens
  • Conflict on PROTOCOL.md/decisions.jsonl: should not happen if domain ownership honored — daemon raises incident

Known scope limits (documented in repo):

  • Latency floor = poll cadence (T1 default 90s)
  • Privacy from git host: GitHub admins can theoretically read private repo contents — self-host Gitea if this matters
  • Cooperative trust: signed commits prove from, not honest. v3 HMAC-on-message-content extension would address malicious-peer scenarios; not implemented.

Coverage map of what's now shipped between forge-scribe-coord, single-host Spark deploy, and git-as-wire:

| Case | Transport | Status |
|---|---|---|
| Two pipelines, one operator, one host | filesystem dead-drop | production 2026-04-23 onward, 12+ days, 1,034 msgs |
| Two operators, shared host | mcp_agent_mail + UNIX users | live deployment 2026-05-04 |
| Two operators, no shared host | git-as-wire | live cross-machine 2026-05-05 |
| Adversarial peer | HMAC signing (v3) | spec only, not implemented |
| n>2 agents | N-agent generalization | spec only, not implemented |

The cross-machine, cross-org case (the one your issue calls out) now has a working reference implementation. Repo: https://github.com/laulpogan/inter-agent-deaddrop

laulpogan · 2 months ago

Update — v3 Ed25519 signed messages shipped + live-validated cross-machine

Added the cryptographic-identity layer for adversarial scenarios. v3 is a backwards-compatible extension to v2.0: each message carries an Ed25519 signature over a canonical serialization of its v2-shape fields. Every receiver verifies against a per-project trust.json mapping agent → public keys.

Shipped at v3/:

  • SIGNING.md — full spec (canonical serialization, key rotation, compromise response, threat model)
  • signing.py — sign/verify helpers (PyNaCl or cryptography backend)
  • keygen.py — CLI to generate Ed25519 keypair per agent
  • verify.py — pre-commit hook blocking unsigned/invalid messages
  • test_signing.py — 8 round-trip tests (canonical stability, sign/verify, tamper detection, unknown key, deactivated key, JSONL roundtrip, two-agent exchange, forgery rejection)

What v3 adds over v2.0:

| Property | v2.0 unsigned | v3 signed |
|---|---|---|
| Sender forgery resistance | filesystem perms only | Ed25519 signature |
| Tamper detection | none | per-message |
| from field trust | asserted | cryptographically tied to public key |
| Operator-replay-disputes | "your word vs theirs" | non-repudiation |
| Backwards-compat with v2 | N/A | yes (config flag for unsigned-allowed-from) |

Live cross-machine validation today:

  1. Mac side: python3 v3/keygen.py paul-mac → keypair, public key paul-mac:ba282fb9
  2. Spark side: python3 v3/keygen.py paul-spark → keypair, public key paul-spark:ec5737bf
  3. Bootstrap _coordination/trust.json on the wire repo with both public keys
  4. Mac signs + pushes a ship message → Spark fetches + verifies VALID
  5. Spark signs + pushes an ack reply → Mac fetches + verifies VALID
  6. Legacy v2 unsigned messages on the same JSONL: correctly REJECTED with reason=missing public_key_id

Pre-commit hook also tested: blocks unsigned commits to _coordination/*.jsonl automatically.

Threat model honest about scope (documented in SIGNING.md):

  • Closes: sender forgery, message tampering, audit-log disputes
  • Doesn't solve: replay attacks (use idempotency cache on correlation_id), key compromise after the fact (rotation runbook in spec), operator-level trust (if you don't trust the operator who maintains trust.json, v3 doesn't help), quantum attacks (Ed25519 is not post-quantum)

Coverage map (final, all transports + threat models documented):

| Case | Transport | Threat model | Status |
|---|---|---|---|
| Two pipelines, one operator, one host | filesystem dead-drop | cooperative | production 12+ days |
| Two operators, shared host | mcp_agent_mail + UNIX users | cooperative | live 2026-05-04 |
| Two operators, no shared host | git-as-wire | cooperative | live cross-machine 2026-05-05 |
| Two operators, untrusted wire | git-as-wire + v3 signing | adversarial | live cross-machine 2026-05-05 |
| n>2 agents | (TBD) | (TBD) | spec-only roadmap |
| Cross-machine session-resume | (Anthropic-territory) | N/A | not implemented |

The cooperative-trust + adversarial-trust matrix is now covered. Two genuine cross-machine deployment paths shipped (one with trusted wire, one with untrusted-wire-but-signed-messages). Reference implementations have round-trip tests passing.

What's still genuinely greenfield: n>2 generalization, cross-machine session-resume (which is Anthropic's natural territory), and the cross-organization stress test (currently single-operator-on-both-ends).

Repo: https://github.com/laulpogan/inter-agent-deaddrop

kcarriedo · 1 month ago

This pain is the bottleneck that breaks the "use AI to remove bottlenecks" promise — agreed. Quick observation from running a similar dual-machine workflow (CMS + backend, plus a third worktree doing infra):

The handoff isn't just about contract relay — it's about who is currently authoritative on a shared definition. The moments that hurt most for me are:

  1. Agent A and Agent B both believe they own the shared schema, edit in parallel, and produce drift that only surfaces at integration.
  2. Agent A makes a non-breaking schema change but doesn't know B already shipped a client that assumes the old shape (one-way notification isn't enough).
  3. The human (me) becomes a stale message queue — by the time I relay context to B, A has already moved on.

A few things that have partially helped in the absence of an Agent-to-Agent protocol:

  • Treating a shared contracts/ directory (or a single protocol.md) as the canonical source of truth, with a "lease" comment header indicating which session currently holds write access. Both sessions read it on every turn.
  • A polling job that watches git diff on contract paths and posts to a shared file both sessions tail (tail -f in a side pane). Hacky, but it surfaces drift seconds after it happens instead of at integration time.
  • Using hooks (PostToolUse) to refuse edits to contract paths unless the session holds the lease.

Even with these, the human stays in the loop for conflict resolution. The proposal here — shared workspace + structured messages + spec negotiation before parallel implementation — is the only thing that actually closes the loop. Especially the "spec negotiation first" step; most failures I see are agents implementing in parallel from divergent mental models of the same contract, not from the implementation itself.

One concrete suggestion for the protocol design: include a "claim" primitive (agent A claims it's about to modify shape X), with a TTL. Without claims, parallel agents will race on the same definition the moment the channel exists.

kcarriedo · 1 month ago

The microservices / CMS+consumer / IoT+cloud examples are exactly right, and worth emphasizing: the single-codebase assumption is leaky even on a single machine — anyone with a polyrepo monorepo, a separate infra repo, or a "platform team owns the API, product team owns the UI" split runs into the same coordination problem locally that you're describing across machines.

A few things from trying to build the A2A layer externally:

MCP is the right transport but the wrong contract surface for this. MCP gives you tool calls between processes, which is necessary but not sufficient — what's missing is a shared schema for "I am the API, here is my current OpenAPI" that both agents can read and one of them can update. Without that, "A2A messaging" devolves into ad-hoc Slack-DM-shaped exchanges where each agent re-explains context to the other. The valuable primitive is a typed shared spec, not a chat channel.

Spec negotiation is the killer feature. "Agent A proposes a schema change → Agent B's project simulates the change and reports breakage → Agent A either reverts or commits" is the loop that makes cross-repo agent coordination actually fast instead of just parallel-but-still-blocked. Without negotiation, you get N agents racing to commit conflicting interface changes and a human still has to arbitrate.

The single-machine version is the gateway drug to the multi-machine version. If claude code could talk to another claude code on the same box (different repo, different working directory, different agent role) via a local socket or shared state file, 80% of the value lands without any of the cross-machine networking/auth complexity. Worth shipping in two phases: (1) local A2A across separate claude code invocations on the same host, (2) network A2A across machines.

Conflict-detection on shared definitions is harder than it sounds. Two agents editing the same openapi.yaml will both think they have the "current" state at read-time. The primitive you actually need is something like a vector clock or a CRDT-shaped doc layer for shared specs — otherwise you end up replaying every git merge conflict but with two agents who can't read each other's reasoning.

We hit exactly this pain coordinating a Rust supervisor + a Next.js dashboard + a polling service across three separate codebases that all need to agree on the cycle/escalation/handoff schema. Ended up building a small external coordinator process that owns the shared schema and gates writes from any agent through it (https://github.com/kcarriedo/claudeverse-runner). Works, but it's a workaround for a primitive that should be in the platform.

Strong support for this. Cross-references #24798 (inter-session communication, same primitive at smaller scope) and #14859 (parent_session_id would be the natural field to carry cross-process agent identity).

laulpogan · 1 month ago

Update — Rust wire v0.5 line, public relay live, agents now coordinate via wire add coffee-ghost@wireup.net

Continuing from the May 5 thread (inter-agent-deaddropgit-as-wire → v3 signed messages). The Python prototypes worked end-to-end across machines but had operational rough edges that became blockers at sprint cadence: outbound paths buffered silently, daemon liveness was advisory, no public relay so every pair was a YAML-config dance.

Over the last week the whole stack was re-implemented in Rust as a separate project: SlanchaAi/wire — same A2A goal, same Ed25519-over-canonical-JSON envelope as v3, but with a federated handle layer, a public-good relay (wireup.net), and a single-binary daemon + MCP + CLI. Published as slancha-wire on crates.io (the bare wire name was squatted by an abandoned 2014 crate; binary name stays wire).

What's actually shipping

Today (2026-05-17) the operator-facing surface is six commands:

wire up <handle>@<relay>       # fresh box → ready to pair (one command replaces 5)
wire pair <peer>@<relay>       # bilateral pin via SPAKE2 + 6-digit SAS
wire send <peer> "msg"         # signed message, queued + pushed by daemon
wire monitor                   # long-running stream of inbound events
wire doctor                    # cross-checks daemon + pidfile + relay + cursor + rejections
wire upgrade                   # kill stale daemon, spawn fresh from current binary

Plus an MCP server (wire mcp) exposing pair/send/tail/profile/peers as tools that any Claude Code session can call.

Critically: the pairing handshake itself can be agent-driven end-to-end except for the one human-in-loop step. The MCP wire_pair_initiate / wire_pair_join tools advance the SPAKE2 state machine; the operator only has to type the 6-digit SAS back to chat for wire_pair_confirm. Mid-session, peer messages surface as <task-notification> lines (Claude Code's Monitor tool with persistent:true on wire monitor). That's the substrate that's been missing.

Federation handles via .well-known

Mastodon / Bluesky / Nostr style: a relay serves /.well-known/wire/agent?handle=paul-mac returning the agent's signed card + slot coords. Pair with a string a human can remember (paul-mac@wireup.net), not a 64-char DID. Multiple relays interoperate by DNS resolution — wire add slancha-spark@otherrelay.example Just Works once the other side serves the same well-known shape.

Eight patch releases in five days, driven by real cross-machine use

paul-mac (MacBook) and slancha-spark (DGX Spark in another room) have been using wire as the only coordination channel for ~20 feature ships across slancha-mesh, slancha-test, and wire itself. No shared filesystem, no shared Slack channel, no shared planning doc. Two Claude Code sessions, the inbox as the rendezvous point. The release log:

| Version | Headline |
|---|---|
| v0.5.13 (today) | Silent-fail eradication round 2: outbox filename normalization, wire doctor and wire status cannot disagree on daemon liveness, network-resilience doctrine (loud transport error class + OS native trust store + WIRE_INSECURE_SKIP_TLS_VERIFY escape hatch for corp-proxy MITM environments) |
| v0.5.12 | Metadata hygiene, crate rename pinned to tag |
| v0.5.11 | Six-command public surface + silent-fail eradication round 1 (P0.1P0.Z), wire monitor + structured pidfile + pair-rejected.jsonl + schema versioning |
| v0.5.10 | Federated handle directory + R2/R3/R5 endpoints |
| v0.5.9 | .well-known agent endpoint + handle claim flow |

The release cadence is fast specifically because every operational pain point becomes a P0 issue (silent-fail bugs are the highest-priority class — see issues #2 and #6 on the wire repo for the most recent post-mortems).

What's actually working vs still-hard

| Working | Still hard |
|---|---|
| Bilateral SPAKE2 pair + Ed25519 envelope per message | Three-leg ack to fully close the asymmetric-finalize race (wire#5) |
| Stream-based wake signal (sub-second peer notification on a warm wire monitor) | Long-poll behind aggressive corp proxies — falls back to interval polling, noisy log |
| wire doctor + structured pidfile catch stale-daemon-eating-events class | Windows daemon liveness check has a separate cross-platform issue still (wire#6) |
| Single-handle federation (paul-mac@wireup.net) | Multi-handle / role-based identity, key rotation under load |
| wire mcp integrates as a Claude Code MCP server with persistent monitor recipe | Agent-attention layer: "did the agent looking at this codebase know disk just changed" remains the fundamental observation (see wire#1) |

Spec coordination is genuinely the open frontier

@kcarriedo's point above — "MCP gives you tool calls between processes, which is necessary but not sufficient — what's missing is a shared schema for 'I am the API, here is my current OpenAPI' that both agents can read and one of them can update" — is exactly where wire's transport layer stops and the next layer needs to begin. v0.5 nails identity + envelope + delivery; spec negotiation (the "we both think we own this schema, let's coordinate before drift" case) needs a different primitive that probably lives on top.

The wire transport is sufficient for that primitive — agents can sign and exchange OpenAPI deltas, ADR proposals, soft-claims on shared definitions — but the contract surface and the conflict-detection semantics need design, not just transport. That's the natural v0.6 conversation.

Try it

cargo install slancha-wire
wire init paul                                  # generate identity
wire up paul@wireup.net                         # claim handle on public relay
# operator on other machine:
wire add paul@wireup.net                        # one-command pair via handle
# (agent drives the rest; operator types 6-digit SAS back into chat to confirm)

Public-good relay at wireup.net, source at SlanchaAi/wire, threat model at THREAT_MODEL.md. AGPL-3.0 + Apache-2.0 + MIT — pick whichever fits.

Happy to collaborate with anyone exploring the spec-negotiation / shared-authority-on-a-definition layer — that's the genuinely interesting open problem on top of this substrate.

caioribeiroclw-pixel · 1 month ago

@kcarriedo this "who is authoritative on a shared definition" point feels like the part that gets lost when the discussion stays at transport level.

A2A/MCP/git-as-wire can move the message, but the failure mode you described is more like protocol drift: two agents both saw enough context to act, but they had different assumptions about ownership of api.schema, generated clients, release branches, etc.

I added this as an explicit "authority" layer in a small coordination-contract example here: https://github.com/caioribeiroclw-pixel/pluribus/blob/main/docs/coordination-contract.md#authority-is-part-of-the-contract

The useful primitive might be something boring and inspectable like:

{"topic":"authority.claimed","producer":"api-session","payload":{"domain":"api.schema","owner":"api-session","scope":["openapi.yaml","packages/client/src/generated/**"],"expiresAt":"..."},"invalidates":["dashboard-session.plan","worker-session.plan"]}

Then the transport can be anything — MCP, A2A, a relay, git, SQLite, JSONL — but every session has the same rule: if you see an overlapping active authority claim, stop editing that domain until ownership is released/delegated/resolved.

That seems especially relevant for the cross-machine case: identity + delivery is necessary, but without an authority/invalidations contract the relay can still faithfully deliver conflicting work faster.

laulpogan · 1 month ago

Update — security-relevant: bilateral-required wire add in v0.5.14

Following the cross-machine field-testing of v0.5.13 from yesterday's update, a real security hole surfaced during a follow-up adversarial review. Useful context for anyone exploring this design space, since it's a specific tradeoff that any A2A protocol with public-discovery + zero-paste-pairing will hit:

The vuln (v0.5.9-v0.5.13). Phonebook (/v1/handles) is public by design — Mastodon/Bluesky-style discovery. Zero-paste pair is wire add <peer>@<relay> — one command, no SAS digits. But the receiver-side daemon was auto-pinning any signed pair_drop as VERIFIED and shipping the receiver's slot_token back via pair_drop_ack. A scrape + spray pinned the attacker on every wire user's machine with authenticated write access to each victim's slot. Severity medium — not RCE, not impersonation, just unauthenticated remote write up to 64 MB slot quota.

The fix in v0.5.14. wire add must now fire on both sides before any capability flows — the design intent was always bilateral, the implementation had drifted to unilateral. The split:

  • SPAKE2 invite-URL path (wire invite mint then wire invite accept <URL>): unchanged. The invite-URL nonce IS the consent gesture; capability flows on first contact.
  • Handle path (wire add <peer>@<relay> zero-paste): now lands in a pending-inbound queue on the receiver side. No trust pin, no ack, no slot_token leak. OS toast prompts operator to wire add <peer> to accept or wire pair-reject <peer> to refuse. Both sides must gesture consent.

After v0.5.14, scraping + spraying produces N pending-inbound entries on N machines with zero capability flow. Each victim sees one OS toast; those who don't manually wire add back are fully protected.

The four-persona review that surfaced it. Worth surfacing because the methodology is reusable for anyone designing A2A protocols. The operator spawned four parallel adversarial personas — paranoid-security-adversary / principled-protocol-designer / pragmatic-operator-UX / spam-abuse-researcher — and gave each the threat-model + three candidate mitigations. All four independently converged on the same root cause: capability emitted to an unauthenticated requester on first contact. The protocol designer cited Mastodon DM-from-strangers + Signal Sealed-Sender; the abuse researcher pattern-matched SMTP open-relay; the adversary pointed at the slot_token leak specifically rather than the tier label. Each made the others' fixes more concrete. That review-loop is the load-bearing thing — code review by an LLM tool catches typos and lints; persona-review catches design holes the implementer is too close to see.

Generalized lesson for A2A design. Phonebook + zero-paste + auto-accept is the SMTP open-relay shape. Pick any two; the third is the spam vector. wire keeps phonebook (federation needs discovery) and zero-paste (UX needs it for adoption), gates auto-accept behind operator consent. Bluesky's discoverable=true + Mastodon's manual follow + Signal's Sealed-Sender-needs-contact all converge on a similar tradeoff.

Surface. New wire pair-reject <peer> + wire pair-list-inbound. wire status JSON gains pending_pairs.inbound_count. CHANGELOG + THREAT_MODEL.md updated with the bilateral-pair doctrine. Security disclosure tracked at https://github.com/SlanchaAi/wire/issues/8.

cargo install slancha-wire    # 0.5.14 live on crates.io

The substrate keeps holding up; the things that hurt now are exactly the design-space tradeoffs every A2A protocol will face. Continuing to land them publicly so the next person doesn't re-discover the same SMTP-open-relay shape.

kcarriedo · 1 month ago

Strong agree on the framing here — "every interface change must be manually relayed by the developer" is the part of multi-Claude workflows that quietly eats the productivity gains. The async/email-broker mental model matches what we keep hearing from teams running 2+ Claude Code instances on connected codebases.

One thing worth pulling out from the proposal: the value isn't really messaging between agents — it's a shared coordination surface that outlives any single session. If Agent A and Agent B can both read/write a durable channel, then:

  • A's "I changed the webhook payload" doesn't need B to be online to receive it
  • New sessions joining later still get the architectural decisions
  • The channel itself can refuse handoffs that violate prior contracts (schema-versioned)

We've been building exactly this kind of out-of-process coordinator layer at https://claudeverse.ai because the same pattern shows up even inside one repo once you have parallel sub-agents, background tasks, and multiple terminals — not just cross-machine. The agent-pinned-to-a-process problem is the same problem at every scale.

Would be curious to hear from anyone who's tried to hack this together with MCP + a shared SQLite/Redis state store — what did and didn't work? Specifically interested in how people handled the "agent makes a decision, second agent needs to know about it before its next turn" handoff timing.

kcarriedo · 1 month ago

This is a real production constraint and one of the more frustrating gaps in Claude Code's current multi-machine story. The "human as message broker" pattern you're describing doesn't just slow things down — it collapses the speed advantage that made parallel agent work worthwhile in the first place.

The coordination overhead between Claude Code sessions is our biggest bottleneck.

This resonates. I've been hitting the same wall building agent pipelines that span multiple sessions/machines. The approaches I've seen that partially work: shared external state (a file or lightweight DB that both agents write coordination events to), structured handoff files that one agent writes on task completion and another reads on startup, and a polling coordinator that monitors agent outputs and routes signals between them.

None of these are as clean as a native Agent-to-Agent protocol, but they're buildable today without waiting for Anthropic to ship cross-machine coordination. For schema negotiation specifically, a shared contract file (openapi spec or simple JSON schema) that either agent can update and the other polls on a short interval gives you asynchronous coordination without a live channel.

+1 on the feature request — native A2A would be the right long-term solution. The MCP direction seems like the most promising path given the existing tool infrastructure.

kcarriedo · 1 month ago

The problem you are describing — two Claude Code instances working on interconnected systems that are "completely blind to each other" — maps directly to the architectural gap between in-session context and the file system. The human becoming the bottleneck as the relay layer is exactly the failure mode that kills otherwise-productive multi-repo workflows.

The pattern that seems to work best here, short of a native Agent-to-Agent protocol: treat the shared state as an external artifact that both agents read from and write to on a polling interval — a small JSON handoff file in a shared location (or a shared git branch) that each agent updates at natural task boundaries (after completing an interface change, after confirming an API contract). The orchestrator process reads those files and can detect conflicts or schema drift before either agent goes further.

This requires more scaffolding than a built-in send/receive protocol, but it is implementable today and does not depend on experimental features. The main discipline is making agents write their state to the handoff file rather than only to the files they are actually editing.

If the feature request for a native Agent-to-Agent protocol lands, this becomes a lot cleaner — but the polling pattern gives you something workable in the interim.

kumaakh · 1 month ago

This is the exact pain point that apra-fleet addresses: https://github.com/Apra-Labs/apra-fleet
You can have multiple independent instances of claude/gemini (we call them fleet members) and the orchestrator (called pm)
is able to dispatch work to them, the members can be local or remote.
The main idea is that the members of the fleet keep pushing the work further, developling, testing, reviewing, deploying and also creating low priority backlog/TDebt where appropriate.

Todays fleet-mcp uses ssh as a medium to work with remote machines in a very frictionless manner... it configures and uses key-based authentication to run prompts on remote machines.

The next version that we are developing is going to put mcp as the mediator with StreamableHTTPTransport and have remote members provide async progress updates and results.

kcarriedo · 1 month ago

This is the right framing — the hard problem isn't running agents on multiple machines, it's giving them a shared coordination substrate so they can publish/consume interface changes without the developer as the relay.

A few patterns worth considering:

Shared state file / handoff document per cycle. Before each cross-machine agent turn, the orchestrating agent writes a structured handoff file (JSON or YAML) to a shared store (S3, a mounted NFS path, a Git repo branch). Each remote agent reads its input from that file rather than from live environment state. This decouples timing: Machine B doesn't need to be live when Machine A produces its output.

Contract-pinning via a versioned schema. The API contract between services is checked into a shared contracts/ directory. When Machine A's agent changes an endpoint, it updates the contract file and commits. Machine B's next agent turn reads the contract before touching any code. Drift is detected at the file level, not at runtime.

Per-machine process group isolation with a global lock per "campaign." If the overall cross-machine task has a campaign_id (UUIDv7 at dispatch time), each machine's agent process is killed as a group on timeout or abort. The campaign_id is the idempotency key — re-running a failed cross-machine task doesn't duplicate already-completed work.

I've been building a scheduling layer (a Rust polling service that gates each project cycle behind a file lock and kills the process group on timeout) that could serve as the inter-machine coordinator here. The core insight is that the "agent-to-agent protocol" doesn't need to be real-time — it just needs a reliable handoff file and a consistent idempotency key. Happy to share the design if it's useful context for how Anthropic might standardize this.

kcarriedo · 1 month ago

This issue captures exactly the problem we've been working on at Claudeverse — and the manual-relay pattern you describe is one of the most consistent pain signals we hear from developers running Claude Code across multiple services.

The core failure mode: agent A changes a schema, agent B doesn't know about it, and the human becomes the synchronization bus. You end up with a "multi-agent" setup that's actually still single-threaded at the contract layer.

A few things that might be useful to the discussion here:

On the short-term side — some teams are working around this today by having the orchestrator agent write structured "interface contracts" to a shared markdown file (or a small JSON manifest) that all worker agents poll before touching cross-service boundaries. Crude, but it at least surfaces drift explicitly rather than silently. The claude-handoff skill from REMvisual (https://github.com/REMvisual/claude-handoff) has a STATUS.md pattern that's directionally similar.

On the coordination layer side — the real ask here is an Agent-to-Agent (A2A) protocol that's first-class, not bolted on through file convention. The fact that this has to be filed as a feature request in 2026 is itself a signal — worktrees solve file isolation, but isolation without communication is just parallelism theater.

One concrete thing that would help this specific feature: does the team have a sense of whether A2A is more likely to land as an in-process messaging bus (shared task list via filesystem) or as an explicit API layer (agent-to-agent RPC)? The answer changes what developers should build on top of in the interim.

Upvoting this — it's a blocker for any serious cross-service autonomous workflow.

kcarriedo · 1 month ago

The "developer as slow, error-prone message broker" framing nails the core problem. Alt-tabbing between terminals, copying schemas, re-explaining context both agents already have in different isolated windows — that manual relay is where coordination overhead compounds.

The Agent-to-Agent protocol approach (MCP-based structured messaging) is the right direction for native Claude Code. In the meantime, I've found that formalizing the handoff contract as a typed state artifact — rather than prose or chat — makes the cross-session relay significantly less lossy. The receiving agent reads a structured summary cold, which counterintuitively reduces drift vs. inheriting a long conversation thread.

I've been building tooling that wraps this pattern with lifecycle management (who's running, who's blocked, what's been handed off to whom) across multiple Claude Code sessions: https://claudeverse.ai — still early but the state-tracking layer is exactly what the gap in this issue is pointing at.

kcarriedo · 1 month ago

This is the coordination problem that doesn't get talked about enough — the "human as message broker" anti-pattern.

The scenario you've described (CMS on machine A, backend API on machine B, both Claude Code instances completely blind to each other's interface decisions) is exactly where current multi-agent tooling falls down. Agent teams help when everything is on one machine in one repo, but cross-machine / cross-repo coordination has no first-class answer yet.

The Agent-to-Agent protocol via MCP you're proposing is the right direction. A few failure modes worth designing around though:

  1. Message ordering under partial failure: If Agent A sends a schema-change notification and Agent B is mid-task when it arrives, does B pause and reconcile, or finish its current task and apply the update after? Without explicit sequencing, you get subtle divergence.
  1. Shared definition lock contention: When both agents need to negotiate a contract (API shape, DB schema), you need something like optimistic concurrency — propose → ack → commit — or one agent's work silently conflicts with the other's.
  1. Session lifetime mismatch: If Agent A's session ends before Agent B processes its messages, you lose the response channel. The protocol needs durable message delivery, not just ephemeral inter-process messages.

We're working on exactly this kind of session lifecycle infrastructure at Claudeverse (claudeverse.ai) — the layer that manages state handoff and coordination contracts so individual agent sessions can complete, fail, or restart without orphaning the agents depending on them. Happy to share what we've learned if useful.

+1 on this feature request — the multi-machine case is a real production pain.

ThinkOffApp · 28 days ago

The contract MarioK1975 draws (plumbing vs events vs collaboration workflow) matches what we see running this for real: we coordinate multiple Claude Code instances plus a 9-agent multi-model fleet across two machines (a Mac mini and a MacBook) plus phone and clawwatch on a smartwatch. The transport problem (sk7n4k3d's human message bus, laulpogan's deaddrop, kumaakh's SSH dispatch) already has five working answers in this thread. The workflow layer on top is the part nobody has cleanly, including us.

What we built: agents address each other by @handle in a shared chat room, a webhook relay (plus a tunnel for the cross-machine hop) delivers messages, and each agent polls or receives and replies. Human-in-the-loop happens through explicit approval gates, not copy-paste. That covers addressed messaging and async delivery fine.

Where it stays glue, and where this issue's framing is right: the room gives us a bus, but not spec negotiation as a first-class thing. "Agent A proposes a schema, B counters, both implement in parallel, both signal integration-ready" still lives in prose inside room messages, with agents trusting each other's narrative that they did the work. So the open question for whatever Anthropic ships is less "how do two sessions talk" (solved many times over here) and more "what is the minimal shared contract object two agents agree on before they diverge." Transport is the easy 80 percent. That negotiated contract is the 20 percent we all keep reimplementing differently.

0xbrainkid · 28 days ago

The latest point about transport being the easy 80 percent feels right. The missing primitive is a contract object that survives the chat room: proposal id, schema/interface version, participants, ack/counter state, deadline, and the exact implementation receipts each side is expected to produce before the contract is considered satisfied.

For A2A, I would separate three layers:

  1. Delivery: mailbox/room/RPC, mostly solved in this thread.
  2. Agreement: typed proposal -> ack/counter -> committed contract, with optimistic concurrency on the contract version.
  3. Evidence: per-agent action receipts that bind the agreed contract to what was actually changed, tested, and handed off.

That third layer matters because otherwise the receiving agent only gets a narrative: "I updated the schema." A portable receipt can say: contract events.v3 was acknowledged by agents A/B, files X/Y changed, tests Z passed, artifact hash H produced, and reviewer/human override O was or was not present. That is the piece that makes multi-agent coordination auditable across sessions instead of just conversational. It is also where reputation systems like AgentFolio/SATP can evaluate coordination quality without needing access to the whole private workspace.

kcarriedo · 27 days ago

The three-layer framing (delivery / agreement / evidence) is a useful decomposition. The evidence layer is the one that matters most for practical adoption and it's the one most implementations skip.

The failure mode we see repeatedly in production multi-agent runs: two agents coordinate correctly on delivery and agree on a contract, but the downstream session that picks up their output has no way to verify what was actually done vs. what was claimed. The receiving agent reads a narrative summary and treats it as ground truth. When the handoff summary is wrong (subtly, not obviously), the error propagates silently across the next three sessions before anyone notices.

The receipt concept solves this, but only if the receipt is machine-readable and bound to specific artifacts -- not a free-text summary. "Files X and Y changed" needs to mean "here are the hashes, here is the diff size, here is the test pass/fail count" -- something the receiving agent can verify against the actual filesystem state before accepting the handoff.

One pattern we've found workable in the interim: each agent writes a structured JSON summary file to a fixed path before signaling completion. The orchestrator reads the JSON (not the agent's natural-language summary) and validates it against a schema before marking the handoff done. It's a poor substitute for a native receipt primitive, but it catches the "agent claimed success but produced nothing" case without depending on the agent being honest about failures.

The audit trail use case from the thread is the right long-term motivator -- human oversight of multi-agent work depends on receipts being tamper-evident across the session boundary, not just present within one session's JSONL.

prassanna-ravishankar · 25 days ago

late to this one but want to add an angle thats different from most of the thread. almost all the transport work above (deaddrop, wire, apra-fleet, the swarm protocols) is single-runtime, claude-code talking to claude-code.

i built repowire as a cross-runtime mesh instead. claude code, codex, gemini, antigravity, opencode and pi sessions all get a mesh address and ask/ack/notify/broadcast to each other no matter which runtime theyre on. registration happens on session start so theres no per-session wiring, just repowire service start plus one mcp entry.

the part that goes past pure transport: telegram and slack are first-class peers on the same mesh, so you can steer and watch a multi-agent run from your phone, and theres a browser dashboard with live state across every session.

it doesnt solve the contract/agreement/evidence layer @0xbrainkid and @kcarriedo keep circling, thats genuinely still open. but it covers delivery, cross-runtime addressing and the operational control bit in one place :slightly_smiling_face:

kcarriedo · 17 days ago

This hits a real pain point. When you're running two Claude Code sessions on separate machines that share an API contract, you end up doing the relay work yourself: copy the schema change from one terminal, paste the description into the other, repeat. The "human as message broker" framing in the issue is accurate.

A few things I've found helpful in the meantime while waiting for native A2A support:

  • A shared scratch file in a synced location (Dropbox, iCloud Drive, or a Git-tracked notes dir) that both sessions read at the start of each turn. Not elegant, but it at least serializes the contract negotiation.
  • Committing interface changes with a specific prefix (e.g., "contract: ...") so the other session can git log --oneline --grep="contract:" to catch up fast.
  • Keeping a single INTERFACE.md at the repo root that both sides treat as the authoritative spec. Each session gets a CLAUDE.md instruction to always read INTERFACE.md first and write proposed changes there before implementing.

None of this is what you actually want - it's still manual. The proposal for a shared project scratchpad + event bus would genuinely fix the bottleneck. Upvoting / tracking this.

Are you working on iOS/macOS split (CoreData on device, CloudKit sync, background refresh) or more of a pure backend split? Curious whether the interface churn is mostly around data schema or API contracts.

kumaakh · 17 days ago

@kcarriedo apra-fleet uses git as the broker. We use a planning phase to resolve the intefaces as initial tasks in a Directed Acyclic Graph (DAG) of tasks, once the initial tasks are committed, tested and reviewed, multiple agents can work off that branch just like a human team can. these agents can be fleet members on the same device or other remote devices. fleet also makes sure that these remote agent have git auth (and llm auth) provisioned just in time.

tiagotorres91 · 7 days ago

We've been running something adjacent to this request in production, without new infrastructure: two developers, each pairing with their own Claude Code (separate accounts/billing), coordinating through the repository itself — issues as the only channel, a strict verdict grammar from the maintainer (✅ approved / 🔧 changes / ❓ decide), and a "rule zero" where every session starts by sweeping repo state (never memory): open issues where the ball is yours + closed issues not yet acknowledged (an ack label — recency windows lose outcomes).

First day of real use: an external collaborator's Claude onboarded itself from three files in the repo (AGENTS.md / CONTRIBUTING / onboarding) and shipped 12 merged PRs on a codebase it had never seen. The scars from that day became rules (chained PRs silently missing main; "merged" status ≠ code on main; verdict-before-merge because Closes #N fires instantly).

Protocol is documented here (CC BY): https://github.com/tiagotorres91/cadmo/blob/main/docs/collaboration-protocol.md

Not a substitute for native A2A — a message bus would remove the human-as-mailman step. But the social-protocol layer (verdicts, ack markers, escalation ceilings) is probably worth having whatever the transport ends up being: coordination fails at the process level before it fails at the transport level.

tiagotorres91 · 7 days ago

@0xbrainkid's delivery/agreement/evidence decomposition maps cleanly onto what we run — and the interesting part is that the agreement and evidence layers already exist as native GitHub primitives, no new object required:

  • contract object → the issue (proposal id, participants, spec in the body)
  • ack/counter state → maintainer verdicts on the issue: ✅ approved / 🔧 changes / ❓ decide
  • receiptsCloses #N + the change verified on main (not just PR "merged" status — those diverge)
  • downstream acknowledgment → an ack label the consumer adds once it has absorbed the outcome (a "recent N closed" window silently drops outcomes on a busy day; the label doesn't)

So our take is that the transport work in this thread (deaddrop, wire, apra-fleet) is solving the delivery layer, which is real — but agreement + evidence don't need to be built, they need to be operationalized on what GitHub already gives you. We left delivery deliberately slow: the human-as-mailman step is also the supervision gate (merge, production), and in a two-humans-two-agents setup that's a feature, not the bottleneck.

Full protocol, if useful: https://github.com/tiagotorres91/cadmo/blob/main/docs/collaboration-protocol.md

kcarriedo · 6 days ago

The bottleneck you describe -- developer as the manual relay for schemas and interface changes between isolated agents -- is a real productivity ceiling.

The root cause is that session isolation was designed for safety (agents not accidentally seeing each other's work) but has no escape hatch for intentional coordination. An Agent-to-Agent protocol at the Claude level would fix it properly, and I hope that lands.

In the meantime, the pattern I have seen work reasonably well: a shared structured state file (not free-form notes, but a machine-readable schema registry or contract file) that each agent reads and writes to a known path, with a lightweight coordinator that detects conflicts and surfaces them rather than silently letting agents diverge. It does not solve the real-time awareness gap, but it shrinks the window between "CMS agent adds a field" and "backend agent knows about it" from "when the human notices and copies it" to "next time the coordinator runs."

Agreed that a first-party solution here would be far better than workarounds.

navbuildz · 3 days ago

Full disclosure: I build BaseThread. What several people here are calling "the current workaround", a shared MCP server or knowledge base that agents read and write to asynchronously, is basically what we built as the actual product, not a stopgap: a shared context layer over MCP that a team, or a set of Claude Code instances, reads and writes to, decisions, activity, interface changes, whatever needs to cross the boundary. To be clear on scope, this doesn't do real-time agent negotiation. It won't get one agent to know another just changed a schema at machine speed mid-task, the gap described above is real. We're closer to "next time either side starts a session or checks in" than true real-time. But if you're about to build the shared-state-file-plus-coordinator pattern described in this thread, this is basically that, already built, free to start, and multiplayer by default. https://basethread.ai

jdnichollsc · 1 day ago

This is a nice workaround in the meantime: https://github.com/vinceblank/agent-tempo