Google ADK 全开源:多 Agent 编排框架实战与核心概念解析

发布时间:2026/9/30 4:59:29
Google ADK 全开源:多 Agent 编排框架实战与核心概念解析 1. 从 Hacker News 登顶说起这个项目到底解决了什么痛点如果你最近在折腾 AI Agent大概率会有一种感觉框架多到用不过来。LangChain、AutoGPT、CrewAI、AutoGen、MetaGPT……每隔几周就冒出一个新东西每个都号称能帮你编排多个 Agent 协同干活。但真正上手之后你会发现一个很尴尬的问题——Agent 之间的通信、任务分发、状态管理几乎全靠自己手搓。你写一个 Agent 负责查资料再写一个负责写代码第三个负责审核然后你发现它们之间怎么传消息、怎么保证不重复劳动、怎么在某个 Agent 挂掉之后自动恢复这些破事全得自己处理。这就是 Google 这次开源的Agent Development KitADK想要解决的问题。项目在 Hacker News 上登顶那天我正好在刷看到标题里写着 “Apache 2.0 全开源”第一反应是Google 终于舍得把内部用的 Agent 编排框架拿出来了。要知道 Google 内部做 Agent 相关的东西已经有好几年了从最早的 Dialogflow 到后来的 Vertex AI Agent Builder积累了不少工程经验。这次开源的 ADK 不是那种“演示级”的玩具而是一个面向生产环境的 Agent 开发框架支持多 Agent 编排、工具调用、状态管理、可观测性等一整套东西。简单来说ADK 能帮你做这几件事定义单个 Agent 的能力边界它能用什么工具、能访问什么数据把多个 Agent 组织成一个工作流谁先谁后、谁给谁传数据管理整个执行过程的状态某个步骤失败了怎么重试、上下文怎么传递以及提供调试和监控的手段每个 Agent 到底干了什么、花了多少 token。适合谁用如果你正在做 AI 应用开发尤其是那种需要多个 Agent 协作完成复杂任务的场景比如自动客服、代码生成流水线、数据分析管道那 ADK 值得你花时间研究一下。哪怕你只是好奇 Google 内部是怎么做 Agent 编排的这个项目的源码也很有参考价值。2. 核心设计思路拆解为什么 Google 要造这个轮子2.1 现有 Agent 框架的三大痛点在 ADK 出现之前市面上主流的 Agent 框架大致分两类。一类是通用编排框架比如 LangChain 的 Agent 模块和 AutoGen它们提供了很灵活的抽象但灵活意味着你需要自己定义很多东西。另一类是垂直场景框架比如专门做代码生成的 MetaGPT开箱即用但很难定制。这两类框架在实际生产环境中都会遇到问题。第一个痛点是状态管理混乱。多 Agent 协作时每个 Agent 都有自己的上下文这些上下文怎么共享、怎么隔离、怎么在 Agent 之间传递大部分框架没有给出标准答案。你经常需要自己写一个全局的 state 对象然后在各个 Agent 之间手动传递代码写起来又臭又长。第二个痛点是错误处理缺失。单个 Agent 调用 LLM 可能会超时、可能会返回格式错误的结果、可能会陷入死循环。多 Agent 场景下一个 Agent 挂掉可能导致整个工作流卡死。大部分框架只提供了最基础的 try-catch没有内置重试、降级、回滚机制。第三个痛点是可观测性差。当你有五六个 Agent 协同工作时出了问题你根本不知道是哪个环节出了错。是第一个 Agent 没查到资料还是第二个 Agent 解析错了还是第三个 Agent 调用工具时参数传错了没有详细的日志和追踪调试全靠 print。2.2 ADK 的解题思路分层抽象 显式编排Google 的 ADK 选择了一条中间路线。它不像 LangChain 那么底层也不像 MetaGPT 那么高层而是把 Agent 开发拆成了几个清晰的概念层。最底层是Agent 定义层。每个 Agent 是一个独立的单元你定义它的名称、描述、使用的模型、可调用的工具列表、以及它的指令instruction。这个指令就是告诉 Agent “你是谁、你能干什么、你不能干什么”。ADK 支持多种类型的 Agent包括基于 LLM 的 Agent、基于规则的 Agent、以及自定义的 Agent。中间层是编排层。ADK 提供了几种编排模式顺序执行Sequential、并行执行Parallel、循环执行Loop、以及条件分支Conditional。你可以把这些模式组合起来形成一个有向图或者工作流。每个节点是一个 Agent边定义了数据流向和执行顺序。这种显式编排的好处是整个流程一目了然不像某些框架那样把逻辑藏在 Agent 的 prompt 里。最上层是运行时层。ADK 内置了一个执行引擎负责调度 Agent、管理状态、处理错误、记录日志。这个执行引擎支持同步和异步两种模式也支持流式输出。你可以把它理解为一个专门为 Agent 工作流设计的轻量级运行时。2.3 为什么选择 Apache 2.0 全开源Google 这次选择 Apache 2.0 许可证而不是像某些项目那样搞“开源核心 商业插件”的模式这个决策很值得玩味。Apache 2.0 意味着你可以自由地商用、修改、分发甚至把它集成到自己的闭源产品里。这对于企业用户来说非常重要——很多公司不愿意把核心业务逻辑绑定在一个许可证不清晰或者有商业限制的框架上。从生态角度看Apache 2.0 也更容易吸引社区贡献。开发者可以放心地提交 PR、写扩展、做集成不用担心自己的贡献被某家公司独占。Google 显然是想把 ADK 做成一个中立的、社区驱动的标准而不是一个只服务于自家云平台的工具。这一点从项目结构也能看出来ADK 的核心代码不依赖任何 Google 特有的服务你可以用 OpenAI 的模型、Anthropic 的模型、或者本地部署的开源模型来跑。3. 核心概念与实操要点从零搭建一个多 Agent 工作流3.1 环境准备与安装ADK 是一个 Python 库目前要求 Python 3.10 以上。安装方式很简单直接 pip 安装即可。不过要注意ADK 的依赖比较多建议在虚拟环境里安装避免和系统里的其他包冲突。python -m venv adk-env source adk-env/bin/activate # Windows 用 adk-env\Scripts\activate pip install google-adk安装完成后你可以用adk --version来验证是否安装成功。如果遇到依赖冲突最常见的问题是 protobuf 版本不兼容。ADK 依赖较新的 protobuf如果你之前装过 TensorFlow 之类的库可能需要先升级 protobuf。提示如果你在国内网络环境下安装可能会遇到下载速度慢的问题。可以临时指定镜像源比如pip install google-adk -i https://pypi.tuna.tsinghua.edu.cn/simple。这个镜像源是清华大学的开源镜像稳定性和速度都不错。3.2 定义第一个 AgentADK 里定义一个 Agent 非常直观。你只需要创建一个LlmAgent对象指定模型、名称、指令和工具列表。下面是一个最简单的例子一个能查天气的 Agentfrom google.adk.agents import LlmAgent from google.adk.tools import FunctionTool def get_weather(city: str) - dict: 查询指定城市的天气 # 实际项目中这里会调用天气 API return {city: city, temperature: 25°C, condition: 晴} weather_tool FunctionTool(funcget_weather) weather_agent LlmAgent( nameweather_agent, modelgemini-2.0-flash, instruction你是一个天气助手用户问你天气时调用 get_weather 工具查询。, tools[weather_tool] )这里有几个关键点需要注意。instruction参数是 Agent 的“人设”它决定了 Agent 的行为方式。写 instruction 的时候要尽量具体告诉 Agent 什么情况下该调用工具、什么情况下该直接回答。tools参数是一个列表里面可以放多个工具。ADK 会自动把工具的签名和文档字符串转换成 LLM 能理解的格式所以你的工具函数一定要写清楚参数类型和 docstring。3.3 多 Agent 编排的三种模式单个 Agent 只能做简单任务真正体现 ADK 价值的是多 Agent 编排。ADK 提供了三种基本的编排模式你可以根据任务特点来选择。顺序模式适合有明确先后依赖的任务。比如一个“写报告”的工作流先让 research_agent 查资料再把资料传给 writing_agent 写初稿最后让 review_agent 审核。用 ADK 的SequentialAgent可以这样写from google.adk.agents import SequentialAgent report_workflow SequentialAgent( namereport_workflow, sub_agents[research_agent, writing_agent, review_agent] )并行模式适合可以同时进行的子任务。比如你要分析一份数据可以同时让 statistical_agent 做统计分析、visualization_agent 做图表、summary_agent 写摘要最后汇总。用ParallelAgent来实现from google.adk.agents import ParallelAgent analysis_workflow ParallelAgent( nameanalysis_workflow, sub_agents[statistical_agent, visualization_agent, summary_agent] )循环模式适合需要反复迭代的任务。比如代码生成场景你让 code_agent 写代码test_agent 跑测试如果测试不通过就把错误信息传回 code_agent 重新写直到通过或者达到最大迭代次数。用LoopAgent来实现from google.adk.agents import LoopAgent code_workflow LoopAgent( namecode_workflow, sub_agents[code_agent, test_agent], max_iterations5 )这三种模式可以嵌套使用。比如你可以在一个 SequentialAgent 里面放一个 ParallelAgent 作为其中一个步骤实现更复杂的编排逻辑。3.4 状态管理与上下文传递多 Agent 协作时状态管理是最容易出问题的地方。ADK 的做法是引入一个Session概念。每个工作流执行时都会创建一个 SessionSession 里有一个state字典所有 Agent 都可以读写这个字典。Agent 之间传递数据就是通过往 state 里写 key-value 来实现的。# 在 research_agent 里写入数据 def save_research_result(session, result): session.state[research_result] result # 在 writing_agent 里读取数据 def get_research_result(session): return session.state.get(research_result, )这种设计的好处是解耦了 Agent 之间的直接依赖。research_agent 不需要知道谁会消费它的输出writing_agent 也不需要知道数据是谁生产的。但要注意state 是全局共享的如果多个 Agent 同时写同一个 key可能会产生竞态条件。ADK 在并行模式下会为每个子 Agent 创建独立的 state 副本最后再合并避免这个问题。注意state 里不要放太大的对象比如整个 DataFrame 或者大段文本。ADK 会把 state 序列化后存储太大的对象会影响性能。如果确实需要传递大数据建议存到外部存储比如文件或数据库state 里只放引用路径。4. 完整实操流程搭建一个自动代码审查工作流4.1 场景定义与架构设计光说不练假把式。我们用一个完整的例子来演示 ADK 的实际用法自动代码审查工作流。这个工作流的输入是一个 GitHub PR 的 diff输出是一份审查报告包含代码风格问题、潜在 bug、以及改进建议。整个工作流分四个步骤。第一步diff_parser_agent解析 diff提取出变更的文件和代码片段。第二步style_checker_agent检查代码风格比如命名规范、缩进、注释完整性。第三步bug_hunter_agent分析潜在 bug比如空指针、资源泄漏、边界条件。第四步report_writer_agent汇总前两步的结果生成最终的审查报告。这个场景很适合用 ADK 来实现因为四个步骤有明确的先后顺序而且每个步骤都可以独立测试和替换。比如你以后想加一个安全检查步骤只需要在 style_checker 和 bug_hunter 之间插入一个 security_agent 就行不需要改动其他部分。4.2 工具定义与参数计算每个 Agent 都需要一些工具来完成任务。diff_parser_agent 需要一个解析 diff 的工具style_checker_agent 需要一个检查命名规范的工具bug_hunter_agent 需要一个静态分析的工具。这些工具可以用 Python 函数来实现也可以用现成的库。以命名规范检查为例我们可以写一个简单的工具函数import re def check_naming_convention(code: str, language: str python) - list: 检查代码中的命名规范问题 issues [] if language python: # 检查函数名是否使用 snake_case func_pattern rdef\s([a-zA-Z_][a-zA-Z0-9_]*)\s*\( for match in re.finditer(func_pattern, code): func_name match.group(1) if not re.match(r^[a-z_][a-z0-9_]*$, func_name): issues.append(f函数名 {func_name} 不符合 snake_case 规范) # 检查类名是否使用 PascalCase class_pattern rclass\s([a-zA-Z_][a-zA-Z0-9_]*)\s*[:\(] for match in re.finditer(class_pattern, code): class_name match.group(1) if not re.match(r^[A-Z][a-zA-Z0-9]*$, class_name): issues.append(f类名 {class_name} 不符合 PascalCase 规范) return issues这个工具函数虽然简单但已经能覆盖大部分命名规范问题。在实际项目中你可以把它替换成 pylint 或者 flake8 的封装获得更全面的检查能力。4.3 工作流组装与执行定义好各个 Agent 和工具之后就可以组装工作流了。我们用 SequentialAgent 把四个 Agent 串起来from google.adk.agents import LlmAgent, SequentialAgent from google.adk.tools import FunctionTool # 定义工具 parse_diff_tool FunctionTool(funcparse_diff) check_naming_tool FunctionTool(funccheck_naming_convention) static_analysis_tool FunctionTool(funcrun_static_analysis) # 定义 Agent diff_parser LlmAgent( namediff_parser, modelgemini-2.0-flash, instruction你是一个 diff 解析器。用户会给你一个 PR 的 diff你需要调用 parse_diff 工具提取变更的文件和代码片段。, tools[parse_diff_tool] ) style_checker LlmAgent( namestyle_checker, modelgemini-2.0-flash, instruction你是一个代码风格检查器。根据上一步提取的代码片段调用 check_naming 工具检查命名规范并给出风格改进建议。, tools[check_naming_tool] ) bug_hunter LlmAgent( namebug_hunter, modelgemini-2.0-flash, instruction你是一个 bug 猎手。根据代码片段调用 static_analysis 工具进行静态分析找出潜在的 bug 和边界条件问题。, tools[static_analysis_tool] ) report_writer LlmAgent( namereport_writer, modelgemini-2.0-flash, instruction你是一个报告撰写者。汇总前面步骤的风格问题和 bug 问题生成一份结构清晰的审查报告包含问题列表和改进建议。 ) # 组装工作流 code_review_workflow SequentialAgent( namecode_review_workflow, sub_agents[diff_parser, style_checker, bug_hunter, report_writer] )执行这个工作流只需要调用run方法传入初始输入result code_review_workflow.run( input请审查这个 PR\ndiff\ndef BadName():\n pass\n ) print(result.output)ADK 会自动按顺序执行四个 Agent把前一个的输出作为后一个的输入最后返回 report_writer 的输出。4.4 调试与可观测性配置工作流跑起来之后你肯定想知道每个 Agent 到底干了什么。ADK 内置了日志和追踪功能可以通过配置来开启。最简单的方式是设置环境变量ADK_LOG_LEVELDEBUG这样执行过程中会打印详细的日志包括每个 Agent 的输入输出、工具调用参数和返回值。如果你想要更结构化的追踪数据ADK 支持导出 OpenTelemetry 格式的 trace。你可以在代码里配置一个 exporter把 trace 数据发到 Jaeger 或者 Zipkin 之类的追踪系统里。这样你就能看到一个完整的调用链路哪个 Agent 花了多长时间、调用了哪些工具、消耗了多少 token。from google.adk.tracing import setup_tracing setup_tracing( exporterotlp, endpointhttp://localhost:4317, service_namecode-review-workflow )提示在开发阶段建议把ADK_LOG_LEVEL设为 DEBUG方便排查问题。但在生产环境建议设为 INFO 或 WARN避免日志量过大影响性能。另外ADK 的日志里可能会包含代码片段等敏感信息上线前记得检查一下日志脱敏配置。5. 常见问题与排查技巧实录5.1 Agent 不调用工具怎么办这是新手最常遇到的问题。你定义了一个工具但 Agent 就是不用直接用自己的知识回答了。原因通常有三个。第一instruction 写得不够明确没有告诉 Agent 什么情况下必须调用工具。第二工具的 docstring 写得太模糊LLM 不理解这个工具是干什么的。第三模型本身的能力问题一些小模型对工具调用的支持不好。解决办法在 instruction 里明确写“当用户询问 X 时必须调用 Y 工具不要自己编造答案”。工具的 docstring 要写清楚功能、参数含义、返回值格式。如果还是不行换一个工具调用能力更强的模型试试。5.2 工作流执行到一半卡住了多 Agent 工作流卡住的原因比较多。最常见的是某个 Agent 陷入了循环一直在调用同一个工具。ADK 的 LoopAgent 有max_iterations参数可以限制循环次数但 SequentialAgent 里的单个 Agent 如果自己陷入循环就需要在 Agent 层面设置超时。agent LlmAgent( namemy_agent, modelgemini-2.0-flash, instruction..., tools[...], max_tool_calls10 # 限制单个 Agent 最多调用 10 次工具 )另一个常见原因是工具函数抛出了未捕获的异常。ADK 默认会把异常包装成错误信息返回给 Agent但如果异常信息太长或者格式不对Agent 可能会无法理解。建议在工具函数里做好异常处理返回结构化的错误信息。5.3 状态数据丢失或错乱前面提到过并行模式下 ADK 会为每个子 Agent 创建独立的 state 副本。但如果你在并行 Agent 里直接修改了全局变量而不是通过 session.state 来传递数据就会出现数据错乱。记住一个原则所有跨 Agent 的数据传递都必须通过 session.state不要用全局变量或者闭包。另外state 的 key 命名要有规范建议用{agent_name}_{data_name}的格式比如research_agent_result、writing_agent_draft。这样可以避免不同 Agent 之间的 key 冲突。5.4 常见问题速查表问题现象可能原因排查方法解决方案Agent 不调用工具instruction 不明确 / docstring 模糊查看 DEBUG 日志中 Agent 的决策过程明确 instruction完善工具文档工作流卡住Agent 循环调用 / 工具异常检查日志中是否有重复的工具调用设置 max_tool_calls 和超时状态数据丢失未使用 session.state / key 冲突打印 state 字典查看内容统一通过 session.state 传递规范 key 命名输出格式错误instruction 未指定格式 / 模型能力不足查看 Agent 原始输出在 instruction 中给出输出格式示例执行速度慢串行执行 / 模型响应慢查看各步骤耗时改用并行模式或换更快的模型Token 消耗过大上下文过长 / 重复调用查看 token 统计精简 instruction设置上下文窗口限制5.5 几个踩过的坑第一个坑是模型选择。ADK 默认用 Gemini 模型但如果你用 OpenAI 的模型需要额外配置 adapter。我试过用 GPT-4 跑同样的工作流工具调用的成功率明显低于 Gemini尤其是在多轮工具调用的场景下。所以如果你要用非 Gemini 模型建议先做一轮小规模测试。第二个坑是工具函数的参数类型。ADK 会根据函数签名生成工具的 JSON Schema如果参数类型是复杂的嵌套对象生成的 Schema 可能会让 LLM 困惑。建议工具参数尽量用简单类型字符串、数字、布尔值、简单的列表和字典。第三个坑是日志里的敏感信息。ADK 的 DEBUG 日志会打印完整的输入输出如果你的工作流处理的是用户数据或者代码这些信息可能会泄露到日志里。上线前一定要配置日志脱敏或者把日志级别调到 INFO 以上。6. 这个项目后续还能怎么玩ADK 目前还在快速迭代中社区贡献的插件和扩展也越来越多。我个人比较看好的几个方向一是与现有 CI/CD 系统集成把代码审查工作流嵌入到 GitHub Actions 或者 GitLab CI 里每次 PR 自动触发二是多模态 AgentADK 已经开始支持图像和音频输入你可以做一个能看设计稿、听会议录音的 Agent三是本地模型支持随着 Ollama 和 vLLM 的成熟用本地模型跑 ADK 工作流完全可行这对数据敏感的场景很有吸引力。我在实际使用中的体会是ADK 最大的价值不在于它提供了多少现成的功能而在于它把 Agent 开发中的那些“脏活累活”标准化了。状态管理、错误处理、可观测性这些在 demo 阶段可以忽略的东西在生产环境里一个都不能少。Google 把自己踩过的坑变成了框架的一部分这对整个生态来说都是好事。如果你正在做 Agent 相关的项目建议花一个下午把 ADK 的官方示例跑一遍感受一下它的设计思路哪怕最后不用它也能帮你理清很多概念。