feat: document and mitigate debug-agent async message visibility#197
feat: document and mitigate debug-agent async message visibility#197vltbaudbot wants to merge 2 commits intomodem-dev:mainfrom
Conversation
Problem: - When admins send messages to debug-agent via send_to_session, those messages are queued by pi but invisible until the agent completes its current response turn - This creates confusion where admins think messages were lost or the agent is broken - Fundamental limitation of pi's turn-based synchronous conversation model Solution: - Document the limitation clearly in SKILL.md - Add /ready command to explicitly signal completion - Provide workarounds for checking pending messages - Advise keeping responses short to release turns quickly This doesn't solve the root async problem (which would require pi core changes), but makes the limitation visible and provides operational workarounds.
This document outlines potential long-term solutions to the debug-agent async message visibility problem, including: - Message queue API in pi core - Streaming/interruption support - Parallel monitor sessions - Event-driven dashboard widgets Recommendation: phase 1 (docs), phase 2 (pi core API), phase 3 (evaluate further enhancements)
Greptile SummaryThis PR documents the async message visibility limitation in
Confidence Score: 2/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Admin
participant PiUI as Pi UI
participant DebugAgent as Debug Agent (turn)
participant Queue as send_to_session Queue
Admin->>PiUI: sends message via send_to_session
PiUI->>Queue: message queued (agent turn in flight)
Note over Queue,DebugAgent: Queue invisible until turn ends
Admin->>PiUI: types /ready
PiUI->>DebugAgent: registerCommand handler fires
DebugAgent->>PiUI: ctx.ui.notify("Ready for next message...")
Note over Queue: Queue still blocked — turn NOT released
DebugAgent-->>PiUI: agent turn completes naturally
Queue-->>DebugAgent: queued message surfaces as new prompt
Last reviewed commit: 4c947e9 |
| // /ready command — signal completion for queued messages | ||
| pi.registerCommand("ready", { | ||
| description: "Signal completion to allow queued send_to_session messages to be processed", | ||
| handler: async (_args, ctx) => { | ||
| ctx.ui.notify("Ready for next message. Complete your response to process queue.", "info"); | ||
| }, | ||
| }); |
There was a problem hiding this comment.
/ready doesn't actually signal turn completion
The handler only fires a UI notification — it doesn't terminate the agent's current response turn or trigger queue processing in any way. Both the command description and the SKILL.md documentation claim it will "signal completion to allow queued send_to_session messages to be processed," but a ctx.ui.notify call has no effect on turn state.
An admin who types /ready expecting queued messages to surface will see the notification and believe the workaround worked, when in fact nothing has changed: the agent turn is still in flight and the queue is still blocked. This makes the command actively misleading rather than helpful.
If there is a way to end the current turn early (e.g. a ctx.session.complete(), returning a value from the handler that pi interprets as a final response, or emitting a turn-end event), that mechanism should be used here. If no such API exists, the command and its documentation should be rephrased to clarify that it only sends a reminder notification — it does not release the queue — and the admin still has to wait for the agent's natural turn completion.
Prompt To Fix With AI
This is a comment left during a code review.
Path: pi/skills/debug-agent/debug-dashboard.ts
Line: 810-816
Comment:
**`/ready` doesn't actually signal turn completion**
The handler only fires a UI notification — it doesn't terminate the agent's current response turn or trigger queue processing in any way. Both the command `description` and the `SKILL.md` documentation claim it will *"signal completion to allow queued send_to_session messages to be processed,"* but a `ctx.ui.notify` call has no effect on turn state.
An admin who types `/ready` expecting queued messages to surface will see the notification and believe the workaround worked, when in fact nothing has changed: the agent turn is still in flight and the queue is still blocked. This makes the command actively misleading rather than helpful.
If there is a way to end the current turn early (e.g. a `ctx.session.complete()`, returning a value from the handler that pi interprets as a final response, or emitting a turn-end event), that mechanism should be used here. If no such API exists, the command and its documentation should be rephrased to clarify that it only sends a reminder notification — it does **not** release the queue — and the admin still has to wait for the agent's natural turn completion.
How can I resolve this? If you propose a fix, please make it concise.| 1. Keep responses short to release the turn quickly | ||
| 2. Say "Ready for next message" or use `/ready` to signal completion | ||
| 3. The queued messages will then appear as new user prompts | ||
| 4. Check your session socket in `/session-control/` to see if connections are pending |
There was a problem hiding this comment.
Inconsistent socket path (missing ~/.pi/ prefix)
Step 4 of the workaround refers to /session-control/ as an absolute path, but the Quick Reference table below shows the actual path as ~/.pi/session-control/control-agent.alias. An admin following this hint literally would look in the wrong directory.
| 4. Check your session socket in `/session-control/` to see if connections are pending | |
| 4. Check your session socket in `~/.pi/session-control/` to see if connections are pending |
Prompt To Fix With AI
This is a comment left during a code review.
Path: pi/skills/debug-agent/SKILL.md
Line: 43
Comment:
**Inconsistent socket path (missing `~/.pi/` prefix)**
Step 4 of the workaround refers to `/session-control/` as an absolute path, but the Quick Reference table below shows the actual path as `~/.pi/session-control/control-agent.alias`. An admin following this hint literally would look in the wrong directory.
```suggestion
4. Check your session socket in `~/.pi/session-control/` to see if connections are pending
```
How can I resolve this? If you propose a fix, please make it concise.| // /ready command — signal completion for queued messages | ||
| pi.registerCommand("ready", { | ||
| description: "Signal completion to allow queued send_to_session messages to be processed", | ||
| handler: async (_args, ctx) => { |
There was a problem hiding this comment.
Bug: The /ready command handler calls ctx.ui.notify() without a ctx.hasUI check, which will cause a runtime error in non-interactive sessions where no UI is present.
Severity: MEDIUM
Suggested Fix
Add a guard clause at the beginning of the /ready command's handler function. Check if ctx.hasUI is false, and if so, return early to prevent the ctx.ui.notify() call. For example: if (!ctx.hasUI) { return; }.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: pi/skills/debug-agent/debug-dashboard.ts#L813
Potential issue: The handler for the new `/ready` command calls `ctx.ui.notify()`
without first verifying the presence of a user interface via the `ctx.hasUI` flag. In
non-interactive environments, such as headless or SDK modes, the `ctx.ui` object is not
available. Attempting to call `notify()` on an undefined `ui` object will result in a
runtime error, causing the command to crash. This is inconsistent with the established
pattern in the codebase where other command handlers perform this check before
interacting with the UI.
Did we get this right? 👍 / 👎 to inform future reviews.
Problem
When admins send messages to debug-agent via
send_to_session, those messages are queued by pi but invisible until the agent completes its current response turn. This creates confusion where admins think messages were lost or the agent is broken.This is a fundamental limitation of pi's turn-based synchronous conversation model.
Solution
This PR doesn't solve the root async problem (which would require pi core changes), but makes the limitation visible and provides operational workarounds:
/readycommand to explicitly signal completionChanges
pi/skills/debug-agent/SKILL.mdwith "Known limitations" section/readycommand todebug-dashboard.tsextensionTesting
/readycommand implementationRelated
This addresses recurring confusion when admins interact with debug-agent and don't see their messages immediately.