Skip to content

feat(adk): export NewEventSenderToolWrapper for customizable tool event position#926

Merged
shentongmartin merged 1 commit intoalpha/09from
feat/customize_tool_event_sender
Apr 1, 2026
Merged

feat(adk): export NewEventSenderToolWrapper for customizable tool event position#926
shentongmartin merged 1 commit intoalpha/09from
feat/customize_tool_event_sender

Conversation

@shentongmartin
Copy link
Copy Markdown
Contributor

@shentongmartin shentongmartin commented Mar 31, 2026

Summary

Item Details
Problem eventSenderToolHandler was unexported and unconditionally injected, giving users no control over when tool-result AgentEvents fire in the middleware chain. The model side already had NewEventSenderModelWrapper for this.
Solution Export NewEventSenderToolHandler() ChatModelAgentMiddleware so users place it in Handlers, controlling its position. Converge default and user paths onto the single eventSenderToolWrapper implementation.
Breaking No — default behavior is preserved when the user does not supply the handler.

Key Insight

The model event sender used a clean interface type-assertion for detection (handler.(*eventSenderModelWrapper)), while the initial tool implementation used sync.Map + reflect.ValueOf().Pointer() because compose.ToolMiddleware is a struct, not an interface. Switching the tool event sender to a ChatModelAgentMiddleware (just like the model wrapper) eliminated this asymmetry — both now use the same detection pattern. The default path also converges: it creates a NewEventSenderToolHandler() and adapts it through handlersToToolMiddlewares, eliminating the old eventSenderToolHandler struct entirely.

What Changed

adk/wrappers.go

  • Removed eventSenderToolHandler struct and its 4 compose-level methods (141 lines of dead code after convergence).
  • Added eventSenderToolWrapper struct implementing ChatModelAgentMiddleware with 4 Wrap*ToolCall methods.
  • Added NewEventSenderToolHandler() ChatModelAgentMiddleware constructor.
  • Added hasUserEventSenderToolHandler() using type assertion (same pattern as hasUserEventSender for models).

adk/chatmodel.go

  • Default path now creates NewEventSenderToolHandler() and converts it via handlersToToolMiddlewares(), then prepends as outermost — no direct compose.ToolMiddleware construction.
  • Detection checks config.Handlers for *eventSenderToolWrapper via type assertion.
  • Documentation updated with "Custom Tool Event Sender Position" section.

adk/wrappers_test.go

  • 12 sub-tests covering all 4 tool types (Invokable, Streamable, EnhancedInvokable, EnhancedStreamable) x 3 scenarios (DefaultSendsEvent, UserConfiguredSkipsDefault, InnermostGetsOriginalOutput).
  • Coverage: WrapInvokableToolCall 83%, WrapStreamableToolCall 90%, WrapEnhancedInvokableToolCall 81%, WrapEnhancedStreamableToolCall 88%, handlersToToolMiddlewares 81%.

Usage

agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Handlers: []adk.ChatModelAgentMiddleware{
        myCustomHandler,                    // Outermost — modifies tool output
        adk.NewEventSenderToolHandler(),    // Innermost — events have original output
    },
})

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (alpha/09@b49a364). Learn more about missing BASE report.

Additional details and impacted files
@@             Coverage Diff             @@
##             alpha/09     #926   +/-   ##
===========================================
  Coverage            ?   81.46%           
===========================================
  Files               ?      158           
  Lines               ?    18902           
  Branches            ?        0           
===========================================
  Hits                ?    15399           
  Misses              ?     2367           
  Partials            ?     1136           

☔ View full report in Codecov by Sentry.
📢 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.

@shentongmartin shentongmartin force-pushed the feat/customize_tool_event_sender branch 3 times, most recently from 0a17522 to 66ddc57 Compare March 31, 2026 13:18
@shentongmartin shentongmartin changed the title feat(adk): export NewEventSenderToolHandler for customizable tool event position feat(adk): export NewEventSenderToolWrapper for customizable tool event position Mar 31, 2026
@shentongmartin shentongmartin force-pushed the feat/customize_tool_event_sender branch from 66ddc57 to 13eb46d Compare March 31, 2026 13:31
…nt position

Change-Id: I273d897c22489b19cda204e257cf1c9050e28280
@shentongmartin shentongmartin force-pushed the feat/customize_tool_event_sender branch from 13eb46d to 04527e2 Compare March 31, 2026 13:36
@shentongmartin shentongmartin merged commit 41ec9e4 into alpha/09 Apr 1, 2026
16 checks passed
@shentongmartin shentongmartin deleted the feat/customize_tool_event_sender branch April 1, 2026 03:41
mrh997 pushed a commit that referenced this pull request Apr 10, 2026
N3kox pushed a commit that referenced this pull request Apr 14, 2026
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