adk-samples / oauth-user-consent-flow
AGENTS.md11k starsChanged 44 days agoApache-2.0View on GitHub
A clone-and-study ADK agent that reads a user's Google Drive files on their behalf, gated by an OAuth 2.0 user-consent flow. The agent is deployed to Agent Runtime (Vertex AI Agent Engine) and registered with Gemini Enterprise. The interesting part is not the agent (a thin wrapper around one Drive tool); it's the OAuth consent plumbing — the negotiate_creds() three-stage credential resolution that makes the same code work in both local ADK Web UI dev and production Gemini Enterprise, plus…
- Reads credentials
1 other project uses a version of this.
Trending
More talk lately.about the whole repository
Most recently taken up by
- google/adk-recipesword for word, first seen Oct 13, 2026
Who's talking about google/adk-samples
- @stephanjanssen.be“Google just open sourced a Python Agent Development Kit @ github.com/google/adk-p... Native Streaming and …”Bluesky · Apr 9, 2025 · 12 likes
- google/adk-python“stream_query and HTTP Streaming to Vertex AI Agent Return Empty/Exhausted Responses (Works via ADK Web)”GitHub · Jul 8, 2025 · 5 reactions
- google/adk-recipes“Support running agents fully locally without Vertex AI (offline mode)”GitHub · Apr 14, 2025 · 4 reactions
- google/adk-recipes“[BUG]: Deployment of Data Science agent to Agent Engine fails ”GitHub · Oct 1, 2025 · 3 reactions
- A Hacker News story“CaMeL-Powered Secure Agent Demo with ADK”Hacker News · Aug 9, 2025 · 3 points
The biggest 5 of 32 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 32
Talked about on GitHub, Bluesky, Hacker News and Stack Overflow (32 times).
On GitHub · 23
- Jul 8, 2025stream_query and HTTP Streaming to Vertex AI Agent Return Empty/Exhausted Responses (Works via ADK Web) — google/adk-python5 reactions
- Apr 14, 2025Support running agents fully locally without Vertex AI (offline mode) — google/adk-recipes4 reactions · 7 comments
- Oct 1, 2025[BUG]: Deployment of Data Science agent to Agent Engine fails — google/adk-recipes3 reactions · 1 comment
- Oct 28, 2026docs: fix 5 broken internal anchor links and 1 dead external link — google-gemini/gemini-cli1 reaction · 4 comments
- Oct 20, 2026Update adk-samples references and python/agents discovery paths for google/adk-recipes restructure — google/agents-cli1 reaction · 2 comments
18 more on GitHub
- Oct 12, 2026list: scan the template dir we cloned, not the clone root — GoogleCloudPlatform/agent-starter-pack1 reaction
- Feb 12, 2026interrupted sometimes didn't work — google/adk-python1 reaction · 10 comments
- Jan 8, 2026Implement 5 ADK agent projects that can be easily run by newbies — addyosmani/adk-product-engineers1 reaction
- Nov 20, 2025[BUG]: deep-search/gemini-fullstack: Wrong prompt to access session state — google/adk-recipes1 reaction
- Jun 21, 2025unable to import StdioServerParameters — google/adk-recipes1 reaction · 2 comments
- Jun 17, 2025VertexAiRagRetrieval needs llama-index package — google/adk-recipes1 reaction · 3 comments
- Jun 5, 2025Bug: display_name in file uploads causes error with Google.GenAI backend (non-Vertex) — google/adk-python1 reaction · 6 comments
- May 18, 2025Missing Image — google/adk-recipes1 reaction
- Apr 11, 2025Duplicate key name — google/adk-recipes1 reaction · 1 comment
- Oct 18, 2026Fix(audit,#17387): Day4 Track2 tranche 1 -- Lab8/Lab9 reformulations honnetes, cures accents — jsboige/CoursIA0 reactions · 14 comments
- Sep 17, 2026Rename sample references to recipe across repository — google/adk-recipes0 reactions
- Sep 12, 2026docs(deep-search): fix cloud deployment instructions and scaffold path (#2575) — google/adk-recipes0 reactions · 4 comments
- Sep 12, 2026docs: fix 404 link to relocated Deep Search sample — google/adk-docs0 reactions · 1 comment
- Sep 9, 2026Add repo skills instructions and documentation links to AI issue response workflow — google/adk-recipes0 reactions
- Jul 24, 2026Fix broken adk-samples links from deleted sample agents and notebooks — google/adk-docs0 reactions · 1 comment
- Jun 12, 2026ci: run the spam-detection bot via the adk-samples reusable workflow — google/adk-go0 reactions · 1 comment
- May 27, 2026Add Deep Search Agent project to portfolio showcase — asafsilner/silner-showcase-prime0 reactions
- Feb 12, 2026fix: path typo in story teller example — google/adk-recipes0 reactions · 3 comments
On Bluesky · 4
- Apr 9, 2025Google just open sourced a Python Agent Development Kit @ github.com/google/adk-p... Native Streaming and #MCP support out of the box 👀… — @stephanjanssen.be12 likes and reposts
- Jul 12, 2026Exploring the ADK Samples repo from Google—it’s like a guidebook for building intelligent agents. Seeing multi-language support reflects… — @iam.slys.dev1 likes and repost
- Dec 9, 2025📦 google / adk-samples ⭐ 6,900 (+67) 🗒 Python A collection of sample agents built with Agent Development Kit (ADK) — @github-trending.bsky.social1 likes and repost
- May 20, 2025Explore practical use-cases & build! 🧪 Hands-on Patent Search Codelab: codelabs.developers.google.com/patent-searc... 📚 Check out sample… — @kweinmeister.bsky.social0 likes and reposts · 1 reply
On Hacker News · 3
- Aug 9, 2025CaMeL-Powered Secure Agent Demo with ADK3 points · 1 comment
- Jun 13, 2025A collection of sample agents built with Agent Development (ADK)2 points
- Aug 13, 2025CaMeL agent to protect against indirect prompt injection1 point · 1 comment
On Stack Overflow · 2
- Aug 30, 2025Google ADK SequentialAgent sub_agents not waiting for user input1 vote
- Aug 29, 2025Issue with deploying ADK Agent on Google Agent Engine0 votes
Other versions1 project uses a version of this.
Word for word · 1
- google/adk-recipes★ 11k100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,843 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository43 other files it gives its agents.
- AGENTS.mdAGENTS.md
- contrib/kotlin/llm-auditor/AGENTS.mdAGENTS.md
- core/python/adk-voice-agent/AGENTS.mdAGENTS.md
- core/python/adk-voice-agent/sandbox/home/AGENTS.mdAGENTS.md
- core/python/adk-voice-agent/tests/eval/fixtures/alex/repos/portland-trip/AGENTS.mdAGENTS.md
- core/python/ambient-expense-agent/AGENTS.mdAGENTS.md
- core/python/ambient-quality-agent/AGENTS.mdAGENTS.md
- core/python/cross-session-memory/AGENTS.mdAGENTS.md
- core/python/deep-search/AGENTS.mdAGENTS.md
- core/python/genmedia-for-commerce/AGENTS.mdAGENTS.md
- core/python/long-horizon-harness/AGENTS.mdAGENTS.md
- core/python/rag-agent-search/AGENTS.mdAGENTS.md
- core/python/rag-vector-search/AGENTS.mdAGENTS.md
- core/python/safety-plugins/AGENTS.mdAGENTS.md
- core/python/adk-voice-agent/sandbox/home/CLAUDE.mdCLAUDE.md
- core/python/genmedia-for-commerce/CLAUDE.mdCLAUDE.md
- align-recipe-pyprojectSkill
- extract-python-environment-variablesSkill
- generate-manifestSkill
- generate-python-runnability-testSkill
- github-pr-reviewSkill
- make-python-recipe-deployableSkill
- prepare-python-recipeSkill
- repo-oracleSkill
- scaffold-python-recipeSkill
- blog-writerSkill
- content-research-writerSkill
- approvalsSkill
- coding-workflowSkill
- connected-apps-mcpSkill
- deliverablesSkill
- filesystemSkill
- recommendationsSkill
- agents-cli-aquaSkill
- custom-investigationSkill
- rcaSkill
- bootstrap-google-toolsSkill
- find-skillsSkill
- google-workspaceSkill
- policySkill
- routinesSkill
- retail-product-searchSkill
- retail-virtual-tryonSkill
The file
We split this AGENTS.md into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 126
Scope: read-only Drive (https://www.googleapis.com/auth/drive.readonly), defined once in auths.py SCOPES and defaulted again in …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
OAuth User-Consent Flow — Agent Runtime + Gemini Enterprise
Intent
A clone-and-study ADK agent that reads a user's Google Drive files on their
behalf, gated by an OAuth 2.0 user-consent flow. The agent is deployed to
Agent Runtime (Vertex AI Agent Engine) and registered with Gemini
Enterprise. The interesting part is not the agent (a thin wrapper around
one Drive tool); it's the OAuth consent plumbing — the negotiate_creds()
three-stage credential resolution that makes the same code work in both local
ADK Web UI dev and production Gemini Enterprise, plus the register-oauth step
that tells Gemini Enterprise which credentials to prompt with.
When To Use
- The user needs an agent that calls a user-scoped Google API (Drive, Gmail, Calendar, …) and must obtain explicit user consent via OAuth 2.0.
- The user wants one codebase that works both locally (ADK Web UI drives the consent screen) and in production (Gemini Enterprise injects the token).
- The user wants a worked example of registering an OAuth authorization resource with the Discovery Engine API and linking it to a deployed agent.
Eval
- Scenarios Path:
tests/eval/evalsets/(config:tests/eval/eval_config.json) - Minimum Score:
rubric_based_final_response_quality_v1threshold0.8(LLM judgegemini-3.5-flash, rubrics:relevance,helpfulness)
Cases in basic.evalset.json cover a greeting and a Drive-read request; they
exercise the agent's response quality, not a live OAuth exchange. Run with
make eval (single evalset) or make eval-all (every *.evalset.json).
End-to-end flow
The negotiate_creds() three-stage pattern makes one tool work in two
environments:
LOCAL (ADK Web UI) PRODUCTION (Gemini Enterprise)
------------------ ------------------------------
user asks to read a Drive file user asks to read a Drive file
-> negotiate_creds() Stage 3: -> Gemini Enterprise sees the agent's
request_credential() -> consent authorizationConfig, prompts consent
screen (OAUTH_CLIENT_ID/SECRET using the registered auth resource
from auths.py) -> token injected into
-> user grants drive.readonly tool_context.state["temp:<AUTH_ID>"]
-> Stage 2: get_auth_response() -> negotiate_creds() Stage 1 finds it
exchanges code -> Credentials immediately (never hits 2 or 3)
-> cached in tool_context.state -> read_drive_file() calls Drive API
(Stage 1 on next call)- Register OAuth creds once (
make register-oauth) → an authorization resource in the Discovery Engine API. - Deploy the agent (
make deploy) → Agent Runtime, ID saved todeployment_metadata.json. - Link the deployed agent to Gemini Enterprise with the auth resource
(
make register-gemini-enterprise AUTH_ID_RESOURCE=... GE_APP_ID=...). - At runtime
read_drive_file()callsnegotiate_creds(), gets a token, builds adrive v3client, and returns file content (Docs/Sheets/Slides viaexport, everything else viaget_media).
Most interesting files to study (in order)
OAuth consent flow (the heart of this recipe)
app/tools.py— the core of the recipe.negotiate_creds()implements the three-stage credential resolution: Stage 1 reads a cached/injected token fromtool_context.state(checks bothTOKEN_CACHE_KEYand thetemp:<AUTH_ID>key Gemini Enterprise injects; handles both a raw access-tokenstrand a full credentialdict, refreshing when expired); Stage 2 picks up a completed ADK exchange viatool_context.get_auth_response()and buildsCredentials(caching them); Stage 3 callstool_context.request_credential()and returns{"pending": True, …}to trigger the consent screen.read_drive_file()short-circuits on a pending dict, else builds adrive v3client and exports/downloads by MIME type.app/auths.py— the OAuth config. DefinesAUTH_SCHEME(OAuth2/authorizationCodewith Google's authorize + token URLs and theSCOPESdict),AUTH_CREDENTIAL(client id/secret fromOAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET), andAUTH_CONFIG.TOKEN_CACHE_KEY=AUTH_ID(defaultgoogle-drive-auth) is the seam: it must match the id registered with Gemini Enterprise so Stage 1 finds the injectedtemp:<AUTH_ID>token. In production the client id/secret here are never used — onlyTOKEN_CACHE_KEYandSCOPESmatter.tools/register_oauth.py— the standaloneregister-oauthstep (not deployed with the agent). Interactively (or from env) gathers project / location /AUTH_ID/ client id+secret / scopes, then POSTs aserverSideOauth2authorization resource to{endpoint}-discoveryengine.googleapis.com/v1alpha/.../authorizations. Note it builds anauthorizationUriwithaccess_type=offlineandprompt=consent(required — a bare URL is rejected), and handles a409by delete-and-recreate. This resource is what Gemini Enterprise uses to prompt the user; its full resource name feedsregister-gemini-enterprise.
Deployment & Gemini Enterprise wiring
app/agent_engine_app.py— wrapsapp.agent.appin anAdkAppsubclass (AgentEngineApp) for Agent Runtime:set_up()initialisesvertexai+ telemetry + Cloud Logging, andregister_feedback/register_operationsexpose a feedback op. The module-levelagent_engineobject is the deploy entrypoint. Artifact service is GCS (LOGS_BUCKET_NAME) or in-memory.app/app_utils/deploy.py— the Click CLI behindmake deploy. Imports the entrypoint object, generatesclass_methodsfromregister_operations, and callsclient.agent_engines.create/updateon Vertex AI (create-or-update by display name), then writesdeployment_metadata.json. Also supports--agent-identity(per-agent IAM, Preview) and--set-secrets.Makefile— theregister-gemini-enterprise(viauvx agent-starter-pack register-gemini-enterprise, passing--authorization-id) andunregister-gemini-enterprise(aDELETEcurl against Discovery Engine) targets are the second half of the OAuth story — read them alongsideregister_oauth.py.
Agent (thin layer — read last)
app/agent.py— the runtime. A singleAgent(root_agent) on Gemini (MODEL_NAMEenv var) with one tool,read_drive_file, and an instruction telling it to ask for a file id and to explain the "pending" auth state.App(root_agent=…, name="app")is exported for bothadk weband deployment.
Data handling
- No datastore. The only "data" is whatever Drive file the user names; there is no ingestion, indexing, or embedding.
- Token handling is the real data path. Credentials live in
tool_context.statekeyed byTOKEN_CACHE_KEY/AUTH_ID. Locally the full credential dict is cached (and refreshed via the refresh token when expired); in production Gemini Enterprise injects a raw access-token string undertemp:<AUTH_ID>. Nothing is persisted outside session state. - Scope: read-only Drive (
https://www.googleapis.com/auth/drive.readonly), defined once inauths.pySCOPESand defaulted again inregister_oauth.py. - File reads: Google Docs →
text/plain, Sheets →text/csv, Slides →text/plain(all viafiles().export); everything else viafiles().get_media. Bytes are decoded as UTF-8.
Gotchas / things to know
AUTH_IDmust match everywhere.TOKEN_CACHE_KEYinauths.py, theAUTH_IDyou pass tomake register-oauth, and the authorization id insideAUTH_ID_RESOURCEformake register-gemini-enterprisemust all agree, or Stage 1 will never find the injectedtemp:<AUTH_ID>token in production.register-gemini-enterprisemust be givenAUTH_ID_RESOURCE— the full resource name fromregister-oauthoutput (projects/<num>/locations/<loc>/authorizations/<id>), not the bare id. Omit it and the agent registers withoutauthorizationConfigand production getsNo OAuth token available. Verify with thecurlin the README.- The Makefile
deployandevaltargets reference anadk_ae_oauthpackage (e.g.--source-packages=./adk_ae_oauth,adk eval ./adk_ae_oauth), but the agent code actually lives underapp/(seepyproject.tomlmodule-name = "app"anddeploy.py's own./appdefaults). Adjust those targets toappif they fail — this is a leftover from the template's project name. - Local dev needs a real OAuth client.
OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRETmust be set (inapp/.env) andhttp://localhost:8501/dev-ui/must be an authorized redirect URI, or the ADK Web UI consent screen (Stage 3) won't work. GOOGLE_CLOUD_LOCATION=global.agent.pyforces the location toglobalat import and resolves the project fromgoogle.auth.default(), so imports need ADC. Tests import lazily / patchgoogle.auth.defaultto avoid this.- Integration tests need
INTEGRATION_TEST.conftest.pyignorestests/integration/*unlessINTEGRATION_TESTis set (they import the agent package at module level and hit live GCP).make testrunstests/unitthentests/integration. - First-time Discovery Engine setup.
register-oauthfails with aTenantProject … global does not exist (404)until Vertex AI Search / Conversation has been initialised once in the project (create any dummy Search or Chat app).
Where to run things
Makefile targets:
make install—uv sync(installs deps, bootstrapsuvif missing).make playground— local ADK Web UI on port 8501 (adk web . --reload_agents).make deploy(aliasmake backend) — deploy to Agent Runtime viaapp_utils/deploy.py; writesdeployment_metadata.json.make test—uv run pytest tests/unitthentests/integration.make eval/make eval-all—adk evalagainsttests/eval/evalsets/*.evalset.jsonwithtests/eval/eval_config.json.make lint—codespell+ruff check+ruff format --check+ty check.make register-oauth— register the OAuth authorization resource (tools/register_oauth.py).make register-gemini-enterprise/make unregister-gemini-enterprise— link / unlink the deployed agent in Gemini Enterprise (passAUTH_ID_RESOURCE,GE_APP_ID, and for unregisterAGENT_NAME).
Reuse (copy as-is)
app/auths.py+app/tools.pyare the reusable OAuth core — copy both into another ADK tool to get thenegotiate_creds()three-stage pattern. SwapSCOPESand the Google API client inread_drive_file()for whatever user-scoped API you need; the credential negotiation is API-agnostic.tools/register_oauth.pyis a self-contained script for registering an OAuth authorization resource with the Discovery Engine API — run it standalone (env vars or interactive prompts) for any Gemini Enterprise agent, not just this one.app/app_utils/(deploy.py,telemetry.py,typing.py) +app/agent_engine_app.pyare generic Agent Runtime scaffolding — copy them to deploy any ADKAppto Vertex AI Agent Engine.- There is no coupling to a datastore or infra: the only external contract
is the OAuth
AUTH_ID(shared betweenauths.pyand the two registration steps) and the standardGOOGLE_CLOUD_PROJECT/MODEL_NAMEenv vars.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

