@ctliz/agent-intercom-pi 0.11.0-connect.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/COPYRIGHT +6 -0
- package/LICENSE +661 -0
- package/LICENSE_TRANSITION.md +26 -0
- package/README.md +693 -0
- package/THIRD_PARTY_NOTICES.md +17 -0
- package/banner.png +0 -0
- package/boss-team-scope.ts +241 -0
- package/broker/access-credential.ts +76 -0
- package/broker/access-registry.ts +460 -0
- package/broker/audit.ts +60 -0
- package/broker/authorization.ts +140 -0
- package/broker/boss-adapter.ts +383 -0
- package/broker/broker-impl.ts +2019 -0
- package/broker/broker.ts +7 -0
- package/broker/client.ts +932 -0
- package/broker/framing.ts +87 -0
- package/broker/ownership.ts +61 -0
- package/broker/paths.ts +161 -0
- package/broker/protected-service.ts +158 -0
- package/broker/registration.ts +173 -0
- package/broker/spawn.ts +448 -0
- package/config.ts +183 -0
- package/control.ts +150 -0
- package/durable-json.ts +25 -0
- package/inbound-inbox.ts +296 -0
- package/index.ts +2826 -0
- package/licenses/MIT-pi-intercom.txt +21 -0
- package/outbound-outbox.ts +116 -0
- package/package.json +72 -0
- package/protocol-v4/contract.ts +39 -0
- package/provider/provider.mjs +34 -0
- package/reply-tracker.ts +231 -0
- package/skills/pi-intercom/SKILL.md +537 -0
- package/team.ts +192 -0
- package/types.ts +183 -0
- package/ui/compose.ts +229 -0
- package/ui/inline-message.ts +126 -0
- package/ui/session-identity.ts +55 -0
- package/ui/session-list.ts +205 -0
- package/ui/timestamps.ts +50 -0
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pi-intercom
|
|
3
|
+
description: |
|
|
4
|
+
Streamline session-to-session coordination with pi-intercom. Send messages,
|
|
5
|
+
delegate tasks, and coordinate work across multiple pi sessions on the same
|
|
6
|
+
machine. Use for planner-worker workflows, cross-session context sharing,
|
|
7
|
+
and real-time collaboration between sessions.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Pi Intercom Skill
|
|
11
|
+
|
|
12
|
+
Use this skill when you need to coordinate work across multiple pi sessions
|
|
13
|
+
running on the same machine. Pi-intercom enables direct 1:1 messaging between
|
|
14
|
+
sessions for delegation, context sharing, and collaborative workflows.
|
|
15
|
+
|
|
16
|
+
When you are supervising `pi-subagents`, delegated child agents can escalate to
|
|
17
|
+
you via `contact_supervisor` if `pi-subagents` supplied child bridge metadata.
|
|
18
|
+
This skill covers how to handle those orchestrator-side escalations.
|
|
19
|
+
|
|
20
|
+
## When to Use
|
|
21
|
+
|
|
22
|
+
- **Task delegation**: Split work between a planner session and worker sessions
|
|
23
|
+
- **Context handoffs**: Send findings from a research session to an execution session
|
|
24
|
+
- **Clarification loops**: Worker asks questions, planner answers, work continues
|
|
25
|
+
- **Multi-session workflows**: Coordinate between specialized sessions (frontend/backend, research/implementation)
|
|
26
|
+
|
|
27
|
+
## Core Patterns
|
|
28
|
+
|
|
29
|
+
### Pattern 1: Planner-Worker Delegation
|
|
30
|
+
|
|
31
|
+
The most common pattern. One session holds the big picture, others do hands-on work.
|
|
32
|
+
|
|
33
|
+
**Setup** (in each session):
|
|
34
|
+
```
|
|
35
|
+
/name planner # Terminal 1
|
|
36
|
+
/name worker # Terminal 2
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Planner delegates a task** (fire-and-forget):
|
|
40
|
+
```typescript
|
|
41
|
+
intercom_send({
|
|
42
|
+
to: "worker",
|
|
43
|
+
message: "Task-3: Add retry logic to API client. Key files: src/api/client.ts. Ask if anything's unclear."
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Worker asks for clarification** (waits briefly, then continues asynchronously if needed):
|
|
48
|
+
```typescript
|
|
49
|
+
intercom_ask({
|
|
50
|
+
to: "planner",
|
|
51
|
+
message: "Should I use exponential backoff or fixed intervals?"
|
|
52
|
+
})
|
|
53
|
+
// → Returns a prompt reply as the result
|
|
54
|
+
// → After 30 seconds, returns control; a late reply arrives as a new intercom message
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Worker reports completion**:
|
|
58
|
+
```typescript
|
|
59
|
+
intercom_send({
|
|
60
|
+
to: "planner",
|
|
61
|
+
message: "Task-3 complete. Added exponential backoff (100ms → 1600ms, max 5 retries)."
|
|
62
|
+
})
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use `ask` only when the next step genuinely depends on an answer. Keep at most one unresolved ask to the same recipient; the broker rejects a second one. Different recipients may be asked concurrently when their answers are genuinely blocking. Assignments, completion notices, follow-ups, progress requests, and status checkpoints should use `send` so they do not create unnecessary wait edges.
|
|
66
|
+
|
|
67
|
+
### Pattern 2: Send Related Updates as a Burst
|
|
68
|
+
|
|
69
|
+
The receiver durably queues every message and combines messages that arrive within a 300 ms quiet window into one model turn (never waiting more than 1 second). This means several independently produced updates can be sent promptly without waking the recipient once per message:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
intercom_send({ to: "planner", message: "Tests pass." })
|
|
73
|
+
intercom_send({ to: "planner", message: "One API compatibility concern remains." })
|
|
74
|
+
intercom_send({ to: "planner", message: "See src/client.ts:88." })
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Do not add artificial sleeps to form a batch. Each original message keeps its sender, ID, attachments, timestamp, and reply context.
|
|
78
|
+
|
|
79
|
+
### Pattern 3: Find Your Manager or Team
|
|
80
|
+
|
|
81
|
+
Orchestrator-owned coworkers should use the no-argument team tool instead of searching the global peer list:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
intercom_team({})
|
|
85
|
+
// → Manager target plus live coworkers owned by that manager
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Use the returned manager target directly with `intercom_send` or `intercom_ask`. The manager follows adoption dynamically.
|
|
89
|
+
|
|
90
|
+
### Pattern 4: Global Status Check
|
|
91
|
+
|
|
92
|
+
Use the global list only when you need independently launched peers:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
intercom_list({})
|
|
96
|
+
// → Shows all connected sessions with names, cwd, models, and live status (`idle`, `thinking`, `tool:<name>`)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Pattern 5: Reply Naturally
|
|
100
|
+
|
|
101
|
+
When responding to an inbound ask, prefer `reply` instead of reconstructing raw IDs:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// In the turn triggered by the ask:
|
|
105
|
+
intercom_reply({
|
|
106
|
+
message: "Use exponential backoff starting at 100ms."
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
// If replying later and there might be more than one pending ask:
|
|
110
|
+
intercom_pending({})
|
|
111
|
+
intercom_pending({ askId: "ask-..." }) // Retrieve the full untruncated body when needed
|
|
112
|
+
intercom_reply({ askId: "ask-...", message: "Use exponential backoff starting at 100ms." })
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`intercom_reply` preserves exact threading internally. `intercom_pending` returns stable receiver-local ask IDs and short previews; models never see or construct the protocol message ID. Managers can pass `session` with an owned coworker target from `intercom_team` to inspect that coworker's pending inbox.
|
|
116
|
+
|
|
117
|
+
### Pattern 5: Broadcast to Multiple Workers
|
|
118
|
+
|
|
119
|
+
Send to multiple sessions in parallel:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const workers = ["worker-1", "worker-2", "worker-3"];
|
|
123
|
+
const task = "Check for null pointer exceptions in your assigned files";
|
|
124
|
+
|
|
125
|
+
// Fire-and-forget to all workers
|
|
126
|
+
workers.forEach(w =>
|
|
127
|
+
intercom_send({ to: w, message: task })
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Pattern 6: Send with Attachments
|
|
132
|
+
|
|
133
|
+
Share code snippets, files, or context:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
intercom_send({
|
|
137
|
+
to: "worker",
|
|
138
|
+
message: "Here's the fix for the auth issue:",
|
|
139
|
+
attachments: [{
|
|
140
|
+
type: "snippet",
|
|
141
|
+
name: "auth.ts",
|
|
142
|
+
language: "typescript",
|
|
143
|
+
content: `function validateUser(user: User | null) {
|
|
144
|
+
if (!user) throw new Error("User required");
|
|
145
|
+
return user.email?.includes("@");
|
|
146
|
+
}`
|
|
147
|
+
}]
|
|
148
|
+
})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Pattern 7: Handle Subagent Escalations (Orchestrator Side)
|
|
152
|
+
|
|
153
|
+
When `pi-subagents` spawns a delegated child and supplies child bridge metadata,
|
|
154
|
+
that child can reach you through `contact_supervisor`. You receive a formatted
|
|
155
|
+
message that includes run metadata:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
**From subagent-worker-78f659a3-1**
|
|
159
|
+
|
|
160
|
+
Subagent needs a supervisor decision.
|
|
161
|
+
Run: 78f659a3
|
|
162
|
+
Agent: worker
|
|
163
|
+
Child index: 0
|
|
164
|
+
|
|
165
|
+
Which API should I use?
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Reply using `reply`:**
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// The reply hint in the incoming message will show the exact call:
|
|
172
|
+
intercom_reply({ message: "Use the stable v2 API." })
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
This works because `reply` resolves the correct sender and message ID automatically.
|
|
176
|
+
|
|
177
|
+
**Three types of escalations to expect:**
|
|
178
|
+
|
|
179
|
+
| Type | What it means | How to respond |
|
|
180
|
+
|------|---------------|----------------|
|
|
181
|
+
| `need_decision` | Subagent waits up to 30 seconds, then continues asynchronously while the request remains open. | Reply promptly with a clear decision. If you need more context, ask follow-up questions via `reply`. |
|
|
182
|
+
| `interview_request` | Subagent waits up to 30 seconds for structured answers, then continues asynchronously. | Reply with plain JSON or a fenced `json` block using the provided `{ "responses": [...] }` shape. |
|
|
183
|
+
| `progress_update` | Subagent is sharing meaningful progress or a plan-changing discovery. Not blocking. | Read and acknowledge. No reply required unless you want to redirect. |
|
|
184
|
+
|
|
185
|
+
**When a subagent asks:**
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// In the turn triggered by the incoming ask:
|
|
189
|
+
intercom_reply({ message: "Use exponential backoff, max 3 retries." })
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**When a subagent sends an interview request:**
|
|
193
|
+
|
|
194
|
+
Read the rendered questions in the incoming message and reply with the exact ids in JSON. `info` questions are context-only and do not need response entries:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
intercom_reply({
|
|
198
|
+
message: "```json\n{\n \"responses\": [\n { \"id\": \"api\", \"value\": \"Stable API\" },\n { \"id\": \"constraints\", \"value\": \"Keep the public error shape unchanged.\" }\n ]\n}\n```"
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**If you receive multiple pending asks from different subagents:**
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
intercom_pending({})
|
|
206
|
+
// → Shows all unresolved inbound asks with stable ask ID, sender, elapsed time, and preview
|
|
207
|
+
|
|
208
|
+
intercom_reply({ askId: "ask-...", message: "Use the v2 API." })
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Important:** Only sessions where `pi-subagents` supplied child bridge metadata
|
|
212
|
+
get the `contact_supervisor` tool. Normal sessions use the split `intercom_send`,
|
|
213
|
+
`intercom_ask`, `intercom_reply`, `intercom_team`, `intercom_list`, `intercom_pending`, and
|
|
214
|
+
`intercom_status` tools. If you see the formatted supervisor decision/progress update message, treat
|
|
215
|
+
it as a `contact_supervisor` escalation.
|
|
216
|
+
|
|
217
|
+
## Key Differences
|
|
218
|
+
|
|
219
|
+
| Action | Behavior | Use When |
|
|
220
|
+
|--------|----------|----------|
|
|
221
|
+
| `send` | Fire-and-forget | You don't need a response |
|
|
222
|
+
| `ask` | Waits up to 30 seconds, then continues asynchronously | You need an answer but should not hold the agent indefinitely |
|
|
223
|
+
| `reply` | Responds to the active or pending inbound ask | You were asked something and need to answer naturally |
|
|
224
|
+
| `pending` | Lists unresolved inbound asks | You need to see who is waiting before replying |
|
|
225
|
+
| `list` | Returns all sessions with live status | You need to discover targets or choose an idle peer |
|
|
226
|
+
| `status` | Returns your connection state | Troubleshooting |
|
|
227
|
+
|
|
228
|
+
## Optional: Visible Peer Sessions via cmux or tmux
|
|
229
|
+
|
|
230
|
+
If no suitable intercom-connected peer session already exists and the task benefits from a long-lived visible conversation, you may spawn a new `pi` session.
|
|
231
|
+
|
|
232
|
+
Prefer `cmux new-split right` over new surfaces or workspaces so both sessions are visible side by side.
|
|
233
|
+
|
|
234
|
+
If `cmux` is unavailable, `tmux` is an optional fallback when it is installed and relevant. Use it with a private socket so the session is isolated and observable.
|
|
235
|
+
|
|
236
|
+
Use spawned peer sessions only for:
|
|
237
|
+
- same-codebase worker/planner splits
|
|
238
|
+
- reference-codebase scouting
|
|
239
|
+
- long-lived visible conversations where the user benefits from watching both sides
|
|
240
|
+
|
|
241
|
+
Do not use this for unrelated repos, trivial questions, or work you can finish cleanly in the current session.
|
|
242
|
+
|
|
243
|
+
### Preferred: cmux Worker or Scout Session
|
|
244
|
+
|
|
245
|
+
Same codebase:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
cmux new-split right
|
|
249
|
+
sleep 0.5
|
|
250
|
+
cmux send --surface right 'cd /path/to/current/repo && pi\n'
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Reference codebase:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
cmux new-split right
|
|
257
|
+
sleep 0.5
|
|
258
|
+
cmux send --surface right 'cd /path/to/reference/repo && pi\n'
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Optional Fallback: tmux Worker or Scout Session
|
|
262
|
+
|
|
263
|
+
Same codebase:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
SOCKET_DIR=${TMPDIR:-/tmp}/pi-tmux-sockets
|
|
267
|
+
mkdir -p "$SOCKET_DIR"
|
|
268
|
+
SOCKET="$SOCKET_DIR/pi.sock"
|
|
269
|
+
SESSION=pi-worker
|
|
270
|
+
tmux -S "$SOCKET" new -d -s "$SESSION" -c "/path/to/current/repo" 'pi'
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Reference codebase:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
SOCKET_DIR=${TMPDIR:-/tmp}/pi-tmux-sockets
|
|
277
|
+
mkdir -p "$SOCKET_DIR"
|
|
278
|
+
SOCKET="$SOCKET_DIR/pi.sock"
|
|
279
|
+
SESSION=pi-reference-auth
|
|
280
|
+
tmux -S "$SOCKET" new -d -s "$SESSION" -c "/path/to/reference/repo" 'pi'
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
When you use `tmux`, tell the user how to watch it:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
tmux -S "$SOCKET" attach -t "$SESSION"
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
After launch, name the new session clearly so it is easy to target:
|
|
290
|
+
|
|
291
|
+
```text
|
|
292
|
+
/name worker
|
|
293
|
+
/name reference-auth
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Then coordinate from the current session:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
intercom_send({
|
|
300
|
+
to: "worker",
|
|
301
|
+
message: "Take task X. Ask if blocked."
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
intercom_ask({
|
|
305
|
+
to: "reference-auth",
|
|
306
|
+
message: "How does this repo structure token refresh retries?"
|
|
307
|
+
})
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Spawn Decision Rule
|
|
311
|
+
|
|
312
|
+
Spawn a visible peer session only when all of these are true:
|
|
313
|
+
- no existing intercom-connected session already fits the need
|
|
314
|
+
- the work benefits from a long-lived visible peer session
|
|
315
|
+
- the peer session is either in the same codebase or in an intentional reference codebase
|
|
316
|
+
- `cmux` is available, or `tmux` is available as an intentional fallback
|
|
317
|
+
|
|
318
|
+
If neither `cmux` nor `tmux` is available, skip this path and use normal `intercom` workflows.
|
|
319
|
+
|
|
320
|
+
## Important Constraints
|
|
321
|
+
|
|
322
|
+
### `ask` Limitations
|
|
323
|
+
|
|
324
|
+
- **30-second soft wait**: If no reply arrives, the tool returns a successful pending result and the agent continues
|
|
325
|
+
- **10-minute reply window**: The recipient can still answer later; the reply arrives as a new intercom message
|
|
326
|
+
- **One synchronous wait per recipient**: Independent recipients may be asked concurrently, but a second unresolved ask to the same recipient is rejected
|
|
327
|
+
- **Deferred is not cancelled**: After the soft wait, reverse asks are allowed and the original request stays late-replyable, including across broker restart
|
|
328
|
+
- **Cannot self-target**: A session cannot ask itself
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
// Check if already waiting before asking
|
|
332
|
+
const result = await intercom_ask({ to: "planner", message: "..." });
|
|
333
|
+
if (result.isError && result.content[0].text.includes("Already waiting")) {
|
|
334
|
+
// Use send instead, or wait for current ask to complete
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### `send` Behavior
|
|
339
|
+
|
|
340
|
+
- **No reply wait**: `send` waits only until the receiver durably queues and acknowledges the message; it never waits for a conversational reply
|
|
341
|
+
- **Structured delivery**: `accepted` means broker-accepted, while `delivered` means receiver-acknowledged
|
|
342
|
+
- **Crash replay**: Unfinished sends are durably replayed with the same message ID after broker reconnect, so do not invent a new ID for a manual retry
|
|
343
|
+
- **Burst batching**: Nearby inbound messages become one recipient turn after 300 ms quiet, capped at 1 second
|
|
344
|
+
- **Confirmation dialogs**: If `confirmSend: true` in config, interactive sessions show a confirmation dialog
|
|
345
|
+
- **Replies skip confirmation**: `intercom_reply` never shows a send confirmation dialog
|
|
346
|
+
|
|
347
|
+
## Best Practices
|
|
348
|
+
|
|
349
|
+
### Use `ask` for decision workflows
|
|
350
|
+
|
|
351
|
+
When the worker needs information to proceed:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
// GOOD: Worker waits briefly for a prompt decision
|
|
355
|
+
const reply = await intercom_ask({
|
|
356
|
+
to: "planner",
|
|
357
|
+
message: "API rate limit is 100/min. Should I implement client-side throttling or batching?"
|
|
358
|
+
});
|
|
359
|
+
// If reply.details?.pending is true, continue only with work that does not depend on the answer.
|
|
360
|
+
// A late answer will arrive as a new intercom message.
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Use `send` for notifications
|
|
364
|
+
|
|
365
|
+
When you just want to inform:
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
// GOOD: Fire-and-forget notification
|
|
369
|
+
intercom_send({
|
|
370
|
+
to: "reviewer",
|
|
371
|
+
message: "PR #123 is ready for review. Key changes in auth.ts."
|
|
372
|
+
});
|
|
373
|
+
// Continue immediately, don't wait
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Include reply hints in messages
|
|
377
|
+
|
|
378
|
+
Make it easy for recipients to respond:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// GOOD: Recipient sees exact command to reply
|
|
382
|
+
intercom_send({
|
|
383
|
+
to: "worker",
|
|
384
|
+
message: `Found the issue in auth.ts:142. Use getUserById() instead of getUser().
|
|
385
|
+
|
|
386
|
+
Reply with: intercom_reply({ message: "..." })`
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Name sessions meaningfully
|
|
391
|
+
|
|
392
|
+
Use `/name` so others can target you easily:
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
/name api-worker
|
|
396
|
+
/name frontend-dev
|
|
397
|
+
/name planner
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## Error Handling
|
|
401
|
+
|
|
402
|
+
### Common Errors and Solutions
|
|
403
|
+
|
|
404
|
+
**"Already waiting for a reply"**
|
|
405
|
+
```typescript
|
|
406
|
+
// You already have an unresolved ask to this recipient.
|
|
407
|
+
// Use send for a non-blocking follow-up or progress/status request.
|
|
408
|
+
intercom_send({ to: "planner", message: "Additional context for the open question." });
|
|
409
|
+
|
|
410
|
+
// Or wait for the current ask to resolve before asking another question.
|
|
411
|
+
// Asks to a different recipient may proceed concurrently.
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**"Cannot message the current session"**
|
|
415
|
+
```typescript
|
|
416
|
+
// You cannot target yourself
|
|
417
|
+
// This usually means you confused session names - double-check the target
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**"Session not found"**
|
|
421
|
+
```typescript
|
|
422
|
+
const result = await intercom_send({ to: "worker", message: "..." });
|
|
423
|
+
if (!result.delivered) {
|
|
424
|
+
console.log("Failed:", result.reason);
|
|
425
|
+
// → "Session not found" - check the name and list available sessions
|
|
426
|
+
await intercom_list({});
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
**Ask continues asynchronously after 30 seconds**
|
|
431
|
+
```typescript
|
|
432
|
+
const result = await intercom_ask({ to: "planner", message: "..." });
|
|
433
|
+
if (result.details?.pending) {
|
|
434
|
+
// The message was delivered, but no prompt reply arrived.
|
|
435
|
+
// Continue independent work; a late reply will trigger a new intercom message.
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Troubleshooting
|
|
440
|
+
|
|
441
|
+
### Session not appearing in list
|
|
442
|
+
|
|
443
|
+
1. Check intercom is enabled: `intercom_status({})`
|
|
444
|
+
2. Verify the target session has loaded pi-intercom
|
|
445
|
+
3. Ensure both sessions are on the same machine (intercom is same-machine only)
|
|
446
|
+
|
|
447
|
+
### Session name flips or registration reports `SESSION_ID_IN_USE`
|
|
448
|
+
|
|
449
|
+
The same Pi session is open in more than one live runtime, such as a desktop terminal and a mobile/RPC host. Intercom keeps the first runtime authoritative instead of allowing the two clients to evict each other. Close or switch away from the duplicate runtime; one transcript/session ID must have only one live owner.
|
|
450
|
+
|
|
451
|
+
### Message not delivered
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
const result = await intercom_send({ to: "worker", message: "..." });
|
|
455
|
+
if (!result.delivered) {
|
|
456
|
+
console.log("Failed:", result.reason);
|
|
457
|
+
// → "Session not found" or delivery failure reason
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Connection lost
|
|
462
|
+
|
|
463
|
+
Sessions automatically reconnect if the broker restarts. If persistently disconnected:
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
intercom_status({})
|
|
467
|
+
// Check if broker is running and restart if needed
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Common Workflows
|
|
471
|
+
|
|
472
|
+
### Research → Implementation Handoff
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
// Research session finds relevant code
|
|
476
|
+
intercom_send({
|
|
477
|
+
to: "impl-session",
|
|
478
|
+
message: "Found the bug. The issue is in validateUser() - it doesn't check for null.",
|
|
479
|
+
attachments: [{
|
|
480
|
+
type: "snippet",
|
|
481
|
+
name: "validate.ts",
|
|
482
|
+
language: "typescript",
|
|
483
|
+
content: `// Line 45-52 - missing null check
|
|
484
|
+
function validateUser(user: User) {
|
|
485
|
+
return user.email?.includes("@"); // crashes if user is null
|
|
486
|
+
}`
|
|
487
|
+
}]
|
|
488
|
+
});
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Pair Debugging
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
// Session A encounters error
|
|
495
|
+
intercom_ask({
|
|
496
|
+
to: "session-b",
|
|
497
|
+
message: "Getting 'Cannot read property of undefined' at line 78. Can you check if data.users is populated before this call?"
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// Session B investigates and replies
|
|
501
|
+
intercom_reply({
|
|
502
|
+
message: "data.users is null. The fetch failed silently. Add error handling in loadUsers()."
|
|
503
|
+
});
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Progress Reporting
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
// Worker sends periodic updates
|
|
510
|
+
intercom_send({ to: "planner", message: "Task-1 complete (15min). Starting Task-2." });
|
|
511
|
+
// ... work ...
|
|
512
|
+
intercom_send({ to: "planner", message: "Task-2 complete (30min). Task-3 blocked - need API key." });
|
|
513
|
+
// ... get unblocked ...
|
|
514
|
+
intercom_send({ to: "planner", message: "Task-3 complete. All done." });
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Long-Running Task with Checkpoints
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
// For long tasks, use send for progress and ask only for concrete decisions
|
|
521
|
+
|
|
522
|
+
// 1. Initial send with full context
|
|
523
|
+
intercom_send({
|
|
524
|
+
to: "worker",
|
|
525
|
+
message: "Implement user authentication. This will take 30+ minutes. I'll check in at milestones."
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// 2. Worker sends progress via send (no timeout)
|
|
529
|
+
intercom_send({ to: "planner", message: "Milestone 1: Login form complete (10min)" });
|
|
530
|
+
|
|
531
|
+
// 3. Worker asks for specific decision when needed
|
|
532
|
+
const decision = await intercom_ask({
|
|
533
|
+
to: "planner",
|
|
534
|
+
message: "Should we use JWT or session cookies? Need decision to continue."
|
|
535
|
+
});
|
|
536
|
+
// Continue with the decision when prompt; otherwise continue only independent work.
|
|
537
|
+
```
|