From Zero to Deployed: Building a RAG-Powered Coffee Barista Agent with Google ADK, Streamlit, and Cloud Run
Gen AI Academy Track 1 — Hack2Skill x Google Cloud
· Ajoy Saha
Why I Picked Up This Codelab
With 23+ years in financial services technology delivery, most of my work lives in the world of programs, stakeholders, and delivery frameworks. But the last couple of years have pulled me deeper into hands-on AI/ML engineering — building multi-agent systems, experimenting with RAG pipelines, and generally trying to understand these tools from the inside out rather than just from a program manager's vantage point.
So when the Gen AI Academy Track 1 challenge showed up — "Build and Deploy a Customer-Facing AI Agent" — it was an easy yes. The brief was simple to state and satisfying to execute: build a Retrieval-Augmented Generation (RAG) agent, wrap it in a Streamlit front end, orchestrate it with Google's Agent Development Kit (ADK), and ship it live on Cloud Run. I decided to build a coffee shop assistant — a barista bot that could answer questions grounded in an actual menu rather than hallucinating drink names.
Here's how the build went, what I learned, and what I'd tell someone starting the same codelab today.
Setting Up: Cloud Shell as the Workbench
I started entirely inside Google Cloud Shell — no local environment setup, no dependency conflicts, just a browser tab and a terminal. First order of business was enabling the APIs the project would lean on:
gcloud services enable \ run.googleapis.com \ aiplatform.googleapis.com \ cloudbuild.googleapis.comThree services, three responsibilities: Cloud Run for hosting, Vertex AI for the model backing the agent, and Cloud Build for the container build pipeline underneath the deploy command. This is the kind of infrastructure sequencing that feels familiar from enterprise delivery work — you provision the platform before you write a line of application logic.
With the project scaffolded (mkdir coffee-barista-agent), I laid down the file structure directly in the Cloud Shell Editor:
menu.json— the knowledge base: a structured list of drinks, descriptions, and prices that the RAG layer would retrieve fromagent.py— the ADK agent definition and retrieval logicapp.py— the Streamlit front endseed.py— a helper to seed/index the menu datarequirements.txt— dependencies
One small but useful habit from the codelab: validating the JSON before wiring it into the agent —
cat menu.json | python3 -m json.tool > /dev/null && echo "Valid JSON!"A trivial step, but exactly the kind of "fail fast, fail cheap" discipline that saves a debugging session an hour later when the retrieval layer starts throwing parsing errors instead.
Locking Down Identity: Service Accounts Done Properly
Rather than running the deployed service under a broad default identity, the codelab has you create a dedicated service account scoped to exactly what the agent needs:
gcloud iam service-accounts create barista-agent-sa \ --description="Service account for Coffee Barista ADK agent on Cloud Run" \ --display-name="Barista Agent Service Account" gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/aiplatform.user"This is a small thing that matters a lot once you've spent two decades around enterprise governance reviews: least-privilege by default. The barista agent gets exactly the aiplatform.user role it needs to call Vertex AI models — nothing more, nothing that would raise an eyebrow in a security audit.
The Deploy Step — and a Very Instructive Error
This is where the journey got genuinely educational. My first deploy attempt failed:
ERROR: (gcloud.run.deploy) Invalid value for property [api_endpoint_overrides/run]:The endpoint_overrides property must be an absolute URI beginning with http:// orhttps:// and ending with a trailing '/'.The root cause, once I traced it back, was almost embarrassingly simple: I'd copied the codelab's export REGION=[insert-region-here] line without swapping in a real region — so REGION was literally the string [insert-region-here], brackets included. When gcloud run deploy tried to construct the Cloud Run endpoint URL from that, it produced garbage.
The fix was a one-line correction:
export REGION=asia-south1It's a small bug, but it's a good reminder of a lesson that applies far beyond cloud tooling: placeholder text is a landmine in copy-paste workflows. In a 23-year delivery career, I've seen far more expensive versions of this same mistake — a config value never replaced, an environment variable left as a template string — cascading into production incidents. Catching it here, in a sandboxed codelab, was a cheap and welcome refresher.
With the region corrected, the real deploy command went through:
gcloud run deploy coffee-barista \ --source . \ --region $REGION \ --allow-unauthenticated \ --labels dev-tutorial=codelab-streamlit-rag-adk \ --command "/cnb/lifecycle/launcher" \ --args "sh,-c,python3 -m streamlit run app.py --server.port=\$PORT --server.address=0.0.0.0 --server.enableCORS=false --server.enableXsrfProtection=false" \ --service-account "barista-agent-sa@$PROJECT_ID.iam.gserviceaccount.com" \ --set-env-vars GOOGLE_GENAI_USE_VERTEXAI=TRUE,GOOGLE_CLOUD_PROJECT=$PROJECT_ID,GOOGLE_CLOUD_LOCATION=globalA few details worth calling out for anyone attempting this next:
--source .tells Cloud Run to build the container directly from the source directory using Buildpacks — no hand-written Dockerfile required.--command/--argsoverride the buildpack's default entrypoint so Cloud Run launches Streamlit correctly, binding to the$PORTCloud Run assigns dynamically and disabling CORS/XSRF protections that would otherwise block the app in a headless container context.GOOGLE_GENAI_USE_VERTEXAI=TRUEis the switch that routes the agent's model calls through Vertex AI (using the service account's IAM identity) rather than requiring an API key.
A few minutes later, Cloud Build finished, the container went live, and the terminal handed back a service URL. That's the moment a codelab stops being an exercise and starts being your application, reachable from anywhere:
🔗 coffee-barista-330208986773.asia-south1.run.app
What This Build Actually Demonstrates
Stepping back from the command-line mechanics, this codelab is a compact but complete tour of a production-shaped RAG pattern:
- Grounded retrieval, not free-floating generation — the agent answers from
menu.json, not from whatever a base model assumes a "coffee menu" looks like. That's the entire point of RAG: constrain the model's answers to a trusted, current source of truth. - Agent orchestration via ADK — rather than hand-rolling prompt chains, the ADK gives structure to how the agent reasons over retrieved context and responds.
- A real, if minimal, front end — Streamlit turns the agent into something a non-technical user could actually interact with, which is the difference between a notebook demo and a "customer-facing" agent, as the challenge brief specifically asked for.
- Cloud-native deployment discipline — scoped IAM, serverless hosting, container builds from source. Nothing here required managing a server.
Where I'd Take It Next
A few extensions I'm considering now that the base agent is live:
- Swapping the static
menu.jsonfor a small vector store, so retrieval scales past a hand-maintained JSON file - Adding conversation memory so the agent can handle multi-turn orders ("make that a large" without repeating the drink name)
- Wiring in basic observability — the kind of structured logging and tracing I lean on in enterprise delivery work — to see what the agent retrieves and why, not just what it outputs
Closing Thought
What made this codelab worthwhile wasn't the coffee menu — it was the end-to-end shape of the exercise: identity and access, infrastructure provisioning, a real debugging moment, and a genuinely deployed, publicly reachable service at the end of it. That full loop, compressed into an afternoon, is exactly the kind of hands-on rep that turns "I understand RAG conceptually" into "I've shipped a RAG agent."
For anyone else working through this Track 1 challenge: read the region placeholder twice before you export it. Ask me how I know.
Built as part of Gen AI Academy Track 1 — Build and Deploy a Customer-Facing AI Agent, Hack2Skill x Google Cloud. Deployed agent: coffee-barista-330208986773.asia-south1.run.app