Skip to content

fix(adk): stop forwarding backgrounded sub-agent events to the parent turn#1128

Merged
hi-pender merged 3 commits into
alpha/10from
fix/subagent-background-event-forwarding
Jul 6, 2026
Merged

fix(adk): stop forwarding backgrounded sub-agent events to the parent turn#1128
hi-pender merged 3 commits into
alpha/10from
fix/subagent-background-event-forwarding

Conversation

@hi-pender

Copy link
Copy Markdown
Contributor

Summary

  • A managed sub-agent run that is backgrounded (explicit run_in_background, or auto-moved to the background at the foreground deadline) runs detached and outlives the turn that launched it. It kept forwarding the inner agent's events to the parent turn's event generator, which the turn closes on end — injecting events into a stream the user has stopped watching, and racing a send against that close.
  • Introduce a lifecycle signal backgroundtask.TaskInfo.Backgrounded (<-chan struct{}) that closes when a task moves to the background: before work starts for an explicit RunInBackground launch, and at the auto-background transition (detach). Foreground-completing runs never fire it.
  • Add AgentTool option adk.WithAgentToolParentForwardUntil(done) that bounds parent forwarding by that signal. The subagent middleware wires the two together, so forwarding stops the moment a run detaches; foreground runs are unaffected.

Design notes

  • Concerns are decoupled: backgroundtask owns the lifecycle signal (event-agnostic), adk/agent_tool owns the forwarding action + the "forward until" gate, subagent middleware is the only layer that wires them (one line in the work closure). No reading/overriding of the parent generator option, no interposed channel/pump/atomic.
  • The gated (background-capable) path uses a non-panicking send by definition — it may outlive its consumer. The plain foreground AgentTool path keeps a panicking Send, so a send on an unexpectedly-closed generator still surfaces as the bug it is.
  • Known, documented residual: under auto-background the detached forwarder's lifetime exceeds the parent turn; the gate narrows but cannot fully eliminate the race with the parent close. The gated path's non-panicking send is what makes that safe, and it does not affect the synchronous path.

Test plan

  • go test -race ./adk/... (passes locally)
  • golangci-lint run ./adk/... (0 issues locally)
  • backgroundtask: signal timing — explicit (closed before work), foreground (stays open), auto-background (closes at detach)
  • adk/agent_tool: open gate forwards, closed gate drops, closed parent generator on gated path does not panic

🤖 Generated with Claude Code

@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.75000% with 3 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (alpha/10@c8af907). Learn more about missing BASE report.

Files with missing lines Patch % Lines
adk/agent_tool.go 86.66% 2 Missing ⚠️
adk/backgroundtask/manager.go 95.83% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             alpha/10    #1128   +/-   ##
===========================================
  Coverage            ?   81.84%           
===========================================
  Files               ?      189           
  Lines               ?    30578           
  Branches            ?        0           
===========================================
  Hits                ?    25028           
  Misses              ?     3737           
  Partials            ?     1813           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread adk/agent_tool.go Outdated
hi-pender and others added 3 commits July 5, 2026 12:35
… turn

A managed sub-agent run that is backgrounded (explicit run_in_background or
auto-moved at the foreground deadline) runs detached and outlives the turn
that launched it. It kept forwarding the inner agent's events to the parent
turn's event generator, which the turn closes on end — injecting events into a
stream the user has stopped watching, and racing a send against that close.

Introduce a lifecycle signal (backgroundtask TaskInfo.Backgrounded) that closes
when a task moves to the background, and an AgentTool option
(WithAgentToolParentForwardUntil) that bounds parent forwarding by it. The
subagent middleware wires the two together, so forwarding stops the moment a run
detaches; foreground runs are unaffected. The gated path uses a non-panicking
send by definition (it may outlive its consumer); the plain foreground path
keeps a panicking send so an unexpected closed-generator send still surfaces.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
…ntation

Make the two halves of AgentTool event forwarding read as a pair: the target
(where inner events go) and the bound (how long they go there).

- withAgentToolEventGenerator     -> withAgentToolEventForwardTarget
- withTypedAgentToolEventGenerator -> withTypedAgentToolEventForwardTarget
- WithAgentToolParentForwardUntil  -> WithAgentToolEventForwardUntil
- agentToolOptions.gatedForward/forwardParentUntil ->
  eventForwardGated/eventForwardUntil

Behavior is unchanged; this is a naming-only refactor.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
….ForwardGate

Move the event-forwarding gate option to a self-documenting ForwardGate
struct in internal/agenttool, replacing the split across agentToolOptions
and the exported WithAgentToolEventForwardUntil. Also remove the AgentEvent
type-specialization wrapper (withAgentToolEventForwardTarget) in favor of
the generic withTypedAgentToolEventForwardTarget.

Co-Authored-By: Claude <noreply@anthropic.com>
@hi-pender hi-pender force-pushed the fix/subagent-background-event-forwarding branch from 5b5414b to b065dd3 Compare July 6, 2026 03:45
@hi-pender hi-pender merged commit 43d03da into alpha/10 Jul 6, 2026
16 checks passed
@hi-pender hi-pender deleted the fix/subagent-background-event-forwarding branch July 6, 2026 07:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants