Repository navigation
fix(agent-invocations): Route child work by stored parent and fail it on the last try - #2500
Merged
sentry-junior[bot] merged 2 commits intoNov 1, 2026
Conversation
The server picked the worker for a Conversation by asking a list of questions about the work, in order. A wrong order sent a child resume to a root worker. Now the stored parentConversationId decides once: a child Conversation only reaches the child worker, and work that no agent invocation owns is an error instead of falling through. Root wakes also skip the agent invocation SQL reads. Co-Authored-By: David Cramer <[email protected]>
isFinalAttempt came only from message delivery counts, so a resume attempt with no messages was never final. When a resumed Turn kept failing, the worker gave up without telling the adapter. A child agent then stayed paused, the parent was never told, and later results of that child were held back as replaced. The retry count now also marks the last attempt as final. On that attempt the agent invocation worker fails the invocation for any error, also a save error without an AgentRunError wrapper, and reports it to the parent. Root Turns and dispatches get the same final attempt. Co-Authored-By: David Cramer <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
sentry-junior
Bot
merged commit Nov 1, 2026
8be6f2d
into
fix/child-agent-resume-routing
7 checks passed
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2499. Merge that first.
#2499 fixed the reproduced bug, where a child agent's watch-event resume went to the root worker and crashed. This PR fixes the two design gaps behind it, so the same kind of bug cannot happen again quietly.
1. The stored parent picks the worker (
app/conversation-work.ts,agent-invocations/result.ts,cli/chat.ts)Before,
runpicked a worker by trying a list of checks in order: message labels, the Turn Source, and agent invocation lookups. The bug came from that order. Nowrunreads the Conversation record once. If it has aparentConversationId, the work goes only tocreateChildConversationWorker. That worker always returns a result. Work that no agent invocation owns throws an error and does not fall through to a root worker. Root wakes also skip the agent invocation SQL reads they made before.2. A resume attempt can be the final attempt (
task-execution/worker.ts,agent-invocations/work.ts)isFinalAttemptwas set only from how many times a message had been delivered. A resume wake has no messages, so it was never final. When a resumed Turn kept failing, the worker gave up and dropped the mailbox, but no adapter got a chance to record the failure. For a child agent, the invocation stayedpaused. The parent was never told. Later results from that child were also held back asreplaced, becausehasOpenChildWorkstill saw the stuck invocation.Now the retry count also sets
isFinalAttempt: an attempt is final when one more failure reachesCONVERSATION_WORK_MAX_RETRIES. On that attempt, the agent invocation worker fails the invocation for any error and reports it to the parent. This includes save errors without anAgentRunErrorwrapper, which it used to rethrow even on the final attempt. Root conversation Turns and dispatches use the same flag, so a resume that keeps failing now ends with their normal final-attempt failure path (a fallback reply or a failed dispatch), not a silent stall.Worker crashes: this does not need a separate repair job. If a child's worker dies in the middle of a Turn, the next wake fails that Turn through
projectTerminalTurn, well before the retry limit is reached.Tests
The resume test in
agent-invocation-work.test.tsgoes through real production routing. It now has a fourth case: a child yields, then its resume throws on every attempt. Without the worker change, the last attempt gives up (conversation.work.retry.exhausted) and the invocation stays open. With the change, the invocation endsfailedand its result is appended to the parent mailbox.tsc,oxlint, depcruise, the test-architecture check, and the file-length check pass.durable-queue.test.ts(2 tests) andagent-dispatch-work.test.ts(1 test) time out in my sandbox. They time out the same way on the fix(agent-invocations): Route subagent resumes to subagent code #2499 head without this change.Still open (not in this PR)
via David Cramer.
--
View Session [Sentry]