Google ADK Java 1.0版本 核心机制与实战 Demo

Google ADK Java 1.2 核心机制与实战 Demo

本文基于源码 /com/google/adk/google-adk/1.2.0/google-adk-1.2.0-sources.jar 阅读整理,同时参考 ADK 在线文档。需要注意:在线文档会持续演进,可能展示高于 1.2.0 的 API 或新增能力。本文讨论的源码级实现细节,以 ADK Java 1.2.0 为准。

1. 先用一句话理解 ADK

ADK 可以理解成一个"Agent 应用运行时":你把模型、提示词、工具、子 Agent、会话服务、插件等组件交给它,它负责把一次用户请求变成一串可观察、可持久化、可扩展的 Event

最小运行链路是:

text 复制代码
用户输入 Content
  -> Runner.runAsync(userId, sessionId, content)
  -> SessionService 读取/创建 Session
  -> Runner 把用户消息追加成 user Event
  -> InvocationContext 携带 session、services、plugins、runConfig
  -> BaseAgent.runAsync(...)
  -> LlmAgent / SequentialAgent / ParallelAgent / LoopAgent 执行
  -> 产出 Event 流
  -> Runner 把 Event 回写 Session,并触发 Plugin

这条链路里最关键的概念只有五个:

概念 通俗解释 源码类
Agent 干活的人或流程节点 BaseAgentLlmAgentSequentialAgentParallelAgentLoopAgent
Runner 调度器和执行入口 RunnerInMemoryRunner
Session 一条对话线程 SessionStateBaseSessionService
Event 执行过程留下的记录 EventEventActions
Tool/Plugin/Callback 扩展点 FunctionToolToolContextPluginCallbacks

官方文档也把这些列为 ADK 的核心原语:Agent、Tool、Callbacks、Session/State、Memory、Artifact、Planning、Model、Event、Runner。

2. Agent:ADK 的执行单元

BaseAgent 是所有 Agent 的基类。源码里它做了几件基础但很重要的事:

  1. 校验 Agent 名称,禁止空名称和保留名称 user
  2. 维护父子树关系,subAgents 会自动设置 parentAgent
  3. 统一执行模板:先触发 before-agent 插件和回调,再执行子类的 runAsyncImpl,最后触发 after-agent 插件和回调。
  4. 每次执行都会从父 InvocationContext 拷贝一个新 context,并把当前 agent 和 branch 信息写进去。

也就是说,BaseAgent 提供的是"生命周期骨架",真正干活的是各个子类。

2.1 LlmAgent:会调用模型的 Agent

LlmAgent 是最常用的智能 Agent。源码中的 Builder 支持:

能力 说明
model(...) 指定模型名称或 BaseLlm 实例
instruction(...) 当前 Agent 的任务指令
globalInstruction(...) 全局指令
tools(...) 注入 BaseToolBaseToolset
outputKey(...) 把最终回复写入 session state
planning(...) 开启规划能力
maxSteps(...) 限制模型-工具循环步数
inputSchema(...) / outputSchema(...) 约束输入输出结构
model/tool/agent callbacks 在模型、工具、Agent 生命周期中插入自定义逻辑
codeExecutor(...) 代码执行能力

最常见的 Java 写法是直接用 Builder 创建 LlmAgent

java 复制代码
LlmAgent llmAgent = LlmAgent.builder()
        .name("javaTutor")
        .description("回答 Java 学习问题")
        .model("gemini-2.5-flash")
        .instruction("你是一个 Java 技术导师,回答要准确、简洁、带例子。")
        .outputKey("answer")
        .build();

如果你使用 Spring AI,也可以通过 google-adk-spring-ai 模块把 Spring AI 的 ChatModel 适配成 ADK 可调用的模型;但这属于集成选择,不影响 ADK 自身的 Agent 执行机制。

outputKey 值得单独说一下。LlmAgent 在源码中会检查事件是否是 finalResponse(),如果是,就把最终文本写入 event.actions().stateDelta()。随后 Runner 把事件追加到 Session,SessionService 再把 stateDelta 合并进当前会话状态。这样后续 Agent 就可以通过 state 读取上一步结果。

2.2 Workflow Agent:不靠模型做编排

ADK 1.2.0 的 SequentialAgentParallelAgentLoopAgent 都是确定性编排节点。它们自己不问模型"下一步怎么走",而是按固定源码逻辑调度子 Agent。

Agent 源码执行逻辑 适合场景
SequentialAgent Flowable.fromIterable(subAgents()).concatMap(...) 分析 -> 生成 -> 审查等流水线
ParallelAgent 为分支设置 branch,然后 Flowable.merge(...) 多路研究、多方案生成、多视角分析
LoopAgent 子 Agent 串行执行后 repeat(...),直到 maxIterationsescalate 生成-检查-修正这类迭代流程

这也是理解 ADK workflow 的关键:workflow agent 是"确定性控制器",不是"LLM 决策器"。官方文档也强调 template workflow agents 根据预定义逻辑控制子 Agent 的执行顺序,具有可预测的执行模式。

3. Runner:一次请求真正从这里开始

Runner 是 ADK 的执行引擎。InMemoryRunner 只是一个便捷封装,它默认装配:

text 复制代码
InMemoryArtifactService
InMemorySessionService
InMemoryMemoryService

所以 InMemoryRunner 很适合本地开发、单机 demo、单元测试,但不适合直接承担生产级持久化。进程重启后,内存里的 Session、State、Memory 都会丢失。

源码里 Runner.runAsync(...) 的主要步骤是:

  1. appName + userId + sessionIdSessionService 读取会话。
  2. 如果配置允许,也可以自动创建会话。
  3. 构造 InvocationContext,把 Session、Agent、Services、PluginManager、RunConfig 放进去。
  4. 触发 onUserMessageCallback,允许插件改写用户输入。
  5. 把用户输入追加成一个 author=userEvent
  6. 重新读取更新后的 Session。
  7. 执行当前应该运行的 Agent。
  8. 把 Agent 产出的每个 Event 追加回 Session。
  9. 对每个事件触发 onEventCallback
  10. 执行完成后触发 afterRunCallback,并按配置压缩历史事件。

这里有一个工程细节很重要:同一个 sessionId 上的请求会被 activeSessionCompletables 串行化。也就是说,同一会话里的多次 runAsync 不会随意并发交错,这对维护上下文一致性很关键。

4. Session、State、Event:ADK 的上下文账本

很多 Agent 框架最难调试的地方是:模型到底看到了什么、工具何时被调用、状态什么时候变了。ADK 的答案是把过程事件化。

4.1 Session 是一条会话线程

Session 持有:

java 复制代码
private final String id;
private final String appName;
private final String userId;
private final State state;
private final List<Event> events;
private Instant lastUpdateTime;

这说明 Session 不只是"聊天 ID",它同时保存历史事件和当前状态。官方文档也把 Session 描述为当前 conversation thread,包含本次交互中的 Events 和临时 State。

4.2 State 是当前会话内的工作内存

State 实现了 ConcurrentMap<String, Object>,内部有两个 map:

text 复制代码
state: 当前完整状态
delta: 本次新增、修改、删除的状态变更

当你 putreplaceremove 时,State 会同步记录 delta。这样 ADK 可以把"当前状态"和"本次事件造成的状态变化"分开处理。

State 里有三个前缀常量:

前缀 含义
app: 应用级状态
user: 用户级状态
temp: 临时状态

4.3 Event 是可观察、可回放的执行记录

Event 代表执行过程中发生的一件事,例如:

Event 内容 例子
用户消息 author=user,content 是用户输入
模型回复 author=agentName,content 是模型输出
工具调用 content 中包含 functionCall
工具返回 content 中包含 functionResponse
状态变化 actions.stateDelta
工作流控制 actions.escalateactions.transferToAgent
流式片段 partial=true

Event.finalResponse() 的判断也很实用:没有 function call、没有 function response、不是 partial、没有尾部代码执行结果,就可以认为这是最终回复。业务侧常见的同步接口会消费 Flowable<Event>,再用 event.stringifyContent() 抽取内容。

5. Tool:让 Agent 能做事,而不只是聊天

BaseTool 是 ADK 工具基类。它定义了两个核心动作:

  1. declaration():把工具描述成模型能理解的函数声明。
  2. runAsync(args, toolContext):实际执行工具。

FunctionTool 是最常用的工具包装器。它通过 Java 反射读取方法签名,结合 @Schema 注解生成 function declaration,再在模型调用工具时把参数转换为 Java 方法参数。

官方 Java Quickstart 的模式是:

java 复制代码
LlmAgent.builder()
        .name("hello-time-agent")
        .description("Tells the current time in a specified city")
        .instruction("Use the getCurrentTime tool.")
        .model("gemini-flash-latest")
        .tools(FunctionTool.create(HelloTimeAgent.class, "getCurrentTime"))
        .build();

ADK 1.2.0 里还有一个非常适合理解 Loop 的内置工具:ExitLoopTool。它的核心就是:

java 复制代码
toolContext.setActions(
        toolContext.actions().toBuilder()
                .escalate(true)
                .skipSummarization(true)
                .build());

这解释了为什么 LoopAgent 不是解析 "PASS/FAIL" 文本来停止,而是看事件动作:只要某个事件带有 actions.escalate=true,循环就会停止。

6. Plugin 与 Callback:两类扩展点

ADK 有两层拦截机制:

扩展点 作用范围 适合用途
Callback 绑定在某个 Agent 上 单个 Agent 的输入校验、模型请求改写、工具结果修正
Plugin 注册在 Runner 上,全局生效 日志、审计、权限、风控、缓存、指标、统一响应改写

Plugin 接口覆盖的生命周期很完整:

阶段 方法
用户消息进入 onUserMessageCallback
Runner 开始 beforeRunCallback
Agent 前后 beforeAgentCallbackafterAgentCallback
模型前后和异常 beforeModelCallbackafterModelCallbackonModelErrorCallback
工具前后和异常 beforeToolCallbackafterToolCallbackonToolErrorCallback
事件产出 onEventCallback
Runner 结束 afterRunCallback
资源释放 close

源码里的 PluginManager 会按注册顺序执行插件。返回 Maybe 的回调采用"第一个非空结果即提前结束"的策略,所以插件顺序会影响最终行为。

7. 实战 Demo:用 Java 写一个"生成-审查-通过即退出"的循环 Agent

下面这个 demo 刻意选择一个能体现 ADK 核心机制的场景:让一个 Agent 生成答案,让另一个 Agent 审查答案。如果审查通过,就调用 exit_loop 工具退出循环;如果不通过,就继续下一轮,最多循环 3 次。

这个例子覆盖了:

  1. LlmAgent 调模型。
  2. LoopAgent 做确定性循环。
  3. SequentialAgent 把"循环"和"最终总结"串起来。
  4. outputKey 把中间结果写入 State
  5. ExitLoopTool 通过 EventActions.escalate=true 控制循环停止。
  6. Runner + Session + Event 完成一次请求执行。

7.1 Maven 依赖

本文 demo 使用的是 1.2.0

xml 复制代码
<dependency>
    <groupId>com.google.adk</groupId>
    <artifactId>google-adk</artifactId>
    <version>1.2.0</version>
</dependency>

如果你直接照官方 Quickstart 新建项目,页面示例可能已经使用更新版本。学习机制时可以看新版;复现本文源码细节时请使用 1.2.0

7.2 Demo 代码

java 复制代码
package demo;

import com.google.adk.agents.BaseAgent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.RunConfig;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.events.Event;
import com.google.adk.runner.InMemoryRunner;
import com.google.adk.sessions.Session;
import com.google.adk.tools.ExitLoopTool;
import com.google.genai.types.Content;
import com.google.genai.types.Part;
import io.reactivex.rxjava3.core.Flowable;

public class ReviewLoopDemo {

    public static void main(String[] args) {
        BaseAgent rootAgent = buildAgent();

        InMemoryRunner runner = new InMemoryRunner(rootAgent, "review-loop-demo");
        Session session = runner.sessionService()
                .createSession(runner.appName(), "user-001")
                .blockingGet();

        Content userMessage = Content.fromParts(Part.fromText("""
                请写一段 150 字以内的 Java Optional 使用建议。
                要求:通俗、准确、包含一个典型误区。
                """));

        Flowable<Event> events = runner.runAsync(
                session.userId(),
                session.id(),
                userMessage,
                RunConfig.builder().build());

        events.blockingForEach(event -> {
            System.out.printf(
                    "[author=%s, final=%s, escalate=%s]%n",
                    event.author(),
                    event.finalResponse(),
                    event.actions().escalate().orElse(false));

            String text = event.stringifyContent();
            if (!text.isBlank()) {
                System.out.println(text);
                System.out.println();
            }
        });
    }

    private static BaseAgent buildAgent() {
        LlmAgent writer = LlmAgent.builder()
                .name("writer")
                .description("生成第一版技术说明")
                .model("gemini-2.5-flash")
                .instruction("""
                        你是 Java 技术作者。
                        根据用户要求写一段短说明。
                        输出必须简洁、准确、适合初学者。
                        """)
                .outputKey("draft")
                .build();

        LlmAgent reviewer = LlmAgent.builder()
                .name("reviewer")
                .description("审查技术说明,合格时退出循环")
                .model("gemini-2.5-flash")
                .instruction("""
                        你是严格的 Java 审稿人。
                        请审查 session state 中的 {draft}。

                        如果 draft 同时满足:
                        1. 150 字以内;
                        2. 对 Optional 的描述准确;
                        3. 包含一个典型误区;
                        4. 对初学者友好;

                        你必须先给出 PASS,然后调用 exit_loop 工具。
                        如果不满足,请给出 FAIL 和需要修改的原因,不要调用工具。
                        """)
                .tools(ExitLoopTool.INSTANCE)
                .build();

        LoopAgent reviewLoop = LoopAgent.builder()
                .name("reviewLoop")
                .description("反复生成和审查,直到 reviewer 通过或达到最大次数")
                .subAgents(writer, reviewer)
                .maxIterations(3)
                .build();

        LlmAgent summarizer = LlmAgent.builder()
                .name("summarizer")
                .description("输出最终答案")
                .model("gemini-2.5-flash")
                .instruction("""
                        你是最终答复 Agent。
                        请读取 session state 中的 {draft}。
                        直接输出当前最终版,不要解释流程。
                        """)
                .build();

        return SequentialAgent.builder()
                .name("root")
                .description("生成、审查、总结")
                .subAgents(reviewLoop, summarizer)
                .build();
    }
}

7.3 这段代码背后的执行过程

text 复制代码
Runner 收到用户问题
  -> 追加 user Event
  -> SequentialAgent(root)
      -> LoopAgent(reviewLoop), 最多 3 轮
          -> writer 生成 draft,并通过 outputKey 写入 stateDelta["draft"]
          -> reviewer 读取 {draft}
              -> 不通过:输出 FAIL,循环进入下一轮
              -> 通过:调用 exit_loop
                   -> ToolContext.actions.escalate = true
                   -> Event.actions.escalate = true
                   -> LoopAgent.takeUntil(...) 停止
      -> summarizer 读取 {draft} 输出最终结果
  -> Runner 把所有 Event 回写 Session

关键点不是"reviewer 输出了 PASS",而是"reviewer 调用了 exit_loop 工具,工具把 escalate 写进 EventActions"。这就是 ADK 里文本语义和流程控制的分界线:文本给人看,EventActions 给运行时看。

7.4 Demo 的工程提醒

  1. InMemoryRunner 的 Session、Memory、Artifact 都是内存实现,重启会丢。
  2. LoopAgent 不会自动解析自然语言判断是否停止,必须通过 tool、callback 或自定义 Agent 写入 escalate
  3. outputKey 只在 finalResponse() 为 true 时保存最终文本。调用 exit_loop 后循环会在工具返回事件处停止,所以不要假设 reviewer 还能再输出一段可保存的最终审查文本。
  4. 多个并行分支不要写同一个 outputKey,否则会有覆盖风险。
  5. 生产环境建议把 SessionServiceMemoryServiceArtifactService 换成可持久化实现,并加上 Plugin 做审计、权限和指标。

8. ADK Java 1.2 的 YAML 配置能力

除了用 Builder 手写 Agent,ADK Java 1.2.0 源码里还提供了一套 YAML 配置加载能力,入口是:

java 复制代码
BaseAgent rootAgent = ConfigAgentUtils.fromConfig("agents/root.yaml");
InMemoryRunner runner = new InMemoryRunner(rootAgent, "yaml-demo");

示例代码需要的核心 import 是:

java 复制代码
import com.google.adk.agents.BaseAgent;
import com.google.adk.agents.ConfigAgentUtils;
import com.google.adk.runner.InMemoryRunner;

这套能力的定位要说清楚:源码注释里标了 Config agent features are not yet ready for public use.,所以在 1.2.0 中更适合当作实验性配置能力理解。它的价值在于把 Agent 树、workflow、工具引用、callback 引用从 Java Builder 代码里抽出来,便于阅读和调整。

8.1 YAML 到 Agent 的加载过程

ConfigAgentUtils.fromConfig(...) 的源码流程是:

text 复制代码
读取 YAML 文件
  -> YamlPreprocessor 把 snake_case key 转成 camelCase
  -> 先反序列化成 BaseAgentConfig,读取 agent_class
  -> ComponentRegistry.resolveAgentClass(agent_class)
  -> 根据 Agent 类型选择具体 Config 类
       LlmAgentConfig / SequentialAgentConfig / ParallelAgentConfig / LoopAgentConfig
  -> 再次反序列化 YAML
  -> 反射调用 XxxAgent.fromConfig(config, configAbsPath)
  -> 递归解析 sub_agents、tools、callbacks
  -> 返回 BaseAgent

其中 YamlPreprocessor 很实用:你可以在 YAML 里写更自然的 agent_classoutput_keymax_iterations,它会转成 Java 对象需要的 agentClassoutputKeymaxIterations

agent_class 不写时默认是 LlmAgentComponentRegistry 默认预注册了 ADK 核心 Agent 类,所以 LlmAgentSequentialAgentParallelAgentLoopAgent 这些简单名可以直接用;自定义 Agent 则需要提前注册到 ComponentRegistry,或者使用能被 registry 解析的类名。

8.2 LlmAgent YAML 示例

writer.yaml

yaml 复制代码
agent_class: LlmAgent
name: writer
description: 生成第一版技术说明
model: gemini-2.5-flash
instruction: |
  你是 Java 技术作者。
  根据用户要求写一段短说明。
  输出必须简洁、准确、适合初学者。
output_key: draft

这个文件会被加载为 LlmAgentConfig,再由 LlmAgent.fromConfig(...) 创建 LlmAgent。在 1.2.0 里,LlmAgentConfig 支持的主要字段包括:

YAML 字段 Java 配置字段 作用
agent_class agentClass Agent 类型,例如 LlmAgent
name name Agent 名称
description description Agent 描述
model model 模型名称
instruction instruction 任务指令
output_key outputKey 把最终回复写入 session state
tools tools 工具或工具集引用
include_contents includeContents 是否携带历史内容
generate_content_config generateContentConfig 透传模型生成配置
disallow_transfer_to_parent disallowTransferToParent 禁止向父 Agent 转交
disallow_transfer_to_peers disallowTransferToPeers 禁止向同级 Agent 转交
before_agent_callbacks / after_agent_callbacks agent callbacks Agent 前后回调
before_model_callbacks / after_model_callbacks model callbacks 模型前后回调
before_tool_callbacks / after_tool_callbacks tool callbacks 工具前后回调

8.3 Workflow YAML 示例

review-loop.yaml

yaml 复制代码
agent_class: LoopAgent
name: reviewLoop
description: 反复生成和审查,直到通过或达到最大次数
max_iterations: 3
sub_agents:
  - config_path: writer.yaml
  - config_path: reviewer.yaml

root.yaml

yaml 复制代码
agent_class: SequentialAgent
name: root
description: 生成、审查、总结
sub_agents:
  - config_path: review-loop.yaml
  - config_path: summarizer.yaml

sub_agents 支持两种引用方式:

写法 含义
config_path: writer.yaml 从另一个 YAML 文件递归加载子 Agent,支持相对路径
code: someRegisteredAgent ComponentRegistry 里读取已注册的 Agent 实例

这种拆分方式比较适合多 Agent 应用:每个 LLM Agent 一个 YAML,workflow YAML 只负责组织结构。

8.4 Tool 和 Callback 如何配置

在 YAML 中,tools 是一组 ToolConfig

yaml 复制代码
tools:
  - name: com.google.adk.tools.ExitLoopTool.INSTANCE
  - name: com.example.tools.SearchTool
    args:
      endpoint: https://search.example.com
      timeout_ms: 3000

源码里的 ToolResolver 会按顺序尝试:

  1. ComponentRegistry 解析已注册的 tool/toolset 实例。
  2. 如果 name 像 Java 全限定名,尝试通过反射读取静态字段,例如 com.google.adk.tools.ExitLoopTool.INSTANCE
  3. 尝试把 name 当成 BaseTool 子类,使用默认构造器创建。
  4. 如果提供了 args,要求工具类提供静态 fromConfig(ToolArgsConfig, String) 工厂方法。
  5. BaseToolset 也有类似解析逻辑。

ComponentRegistry 默认还预注册了几个常用工具实例,例如 google_searchcode_executionexit_loopurl_contextgoogle_maps_grounding。因此退出循环工具也可以写成:

yaml 复制代码
tools:
  - name: exit_loop

Callback 引用也不是直接在 YAML 里写 Java 代码,而是写注册名:

yaml 复制代码
before_model_callbacks:
  - name: safetyGuard
after_tool_callbacks:
  - name: auditToolResult

这些名字会通过 ComponentRegistry 解析成对应 callback 实例。因此,YAML 配置负责声明结构和引用,真正的 Java 对象仍然需要提前注册或能被反射创建。

8.5 YAML 配置的边界

ADK Java 1.2.0 的 YAML 能力适合描述 Agent 树和基础参数,但不要把它理解成完整的低代码编排语言。

能力 1.2.0 YAML 支持情况
创建 LlmAgent 支持
创建 SequentialAgent / ParallelAgent / LoopAgent 支持
sub_agents.config_path 组合多文件 Agent 树 支持
引用注册过的 Agent / Tool / Callback 支持
配置 output_keytoolsgenerate_content_config 支持
声明 if/else、switch、DAG 条件边 不支持
LoopAgent 自动解析 PASS/FAIL 文本停止 不支持,仍需要 tool/callback/custom agent 写入 escalate
配置 Runner、SessionService、MemoryService、ArtifactService 这套 Agent YAML 不负责,需要 Java 代码装配 Runner

一句话总结:YAML 负责"声明 Agent 是谁、怎么连、带哪些工具和回调";Runner、会话服务、持久化、部署等运行时设施,仍然建议用 Java 代码显式装配。

9. 附录:ADK 能力组件速查表

能力组件 关键类/概念 Java 1.2.0 状态 用途 使用建议
基础 Agent BaseAgent 支持 所有 Agent 的生命周期模板和父子树管理 自定义确定性节点时继承它
LLM Agent LlmAgent 支持 调用模型、工具、规划、保存输出 常规智能任务首选
串行工作流 SequentialAgent 支持 子 Agent 逐个执行 适合流水线
并行工作流 ParallelAgent 支持 子 Agent 并发执行并合并事件流 注意 branch 和 outputKey 冲突
循环工作流 LoopAgent 支持 子 Agent 重复执行 停止依赖 maxIterationsescalate
Agent 树 parentAgentsubAgentsrootAgent() 支持 组织多 Agent 层级 Agent 名称必须唯一
动态路由/转交 transferToAgentAutoFlow 支持基础能力 LLM 决定转交给父/同级 Agent 复杂业务需加约束和观测
执行入口 Runner 支持 编排 Session、Agent、Plugin、Service 生产中优先 Builder 和持久化服务
本地运行器 InMemoryRunner 支持 快速创建内存版 Runner 适合 demo,不适合生产持久化
运行配置 RunConfig 支持 控制运行参数、流式、工具执行模式等 按接口场景显式传入
调用上下文 InvocationContext 支持 贯穿一次 invocation 的上下文对象 Tool、Callback、Plugin 读取运行时信息
会话 Session 支持 保存会话 ID、用户、应用、状态、事件 作为一条对话线程管理
会话服务 BaseSessionServiceInMemorySessionServiceVertexAiSessionService 支持 创建、读取、追加事件、管理会话 生产换持久化实现
状态 State 支持 当前 Session 内工作内存和 delta 跟踪 outputKey 或 callback/tool 写入
长期记忆 BaseMemoryServiceInMemoryMemoryService 支持 跨 Session 检索长期信息 用户画像、长期偏好、知识摘要
事件 Event 支持 用户消息、模型回复、工具调用、状态变化 调试和前端流式输出的核心
事件动作 EventActions 支持 状态变更、artifact 变更、转交、升级、确认请求 流程控制不要只依赖文本
内容 Content 支持 一条消息 由多个 Part 组成
消息片段 Part 支持 文本、函数调用、函数响应、文件/图片等 多模态入口使用它
工具基类 BaseTool 支持 工具声明和执行抽象 自定义复杂工具时继承
函数工具 FunctionTool 支持 把 Java 方法包装成模型可调用工具 参数建议加 @Schema
长耗时工具 LongRunningFunctionTool 支持 处理需要异步确认或长时间执行的任务 适合工单、审批、外部任务
Agent 作为工具 AgentTool 支持 让一个 Agent 被另一个 Agent 当工具调用 适合封装子能力
退出循环工具 ExitLoopTool 支持 设置 escalate=true 退出 Loop 条件循环的标准做法
工具上下文 ToolContext 支持 工具访问 actions、memory、confirmation 工具需要影响流程时使用
工具集 BaseToolset 支持 动态提供一组工具 适合 MCP、外部系统工具集合
MCP 工具 McpToolsetMcpAsyncToolsetMcpTool 支持 接入 MCP Server 暴露的工具 适合外部工具生态
内置搜索/地图等工具 GoogleSearchToolGoogleMapsToolVertexAiSearchTool 支持部分 搜索、地图、企业检索 视模型和平台权限使用
模型抽象 BaseLlmModelLlmRegistry 支持 屏蔽底层模型提供商差异 多模型接入从这里扩展
Gemini 模型 Gemini 支持 Google Gemini 接入 官方默认路线
Claude/Apigee/Chat 模型适配 ClaudeApigeeLlmchat/* 支持 非 Gemini 或网关接入 结合企业网关治理
Spring AI 适配 google-adk-spring-aiSpringAI 支持 把 Spring AI ChatModel 接入 ADK 适合 Spring 项目
Agent callback beforeAgentCallbackafterAgentCallback 支持 单 Agent 前后处理 局部逻辑用 callback
Model callback beforeModelCallbackafterModelCallbackonModelErrorCallback 支持 模型请求改写、响应审计、异常兜底 做 prompt 注入、缓存、降级
Tool callback beforeToolCallbackafterToolCallbackonToolErrorCallback 支持 工具权限、参数校验、结果修正 生产必须加审计和权限
Plugin PluginBasePluginPluginManager 支持 Runner 全局拦截器 横切能力优先用 Plugin
日志插件 LoggingPlugin 支持 记录运行过程 本地调试和审计
上下文过滤插件 ContextFilterPlugin 支持 控制上下文内容 控制成本和隐私
全局指令插件 GlobalInstructionPlugin 支持 注入全局要求 安全、风格、合规提示
BigQuery 分析插件 BigQueryAgentAnalyticsPlugin 支持 事件和行为分析 企业观测场景
Artifact BaseArtifactServiceInMemoryArtifactService 支持 保存文件、图片、代码、报告等二进制产物 多模态和文件生成场景
输入文件落盘 saveInputBlobsAsArtifacts 支持 把 inline bytes 保存成 artifact 大文件不要长期塞进 prompt
代码执行 BaseCodeExecutorBuiltInCodeExecutionTool 支持 让 Agent 生成并执行代码 注意沙箱和权限
规划 planning 支持 复杂任务拆解 需要配合 maxSteps 和工具观测
结构化输入输出 inputSchemaoutputSchema 支持 限定模型输入输出结构 面向 API 集成时优先使用
流式执行 runLiveLiveRequestQueueActiveStreamingTool 支持部分 实时文本/音频/工具流 Java 1.2 中 workflow live 支持不完整
事件压缩 EventsCompactionConfigSlidingWindowEventCompactor 支持 控制长会话上下文长度 长对话生产环境需要
Dev UI google-adk-devAdkWebServer 支持 本地调试 Agent 只用于开发调试
评估 官方 CLI/Dev UI evaluation 生态支持 多轮数据集评估 Agent 质量 生产前应建立回归集
部署 官方运行时/Cloud Run/GKE 等 生态支持 上线 Agent 应用 Java 项目需结合自身服务框架
A2A A2A Protocol 文档与组件 生态支持 Agent 间协议互操作 多 Agent 跨系统协作时关注

10. 参考资料

相关推荐
Tbisnic1 小时前
AI大模型学习第十一天:技术选型、安全防护与金融实战
python·学习·ai·大模型·提示词工程
Roann_seo%1 小时前
C++文件操作完全指南:从文本读写到二进制文件处理
开发语言·c++
hboot2 小时前
AI工程师第一课 - Python
前端·后端·python
焦虑的说说2 小时前
秒杀系统设计方案
java
huangdong_2 小时前
淘宝商品SKU图自动分类技术深度解析:从DOM解析到智能归档
开发语言·javascript·ecmascript
阿正的梦工坊2 小时前
【Rust】12-借用检查器与非词法生命周期
开发语言·后端·rust
许彰午2 小时前
30_Java Stream流操作全解
java·windows·python
qq_2518364573 小时前
基于java Web网络订餐系统设计与实现 源码文档
java·开发语言·前端
秋93 小时前
3年经验Python后端转AI Engineer:3个月实战转型计划(2026版)
开发语言·人工智能·python