[Bug] Parent agent_message nudges can sit in a child's queue forever after the child goes idle #1776
Dmatut7
started this conversation in
Bug reports
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
What happens
When a parent RLM session assigns work to a child and later nudges it with
agent_message, the nudge often never reaches the child's next turn. The child looks stuck. The parent waits, sends another nudge, and that one queues too. In the TUI this shows as a longWaiting · …on the child plus queued chips that never drain.This is not one failure. Three things stack:
We are asking whether (2) is intended, and what the supported recovery path is for a headless child (no human Enter on that session).
Steps to reproduce
await rlm(...), child replies withagent_message.send(..., receiver_role="parent")).await agent_message.send("please report status", receiver_role="child", ...).queuedCount/ queued message chips, and whether the first nudge ever appears in the child's transcript.Expected
Once the child is idle and not abort-suspended, queued parent
agent_messages should start a turn (or there should be a documented, automatic drain for programmatic senders). The parent should be able to tell the child is idle-with-queue vs still running.Actual
queued.queued(unfinishedActionCount > 0keepsacceptAgentSessionMessageon the queue path).agent_statuswithtaskState: "needs_input"andsummary: "".What we already ruled out
We scanned ~320 local session journals (parent + children).
toolCallids we found were aborted/terminated streams that the next turn recovered from.agent_observeerror we saw was the model callingrecent_messages(name=...)instead oftarget=.So the user-visible "child is stuck and my nudge cannot get in" is a delivery / scheduler problem, not a missing tool timeout.
Code path (current
main)Parent send:
DaemonMode.acceptAgentSessionMessage(packages/coding-agent/src/modes/daemon/daemon-mode.ts).unfinishedActionCount > 0→queueAgentMessagePrompt(prompt, "steer").acceptAgentMessagePrompt(...)withresumeIfIdlehardcodedfalse.Queue admission:
AgentSession._admitSessionInput(packages/coding-agent/src/core/agent-session.ts).The pump is scheduled only when:
disposition === "starts_when_admitted", ordelivery === "next_turn_boundary" && this.isStreaming, orwake === "immediate".queueAgentMessagePromptdoes not passimmediatelyEligibleorresumeIfIdle. Steer therefore getswake: "on_lower_boundary". That wakes the pump only while the child is still streaming.We then could not find any
_scheduleSessionInputPump()on a normalagent_end. Other call sites exist (compaction, bash end, refine,resumeQueuedWork,waitForIdlewaiters). After a clean turn end, a steer that arrived mid-turn can sit in the store with nobody selecting it.wake === "immediate"also calls_resumeSessionInputAdmission(), which clears_sessionInputPumpSuspended. That looks like the reasonacceptAgentMessagePromptforcesresumeIfIdle: false: a child/parent message must not undo a user Ctrl+C. We do not want to flip that blindly.Related, not the same report
Enter→resume_queue). A parent cannot press Enter in the child.agent_statuswrites whenprime-inferencehas no auth. We hit the same journal (thousands of identicalneeds_input/summary: ""rows). It makes idle children look busy/stuck in the tree and burns disk. Not the queue-drain bug.Questions for maintainers
agent_end(no abort, no update-restart), should queued parentagent_messages drain automatically? If yes, is_scheduleSessionInputPump()onagent_end(no-op while_sessionInputPumpSuspended) the intended fix, or is there another wake we missed?acceptAgentMessagePrompt({ resumeIfIdle: false })only meant to preserve Ctrl+C / update-restart holds? If so, should idle + not-suspended parent→child still useimmediatelyEligible/ schedule the pump without clearing the abort flag?resume_queueexists, butagent_messagedoes not call it, and#1519is TUI-only.agent_observeexpose something likequeuedCount+idleMs/ last activity so a parent can tell "queued and idle" from "still in a turn"? The list summary already hasisStreaming/queuedCount, but nothing that means "pump parked" or "last message age".Happy to open a PR if you want implementation on a specific option. We would rather not guess the abort / update-restart invariants.
Environment
main)agent_messageAll reactions