Skip to content

fix: auto-reply in pipe mode instead of aborting on incoming messages#5

Open
cad0p wants to merge 2 commits into
nicobailon:mainfrom
cad0p:fix/pipe-mode-auto-reply
Open

fix: auto-reply in pipe mode instead of aborting on incoming messages#5
cad0p wants to merge 2 commits into
nicobailon:mainfrom
cad0p:fix/pipe-mode-auto-reply

Conversation

@cad0p

@cad0p cad0p commented Apr 14, 2026

Copy link
Copy Markdown

Problem

When a background (pipe mode) subagent receives an intercom message while busy streaming, the interrupt path in handleIncomingMessage calls ctx.abort(), which kills the agent's current turn. Pipe mode then exits in its finally block, and session_shutdown clears the pending message queue before the scheduled flushInterruptedMessages can fire. The message is lost, the subagent disconnects from the broker, and the sender's ask gets Failed: Cancelled.

Root cause chain

  1. handleIncomingMessagectx.abort() (interrupt path)
  2. Agent turn ends → pipe mode's finally block fires
  3. session_shutdown runs synchronously: clears pendingInterruptedMessages, disconnects client
  4. setTimeout(flushInterruptedMessages, 0) fires too late — queue empty, client gone
  5. Subagent exits. Sender's waitForReply never resolves → Cancelled

Interactive mode survives because it has a persistent event loop — after abort, it starts a new turn to process the message.

Fix

Detect non-interactive mode (ctx.hasUI === false) before the interrupt path. When a pipe-mode agent is busy:

  • For messages without replyTo (i.e., ask questions or plain send): auto-reply explaining the agent can't respond
  • For messages with replyTo (replies to previous asks): silently skip

This way:

  • The sender's ask gets a meaningful response instead of hanging
  • The subagent continues its task uninterrupted
  • No disconnection cascade from the broker

Testing

  1. Spawned a background pi -p --no-session with a multi-step task
  2. Confirmed it registered with intercom (intercom list showed it)
  3. From another pi instance, ran intercom ask targeting the subagent
  4. Got the auto-reply: "This agent is running in non-interactive (pipe) mode..."
  5. Confirmed the subagent continued running and completed its task
  6. Previously this caused Failed: Cancelled and killed the subagent's intercom connection

Copilot AI review requested due to automatic review settings April 14, 2026 12:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prevents background (pipe-mode) subagents from aborting their current turn when intercom messages arrive while they’re busy, avoiding lost messages and broker disconnect cascades. Instead, in non-interactive mode it sends a best-effort auto-reply for new incoming messages (non-threaded) and ignores threaded replies.

Changes:

  • Detect non-interactive mode (ctx.hasUI === false) when an incoming message arrives while the agent is not idle.
  • In pipe mode, avoid the interrupt/detach path and ctx.abort(); optionally send an auto-reply for messages without replyTo.
  • Preserve existing interactive-mode behavior (detach/interrupt + queue/flush logic).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread index.ts Outdated
When a background (pipe mode) subagent receives an intercom message while
busy, the interrupt path calls ctx.abort() which kills the agent's turn.
Pipe mode then exits in its finally block, and session_shutdown clears
the pending message queue before the flush can fire. The message is lost
and the sender gets 'Cancelled'.

Instead, detect non-interactive mode (ctx.hasUI === false) and send an
automatic reply explaining the agent can't respond. This way:
- The sender's `ask` gets a meaningful response instead of hanging
- The subagent continues its task uninterrupted
- No disconnection cascade from the broker
@cad0p cad0p force-pushed the fix/pipe-mode-auto-reply branch from 4b83a18 to 9802313 Compare April 14, 2026 12:39
pi requires the `pi-package` keyword in package.json to identify packages
whose extensions should be loaded. Without it, `pi list` discovers the
package but never loads the extension, so the `intercom` tool is unavailable.

Also adds explicit `pi.extensions` declaration pointing to `index.ts`.
@cad0p

cad0p commented May 2, 2026

Copy link
Copy Markdown
Author

@nicobailon is this still happening? let me know and I can close if fixed in other way

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants