Skip to content

Conversation

@N3kox
Copy link
Contributor

@N3kox N3kox commented Nov 28, 2025

What type of PR is this?

feat


Check the PR title.

  • Title matches the format: <type>(optional scope): <description>
  • The description is user-oriented and clear.
  • Attach the PR updating the user documentation if usage-level awareness is required: N/A

(Optional) Translate the PR title into Chinese.

feat: 为 ADK 引入 Agent 与 Runner 的 Callback 能力


(Optional) More detailed description for this PR (en / zh).

en:

  • Introduce agent-level callbacks for ADK.
    • Add callback hooks to current AgentMiddleware : BeforeAgent and OnEvents
    • Add AgentMiddlewareChecker interface. If an agent implements AgentMiddlewareChecker and enables agent middlewares internally, hooks run inside the agent; otherwise, agent middlewares are executed by the flowAgent.
    • flowAgent / ChatModelAgent / workflowAgent Run/Resume adapt to middleware aspect execution, with partial refactoring of ChatModelAgent to adapt to runtime middleware injection and execution.
    • Add middlewares configuration to Plan-Execute and Supervisor Agent
    • Add globalAgentMiddlewares to inject the same middleware at the outermost layer of all agent runtimes from a global perspective.
  • Introduce Multi-Agent for ADK.
    • Add Multi-Agent structure, at the same conceptual level as ChatModelAgent / WorkflowAgents, to solve the problem that Agent operations are at a flat level and difficult to observe in TransferAgent scenarios.
    • flowAgent adapts to Multi-Agent operation
    • Supervisor Agent constructor returns Multi-Agent
  • Add WithGraphCallbacks AgentRunOption, which provides eino graph/chain callback injection inside an agent (mainly for ChatModelAgent).
  • Provide utility helpers (NewAsyncOnSingleEventHandler, NewSyncOnSingleEventHandler, BypassIterator) for event processing.
  • Add tests to verify middleware execution validity (order, deduplication, termination behavior, interruption/resume flows with tool calls, and global agent middleware propagation).

zh:

  • ADK 支持 Agent 级别的回调
    • 向现有的 AgentMiddleware 中新增切面: BeforeAgentOnEvents
    • 新增 AgentMiddlewareChecker 接口用于检查 Agent 是否支持内部运行 AgentMiddleware。如果支持,AgentMiddleware 将在 Agent 内部运行(由 Agent 自行实现运行逻辑);否则将由 flowAgent 在 Agent 外部运行。
    • flowAgent / ChatModelAgent / workflowAgent Run/Resume 适配 middleware 切面运行,对 ChatModelAgent 部分重构来适配运行时的 middleware 注入与运行。
    • 新增 globalAgentMiddlewares,以全局角度向所有 agent 运行时最外侧注入相同的中间件
  • ADK 支持 Multi-Agent 概念
    • 新增 Multi-Agent 结构,概念层级与 ChatModelAgent / WorkflowAgents 一致,用于解决 TransferAgent 情况下各 Agent 运行处于平铺的层级难以进行观测的问题。
    • flowAgentMulti-Agent 运行进行适配
    • Supervisor Agent 构造方法返回 Multi-Agent
  • 增加 WithGraphCallbacks AgentRunOption,提供向 Agent 内部的 graph/chain 运行 eino callback 的能力(主要面向 ChatModelAgent)
  • 提供多个工具方法,用于处理 Iterator 中的 Events (NewAsyncOnSingleEventHandler, NewSyncOnSingleEventHandler, BypassIterator)
  • 补全 middleware 测试,保证功能正确性(顺序、去重、提前终止、中断恢复场景、工具调用、globalAgentMiddlewares 等)

(Optional) Which issue(s) this PR fixes:

Relates to #513.

To fully resolve the issue here, further adaption in eino-ext is required.


(optional) The PR that updates user documentation:

N/A

@N3kox N3kox force-pushed the feat/adk_cb branch 2 times, most recently from 8061819 to 58ffba4 Compare November 28, 2025 10:19
@github-actions
Copy link

github-actions bot commented Nov 28, 2025

📊 Coverage Report:

File coverage threshold (20%) satisfied:	PASS
Package coverage threshold (30%) satisfied:	PASS
Total coverage threshold (83%) satisfied:	PASS
Total test coverage: 84.6% (6909/8166)

@marwan38
Copy link

Does this PR resolve/relate to #513?
Thank you

@N3kox
Copy link
Contributor Author

N3kox commented Dec 2, 2025

Does this PR resolve/relate to #513? Thank you

Yes, this pr, combined with further prs in eino-ext, will resolve the issues here.

@N3kox N3kox force-pushed the feat/adk_cb branch 3 times, most recently from 818b8c4 to 52ba21c Compare December 3, 2025 09:47
@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

❌ Patch coverage is 86.02151% with 65 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.65%. Comparing base (8d7ea18) to head (72ff0d0).

Files with missing lines Patch % Lines
adk/chatmodel.go 85.77% 19 Missing and 12 partials ⚠️
adk/flow.go 83.78% 7 Missing and 5 partials ⚠️
adk/utils.go 70.37% 6 Missing and 2 partials ⚠️
adk/multi_agent.go 86.04% 3 Missing and 3 partials ⚠️
adk/agent_middleware.go 91.11% 3 Missing and 1 partial ⚠️
adk/prebuilt/supervisor/supervisor.go 83.33% 1 Missing and 1 partial ⚠️
adk/workflow.go 94.87% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #590      +/-   ##
==========================================
+ Coverage   80.36%   80.65%   +0.29%     
==========================================
  Files         124      126       +2     
  Lines       11906    12176     +270     
==========================================
+ Hits         9568     9821     +253     
- Misses       1607     1613       +6     
- Partials      731      742      +11     

☔ 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.

@N3kox N3kox changed the title feat: agent callbacks for adk feat: Runner / Agent callbacks for adk Dec 3, 2025
@N3kox N3kox marked this pull request as ready for review December 4, 2025 02:48
@N3kox N3kox marked this pull request as draft December 4, 2025 06:07
@N3kox N3kox changed the title feat: Runner / Agent callbacks for adk feat: Agent callbacks and Multi-Agent definition for adk Dec 23, 2025
@N3kox N3kox force-pushed the feat/adk_cb branch 4 times, most recently from 5019423 to 0f2c0cf Compare December 23, 2025 07:13
@N3kox N3kox marked this pull request as ready for review December 23, 2025 07:19

// BypassIterator creates a goroutine that simply passes events from the input iterator to the output generator.
// This is useful when you need to do something without modifying events.
func BypassIterator(iter *AsyncIterator[*AgentEvent], gen *AsyncGenerator[*AgentEvent]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要大写吗

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

要的吧,这个也是实现方可能用到的方法,内部反而目前没有使用。
当前不提供 utils 我觉得也 ok。

Messages []Message
}

type EntranceType string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RunType?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我再考虑下

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InvocationType?


// internal properties, read only
agentName string
entrance EntranceType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

指的是当前这个 Agent 是 Run/Resume ,还是 Runner 入口是 Run/Resume?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

前者,不该有后者这个概念吧,Agent 不感知 Runner

continue
}
dedup[mw.Name] = struct{}{}
helper.beforeAgentFns = append(helper.beforeAgentFns, mw.BeforeAgent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mw.BeforeAgents, mw.OnEvents 判空?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bydesign,BeforeAgents 第 n 个立刻返回时,前 n-1 个 OnEvents 要执行,设置空的 func 是为了 padding index,判空由运行时处理

if termIter != nil {
return termIter
}
// TODO: set back input in runCtx ?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要吗

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要,这个是 mw 实现方需要用到的方法

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.

4 participants