ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ADK Agent Runtime + OAuth 实战:基于 ADK 构建可读取用户 Google Drive 文件的授权 Agent

ADK Agent Runtime + OAuth 实战:基于 ADK 构建可读取用户 Google Drive 文件的授权 Agent ADK Agent Runtime OAuth 实战基于 ADK 构建可读取用户 Google Drive 文件的授权 Agent【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples本篇技术指南以core/python/oauth-user-consent-flow示例为蓝本讲解如何基于 Agent Development KitADK构建一个部署在Agent RuntimeAgent Engine上、通过OAuth 2.0代表已认证用户读取 Google Drive 文件的生产级 Agent。该示例同时支持本地 ADK Web UI 调试与 Gemini Enterprise 生产环境读完你将掌握negotiate_creds()三阶段凭据解析模式、OAuth 授权资源注册、Agent 与 Gemini Enterprise 的关联配置以及一套可复制的部署与排障流程。双模式架构总览示例 Agent 的核心能力是代表用户读取 Google Drive 文件而读取私有文件必须获得用户显式授权OAuth 2.0。其架构的关键设计在于同一份代码两种运行模式——本地开发走 ADK Web UI 的 OAuth 流程生产环境走 Gemini Enterprise 注入的 token二者最终都汇聚到同一个 Google Drive API 调用。┌─────────────────────────────────────────────────────────────────┐ │ TWO MODES OF OPERATION │ ├────────────────────────────┬────────────────────────────────────┤ │ LOCAL DEVELOPMENT │ PRODUCTION │ │ │ │ │ You (browser) │ User (browser) │ │ ↓ │ ↓ │ │ ADK Web UI (:8501) │ Gemini Enterprise UI │ │ ↓ │ ↓ │ │ ADK OAuth Flow │ Gemini Enterprise OAuth Flow │ │ (uses auths.py config) │ (uses registered auth resource) │ │ ↓ │ ↓ │ │ negotiate_creds() │ Token injected into │ │ Stage 2 → Stage 3 │ tool_context.state[temp:ID] │ │ ↓ │ ↓ │ │ Google Drive API │ negotiate_creds() │ │ │ Stage 1 (finds injected token) │ │ │ ↓ │ │ │ Google Drive API │ └────────────────────────────┴────────────────────────────────────┘本地模式下开发者通过浏览器在 ADK Web UI端口 8501中与 Agent 对话ADK 框架负责完整的 OAuth 流程生产模式下用户在 Gemini Enterprise 的 Web UI 中对话Gemini Enterprise 完成 OAuth 授权后把 token 注入到tool_context.state[temp:AUTH_ID]Agent 代码直接消费该 token。二者的衔接点正是negotiate_creds()这一三阶段解析函数。OAuth 2.0 工作原理解析本地开发ADK Web UI运行make playground启动本地环境后ADK 框架会接管 OAuth 流程用户向 Agent 提出读取 Drive 文件请求negotiate_creds()未找到任何缓存 token → 调用tool_context.request_credential()进入 Stage 3ADK Web UI 使用app/auths.py中的OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET将用户重定向到 Google 授权页面用户授予drive.readonly权限后ADK 用授权码auth code换取 token下一次工具调用时negotiate_creds()通过tool_context.get_auth_response()拿到已完成的授权结果进入 Stage 2凭据被缓存到tool_context.state供后续调用复用。关键点本地开发时app/auths.py中必须存在有效的OAUTH_CLIENT_ID和OAUTH_CLIENT_SECRET通过环境变量或app/.env注入。生产环境Agent Runtime Gemini Enterprise用户在 Gemini Enterprise Web UI 中请求读取 Drive 文件Gemini Enterprise 发现 Agent 带有authorizationConfig其中toolAuthorizations指向已注册的 OAuth 授权资源Gemini Enterprise 使用授权资源中存储的凭据通过make register-oauth注册向用户发起 OAuth 授权用户同意后Gemini Enterprise 将访问 token 注入tool_context.state[temp:AUTH_ID]negotiate_creds()在 Stage 1 立即命中注入的 token不会进入 Stage 2 或 Stage 3工具使用注入的 token 调用 Google Drive API。关键点生产环境中auths.py里的OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET永远不会被使用。真正的凭据存放在通过tools/register_oauth.py注册的授权资源中代码只需通过TOKEN_CACHE_KEY其值等于AUTH_ID知道去哪里找注入的 token。negotiate_creds()三阶段模式这一模式让同一份代码在两种环境中都能工作具体定义于 app/tools.pyStage作用适用场景Stage 1检查tool_context.state中的缓存或注入 token生产环境Gemini Enterprise 将 token 注入此处本地此前调用缓存的凭据Stage 2检查tool_context.get_auth_response()是否已完成 OAuth 交换仅本地ADK Web UI 在用户同意后把换取的 token 返回于此Stage 3调用tool_context.request_credential()发起 OAuth 流程仅本地在 ADK Web UI 中触发授权页面源码级实现细节在 app/tools.py 中negotiate_creds()的判定逻辑如下Stage 1先按auths.TOKEN_CACHE_KEY查找再补充查找temp:{TOKEN_CACHE_KEY}前缀键这是 Gemini Enterprise 实际注入的位置。命中后分两种情况处理缓存值是dict用Credentials.from_authorized_user_info()还原凭据若已过期且带refresh_token则通过creds.refresh(Request())自动刷新并把新凭据写回tool_context.state缓存值是str视为裸访问 token直接Credentials(tokencached_token)其它类型则抛出ValueError提示类型非法。Stage 2调用tool_context.get_auth_response(auths.AUTH_CONFIG)若拿到exchanged_creds则用oauth2.access_token、refresh_token、tokenUrl、client_id、client_secret及 scopes 组装Credentials对象并序列化缓存到tool_context.state[TOKEN_CACHE_KEY]。Stage 3调用tool_context.request_credential(auths.AUTH_CONFIG)发起授权并返回{pending: True, message: Awaiting user authentication}。read_drive_file()检测到返回的是 dict而非Credentials时立即提前返回避免在授权未完成时继续调用 Drive API。项目结构在仓库中的完整路径为 core/python/oauth-user-consent-flow其内部结构如下oauth-user-consent-flow/ ├── app/ # Agent 代码部署到 Agent Engine │ ├── __init__.py # 导出 app │ ├── agent.py # 根 Agent 定义指令 工具 │ ├── auths.py # OAuth 配置scheme、credential、AUTH_CONFIG │ ├── tools.py # negotiate_creds() read_drive_file() 工具 │ ├── agent_engine_app.py # Agent Engine 包装器AdkApp 子类 │ ├── app_utils/ # 部署与遥测工具 │ │ ├── deploy.py # Agent Engine 部署脚本 │ │ ├── telemetry.py # OpenTelemetry 配置 │ │ └── typing.py # Feedback 模型 │ └── .env # 本地环境变量不入库 ├── tools/ # 独立脚本不随 Agent 部署 │ └── register_oauth.py # 向 Gemini Enterprise 注册 OAuth 授权资源 ├── tests/ # 单元、集成与评估测试 ├── deployment_metadata.json # 记录已部署的 Agent Engine ID ├── Makefile # 全部命令入口 ├── pyproject.toml # 依赖与配置 └── README.md # 本文档关键文件职责文件职责app/agent.py定义root_agent使用Gemini模型模型名取自MODEL_NAME环境变量并配置 3 次重试与read_drive_file工具内置引导 Agent 与用户交互的指令app/auths.pyOAuth 2.0 配置定义AUTH_SCHEME、AUTH_CREDENTIAL、AUTH_CONFIG供本地开发的 ADK OAuth 流程使用同时定义TOKEN_CACHE_KEY与SCOPES供两种环境下的negotiate_creds()使用app/tools.py包含negotiate_creds()三阶段 OAuth 解析与read_drive_file()通过导出读取 Google Docs/Sheets/Slides通过下载读取普通文件tools/register_oauth.py独立脚本向 Discovery Engine API 注册 OAuth 授权资源告知 Gemini Enterprise 在需要用户授权时应使用哪组 OAuth 凭据。不随 Agent 部署设置阶段运行一次即可app/agent_engine_app.pyAdkApp子类初始化vertexai、遥测与日志并注册register_feedback操作app/app_utils/deploy.py部署脚本将./app打包并创建/更新 Agent Engine 实例支持--set-secrets、--agent-identity等高级选项前置条件Google Cloud 项目且已启用计费gcloudCLI已完成认证gcloud auth login与gcloud auth application-default loginuv包管理器安装启用Google Drive APIgcloud services enable drive.googleapis.com --projectYOUR_PROJECT_ID启用Vertex AI APIgcloud services enable aiplatform.googleapis.com --projectYOUR_PROJECT_ID启用Discovery Engine APIGemini Enterprise 必需gcloud services enable discoveryengine.googleapis.com --projectYOUR_PROJECT_ID在 Google Cloud Console 配置OAuth 2.0 Client ID应用类型Web application授权重定向 URIhttp://localhost:8501/dev-ui/本地 ADK Web UIhttps://vertexaisearch.cloud.google.com/oauth-redirectGemini Enterprise环境配置1. 安装依赖uv sync --dev依赖清单定义于 pyproject.toml核心包括google-adk1.31.0、google-api-python-client、google-cloud-aiplatform[agent-engines]、google-cloud-logging、python-dotenv等要求 Python3.11,3.14。2. 配置环境变量编辑app/.env注意该文件不入库需自行创建.env由 app/agent_engine_app.py 中的load_dotenv()在运行时加载# Google Cloud GOOGLE_CLOUD_PROJECTyour-project-id GOOGLE_CLOUD_LOCATIONglobal GOOGLE_GENAI_USE_VERTEXAITrue # OAuth用于本地 ADK Web UI 测试 OAUTH_CLIENT_IDyour-client-id.apps.googleusercontent.com OAUTH_CLIENT_SECRETyour-client-secret # Auth ID必须与 tools/register_oauth.py 注册时一致 AUTH_IDgoogle-drive-auth各变量在源码中的落点GOOGLE_CLOUD_PROJECT/GOOGLE_CLOUD_LOCATION/GOOGLE_GENAI_USE_VERTEXAI在 app/agent.py 中通过google.auth.default()自动推导项目 ID 后写入环境变量OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET在 app/auths.py 中被AUTH_CREDENTIAL读取AUTH_ID在 app/auths.py 中被TOKEN_CACHE_KEY os.environ.get(AUTH_ID, google-drive-auth)读取——这就是本地缓存与生产注入共用的 state 键名MODEL_NAME在 app/agent.py 中指定 Agent 使用的 Gemini 模型。本地开发启动 ADK Web UImake playground该命令实际执行uv run adk web . --port 8501 --reload_agents。打开 http://127.0.0.1:8501 并选择app文件夹。测试读取 Google Drive 文件从 Google Drive URL 获取文件 IDhttps://drive.google.com/file/d/FILE_ID/view向 Agent 提问Read the file with IDFILE_IDAgent 会触发 OAuth 授权流程——点击 Authorize 并授予drive.readonly权限Agent 读取并展示文件内容read_drive_file()在 app/tools.py 中的处理逻辑为先通过negotiate_creds()获取凭据再构建 Drive v3 客户端build(drive, v3, credentialscreds)按 mimeType 分派读取方式mimeType处理方式application/vnd.google-apps.documentGoogle Docsfiles().export(mimeTypetext/plain)导出为纯文本application/vnd.google-apps.spreadsheetGoogle Sheetsfiles().export(mimeTypetext/csv)导出为 CSVapplication/vnd.google-apps.presentationGoogle Slidesfiles().export(mimeTypetext/plain)导出为纯文本其它普通文本/CSV/JSON 等files().get_media()直接下载返回结构统一为{status: success, file_name, mime_type, content}异常时返回{status: error, message: ...}。生产部署Agent Runtime Gemini Enterprise第 1 步部署到 Agent Runtimemake deploy该命令先用uv export生成依赖清单app/app_utils/.requirements.txt再调用uv run -m app.app_utils.deploy以 app/agent_engine_app.py 中的agent_engine对象为入口点部署到 Agent Engine。部署成功后Agent Runtime ID 会写入deployment_metadata.json。部署脚本 app/app_utils/deploy.py 支持大量可调参数默认值见源码--location默认europe-west4--display-name默认adk-ae-oauth--min-instances/--max-instances默认 1 / 10--cpu/--memory默认4/8Gi--container-concurrency默认 9--num-workers默认 1--set-secrets以ENV_VARSECRET_ID[:VERSION]格式注入 Secret Manager 密钥支持--agent-identity开启按 Agent 粒度的 IAM 身份属于 Preview 功能脚本内置遥测默认值GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRYtrue、OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTtrue。第 2 步注册 OAuth 授权资源将你的 OAuth 凭据注册给 Gemini Enterprise让它知道如何处理 OAuth 授权流程make register-oauth该命令运行 tools/register_oauth.py会交互式提示输入Project ID你的 GCP 项目 IDLocationglobal、eu或us必须与你的 Gemini Enterprise 应用所在位置一致脚本内部将端点映射为global/us→global、eu→euAuthorization ID例如google-drive-auth必须与app/.env中的AUTH_ID一致OAuth Client ID你的 OAuth 客户端 IDOAuth Client Secret你的 OAuth 客户端密钥以getpass隐藏输入Scopes默认为https://www.googleapis.com/auth/drive.readonly脚本会构造带完整参数的 authorizationUri包含client_id、redirect_urihttps://vertexaisearch.cloud.google.com/oauth-redirect、scope、include_granted_scopestrue、response_typecode、access_typeoffline、promptconsent再向https://{endpoint_location}-discoveryengine.googleapis.com/v1alpha/.../authorizations发起注册请求若目标已存在HTTP 409脚本会先 DELETE 再重新 POST覆盖式重建。OAUTH_TOKEN_URI默认取https://oauth2.googleapis.com/token均支持通过环境变量覆盖。第 3 步将 Agent 注册到 Gemini Enterprise将已部署的 Agent 与 Gemini Enterprise 关联并绑定 OAuth 授权# 交互式 make register-gemini-enterprise # 非交互式推荐用于可重复执行 make register-gemini-enterprise \ AUTH_ID_RESOURCEprojects/PROJECT_NUMBER/locations/LOCATION/authorizations/google-drive-auth \ GE_APP_IDprojects/PROJECT_NUMBER/locations/LOCATION/collections/default_collection/engines/ENGINE_ID \ DISPLAY_NAMEDrive Reader Agent \ DESCRIPTIONReads files from Google Drive on behalf of the user \ TOOL_DESCRIPTIONRead content of a Google Drive file using OAuth重要AUTH_ID_RESOURCE必须是make register-oauth输出中的完整资源名projects/.../locations/.../authorizations/...而不是单纯的 auth ID 字符串。该 Makefile 目标底层调用uvx agent-starter-pack0.39.4 register-gemini-enterpriseAUTH_ID_RESOURCE会映射为--authorization-id参数Makefile。第 4 步验证注册结果检查 Agent 是否已正确关联 OAuth 授权curl -s \ -H Authorization: Bearer $(gcloud auth print-access-token) \ -H X-Goog-User-Project: YOUR_PROJECT_ID \ https://LOCATION-discoveryengine.googleapis.com/v1alpha/AGENT_NAME \ | python3 -m json.tool应能看到如下输出authorizationConfig: { toolAuthorizations: [ projects/.../locations/.../authorizations/google-drive-auth ] }更新已有注册CLI 总是创建新注册。若要替换已有注册# 1. 删除旧注册 make unregister-gemini-enterprise \ AGENT_NAMEprojects/.../assistants/default_assistant/agents/AGENT_ID # 2. 重新注册 make register-gemini-enterprise \ AUTH_ID_RESOURCEprojects/.../authorizations/google-drive-auth \ GE_APP_IDprojects/.../engines/ENGINE_IDAGENT_NAME是注册输出中打印的完整名称以/agents/id结尾。Makefile 命令参考命令说明make install使用uv安装依赖make playground在 8501 端口启动 ADK Web UImake deploy部署 Agent 到 Agent Runtimemake register-oauth注册 OAuth 授权资源make register-gemini-enterprise将 Agent 注册到 Gemini Enterprisemake unregister-gemini-enterprise删除 Agent 注册make test运行单元与集成测试make eval运行 Agent 评估基于tests/eval/evalsets/basic.evalset.jsonmake lint运行代码质量检查codespell、ruff、ty测试与验证仓库自带测试可验证 Agent 在无真实凭据场景下的行为tests/integration/test_agent.py通过unittest.mock.patch把app.tools.negotiate_credsmock 为返回{pending: True, ...}模拟无 OAuth token场景验证 Agent 能正常流式返回授权提示文本而不是崩溃tests/integration/test_agent_engine_app.py验证AgentEngineApp.async_stream_query能返回有效流式响应并验证register_feedback对合法反馈正常、对非法score抛ValueErrortests/test_runnability.py检查项目结构可运行性。运行方式make test内部执行uv sync --dev uv run pytest tests/unit uv run pytest tests/integration评估则用make eval。故障排查Google Drive API has not been used in project ... or it is disabled启用 Drive APIgcloud services enable drive.googleapis.com --projectYOUR_PROJECT_IDfile_cache is only supported with oauth2client4.0.0来自 Google API 客户端库的无害提示信息可以安全忽略。端口 8501 出现address already in use杀掉占用进程lsof -ti :8501 | xargs kill -9The authorization URI must contain access_typeoffline注册到 Discovery Engine 的authorizationUri必须包含类似access_typeoffline的查询参数。tools/register_oauth.py 已自动构造完整参数——不要只传基础 URL。ADK Web UI 中未出现 OAuth 授权页面确认app/.env中已设置OAUTH_CLIENT_ID与OAUTH_CLIENT_SECRET且 OAuth 客户端的 Authorized redirect URIs 包含http://localhost:8501/dev-ui/。生产中找不到 tokenNo OAuth token available验证 Agent 注册是否包含授权配置curl -s -H Authorization: Bearer $(gcloud auth print-access-token) \ https://LOCATION-discoveryengine.googleapis.com/v1alpha/AGENT_NAME \ | python3 -m json.tool | grep -A3 authorizationConfig若缺少authorizationConfig说明注册时未携带--authorization-id需先注销再携带正确的 auth 资源重新注册。TenantProjectwith locationglobaldoes not exist (404)该错误出现在试图向**尚未初始化 Vertex AI Search and ConversationDiscovery Engine**的项目注册 OAuth 资源时。解决方案前往 Google Cloud Console 的 Vertex AI Search and Conversation创建一个临时的 Search 或 Chat 应用这会触发内部 tenant project 与默认 collections 的创建。交互式注册后authorizationConfig缺失若第 4 步的curl结果中没有authorizationConfig段说明 Agent 注册时未关联 OAuth 凭据。交互式make register-gemini-enterprise可能跳过了 authorization ID。解决方案删除该注册改用第 3 步中的非交互式命令显式传入AUTH_ID_RESOURCE。控制台点 Preview 时/signin/返回 404在 Gemini Enterprise 控制台点击 Preview 按钮时若出现指向auth.cloud.google的 404很可能是控制台对预览实例的认证路由存在缺陷。解决方案后端 Agent 配置大概率是正确的用第 4 步的curl命令核实即可。替代方案Google Agents CLI也可以通过 Google Agents CLI 创建该 Agent 的生产就绪版本获得更多部署选项安装 CLI一次性uvx google-agents-cli setup基于本示例创建项目将my-adk-ae-oauth替换为你的项目名agents-cli create my-adk-ae-oauth -a adkadk-ae-oauthCLI 会提示你选择部署选项并提供包括自动化 CI/CD 部署脚本在内的额外生产级特性。参考资料Powering Up your Agent in Production with ADK, OAuth and Gemini Enterprise——本实现所遵循的三阶段negotiate_creds()模式、auths.py配置思路以及让 ADK OAuth Gemini Enterprise 协同工作的整体方案均主要参考自 Médéric Hurier 的这篇文章原文为外部文章此处仅作模式来源说明Google ADK 官方文档——ADK 框架与工具开发的官方参考Google Agents CLI——面向 GCP Agent 的生产模板工具ADK Authentication 文档——ADK 中 OAuth 流程的细节说明。上述模式已在仓库中以 app/tools.py、app/auths.py 与 tools/register_oauth.py 完整落地你可直接对照源码与本文逐步复现本地调试与生产部署全流程。【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表