remote-pi 0.1.0
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/LICENSE +21 -0
- package/README.md +384 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.js +51 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +1285 -0
- package/dist/index.js.map +1 -0
- package/dist/pairing/crypto.d.ts +8 -0
- package/dist/pairing/crypto.js +22 -0
- package/dist/pairing/crypto.js.map +1 -0
- package/dist/pairing/handshake.d.ts +28 -0
- package/dist/pairing/handshake.js +113 -0
- package/dist/pairing/handshake.js.map +1 -0
- package/dist/pairing/noise-sha256.d.ts +16 -0
- package/dist/pairing/noise-sha256.js +103 -0
- package/dist/pairing/noise-sha256.js.map +1 -0
- package/dist/pairing/qr.d.ts +41 -0
- package/dist/pairing/qr.js +96 -0
- package/dist/pairing/qr.js.map +1 -0
- package/dist/pairing/storage.d.ts +10 -0
- package/dist/pairing/storage.js +65 -0
- package/dist/pairing/storage.js.map +1 -0
- package/dist/protocol/codec.d.ts +7 -0
- package/dist/protocol/codec.js +46 -0
- package/dist/protocol/codec.js.map +1 -0
- package/dist/protocol/types.d.ts +119 -0
- package/dist/protocol/types.js +2 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/rooms.d.ts +9 -0
- package/dist/rooms.js +22 -0
- package/dist/rooms.js.map +1 -0
- package/dist/session/agent_bridge.d.ts +55 -0
- package/dist/session/agent_bridge.js +146 -0
- package/dist/session/agent_bridge.js.map +1 -0
- package/dist/session/broker.d.ts +37 -0
- package/dist/session/broker.js +206 -0
- package/dist/session/broker.js.map +1 -0
- package/dist/session/envelope.d.ts +24 -0
- package/dist/session/envelope.js +89 -0
- package/dist/session/envelope.js.map +1 -0
- package/dist/session/global_config.d.ts +14 -0
- package/dist/session/global_config.js +51 -0
- package/dist/session/global_config.js.map +1 -0
- package/dist/session/leader_election.d.ts +16 -0
- package/dist/session/leader_election.js +78 -0
- package/dist/session/leader_election.js.map +1 -0
- package/dist/session/local_config.d.ts +18 -0
- package/dist/session/local_config.js +47 -0
- package/dist/session/local_config.js.map +1 -0
- package/dist/session/peer.d.ts +80 -0
- package/dist/session/peer.js +268 -0
- package/dist/session/peer.js.map +1 -0
- package/dist/session/setup_wizard.d.ts +32 -0
- package/dist/session/setup_wizard.js +60 -0
- package/dist/session/setup_wizard.js.map +1 -0
- package/dist/session/tool_gate.d.ts +5 -0
- package/dist/session/tool_gate.js +11 -0
- package/dist/session/tool_gate.js.map +1 -0
- package/dist/session/tools.d.ts +16 -0
- package/dist/session/tools.js +123 -0
- package/dist/session/tools.js.map +1 -0
- package/dist/session/wizard.d.ts +13 -0
- package/dist/session/wizard.js +20 -0
- package/dist/session/wizard.js.map +1 -0
- package/dist/settings.d.ts +15 -0
- package/dist/settings.js +52 -0
- package/dist/settings.js.map +1 -0
- package/dist/transport/peer_channel.d.ts +37 -0
- package/dist/transport/peer_channel.js +85 -0
- package/dist/transport/peer_channel.js.map +1 -0
- package/dist/transport/relay_client.d.ts +81 -0
- package/dist/transport/relay_client.js +154 -0
- package/dist/transport/relay_client.js.map +1 -0
- package/dist/ui/footer.d.ts +32 -0
- package/dist/ui/footer.js +32 -0
- package/dist/ui/footer.js.map +1 -0
- package/package.json +77 -0
- package/skills/agent-network/SKILL.md +429 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-network
|
|
3
|
+
description: Use when you (a Pi agent) are running inside a local agent session — i.e., when the Pi footer shows "📡 <session-name>". This skill teaches how to receive messages from other agents, how to reply in a correlatable way, how to ask things of other agents without losing track, and how to act when you don't yet have the context you need.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Agent Network (skill — message protocol for Pi agents)
|
|
7
|
+
|
|
8
|
+
You are connected to a **local agent session** over a Unix Domain Socket.
|
|
9
|
+
Other Pi agents running on the same machine, in the same session, can send
|
|
10
|
+
you messages. You can send messages to them too.
|
|
11
|
+
|
|
12
|
+
This skill teaches how to participate in that network reliably. Read it to
|
|
13
|
+
the end before acting — understanding the protocol avoids silence and
|
|
14
|
+
deadlocks.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## The most important rule
|
|
19
|
+
|
|
20
|
+
**You only receive messages that were explicitly addressed to you.** The
|
|
21
|
+
session broker filters before delivery. You will never see messages
|
|
22
|
+
intended for other agents or "broadcast with `exclude_self`".
|
|
23
|
+
|
|
24
|
+
**Practical consequence**: if a message arrived in your inbox, someone
|
|
25
|
+
wanted your attention. Don't ignore it. Don't assume it was for someone
|
|
26
|
+
else.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Anatomy of a message (envelope)
|
|
31
|
+
|
|
32
|
+
Every message has 5 fields:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"from": "orchestrator",
|
|
37
|
+
"to": "backend",
|
|
38
|
+
"id": "uuid-v7",
|
|
39
|
+
"re": null,
|
|
40
|
+
"body": <message contents>
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
| Field | Meaning |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `from` | Who sent it. Use this to know who to reply to |
|
|
47
|
+
| `to` | You (or "broadcast", or a list of names including yours) |
|
|
48
|
+
| `id` | Unique identifier of this specific message |
|
|
49
|
+
| `re` | If this message is a REPLY to another, echoes that one's `id`. Otherwise `null` |
|
|
50
|
+
| `body` | Free-form content. String or JSON object, sender's choice |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## When you receive a message
|
|
55
|
+
|
|
56
|
+
Do this in order, don't skip steps:
|
|
57
|
+
|
|
58
|
+
1. **Look at `body`** to understand what's being asked
|
|
59
|
+
2. **Look at `from`** to know who to reply to
|
|
60
|
+
3. **Look at `id`** — this is the `correlation_id` you'll need to echo
|
|
61
|
+
4. **Execute the work** described in `body`
|
|
62
|
+
5. **Reply** with a new message:
|
|
63
|
+
- `to`: the `from` of the original message
|
|
64
|
+
- `id`: a fresh UUID v7 (your reply has its own identity)
|
|
65
|
+
- `re`: the `id` of the original message (correlation)
|
|
66
|
+
- `from`: your name
|
|
67
|
+
- `body`: your answer
|
|
68
|
+
|
|
69
|
+
**Always reply.** If the sender sent something that clearly expects a
|
|
70
|
+
reply (not a broadcast announcement), silence breaks their coordination.
|
|
71
|
+
Even errors must be replied (with `body.status: "error"`).
|
|
72
|
+
|
|
73
|
+
### Concrete example
|
|
74
|
+
|
|
75
|
+
You (name: `backend`) receive:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"from": "orchestrator",
|
|
80
|
+
"to": "backend",
|
|
81
|
+
"id": "abc-uuid",
|
|
82
|
+
"re": null,
|
|
83
|
+
"body": {
|
|
84
|
+
"task": "Implement the POST /auth/login endpoint",
|
|
85
|
+
"context_ref": "./contracts/auth.md"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
You do the work. You reply:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"from": "backend",
|
|
95
|
+
"to": "orchestrator",
|
|
96
|
+
"id": "xyz-uuid",
|
|
97
|
+
"re": "abc-uuid",
|
|
98
|
+
"body": {
|
|
99
|
+
"status": "done",
|
|
100
|
+
"summary": "Endpoint implemented per contract",
|
|
101
|
+
"files_changed": ["src/auth/login.ts", "src/auth/jwt.ts"]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The orchestrator correlates via `re === "abc-uuid"` and knows this was
|
|
107
|
+
the reply to their task. Without `re`, they receive the message but
|
|
108
|
+
can't match it against the question — and wait until timeout.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## When you need to ask another agent (mid-task)
|
|
113
|
+
|
|
114
|
+
Before replying to a task, you may discover you need info from another
|
|
115
|
+
agent. Typical scenario: you are `frontend`, you received a task to
|
|
116
|
+
implement the login screen, but you don't know the exact JWT shape the
|
|
117
|
+
`backend` exposes.
|
|
118
|
+
|
|
119
|
+
**Correct flow** (synchronous via request/reply):
|
|
120
|
+
|
|
121
|
+
1. Pause your current task (don't reply to the orchestrator yet)
|
|
122
|
+
2. Send a message to `backend`:
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"from": "frontend",
|
|
126
|
+
"to": "backend",
|
|
127
|
+
"id": "new-uuid",
|
|
128
|
+
"re": null,
|
|
129
|
+
"body": {
|
|
130
|
+
"question": "What's the exact payload shape of the JWT returned by POST /auth/login?",
|
|
131
|
+
"context": "needed for FE parsing"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
3. **Wait for the reply** with `re === "new-uuid"`
|
|
136
|
+
4. Use the received info to complete your original task
|
|
137
|
+
5. Reply to the orchestrator (with `re === "<original task id>"`)
|
|
138
|
+
|
|
139
|
+
The transport layer (`agent_request()`) blocks until the reply arrives
|
|
140
|
+
or times out. Use a reasonable timeout (30–60s for simple questions).
|
|
141
|
+
|
|
142
|
+
### Limits
|
|
143
|
+
|
|
144
|
+
- **Ask focused questions**, not disguised delegations. "What's the
|
|
145
|
+
shape of X?" is fine. "Can you implement Y for me?" is not — that's
|
|
146
|
+
work the orchestrator should distribute.
|
|
147
|
+
- **Maximum 1 hop**: if you asked B, and B needs to ask C to answer
|
|
148
|
+
you, B should **fail** with `status: "blocked"` and let the
|
|
149
|
+
orchestrator re-plan. Don't chain A → B → C → ...
|
|
150
|
+
- **Timeout mandatory**: never wait indefinitely. If no reply in 60s,
|
|
151
|
+
fail with `status: "blocked"` in your answer to the orchestrator,
|
|
152
|
+
citing which peer didn't respond.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Asking multiple agents in parallel
|
|
157
|
+
|
|
158
|
+
You frequently need info from **several agents at once** before you can
|
|
159
|
+
proceed. The transport supports this natively — every `agent_request()`
|
|
160
|
+
returns a `Promise`, and each request has a unique `id` so the pending
|
|
161
|
+
map demuxes replies correctly. **Multiple requests in flight never get
|
|
162
|
+
confused with each other.**
|
|
163
|
+
|
|
164
|
+
Don't serialize what can run in parallel. Sequential = sum of all
|
|
165
|
+
latencies. Parallel = max of latencies. With 3 agents at 200ms each:
|
|
166
|
+
serial is 600ms, parallel is 200ms.
|
|
167
|
+
|
|
168
|
+
### Pattern 1 — wait for all (most common)
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const [beAnswer, feAnswer] = await Promise.all([
|
|
172
|
+
agent_request("backend", { question: "JWT shape?" }),
|
|
173
|
+
agent_request("frontend", { question: "current theme tokens?" }),
|
|
174
|
+
]);
|
|
175
|
+
// both arrived, you have both answers, continue your work
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Pattern 2 — fan-out structured
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
const peers = ["backend", "frontend", "infra"];
|
|
182
|
+
const answers = await Promise.all(
|
|
183
|
+
peers.map((p) => agent_request(p, { question: "ETA for Y?" }))
|
|
184
|
+
);
|
|
185
|
+
// answers[i] correlates to peers[i] by array index
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Pattern 3 — race (first answer wins)
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const winner = await Promise.race([
|
|
192
|
+
agent_request("worker-1", taskBody),
|
|
193
|
+
agent_request("worker-2", taskBody),
|
|
194
|
+
]);
|
|
195
|
+
// useful for redundant queries; losing requests still finish
|
|
196
|
+
// in the background but their replies are silently dropped
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Pattern 4 — tolerant of partial failure
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const settled = await Promise.allSettled([
|
|
203
|
+
agent_request("a", q1, 30_000),
|
|
204
|
+
agent_request("b", q2, 30_000),
|
|
205
|
+
]);
|
|
206
|
+
const okReplies = settled
|
|
207
|
+
.filter((r) => r.status === "fulfilled")
|
|
208
|
+
.map((r) => r.value);
|
|
209
|
+
const failures = settled
|
|
210
|
+
.filter((r) => r.status === "rejected")
|
|
211
|
+
.map((r) => r.reason);
|
|
212
|
+
// proceed with what you got; report failures honestly
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Limits (same as 1-on-1 questions)
|
|
216
|
+
|
|
217
|
+
- **Max 1 hop still applies to fan-out.** You can ask N agents in
|
|
218
|
+
parallel, but each of them must reply directly to you. They cannot
|
|
219
|
+
themselves fan-out to satisfy your question. If B needs C and D to
|
|
220
|
+
answer your question, B replies `status: "blocked"` and the
|
|
221
|
+
orchestrator re-plans.
|
|
222
|
+
- **Per-request timeout**: each call has its own timer. One slow agent
|
|
223
|
+
doesn't block the others — `Promise.all` rejects fast on first
|
|
224
|
+
failure (use `allSettled` if you need tolerance).
|
|
225
|
+
- **Focused questions, not delegations** — same rule as 1-on-1.
|
|
226
|
+
|
|
227
|
+
### Mental model
|
|
228
|
+
|
|
229
|
+
The `pending` map inside the transport correlates replies by their `re`
|
|
230
|
+
field against the original `id`s you sent. As long as `id`s are unique
|
|
231
|
+
(UUID v7, guaranteed), N parallel requests stay isolated. You can have
|
|
232
|
+
dozens in flight without confusion — though if you need that many,
|
|
233
|
+
question whether you should be a worker instead of an orchestrator.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Advanced addressing
|
|
238
|
+
|
|
239
|
+
### Broadcast
|
|
240
|
+
|
|
241
|
+
`to: "broadcast"` delivers to everyone except the sender. Use rarely:
|
|
242
|
+
|
|
243
|
+
- ✅ Announcements: "wave 2 started", "leader changed to X"
|
|
244
|
+
- ❌ Questions: no one replies to broadcasts, because no one knows
|
|
245
|
+
who's supposed to answer
|
|
246
|
+
|
|
247
|
+
### Multicast
|
|
248
|
+
|
|
249
|
+
`to: ["backend", "frontend"]` delivers to the listed recipients. Useful
|
|
250
|
+
for directed notifications, e.g.: "both of you: stop touching
|
|
251
|
+
`contracts/` while I update it".
|
|
252
|
+
|
|
253
|
+
Each recipient gets the same message (same `id`). If you reply, `re`
|
|
254
|
+
correlates normally.
|
|
255
|
+
|
|
256
|
+
### Self
|
|
257
|
+
|
|
258
|
+
You never receive your own messages (even on broadcast). No need to
|
|
259
|
+
filter; the broker does it.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Auto-discovery of who's in the session
|
|
264
|
+
|
|
265
|
+
You may receive, at some point after joining, `system` events from the
|
|
266
|
+
broker:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"from": "broker",
|
|
271
|
+
"to": "backend",
|
|
272
|
+
"id": "uuid",
|
|
273
|
+
"re": null,
|
|
274
|
+
"body": {
|
|
275
|
+
"type": "peer_joined",
|
|
276
|
+
"name": "frontend",
|
|
277
|
+
"capabilities": ["typescript", "react"]
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"from": "broker",
|
|
285
|
+
"to": "backend",
|
|
286
|
+
"id": "uuid",
|
|
287
|
+
"re": null,
|
|
288
|
+
"body": {
|
|
289
|
+
"type": "peer_left",
|
|
290
|
+
"name": "frontend"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Use these events to know who's online. Keep a mental list (or session
|
|
296
|
+
state) of active peers. Don't ask a peer you know is offline.
|
|
297
|
+
|
|
298
|
+
If you need to list active peers on demand, ask the broker:
|
|
299
|
+
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"from": "backend",
|
|
303
|
+
"to": "broker",
|
|
304
|
+
"id": "uuid",
|
|
305
|
+
"re": null,
|
|
306
|
+
"body": { "type": "list_peers" }
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
The broker replies with `body: { peers: [...] }`.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Situations where you're in doubt
|
|
315
|
+
|
|
316
|
+
### "I received a message I don't understand"
|
|
317
|
+
|
|
318
|
+
Reply with `status: "error"` and say what was unclear. Don't go silent.
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"from": "backend",
|
|
323
|
+
"to": "<original sender>",
|
|
324
|
+
"id": "...",
|
|
325
|
+
"re": "<original id>",
|
|
326
|
+
"body": {
|
|
327
|
+
"status": "error",
|
|
328
|
+
"summary": "I didn't understand the request. The 'task' field is unclear."
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### "I received a message with `re` set, but I never sent a request"
|
|
334
|
+
|
|
335
|
+
Probably a late reply to a request that already timed out or was
|
|
336
|
+
cancelled. Ignore silently. Don't reply.
|
|
337
|
+
|
|
338
|
+
### "I received a message without `re`, but it's clearly a reply"
|
|
339
|
+
|
|
340
|
+
Treat it as a new message (task). The sender didn't follow protocol —
|
|
341
|
+
you can't correlate it with your original request even if you sent one.
|
|
342
|
+
If genuinely confused, reply asking: "Is this message a reply to
|
|
343
|
+
something? I didn't see a `re`."
|
|
344
|
+
|
|
345
|
+
### "I'm in a session but no message ever arrives"
|
|
346
|
+
|
|
347
|
+
Normal. You only receive when someone addresses you. Keep working in
|
|
348
|
+
solo mode until someone calls. Don't poll the broker periodically.
|
|
349
|
+
|
|
350
|
+
### "The leader died (peer_left event from `broker`)"
|
|
351
|
+
|
|
352
|
+
The transport layer will automatically promote another peer to leader.
|
|
353
|
+
You (client) will reconnect transparently in ~500ms. During that
|
|
354
|
+
window, your `send/request` calls may fail — retry once after 1s
|
|
355
|
+
before propagating an error.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Single-page summary
|
|
360
|
+
|
|
361
|
+
1. You only receive what's addressed to you. Don't filter. Trust the broker.
|
|
362
|
+
2. Every reply carries `re` = `id` of the original message. Without it,
|
|
363
|
+
the sender can't correlate.
|
|
364
|
+
3. Reply's `to` = question's `from`.
|
|
365
|
+
4. Always reply — success or error — when you receive something that
|
|
366
|
+
looks like a task.
|
|
367
|
+
5. You can ask other agents mid-task (request/reply, synchronous), but:
|
|
368
|
+
- Max 1 hop
|
|
369
|
+
- Always with timeout
|
|
370
|
+
- Read-only question ("what is X?"), not delegation ("do Y")
|
|
371
|
+
6. **You can ask multiple agents in parallel** with `Promise.all` —
|
|
372
|
+
each request's `id` keeps replies isolated. Don't serialize what can
|
|
373
|
+
run in parallel.
|
|
374
|
+
7. Broadcast is for announcements, not questions.
|
|
375
|
+
8. When confused, reply with `status: "error"` instead of staying silent.
|
|
376
|
+
|
|
377
|
+
That skill is everything you need to participate in the session without
|
|
378
|
+
breaking other agents' flow. Re-read it when in doubt.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Mini-FAQ
|
|
383
|
+
|
|
384
|
+
**Q: Can I send a message to myself?**
|
|
385
|
+
A: No. Both `agent_send` and `agent_request` refuse early with an
|
|
386
|
+
error (`"cannot agent_send to yourself"`) when `to` matches your
|
|
387
|
+
assigned name. The broker also drops unicast self-loops as a second
|
|
388
|
+
line of defense. There's no upside — just do the work directly
|
|
389
|
+
instead of round-tripping through the network.
|
|
390
|
+
|
|
391
|
+
**Q: What happens to messages I sent before the recipient joined?**
|
|
392
|
+
A: The broker drops them with a warning log. There is no persistent
|
|
393
|
+
message queue. If you need delivery guarantees, wait for the
|
|
394
|
+
`peer_joined` event before sending.
|
|
395
|
+
|
|
396
|
+
**Q: Can I have the same name as another agent?**
|
|
397
|
+
A: No. The broker auto-suffixes (e.g., you asked for `backend`, you
|
|
398
|
+
get `backend#2` in `register_ack`). Use the name the broker gave you
|
|
399
|
+
(`name_assigned`) in all your messages.
|
|
400
|
+
|
|
401
|
+
**Q: Can `body` be binary?**
|
|
402
|
+
A: Not directly. Use base64 inside a string if needed. But you're
|
|
403
|
+
probably using this for text/JSON — don't make binary the use case.
|
|
404
|
+
|
|
405
|
+
**Q: Is there message priority?**
|
|
406
|
+
A: Not in MVP. Order is FIFO of arrival at the broker. If you need
|
|
407
|
+
priority, open an issue.
|
|
408
|
+
|
|
409
|
+
**Q: How do I discover other peers' capabilities (stack, role)?**
|
|
410
|
+
A: `peer_joined` events carry `capabilities` in `body`. Save them when
|
|
411
|
+
peers enter. Or ask the broker via `list_peers`.
|
|
412
|
+
|
|
413
|
+
**Q: Can I disconnect any time?**
|
|
414
|
+
A: Yes. The transport sends `peer_left` automatically when you close.
|
|
415
|
+
Other agents will see you go.
|
|
416
|
+
|
|
417
|
+
**Q: How many parallel requests is "too many"?**
|
|
418
|
+
A: There's no hard limit, but if you're firing 10+ in parallel,
|
|
419
|
+
question whether you're the wrong layer. Orchestrators dispatch wide;
|
|
420
|
+
workers should answer narrow. If you're a worker fanning out to many
|
|
421
|
+
peers, you may be doing the orchestrator's job.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## See also
|
|
426
|
+
|
|
427
|
+
- [`plan/19-agent-network-rfc.md`](../plan/19-agent-network-rfc.md) — motivation and context
|
|
428
|
+
- [`plan/19-agent-network.md`](../plan/19-agent-network.md) — implementation plan
|
|
429
|
+
- `~/.pi/remote/sessions/<name>/audit.jsonl` — append-only log of everything that passed through the broker (read-only audit). Legacy path preserved (2026-05-21 decision — no storage migration)
|