adk-samples / ambient-expense-agent
AGENTS.md11k starsChanged 44 days agoApache-2.0View on GitHub
A clone-and-study ambient agent: there is no interactive chat loop. Expense reports arrive as Pub/Sub events, get pushed to an ADK trigger endpoint, and flow through an ADK 2.0 graph-based Workflow. Business rules stay in code (a $100 threshold routes low-value expenses straight to auto-approval); only high-value expenses reach an LLM review_agent, which then pauses for human-in-the-loop approval via RequestInput before logging a decision. The graph itself is compact — the interesting parts are the ambient plumbing: authenticated Pub/Sub push,…
- 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-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/oauth-user-consent-flow/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
2 rules. About 0 are common, 0 are distinctive, and 2 are 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.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 37
To add eval: create tests/eval/ with an eval_config.yaml + datasets/ (mirroring the RAG recipes' agents-cli LLM-judge format), grading the …
- Very specific: line 165
IAP propagation lag: After make deploy, IAP can take 5–10 minutes to propagate.
≈ “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
Ambient Expense Agent — Event-Driven Pub/Sub Workflow with HITL
Intent
A clone-and-study ambient agent: there is no interactive chat loop. Expense
reports arrive as Pub/Sub events, get pushed to an ADK trigger endpoint, and
flow through an ADK 2.0 graph-based Workflow. Business rules stay in code
(a $100 threshold routes low-value expenses straight to auto-approval); only
high-value expenses reach an LLM review_agent, which then pauses for
human-in-the-loop approval via RequestInput before logging a decision. The
graph itself is compact — the interesting parts are the ambient plumbing:
authenticated Pub/Sub push, session-based HITL discovery, an IAP-protected
approval UI, and Cloud Monitoring email alerts, all provisioned by Terraform.
When To Use
- The user wants an event-driven / ambient agent (triggered by Pub/Sub, no user typing at it) rather than a request/response chat agent.
- The user wants business rules in code + the LLM only for judgment calls (deterministic threshold routing, LLM used just for risk analysis).
- The user needs human-in-the-loop approval that pauses a workflow mid-run and resumes it later from a separate UI.
- The user wants a reproducible two-service Cloud Run + Pub/Sub + IAP + Monitoring deployment as a starting point.
Eval
- Scenarios Path: none — this recipe ships no eval datasets and no
tests/eval/directory; nothing is wired intomake test. - What exists instead lives under
tests/:tests/test_runnability.py— importsexpense_agent.agent, patchesgoogle.auth.default(), and assertsroot_agentis defined (a smoke test).tests/test_integration.py— drives the full flow in-process overhttpx.ASGITransport(no real servers): Pub/Sub trigger → auto-approve, trigger → review → HITL approve, → HITL reject, and subscription-name normalization. This is the closest thing to behavioral coverage.
- To add eval: create
tests/eval/with aneval_config.yaml+datasets/(mirroring the RAG recipes'agents-cliLLM-judge format), grading thereview_agent's risk assessment against fixed expense payloads.
End-to-end flow
expense published to Pub/Sub topic "expense-reports"
-> authenticated OIDC push -> POST /apps/expense_agent/trigger/pubsub
-> parse_expense_email (base64/plain JSON -> ExpenseData fields)
-> route_by_amount ($100 threshold, stashes expense_data in ctx.state)
| |
< $100 >= $100
| |
auto_approve review_agent (LLM)
(logs INFO, done) -> emit_expense_alert (JSON stdout)
-> request_approval (RequestInput -> PAUSE)While paused, a structured WARNING log fires a log-based metric → alert
policy → email to the manager. The manager opens the IAP-protected approval
UI, which finds the pending adk_request_input by scanning ADK session events
and resumes the workflow via POST /run:
... PAUSED ... -> manager approves/rejects in approval UI
-> frontend POST /approve -> backend POST /run (functionResponse)
-> process_decision (logs approved/rejected, emits final summary) -> doneThe Pub/Sub push completes as soon as the workflow pauses — the ack deadline is not held for the human; the HITL resume is entirely out-of-band.
Most interesting files to study (in order)
Trigger server (the ambient entry point)
expense_agent/fast_api_app.py— the whole "ambient" seam. Builds the ADK app withget_fast_api_app(..., trigger_sources=["pubsub"])so Pub/Sub can POST expenses to/apps/{app}/trigger/pubsub. Adds middleware that normalizesprojects/.../subscriptions/NAME→NAME, because the ADK trigger handler uses the subscription as the sessionuser_id— and the frontend must query with that same short name.
Deployment plumbing (Terraform — what makes it production-ambient)
terraform/pubsub.tf— the trigger wiring: anexpense-reportstopic and an authenticated push subscription whosepush_configtargets the backend trigger URL with anoidc_token.600sack deadline, exponential retry, and a dead-letter topic after 5 attempts.terraform/cloud_run.tf— the two services. Backend runs the ADK agent; frontend isiap_enabled = trueand getsBACKEND_URL,APP_NAME,PUBSUB_SUBSCRIPTION, andUSE_SERVICE_AUTHwired as env.min_instance_count = 1keeps one instance warm (relevant to in-memory sessions — see Gotchas).terraform/monitoring.tf— the alert path. Agoogle_logging_metricfiltersjsonPayload.alert_type="expense_review"from Cloud Run logs; an alert policy fires an email notification channel with a markdown link straight to the approval UI. This is what turns a stdout log into a manager's email.terraform/iam.tf— least-privilege service accounts:pubsub_invoker(run.invokeron backend +serviceAccountTokenCreatorfor the Pub/Sub service agent's OIDC),frontend_invoker, and the IAP bindings (iap.httpsResourceAccessorfor the notification email +run.invokerfor the IAP service agent).
Approval UI (HITL frontend — separate uv sub-project)
frontend/main.py— a thin proxy, not an agent.GET /pending-approvalsqueries the backend's built-in ADK session APIs, then_extract_pending_ approvalscans each session's events for anadk_request_inputfunction call without a matching response (and grabs theemit_expense_alertrisk summary).POST /approveforwards afunctionResponseto the backend'sPOST /runto resume the paused workflow. On Cloud Run it mints ID tokens for service-to-service auth; locally it calls the backend unauthenticated.
Agent graph & config (read last)
expense_agent/config.py— the auth bootstrap and the two knobs. Picks AI Studio ifGOOGLE_API_KEYis set, else Vertex viagoogle.auth.default()at import time. Exposesmodel(fromMODEL_NAMEenv) andreview_threshold = 100.0.expense_agent/agent.py— the payoff, once you understand how events arrive and approvals flow back. Defines theExpenseDataPydantic schema, the function nodes (parse_expense_email,route_by_amount,auto_approve,request_approval,process_decision), the LLMreview_agent(emit_expense_alerttool), and theWorkflowgraph that stitches them together — a mixed function/LLM graph with conditional routing and aRequestInputHITL pause.expense_agent/__init__.pyrunsload_dotenv()before the submodule imports (hence the# noqa: E402).
Data handling
- No documents, no ingestion. "Data" here is the expense event payload
moving between graph nodes, shaped by the
ExpenseDataPydantic model (amount,submitter,category,description,date). - Decoding:
parse_expense_emailaccepts the Pub/Sub messagedataas base64 (real Pub/Sub) or plain JSON (local testing) and coerces fields with safe defaults. - State handoff:
route_by_amountstashes the parsed dict intoctx.state["expense_data"]so the HITLrequest_approvalnode and the frontend can read it after the pause. - Sessions are the durable substrate. Pending approvals are discovered by
scanning ADK session events for an unanswered
adk_request_input. The sessionuser_idis the Pub/Sub subscription name (normalized by the middleware). No session service URI is configured, so the ADK default in-memory session service is used. - Structured logs are the "output".
auto_approve,emit_expense_alert, andprocess_decisionprint(json.dumps(...))to stdout; Cloud Run captures these as structured Cloud Logging entries that drive the alert metric.
Gotchas / things to know
- Sessions are in-memory. With no persistent session service configured,
pending approvals live only in the backend instance's memory —
min_instance_count = 1keeps one instance warm, but a restart/redeploy drops in-flight approvals. Wire a persistent session service for real use. - The
$100threshold lives in two places.config.review_threshold(backend routing) andREVIEW_THRESHOLD = 100infrontend/main.py(pre-filters which sessions to show). Keep them in sync or the UI and the agent disagree. user_id== subscription name. The frontend queries pending approvals usingPUBSUB_SUBSCRIPTION(defaulttest-sublocally). If it doesn't match thesubscriptionfield in trigger requests, the UI shows nothing — which is exactly whyfast_api_app.pynormalizes the fully-qualified subscription path.- Model comes from
MODEL_NAME.config.pyreadsos.getenv("MODEL_NAME")with no default (so it isNoneif unset)..env.examplesetsgemini-3.5-flash; tests set it explicitly. Don't hardcode model names and don't use deprecated ones (gemini-2.0-flash,gemini-2.5-flash). - Import-time credentials. Without
GOOGLE_API_KEY, importingconfigcallsgoogle.auth.default()immediately — a credential-less import fails unless ADC is present.test_runnability.pypatches it. - Alerts only fire when deployed.
emit_expense_alertjust prints locally; the email path (log-based metric → alert policy → channel) exists only in the deployed Cloud Monitoring setup. - IAP propagation lag. After
make deploy, IAP can take 5–10 minutes to propagate; a403 Forbiddenon the approval UI early on is expected.
Where to run things
Makefile targets:
make install/make install-frontend—uv sync(backend / frontend sub-project).make dev— run the backend trigger server (fast_api_app.py, port 8080).make dev-frontend— run the approval UI againstBACKEND_URL=localhost:8080(port 8081).make playground— local ADK web UI (adk web, port 8501).make test—pytest tests/ -xvs(runnability + in-process integration).make lint—codespell+ruff check --fix+ruff format+mypy.make deploy NOTIFICATION_EMAIL=...— build both images via Cloud Build, thenterraform applythe whole stack.make remote-test— publish a$250test expense to the deployed topic.make clean NOTIFICATION_EMAIL=...—terraform destroy(retries once after 60s for alert-policy propagation).
Reuse (copy as-is)
terraform/is self-contained — two Cloud Run services, Pub/Sub (+ dead-letter), IAM, IAP, and Cloud Monitoring. Copy the directory and setproject_id,region,notification_email, and thebackend_image/frontend_imagevars. It expects prebuilt images, so build them first (theMakefileuses Cloud Build) beforeterraform apply.frontend/is an independent uv sub-project (its ownpyproject.toml,uv.lock, andDockerfile) — a generic ADK HITL approval proxy. It has no code coupling to the backend beyond the ADK session-API contract; point it at any ADK agent viaBACKEND_URL,APP_NAME, andPUBSUB_SUBSCRIPTION.- There is no code coupling into
expense_agent/: the agent is configured purely through env (MODEL_NAME,GOOGLE_API_KEY/GOOGLE_CLOUD_*), and the frontend reaches it only over HTTP.
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.

