fix: use session-pinned agent in RunStream instead of shared currentAgent#2009
Open
dgageot wants to merge 1 commit intodocker:mainfrom
Open
fix: use session-pinned agent in RunStream instead of shared currentAgent#2009dgageot wants to merge 1 commit intodocker:mainfrom
dgageot wants to merge 1 commit intodocker:mainfrom
Conversation
There was a problem hiding this comment.
Review Summary
Assessment: 🟢 APPROVE
This PR correctly fixes a critical bug where background sub-agents were using the root agent's configuration instead of their own. The implementation is sound:
✅ resolveSessionAgent(sess) implementation is correct
- Properly checks
sess.AgentNamefirst for background agent tasks - Safely handles errors from
team.Agent()by falling back toCurrentAgent() - Returns a non-nil agent in all cases
✅ All call sites correctly updated
RunStream: Uses resolved agent consistently throughout the loopprocessToolCalls: Now uses session-pinned agentfinalizeEventChannel: Correctly resolves agent for StreamStopped eventSummarize: Properly resolves agent for compaction eventsconfigureToolsetHandlers&emitAgentWarnings: Now use the passed agent parameter instead of independently callingCurrentAgent()
✅ Eliminates race condition
- Background agent sessions no longer race on the shared
currentAgentfield - Each session consistently uses its pinned agent throughout its lifecycle
✅ Nil-pointer safety improved
- Previous inline code silently discarded errors from
team.Agent()which could theoretically leave agent nil - New helper always returns a valid agent
Findings
No issues identified in the changed code. The refactoring is clean, the fix addresses the root cause, and the implementation handles edge cases correctly.
…gent Sub-agents dispatched via run_background_agent executed with root's toolset, model, and instructions because RunStream resolved the agent through the shared currentAgent field, which is never updated for background sessions. Introduce resolveSessionAgent(sess) that checks sess.AgentName first (set for background agent tasks) and falls back to CurrentAgent() for interactive sessions. Use it consistently in RunStream, processToolCalls, finalizeEventChannel, Summarize, and helper methods that already receive the agent but were independently calling CurrentAgentName(). This also fixes a potential nil-pointer panic: the previous inline resolution silently discarded the error from team.Agent() and could leave the agent nil. Assisted-By: docker-agent
ea307ba to
74ed11c
Compare
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.
Problem
Sub-agents dispatched via
run_background_agentexecuted with root's toolset, model, and instructions. This happened becauseRunStreamresolved the agent through the sharedcurrentAgentfield, which is never updated for background sessions.Root Cause
Multiple places in the streaming loop (
RunStream,processToolCalls,finalizeEventChannel,Summarize, and helper methods) independently calledr.CurrentAgent()orr.CurrentAgentName(), which always returns the root agent for background sessions sincerun_background_agentnever callssetCurrentAgent.Fix
Introduce
resolveSessionAgent(sess)— a single method that checkssess.AgentNamefirst (set for background agent tasks) and falls back toCurrentAgent()for interactive sessions. This is used consistently across all affected call sites.Additional fixes
team.Agent()and could leave the agent nil. The new helper always falls back toCurrentAgent().TeamInfoandToolsetInfoevents before the loop usedr.CurrentAgentName()instead of the resolved agent.emitAgentWarnings/configureToolsetHandlers: These methods already received the agent as a parameter but independently calledr.CurrentAgentName()for event names.Summarize: Usedr.CurrentAgentName()andr.CurrentAgent()instead of the session-aware resolution.Assisted-By: docker-agent