news 2026/9/14 10:09:29

Google ADK(adk-python)Integrations 集成架构指南:可选依赖、懒加载与子包贡献规范

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Google ADK(adk-python)Integrations 集成架构指南:可选依赖、懒加载与子包贡献规范

Google ADK(adk-python)Integrations 集成架构指南:可选依赖、懒加载与子包贡献规范

【免费下载链接】adk-pythonAn open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python

本篇技术指南围绕 src/google/adk/integrations/README.md 展开,系统讲解 ADK 中"集成(Integrations)"目录的定位、设计原则与扩展方式:什么代码应该放进integrations/、如何用可选依赖(extras)保持核心框架轻量、如何通过懒加载给出友好的错误提示,以及如何为外部服务(Agent Registry、BigQuery、Slack、Redis 等)编写自包含的集成子包。读完本文,你将掌握在 adk-python 中新增或使用一个集成模块的完整路径,并能在源码层面理解其背后的依赖管理与加载机制。

Integrations 目录的定位:可扩展的"插槽式"架构

ADK(Agent Development Kit)采用 code-first 的方式构建、评估与部署 AI Agent。随着生态的扩展,Agent 往往需要连接外部工具与服务(Agent Registry、BigQuery、ApiHub、Slack、Redis……)。如果把这些第三方依赖直接打进核心包,会让"轻量的核心"变得臃肿,也会给只使用基础能力的用户带来不必要的安装负担。

为此,adk-python 在 src/google/adk/integrations/ 下划出了一块专门的"集成区":所有与外部系统对接的模块都应放入该目录的子包中。这一集中化管理带来两个直接好处:

  • 可发现性:开发者可以在一处浏览、查找、复用所有官方集成;
  • 可贡献性:第三方集成有明确、统一的落位与规范,社区贡献者更容易参与。

从源码结构看,当前仓库的integrations/下已经存在 21 个集成子包,覆盖 Google Cloud 服务与第三方生态:

集成子包主要职责
agent_identity基于 Google Cloud 的身份凭证与 AuthProvider 方案
agent_registry对接 Google Cloud Agent Registry,注册/发现 Agent 与 MCP Server
api_registry对接 API Registry,管理 API 元数据
bigqueryBigQuery 查询、元数据、搜索与数据洞察工具集
cloud_runCloud Run 部署相关能力
crewai与 CrewAI 工具生态的互操作
daytona/e2b远程沙箱环境(DaytonaEnvironment / E2BEnvironment)
eventarcEventarc 事件发布与消息工具
firestore/gcs/redis持久化存储:Firestore、GCS、Redis 会话服务
langchain与 LangChain 工具/结构的互操作
livekitLiveKit 实时音视频媒体接入
model_armorGoogle Cloud Model Armor 安全防护集成
ociOracle Cloud Infrastructure 生成式 AI(OCIGenAILlm)
parameter_manager/secret_managerGCP 参数与密钥管理
skill_registryGCP Skill Registry
slackSlackRunner:将 Agent 部署到 Slack(Socket Mode)
vmaas漏洞管理相关集成

以上清单依据 src/google/adk/integrations/ 目录实测列出,可作为"什么代码属于这里"的具体参照。

什么属于 Integrations 目录?

原文档给出了两条判断标准,实践中可进一步细化:

  1. 连接外部服务的代码:凡是把 ADK 与其它服务、API 或工具连接起来的模块(例如 agent_registry/agent_registry.py 中直接对https://agentregistry.googleapis.com/v1发起 REST 请求的AgentRegistry客户端),都天然属于此目录。
  2. 依赖第三方库的模块:模块若依赖未包含在 ADK 核心依赖中的第三方库(例如 Slack 集成依赖slack-bolt、Redis 集成依赖redis、Agent Registry 依赖a2a-sdk),也必须放在这里,而不能进入核心包。

反过来,与外部系统无关的通用能力(如 Agent 核心逻辑、Runner、会话服务基类、事件模型等)应留在src/google/adk/下对应的核心子包中(如agents/runners.pysessions/),不要把通用代码放进integrations/

贡献指南详解:五个必须遵守的规范

原文档给出的贡献指南是集成开发的核心约束,以下结合仓库源码逐条展开。

1. 自包含包:每个集成一个独立子目录

每个集成应独立存在于自己的子目录中,例如integrations/my_service/。这样做的目的是保证集成的边界清晰:它可以独立安装、独立测试、独立演进,不会与其它集成产生隐式耦合。

仓库中的 integrations/slack/、integrations/redis/、integrations/bigquery/ 等都是这一模式的实例:每个目录内部都有自己的__init__.py与实现文件,且大多附带独立的 README(如 integrations/slack/README.md、integrations/redis/README.md)。

2. 内部结构自由:不强制遵循核心框架的组织模式

集成子包内部可以自由选择自己的代码结构与设计模式,无需严格照搬核心 ADK 框架的组织方式。例如:

  • integrations/redis/ 内部采用_config.py+_redis_session_service.py的下划线私有模块命名,用 Pydantic 配置类承载连接参数;
  • integrations/agent_registry/ 则用单个agent_registry.py文件承载一个功能完整的高层客户端类;
  • integrations/bigquery/ 拆分为client.pyconfig.pyquery_tool.pymetadata_tool.pysearch_tool.py等多个工具文件。

可见,只要保持"子包自包含",内部是采用扁平单文件、工具拆分、还是配置与实现分离,完全由集成作者根据服务复杂度自行决定。

3. 依赖可选化:extras 是核心原则

为了保持 ADK 核心轻量,集成所需依赖必须是可选的,并通过pyproject.toml中的optional-dependencies(即 pip 的 extras)定义。extra 的名称应与集成目录名一致,用户通过pip install "google-adk[my_service]"安装。

查看仓库根目录的 pyproject.toml,可以看到大量与集成目录一一对应的 extras 定义,例如:

  • optional-dependencies.slackslack-bolt>=1.22aiohttp!=3.14.2(Socket Mode 适配器依赖 aiohttp);
  • optional-dependencies.redisredis>=4.2(注释说明 4.2 是redis.asyncio落地的版本);
  • optional-dependencies.a2aa2a-sdk[http-server]>=0.3.4,<2(Agent Registry 与远程 A2A Agent 需要);
  • optional-dependencies.livekitlivekitlivekit-apipillow(后者用于对入站视频帧做 JPEG 编码);
  • optional-dependencies.ocioci>=2.126
  • optional-dependencies.bigquery-analyticsgoogle-cloud-bigquerygoogle-cloud-storagepyarrow(注释说明 pyarrow 体积约占该 extra 安装体积的三分之一,因此单独拆分);
  • optional-dependencies.gcpmcptoolsextensions等聚合类 extra。

此外optional-dependencies.all是"解锁所有运行时特性"的集合(pyproject.toml中明确排除了 benchmark、community、dev、docs、test 这类服务于构建/测试/文档自身的 extra)。需要一次装齐所有集成能力时可以使用:

pip install "google-adk[all]"

注意:all包含crewai[tools]这类带 Python 版本条件(仅 3.11~3.12)的依赖,实际安装时 pip 会按解释器版本自动过滤。

4. 懒加载:捕获 ModuleNotFoundError 并给出可操作的错误提示

集成代码必须实现懒加载。如果用户未安装对应 extras 就使用该集成,应当捕获ModuleNotFoundError并抛出带有正确安装命令的描述性错误。

这一规范在 integrations/slack/slack_runner.py 中有教科书级的实现:

try: from slack_bolt.adapter.socket_mode.aiohttp import AsyncSocketModeHandler from slack_bolt.app.async_app import AsyncApp except ImportError as e: raise ImportError( "slack_bolt is not installed. Please install it with " '`pip install "google-adk[slack]"`.' ) from e

同样的模式也出现在 integrations/agent_registry/agent_registry.py 中,其错误信息为:

raise ImportError( "AgentRegistry requires the 'a2a-sdk' package. " "Please install it using 'pip install google-adk[a2a]'." ) from e

这里有两个值得借鉴的细节:

  • 使用from e保留原始异常链(raise ... from e),方便调试时追溯根因;
  • 错误信息直接给出精确的安装命令pip install "google-adk[<extra>]",把用户引导到正确的操作上,而不是抛出一个模糊的ModuleNotFoundError: No module named 'slack_bolt'

这种"延迟 import + 友好报错"的组合,让核心包可以安全地不依赖任何第三方库,同时保证用户在误用时第一时间得到解决方案。

5. 文档:每个集成都要有清晰的 setup / configuration / usage 说明

每个集成都应提供清晰文档,包含安装、配置与使用示例。仓库中的集成子包大多遵循这一要求,其中:

  • integrations/slack/README.md 覆盖了前置安装、Slack App 的 Socket Mode/权限/事件订阅配置步骤,以及一段可运行的SlackRunner接入代码;
  • integrations/redis/README.md 则提供了配置参数表、三种连接方式示例(URI、独立连接参数、预配置客户端)、Redis key 结构说明与直接调用RedisSessionService的完整代码。

写作文档时建议沿用这一结构:先讲"装什么"(extras 安装命令),再讲"外部服务怎么配"(如 Slack App 权限、GCP IAM),最后给"最小可用示例"。

实战一:把 Agent 部署到 Slack(以 SlackRunner 为例)

作为"使用一个集成"的完整示例,integrations/slack/README.md 展示了如何把 ADK Agent 通过 Socket Mode 部署到 Slack。整体分四步。

第一步:安装带 Slack 支持的 ADK

pip install "google-adk[slack]"

第二步:在 Slack API Dashboard 配置 App

  1. 打开Socket Mode,启用后生成App-Level Token(以xapp-开头),并确保其具有connections:write权限;
  2. OAuth & Permissions中添加 Bot Token Scopes:app_mentions:read(接收 @提及)、chat:write(发送消息)、im:history(响应私信),按需添加groups:history(私密频道)与channels:history(公开频道);
  3. Event Subscriptions中启用事件订阅,添加 bot 事件app_mentionmessage.im
  4. 将 App 安装到工作区,获得Bot User OAuth Token(以xoxb-开头)。

第三步:初始化并启动 SlackRunner

import asyncio import os from google.adk.runners import Runner from google.adk.integrations.slack import SlackRunner from slack_bolt.app.async_app import AsyncApp async def main(): # 1. 初始化 ADK Runner(传入你的 agent) # runner = Runner(agent=my_agent, session_service=my_session_service) # 2. 用 Bot Token 初始化 Slack AsyncApp slack_app = AsyncApp(token=os.environ["SLACK_BOT_TOKEN"]) # 3. 初始化 SlackRunner slack_runner = SlackRunner(runner=runner, slack_app=slack_app) # 4. 用 App Token 以 Socket Mode 启动 await slack_runner.start(app_token=os.environ["SLACK_APP_TOKEN"]) if __name__ == "__main__": asyncio.run(main())

第四步:理解内部的会话与消息处理机制

从 integrations/slack/slack_runner.py 的源码可以看到几个关键设计:

  • 防循环message事件处理器会跳过带bot_id/bot_profile的消息,避免 Agent 与自己对话造成死循环;
  • 触发条件:仅当channel_type == "im"(私信)或消息处于线程中(thread_ts存在)时才交由_handle_message处理,与 README 中"订阅app_mentionmessage.im"的配置相呼应;
  • 会话 ID 规则(与 README 的 Session Management 小节一致):
    • 私信:直接以channel_id作为会话 ID;
    • 线程:以f"{channel_id}-{thread_ts}"作为会话 ID,维持线程上下文;
    • App 提及且不在线程中:以消息时间戳ts作为thread_ts,从而开启一个新线程会话;
  • 流式体验:先发送_Thinking..._占位消息,随后在runner.run_async(...)的流式事件中,用chat_update把占位消息原地替换为 Agent 输出(thinking_ts置空后再用say发后续内容),结束后若没有文本输出则chat_delete删除占位消息;
  • 错误兜底run_async抛出异常时,把"Sorry, I encountered an error: ..."写入占位消息或直接回复,同时logger.exception记录堆栈。

实战二:用 Redis 做持久化会话(以 RedisSessionService 为例)

另一个典型的"配置项丰富"的集成是 Redis 会话服务,其完整文档见 integrations/redis/README.md。它实现了BaseSessionService,为 Agent 提供基于 Redis 的持久化会话存储。

安装

pip install google-adk redis

最小接入

from google.adk.agents import Agent from google.adk.integrations.redis import RedisSessionService from google.adk.integrations.redis import RedisSessionServiceConfig from google.adk.runners import Runner config = RedisSessionServiceConfig( uri="redis://localhost:6379/0", ttl_seconds=86400 * 7, # 7 天 ) session_service = RedisSessionService(config=config) agent = Agent( name="assistant", instructions="You are a helpful AI assistant.", ) runner = Runner( app_name="my_app", agent=agent, session_service=session_service, )

配置参数表(来自 README,字段默认值可直接照用):

字段类型默认值说明
uriOptional[str]NoneRedis 连接 URI(如redis://[:password@]host:port/db,SSL 用rediss://)。设置后优先于独立连接字段。
hostOptional[str]"localhost"Redis 主机名。
portOptional[int]6379Redis 端口。
passwordOptional[str]NoneRedis 认证密码。
sslboolFalse是否启用 SSL/TLS。
dbint0Redis 数据库索引。
ttl_secondsint604800(7 天)会话 key 的过期时间;设为0或负数则禁用过期。
key_prefixstr"adk:session:"会话服务创建的所有 Redis key 的前缀。

Redis key 结构与状态作用域(README 中的核心设计):

Key 模式数据说明
{key_prefix}{app_name}:{user_id}:{session_id}JSON(Session会话本体:session ID、state、events 列表与最后更新时间,按ttl_seconds过期。
{key_prefix}user_state:{app_name}:{user_id}JSON(dictuser:前缀的用户级状态,跨会话共享,按ttl_seconds过期。
{key_prefix}app_state:{app_name}JSON(dictapp:前缀的应用级状态,跨用户、跨会话共享,按ttl_seconds过期。

状态同步规则:事件追加user:<key>增量时同步到用户级状态 key;追加app:<key>时同步到应用级状态 key;创建会话或更新事件时,三个作用域的状态会合并进会话状态。

直接以服务方式使用(绕过 Runner 单独管理会话):

from google.adk.integrations.redis import RedisSessionService from google.adk.sessions.base_session_service import GetSessionConfig session_service = RedisSessionService() # 创建会话(state 中混合了 user: 作用域与普通作用域键) session = await session_service.create_session( app_name="my_app", user_id="user_123", state={"user:theme": "dark", "topic": "weather"}, ) # 取最近 10 条事件 retrieved = await session_service.get_session( app_name="my_app", user_id="user_123", session_id=session.id, config=GetSessionConfig(num_recent_events=10), ) # 列出该用户所有会话 response = await session_service.list_sessions( app_name="my_app", user_id="user_123", ) # 删除会话 await session_service.delete_session( app_name="my_app", user_id="user_123", session_id=session.id, )

从 Agent Registry 集成看"高层封装"模式

并非所有集成都只是"挂一个工具",integrations/agent_registry/agent_registry.py 展示了一种更高层的封装思路:AgentRegistry客户端不仅封装了 REST 调用,还提供把注册资源转换为可直接使用的 ADK 组件的方法:

  • get_mcp_toolset(mcp_server_name, ...):根据注册的 MCP Server 元数据,自动解析连接 URI、自动从 IAM bindings 解析认证方案(GcpAuthProviderScheme),返回一个配置好的McpToolset
  • get_remote_a2a_agent(agent_name, ...):把注册的 A2A Agent 解析为RemoteA2aAgent(优先使用注册卡card,否则依据 URI/协议绑定手工构造 agent card);
  • list_agents/search_agents/list_mcp_servers/search_mcp_servers/list_endpoints等资源管理方法。

值得注意的实现细节:AgentRegistrySingleMcpToolset(同文件 agent_registry.py)在McpToolset.get_tools()返回的每个工具上注入GCP_MCP_SERVER_DESTINATION_ID这一custom_metadata键,用于在google.adk.telemetry.tracingexecute_toolspan 中标记 MCP 目标——这体现了"集成不仅能调用外部服务,还能与 ADK 的遥测体系深度协作"。

该集成同样遵循懒加载规范,未安装a2a-sdk时会抛出包含pip install google-adk[a2a]的明确错误。同时它还展示了 mTLS 支持:通过GOOGLE_API_USE_MTLS_ENDPOINTauto/always/never)与GOOGLE_API_USE_CLIENT_CERTIFICATE环境变量决定是否走agentregistry.mtls.googleapis.com端点。

从"使用集成"到"编写集成":落地检查清单

综合原文档与仓库实践,无论使用还是贡献集成,都可以用下面的清单快速核对:

  1. 归属:代码是否在连接外部服务或依赖第三方库?若是,放入src/google/adk/integrations/<name>/,而不是核心包;
  2. 自包含:是否所有文件都收敛在integrations/<name>/一个目录内?
  3. extras 一致pyproject.toml中是否定义了与目录同名的optional-dependencies.<name>?用户能否用pip install "google-adk[<name>]"安装?
  4. 懒加载:模块顶部是否用try/except ImportError包裹第三方 import,并在 except 分支抛出带安装命令的ImportError ... from e
  5. 文档:是否提供独立的 README,覆盖安装命令、外部服务配置步骤、配置参数与可运行示例?
  6. 回归测试:是否补充了对应单元测试(可参考 tests/unittests/integrations/ 下按集成分组的测试组织方式)?

总结

ADK 的 Integrations 目录是官方为"可扩展性"预留的标准化插槽:它以"自包含子包 + 可选 extras 依赖 + 懒加载友好报错 + 独立文档"四条规则,在核心轻量与生态丰富之间取得了平衡。对使用者而言,pip install "google-adk[slack]"google-adk[redis]这类命令就是接入能力的入口;对贡献者而言,integrations/<name>/目录加上一份 README 即是新集成的完整交付形态。本文所引用的 integrations/README.md、pyproject.toml 以及 Slack、Redis、Agent Registry 三个子包源码,共同构成了理解 ADK 集成机制的最小但完整的证据集。

【免费下载链接】adk-pythonAn open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 10:09:18

燃料电池混合动力系统PMP能量管理MATLAB实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 10:09:07

多无人机动态避障路径优化:CTCM算法原理与MATLAB实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 10:08:59

解决OpenClaw嵌入式会话上下文窗口超限问题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 10:07:31

雷达海浪反演算法详解:基于MATLAB的迭代求解与频散关系应用

简介&#xff1a;一份基于 MATLAB 的海浪与海流参数反演工具包&#xff0c;面向海洋科学、海洋气象预报及海上工程领域的研究者与工程师。压缩包共包含一个 M 文件&#xff0c;体积仅 3KB&#xff0c;核心代码集中在 diedai 脚本中&#xff0c;通过迭代算法从雷达观测数据中估算…

作者头像 李华
网站建设 2026/9/14 10:01:47

Activepieces 社区 Piece 构建实战:以 PhantomBuster 为例

Activepieces 社区 Piece 构建实战&#xff1a;以 PhantomBuster 为例 【免费下载链接】activepieces AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MC…

作者头像 李华