All Things Agentic Hackathon · Fortified Enterprise Fleet

Warden — system architecture

An authorization gateway for a Travel & Expense agent fleet. Every tool call an agent makes is intercepted, checked against spend policy by a deterministic guardrail and a tiered Gemma → Gemini review, then allowed, blocked, or escalated — before it executes, not after Finance finds out from the statement.

finops-te-agents-warden live deployment Cloud Run · Firestore · Secret Manager
01 — Request flow

One call, three ways to be cleared — and one way to recover

Most calls never reach a model at all. A hard numeric rule is checked in plain code first; a cheap Gemma pass clears the plainly-obvious rest for free; only genuinely ambiguous calls reach the ADK reviewer. When the reviewer blocks a call, the trip doesn't just stop — an orchestrator agent decides whether to retry it through the agent actually scoped for it, live, per call.

Warden request flow: a fleet agent's tool call passes through the Gateway on Cloud Run, a deterministic guardrail, Gemma triage, and an ADK reviewer. Guardrail limit violations and reviewer escalations route to a human-review Escalate step. Reviewer blocks route to an Orchestrator, which either retries the call through the correctly-scoped agent — looping back into the Gateway — or aborts the trip. Every outcome is signed if allowed and written to a hash-chained Firestore ledger, which feeds the live dashboard.
Reading the diagram: color marks the outcome, not the stage — teal is allowed, coral is blocked or aborted, violet is escalated to a human, and dashed orange is the orchestrator's live retry, back into the Gateway through whichever agent is actually scoped for the call. Registry lookups (agent scope) and the ledger both read/write the same Firestore project; omitted above to keep the call path itself legible.
Allowed — token signed Blocked / aborted Escalated — human review Orchestrator retry (in flight) Google Cloud service
02 — Google Cloud & AI platform

What's used, and what for

The Fortified Enterprise Fleet track names specific infrastructure pieces an enterprise agent fleet needs. Every row below is a piece actually running in this repo, not a description matched to a name — file, package, and how it was verified.

Named component Used for Warden file Google package / tech
Agent Gateway Unified routing + policy enforcement — every fleet call passes through one place gateway.py Cloud Run · calls google-adk/google-genai
Agent Registry Publishes each agent's declared scope & spend caps for lookup at call time registry.py google.cloud.firestore
Agent Runtime Runs a whole trip asynchronously in the background, not blocking the request orchestrator.py FastAPI BackgroundTasks · google.adk.runners.InMemoryRunner
Model Armor Inline prompt/response screening on the reviewer's judgment calls reviewer_agent.py google.genai.types.ModelArmorConfig, via Vertex AI
Agent Identity Zero-trust, per-agent cryptographic identity for access control & audit agent_engine/deploy_reviewer.py vertexai.agent_engines · deployed resource's own dedicated IAM service account
Memory Bank Persistent context for one agent across sessions, not just one call same Agent Engine deployment auto-provisioned contextSpec.memoryBankConfig
Agent Observability Audit trail + live reasoning-chain trace for every decision ledger.py + events.py google.cloud.firestore (ledger) · OTel configured, not confirmed exported
Core Cloud infra — Cloud Run, Firestore, ADK runtime Vertex AI — verified live end-to-end Configured, not independently confirmed
Model — reasoning
Gemini 3.5 Flash
Reviewer + Orchestrator, via ADK, on the Gemini Developer API
Model — triage
Gemma
Cheap first pass; most calls never reach a paid model
Framework
Google ADK
Agent + Runner for the Reviewer and Orchestrator
Secrets
Secret Manager
API key and token-signing secret, mounted at deploy
Build
Cloud Build
Source deploy · pinned deps, no backtracking
03 — Model backend

Same agent code, three swappable backends

The Reviewer and Orchestrator are defined once — same ADK Agent, same instruction. MODEL_BACKEND in .env decides which model actually answers, with no other code change. Proven locally before ever touching the cloud.

ADK Agent reviewer_agent.py one instruction, unchanged MODEL_BACKEND ollama LiteLLM · llama3.1:8b fully local · zero cost · no key gemini AI Studio · gemini-3.5-flash deployed default · free tier vertex Vertex AI · gemini-2.5-flash + Model Armor · opt-in · metered Model Armor prompt + response templates setup_model_armor.sh
Why three, not one: ollama is where every decision path got proven before any cloud cost; gemini is what's actually deployed, chosen because Vertex AI's Gemini calls are billed from the first token while AI Studio has a genuine free tier; vertex is a verified, working proof-of-concept for Model Armor screening, kept opt-in rather than the default.
04 — Agent Identity & Memory Bank

Same agent definition, two hosting targets — one grants a real identity

The reviewer's code doesn't change between these two — only where it runs. In-process on Cloud Run (what's actually deployed) it runs as the default compute service account, with nothing persisting between calls. Deployed once to Vertex AI Agent Engine instead, the resource gets a dedicated cryptographic identity and cross-session memory automatically — verified by reading the deployed resource's own spec, not the marketing description.

ADK Agent reviewer_agent.py same instruction, imported not duplicated Cloud Run in-process · InMemoryRunner deployed · what's live today one call, no memory kept Default identity project's compute service account shared, not per-agent no cross-session context Agent Engine vertexai.agent_engines.AdkApp opt-in · agent_engine/ isolated venv · google-adk>=1.5 not scale-to-zero — delete after use Agent Identity effectiveIdentity: dedicated IAM SA Memory Bank contextSpec.memoryBankConfig
What was actually checked: deployed the reviewer to Agent Engine, then queried the live resource's raw spec — spec.effectiveIdentity came back as a dedicated ...-aiplatform-re.iam.gserviceaccount.com service account (not the shared default), and contextSpec.memoryBankConfig was present without having been requested — Memory Bank came from choosing this hosting target, not a separate integration. Queried it live with the same scope-violation scenario the whole demo is built around and got the correct BLOCK decision back. Deleted again immediately after — Agent Engine doesn't share Cloud Run's scale-to-zero cost profile.
05 — Two calls a fleet agent shouldn't be able to make

Same gateway, two different breaches, two different mechanisms

Not two hypotheticals — these are the exact calls demo/trips.py and demo/scopes.py make on every real run. Same Gateway entry point both times; what differs is which layer actually catches it, and what happens next.

Scenario 1 — breaching the spend limit SFO → SIN · payment_agent · flights.search onward Scenario 2 — breaching access scope AUS → CHI · hotel_agent tries a payment tool payment_agent → payments.charge amount_usd: 2,450 · user_confirmed: true flight alone, SFO → SIN Registry lookup payment_agent found · cap: $2,000 Guardrail — plain code $2,450 > $2,000 cap no model has run yet limit fires ESCALATE human approval required regardless of user_confirmed Trip pauses hotel_agent, cab_agent steps never execute hotel_agent → payments.charge amount_usd: 195 · user_confirmed: true "already have the total, charging it now" Registry lookup hotel_agent scope: hotel.search, hotel.hold Guardrail — plain code no $ cap on hotel_agent — passes through Triage — Gemma payments.charge not in allowed_tools escalate to review Reviewer (Gemini) — BLOCK hotel_agent not authorized for payments.charge Orchestrator only payment_agent is scoped for this tool retry via payment_agent Retry: payment_agent → payments.charge same $195 · guardrail passes, under $2,000 cap ALLOW — token signed trip continues to cab_agent steps
The mechanism difference, in one line: the spend limit is a property of the call (a dollar amount checked in plain code, no judgment involved, so it can't be talked around) — the access breach is a property of who's calling (a scope violation, which needs a judgment call on whether recovery is reasonable, so it goes to the reviewer and then the orchestrator). Same Gateway, same registry, genuinely different enforcement paths because they're genuinely different kinds of problems.