Skip to content

Wake waiting agents on channel handoffs instead of blocking in shell polling loops #108

Closed

Description

@iamnbutler

Agents coordinating across channels can wait in long shell polling loops. While a loop runs, a ready handoff from another channel can't start the waiting agent's work, so a review sits idle until a person stops the run by hand.

Observed (Canary 0.0.11, October 5)

github-row-review was waiting to review the change owned by github-row-actions. Times are local, taken from the channel store.

  • 12:03:58 The reviewer reasoned "I can't block on messages, I should poll the lane worktree periodically with a sleep interval instead". It then ran one bash call that loops 60 times over git status/git log with sleep 30 and prints only tail -5 at the end. It set timeout: 1900, so the call could take up to about 30 minutes, and its output stays hidden until it ends.
  • ~12:05 github-row-actions pushed fd5e837. At 12:05:38 it called message to github-row-review with invoke: true and the text "the diff is ready to review…". The tool returned "Delivered to github-row-review".
  • The review chat stayed inside the polling call, and no review work happened.
  • 12:09:23 Nate pressed Stop. The bash call ended as aborted.
  • 12:09:39 Nate sent a fresh prompt that restated the handoff, and the review resumed and completed normally.

Store data seen read-only after the fact

  • In github-row-review, the invoked message has a submission (requestId message:11c3f378486cbd27:169). Its status is unanswered with reason aborted, and it has no transcript entry. The handoff text doesn't appear in the reviewer's transcript. Later agent messages do appear as ace.message entries.
  • This suggests the invocation was queued behind the active run, and that Stop then resolved it as unanswered without placing it. Whether that is the intended behavior of Stop, and what the Canary UI showed for the queued input, was not verified. Treat this as something to investigate, not as a proven lost-message bug.

Inferred / to investigate

  • When an invoked message arrives at a busy chat, it waits for the current run to finish. A long blocking tool call therefore delays the handoff for as long as the call runs.
  • What should Stop do with queued input from another channel: place it, run it next, or discard it? Can the sender and the participants tell which of these happened? "Delivered" currently means the message was accepted, not that the agent saw it.

Desired outcome

  • Finish-and-wake coordination: agent guidance says to end the run and let an incoming channel message (invoke: true) wake the agent, rather than waiting in shell sleep/poll loops for another channel. The waiting agent states in chat what it is waiting for.
  • Avoid long blocking waits: don't use shell polling as a substitute for messaging. Real long-running processes belong in managed jobs (Manage background and interactive jobs from channel tools #53).
  • Visible queued and blocked handoffs: participants can see that a chat has queued input, who sent it, and what is blocking it. They can steer or cancel it (Edit and delete queued messages, and choose steer, follow-up, or interrupt #24), and Stop doesn't make it disappear silently.
  • Consider wake/interrupt support only if guidance and visibility aren't enough. For example, an incoming handoff could end an interruptible wait, or a run could check for pending input between steps. Interrupting a run must never re-run tool calls that already changed something.

Related: #24 (steer queued messages), #53 (background/interactive jobs), #52 (supervising subagents), #57 (cross-host messaging), #12 (attention for waiting work), #99 (plain-language progress and blockers). Dogfooding core/QOL: #5.

Activity

  1. iamnbutler commented on Oct 15, 2026

    @iamnbutler
    ContributorAuthor

    Fixed in #400. While another channel's agent's invoked message is queued for a busy chat, that chat's shell commands stop, and new ones are skipped. The result says Stopped: agent@<sender> sent a message to this chat. and pi then steers the message into the same run, so no tool call reruns. The timeline marks the stopped command. Agent guidance now says to end the run and let an invoked message wake the agent instead of polling. The remaining items are tracked elsewhere: steering or cancelling queued messages in #24, Stop dropping queued input in #279, and managed long-running jobs in #53.

  2. iamnbutler commented on Oct 15, 2026

    @iamnbutler
    ContributorAuthor

    Verified in study 24 on 0.0.41:

    • A 3-minute shell loop in talk stopped about 3s after #builder's agent invoked it.
    • The timeline said "Stopped bash for a message from another channel."
    • The agent replied "received" in the same run, with no rerun.
    • B saw the same thing live from the other Mac.
    • Wording follow-up: the stop message uses the sender's original name (filed separately).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions