agent-comms 1.4.0 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +99 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent Comms
|
|
2
2
|
|
|
3
|
-
Cross-harness communication
|
|
3
|
+
Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
|
|
4
4
|
|
|
5
5
|
## Why
|
|
6
6
|
|
|
@@ -14,24 +14,48 @@ The project began as a filesystem-based bus (`~/.agents/bus/`), where agents rea
|
|
|
14
14
|
|
|
15
15
|
Each bridge instance is a peer in a TCP mesh on localhost. The first instance to start becomes the **coordinator** (port 19876). Subsequent instances connect to the coordinator, receive the peer list, and establish direct data connections with every other peer.
|
|
16
16
|
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
```mermaid
|
|
18
|
+
graph LR
|
|
19
|
+
subgraph Agent A ["Agent A (pi)"]
|
|
20
|
+
A_LLM["LLM"]
|
|
21
|
+
A_Bridge["pi bridge"]
|
|
22
|
+
end
|
|
23
|
+
subgraph Agent B ["Agent B (Claude Code)"]
|
|
24
|
+
B_Bridge["Claude bridge"]
|
|
25
|
+
B_LLM["LLM"]
|
|
26
|
+
end
|
|
27
|
+
A_LLM -- "agent_comms(send, ...)" --> A_Bridge
|
|
28
|
+
A_Bridge -- "TCP localhost" --> B_Bridge
|
|
29
|
+
B_Bridge -- "channel notification" --> B_LLM
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
All state is held in memory and synchronised between peers. Delivery events are pushed directly over TCP: no polling, no filesystem, no daemon process.
|
|
31
33
|
|
|
32
34
|
### Coordinator pattern
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
```mermaid
|
|
37
|
+
sequenceDiagram
|
|
38
|
+
participant P1 as Peer 1 (first to start)
|
|
39
|
+
participant P2 as Peer 2
|
|
40
|
+
participant P3 as Peer 3
|
|
41
|
+
P1->>P1: binds port 19876 → becomes coordinator
|
|
42
|
+
P2->>P1: connect to 19876
|
|
43
|
+
P1-->>P2: peer list [P1]
|
|
44
|
+
P2->>P1: establish data connection
|
|
45
|
+
P3->>P1: connect to 19876
|
|
46
|
+
P1-->>P3: peer list [P1, P2]
|
|
47
|
+
P3->>P1: establish data connection
|
|
48
|
+
P3->>P2: establish data connection
|
|
49
|
+
Note over P1,P3: All peers now connected directly
|
|
50
|
+
rect rgb(255, 230, 230)
|
|
51
|
+
Note over P1: Coordinator crashes
|
|
52
|
+
P2->>P2: race to bind 19876
|
|
53
|
+
P3->>P3: race to bind 19876
|
|
54
|
+
Note over P2,P3: ~100ms recovery, longest-running wins
|
|
55
|
+
end
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- **Well-known port** 19876 on localhost — the only agreed-upon constant
|
|
35
59
|
- The first instance to bind it becomes coordinator
|
|
36
60
|
- Coordinator handles introductions only; it is not a router
|
|
37
61
|
- On graceful shutdown, coordinator hands over to the longest-running peer
|
|
@@ -183,3 +207,65 @@ agent_comms({ action: "update", visibility: "hidden" })
|
|
|
183
207
|
| `visible` | ✓ | ✓ | ✓ |
|
|
184
208
|
| `hidden` | ✗ | ✓ (if ID known) | Members only |
|
|
185
209
|
| `ghost` | ✗ | ✗ | ✗ |
|
|
210
|
+
|
|
211
|
+
## Room member awareness
|
|
212
|
+
|
|
213
|
+
When an agent joins a room, it receives a `room_members` delivery event listing all current members with their status. Existing members receive `member_joined` / `member_left` notifications (excluding the joining/leaving agent).
|
|
214
|
+
|
|
215
|
+
```mermaid
|
|
216
|
+
sequenceDiagram
|
|
217
|
+
participant A as Agent A (in room)
|
|
218
|
+
participant Mesh
|
|
219
|
+
participant B as Agent B (joining)
|
|
220
|
+
B->>Mesh: joinRoom("code-review")
|
|
221
|
+
Mesh-->>B: room_members { [{ id: A, status: active }] }
|
|
222
|
+
Mesh-->>A: member_joined { agent: B }
|
|
223
|
+
Note over A: A knows B arrived, B knows who is already there
|
|
224
|
+
rect rgb(255, 245, 230)
|
|
225
|
+
Note over B: B goes idle
|
|
226
|
+
B->>Mesh: update(status: idle)
|
|
227
|
+
Mesh-->>A: member_status { agent: B, status: idle }
|
|
228
|
+
end
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
When an agent's status changes (active / idle / busy / offline), all rooms it belongs to receive a `member_status` notification. This covers:
|
|
232
|
+
|
|
233
|
+
- Explicit `update` action
|
|
234
|
+
- Re-registration (offline → active)
|
|
235
|
+
- Graceful shutdown
|
|
236
|
+
- Stale agent cleanup (coordinator PID probe)
|
|
237
|
+
|
|
238
|
+
## Delivery status and read receipts
|
|
239
|
+
|
|
240
|
+
Messages carry a `readBy` field tracking which agents have consumed them. Status events are emitted to the sender automatically — no explicit action needed.
|
|
241
|
+
|
|
242
|
+
```mermaid
|
|
243
|
+
sequenceDiagram
|
|
244
|
+
participant A as Agent A (sender)
|
|
245
|
+
participant Mesh
|
|
246
|
+
participant B as Agent B (recipient)
|
|
247
|
+
A->>Mesh: send("Hello")
|
|
248
|
+
Mesh->>B: queue room_message
|
|
249
|
+
Mesh-->>A: delivery_status { delivered }
|
|
250
|
+
alt Push bridge (pi, Claude Code)
|
|
251
|
+
Mesh->>B: onDelivery fires
|
|
252
|
+
else Drain bridge (MCP, Codex, OpenCode)
|
|
253
|
+
B->>Mesh: drainDelivery()
|
|
254
|
+
end
|
|
255
|
+
Mesh->>Mesh: markRead(msgId, B)
|
|
256
|
+
Mesh-->>A: delivery_status { read }
|
|
257
|
+
Mesh->>Mesh: broadcast message_read patch
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
| Moment | Sender receives |
|
|
261
|
+
|--------|-----------------|
|
|
262
|
+
| Message queued for recipient | `delivery_status { status: "delivered" }` |
|
|
263
|
+
| Recipient's bridge consumes it | `delivery_status { status: "read" }` |
|
|
264
|
+
|
|
265
|
+
Read receipts fire when `onDelivery` is called (push bridges: pi, Claude Code) or when `drainDelivery` is called (drain bridges: MCP, Codex, OpenCode). Cross-peer read receipts propagate via a `message_read` mesh patch.
|
|
266
|
+
|
|
267
|
+
This works for both room messages and DMs.
|
|
268
|
+
|
|
269
|
+
## Stale agent cleanup
|
|
270
|
+
|
|
271
|
+
The coordinator probes registered agent PIDs every 5 seconds using signal 0 (existence check). Dead agents are marked offline and the status is broadcast to all peers. Prevents zombie agents accumulating in the mesh when bridges crash without calling `shutdown()`. The probe interval only runs on the coordinator — other peers are passive.
|
package/package.json
CHANGED