Skip to content

Commit 56ad7da

Browse files
committed
docs: A2Aworkarounds.md — four coordination patterns for isolated agents
Knowledge doc covering the four workarounds for Claude Code's lack of native inter-agent communication: 1. File Blackboard (AGENT_LOG.md cat >> heredoc) 2. Branch Pub/Sub (subscribe_pr_activity as webhook bus) 3. Role Teleportation (agent cards on main thread, zero context loss) 4. Structured Handover Files (session-to-session transfer) Includes decision matrix, runtime Layer 1 ↔ session Layer 2 mapping, agent prompt template, and setup instructions for each pattern. READ BY: all agents, all sessions. https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
1 parent 1f827ce commit 56ad7da

1 file changed

Lines changed: 266 additions & 0 deletions

File tree

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
# A2A Workarounds — Cross-Agent Coordination Without Native Support
2+
3+
> **READ BY:** all agents, all sessions.
4+
> **Status:** FINDING (2026-04-24). Tested in-session with 6+ concurrent agents.
5+
> **Context:** Claude Code agents are isolated processes. No shared memory,
6+
> no MCP channel between them, no role-switching within a session.
7+
> These workarounds restore coordination using existing primitives.
8+
9+
---
10+
11+
## The Problem
12+
13+
Claude Code's `Agent()` tool spawns isolated subprocesses. Each agent:
14+
- Gets a fresh context window (no memory of the conversation)
15+
- Cannot call other agents' tools
16+
- Cannot read other agents' in-flight state
17+
- Returns a single result blob to the main thread
18+
19+
This breaks three patterns that worked in earlier Claude/Gemini setups:
20+
1. **Role teleportation** — switching persona in-context with zero loss
21+
2. **Mid-flight coordination** — agent A tells agent B what it found
22+
3. **Cross-session handoff** — session A's work feeds session B in real-time
23+
24+
---
25+
26+
## Workaround 1: File Blackboard (`AGENT_LOG.md`)
27+
28+
**Replaces:** Mid-flight coordination (partially).
29+
**How:** Append-only log file that all agents read before starting
30+
and write to after committing.
31+
32+
### Setup
33+
34+
Already live at `.claude/board/AGENT_LOG.md`. Permission pre-allowed
35+
in `.claude/settings.json`:
36+
37+
```json
38+
"Bash(cat >> .claude/board/AGENT_LOG.md:*)"
39+
```
40+
41+
### Agent prompt template (include in every spawn)
42+
43+
```
44+
Before starting work, read `.claude/board/AGENT_LOG.md` to see what
45+
other agents already shipped or found.
46+
47+
After committing, append your entry:
48+
49+
cat >> .claude/board/AGENT_LOG.md <<'EOF'
50+
51+
## YYYY-MM-DDTHH:MM — description (model, branch)
52+
53+
**D-ids:** ...
54+
**Commit:** `abc1234`
55+
**Tests:** N pass (M new)
56+
**Outcome:** One-line summary.
57+
EOF
58+
```
59+
60+
### Limitations
61+
62+
- Not real-time: agent B only sees what agent A committed, not
63+
what A is currently working on.
64+
- Git staging: if agent A and B both append without committing,
65+
only the last `git add` wins. Mitigation: commit immediately
66+
after append.
67+
- Ordering: entries are appended at bottom (cat >>), but convention
68+
is newest-first. Main thread can reorder during board-hygiene.
69+
70+
---
71+
72+
## Workaround 2: Branch Pub/Sub (`subscribe_pr_activity`)
73+
74+
**Replaces:** Cross-session handoff.
75+
**How:** Open a coordination PR. Both sessions subscribe. Push events
76+
arrive as `<github-webhook-activity>` tags.
77+
78+
### Setup
79+
80+
```bash
81+
# Session A (creates the bus):
82+
git checkout -b claude/blackboard
83+
echo "# Coordination Blackboard" > .claude/board/AGENT_LOG.md
84+
git add .claude/board/AGENT_LOG.md
85+
git commit -m "init coordination blackboard"
86+
git push -u origin claude/blackboard
87+
# Open PR:
88+
mcp__github__create_pull_request(
89+
owner="AdaWorldAPI", repo="lance-graph",
90+
title="A2A coordination blackboard",
91+
head="claude/blackboard", base="main",
92+
body="Cross-session pub/sub bus. Do not merge.",
93+
draft=true
94+
)
95+
# Subscribe:
96+
mcp__github__subscribe_pr_activity(owner="AdaWorldAPI", repo="lance-graph", pullNumber=NNN)
97+
98+
# Session B (joins):
99+
mcp__github__subscribe_pr_activity(owner="AdaWorldAPI", repo="lance-graph", pullNumber=NNN)
100+
git fetch origin claude/blackboard
101+
git checkout claude/blackboard
102+
# Read AGENT_LOG.md → see what session A did
103+
```
104+
105+
### Coordination loop
106+
107+
```
108+
Session A: Session B:
109+
[does work]
110+
cat >> AGENT_LOG.md <<'EOF'
111+
...entry...
112+
EOF
113+
git add && git commit && git push
114+
← <github-webhook-activity> push event
115+
git pull origin claude/blackboard
116+
cat AGENT_LOG.md # read A's entry
117+
[builds on A's findings]
118+
cat >> AGENT_LOG.md <<'EOF'
119+
...entry...
120+
EOF
121+
git add && git commit && git push
122+
← <github-webhook-activity> push event
123+
git pull
124+
# reads B's entry, continues
125+
```
126+
127+
### Why it works
128+
129+
- `subscribe_pr_activity` is already in the MCP toolkit — zero infra.
130+
- GitHub webhooks fire on any push, regardless of content.
131+
- Append-only files merge cleanly (no conflict on concurrent appends
132+
if entries are at different positions).
133+
- The draft PR never merges — it's the bus, not a deliverable.
134+
135+
### Limitations
136+
137+
- GitHub webhook latency: seconds to low minutes.
138+
- Rate limits: GitHub API limits apply (5000/hour authenticated).
139+
- Requires network: doesn't work offline.
140+
- PR must stay open: closing it kills the subscription.
141+
142+
---
143+
144+
## Workaround 3: Role Teleportation via Agent Cards
145+
146+
**Replaces:** In-context role switching.
147+
**How:** Load an agent card's knowledge docs, adopt its perspective,
148+
do the work — all on the main thread. No subprocess spawned.
149+
150+
### When to use
151+
152+
- The task requires seeing the FULL conversation context (not a summary).
153+
- The task is accumulation (multi-source synthesis), not grindwork.
154+
- The role switch is temporary (do 10 minutes of codec work, then
155+
switch back to architecture).
156+
157+
### How
158+
159+
```
160+
# On the main thread, not via Agent():
161+
1. Read `.claude/agents/family-codec-smith.md`
162+
2. Load its Tier-1 knowledge docs (encoding-ecosystem.md, etc.)
163+
3. Do the codec work with full session context intact
164+
4. When done, switch: read `.claude/agents/truth-architect.md`
165+
5. Review the codec work from the architect's perspective
166+
6. Back to main thread — nothing lost
167+
```
168+
169+
### When NOT to use
170+
171+
- The task is mechanical grindwork (file scaffolding, known-spec
172+
implementation) → spawn a Sonnet agent instead.
173+
- The task is truly independent (no context dependency) → parallel
174+
Agent() spawns are faster.
175+
- The task is long-running and would block the main thread →
176+
background Agent() is better.
177+
178+
### Limitations
179+
180+
- Main thread is single-threaded: no parallelism.
181+
- Context window fills: role-switching adds knowledge doc content
182+
to the conversation, consuming context budget.
183+
- No isolation: mistakes made "as codec-smith" are visible to the
184+
truth-architect review (which is actually a feature, not a bug).
185+
186+
---
187+
188+
## Workaround 4: Structured Handover Files
189+
190+
**Replaces:** Session-to-session context transfer.
191+
**How:** Write a structured handover file that the next session
192+
reads at startup via the SessionStart hook.
193+
194+
### Format
195+
196+
```markdown
197+
# Handover — YYYY-MM-DD-HHMM — <from-session> to <next-session>
198+
199+
## What I did
200+
- [bullet list of completed work with commit hashes]
201+
202+
## FINDING
203+
- [verified facts that the next session can rely on]
204+
205+
## CONJECTURE
206+
- [unverified ideas that need probing]
207+
208+
## Blockers
209+
- [things I couldn't resolve]
210+
211+
## Open questions
212+
- [decisions the next session should make]
213+
```
214+
215+
### Where
216+
217+
`.claude/handovers/YYYY-MM-DD-HHMM-<topic>.md`
218+
219+
The SessionStart hook (`.claude/hooks/session-start.sh`) can be
220+
extended to cat the latest handover file into the session context.
221+
222+
---
223+
224+
## Decision Matrix
225+
226+
| Need | Workaround | Cost |
227+
|---|---|---|
228+
| Agent A's findings feed agent B (same session) | File Blackboard (#1) | Low: cat >> + git add |
229+
| Session A's work feeds session B (real-time) | Branch Pub/Sub (#2) | Medium: PR + subscribe |
230+
| Full-context role switch (no loss) | Teleportation (#3) | Zero: just read the card |
231+
| Session-to-session knowledge transfer | Handover Files (#4) | Low: write once, read at startup |
232+
| Parallel independent grindwork | Standard Agent() spawns | Low: fire and forget |
233+
| Multi-source synthesis needing judgment | Teleportation (#3) on Opus main thread | Zero |
234+
235+
---
236+
237+
## Relation to Runtime A2A (Layer 1)
238+
239+
These workarounds mirror the runtime `Blackboard` from
240+
`lance_graph_contract::a2a_blackboard`:
241+
242+
| Runtime (Layer 1) | Session (Layer 2 workaround) |
243+
|---|---|
244+
| `Blackboard.entries` | `AGENT_LOG.md` entries |
245+
| `BlackboardEntry.expert_id` | Agent description + model |
246+
| `BlackboardEntry.capability` | D-ids |
247+
| `BlackboardEntry.result` | Commit hash + outcome |
248+
| `BlackboardEntry.confidence` | Test pass count |
249+
| `Blackboard.round` | Git commit sequence |
250+
| Experts read prior rounds | Agents read prior log entries |
251+
252+
The structural isomorphism is intentional: the same coordination
253+
pattern works at both layers because the problem is the same —
254+
independent experts composing results on a shared substrate.
255+
256+
---
257+
258+
## Future: Native A2A MCP Server
259+
260+
When Claude Code or a third party ships an A2A MCP server with
261+
`post_entry` / `read_entries` / `subscribe` endpoints, these
262+
workarounds can be replaced. The contract types already exist
263+
(`BlackboardEntry`, `ExpertCapability`, `Blackboard`). The MCP
264+
server is a thin serde layer over them.
265+
266+
Until then: `cat >> AGENT_LOG.md <<'EOF'`.

0 commit comments

Comments
 (0)