How to Build and Deploy an AI Agent with Gemini CLI and Google ADK: A

Step-by-Step Vibe Coding Tutorial

A simplified, hands-on walkthrough of Google’s “Agentverse: The Shadowblade’s Codex” codelab, focused on the build itself.

📂 All the commands from this tutorial, in one quick-reference file: github.com/estherirawati/agentverse

Google’s Agentverse codelab wraps everything in a fun fantasy theme. You’re a “Shadowblade,” your terminal is your “primary weapon,” and you’re fighting an entropy monster called The Static. The story is a great hook, and this tutorial keeps a light touch of it while focusing on what you build and how, so you can follow along step by step.

Underneath the theme, this is a genuinely good tour of the modern AI-agent workflow on Google Cloud: prompting code into existence with Gemini CLI, wiring the CLI to external tools, building a real autonomous agent with the Agent Development Kit (ADK), testing it, and shipping it to Cloud Run.

Here’s what the journey actually looks like.

What you’re really building

By the end you’ll have:

  • A working command-line AI assistant (Gemini CLI) that can read your intent and act on it
  • A personal website generated almost entirely from a single prompt
  • The CLI connected to external tools through MCP servers (a self-hosted Git server and an image generator)
  • A real autonomous agent built with ADK that picks the right “weapon” tool for each task
  • An automated test suite for that agent
  • The agent deployed to Cloud Run as a live service

The fantasy theme maps cleanly onto real engineering ideas, and the codelab makes this explicit in its “for non-gamers” sidebars. I’ll translate as we go.

Step 0: Setup (the necessary part)

You’ll need a personal Gmail account — corporate or school accounts won’t work because of the credit grant.

  1. Claim your free Google Cloud credit through the workshop link, sign in, accept the terms.
  2. Open Cloud Shell at console.cloud.google.com, then click Open Editor.
  3. Clone the starter code and run the setup script:
git clone https://github.com/weimeilin79/agentverse-developer.git
chmod +x ~/agentverse-developer/*.sh
cd ~/agentverse-developer
./init.sh # press Enter to accept the default Project ID
  1. Point your config at the new project and turn on the APIs you’ll need:
gcloud config set project $(cat ~/project_id.txt) --quiet
gcloud services enable compute.googleapis.com artifactregistry.googleapis.com
run.googleapis.com cloudbuild.googleapis.com aiplatform.googleapis.com
iam.googleapis.com cloudresourcemanager.googleapis.com
npm update -g @google/gemini-cli

That’s the whole foundation. Now the interesting part.

Step 1: Meet your “weapon” — Gemini CLI

Gemini CLI is an open-source AI agent that lives in your terminal. It runs a reason-and-act (ReAct) loop: it reads your high-level request, breaks it into steps, picks the right tool, runs it, and checks the result.

Start it from a fresh folder:

cd ~/agentverse-developer
mkdir playground
cd playground
gemini # choose "No" when it asks to connect the Cloud Shell editor

A few commands worth knowing right away, run inside the CLI — /help lists commands, /tools shows built-in abilities (ReadFile, WriteFile, GoogleSearch…), the ! prefix runs a normal shell command, and /memorystores context:

/help
/tools
!ls -l
/memory add "My name is [your name]. I'm learning about AI agents."
/memory show

That /memory feature is your first taste of context engineering — deliberately feeding the AI background so its output stays relevant.

Now the headline trick — generating code from a sentence:

Write a Python script called hello.py that prints "I built my first
AI-generated file" and the current date.

Then verify it actually worked:

!ls
!cat hello.py
!python3 hello.py

Exit anytime with Ctrl+C twice. That’s it — you just “vibe-coded.”

What “vibe coding” really means: instead of writing every line by hand, you describe your intent in plain language and let the assistant generate the code and config. The industry term is intent-driven development.

Step 2: Build a real website, then connect external tools

Same idea, bigger ask. Inside the CLI:

Create a personal profile website in the current folder. Dark theme,
electric blue accents. Two files: index.html and styles.css. Use flexbox
for a two-column layout. Include a placeholder spot for a profile picture.
Make the code clean and commented. Don't start any server.

Exit the CLI and preview it:

python -m http.server
# Cloud Shell → Web Preview → port 8000, then Ctrl+C to stop

Giving the CLI hands: MCP servers

So far Gemini CLI can only talk and edit local files. To let it take real action in other systems — Git, databases, APIs — you connect a Model Context Protocol (MCP) server. Think of it as a power cable between the AI’s “brain” and a tool’s “body.”

The codelab spins up Gitea, a self-hosted Git server, as the first tool:

cd ~/agentverse-developer
./gitea.sh
# Web Preview → port 3005 → log in with dev / dev

Then register it in Gemini’s config so the CLI can see it:

if [ ! -f ~/.gemini/settings.json ]; then
echo '{"mcpServers":{"gitea":{"url":"http://localhost:8085/sse"}}}' > ~/.gemini/settings.json
else
jq '. * {"mcpServers":{"gitea":{"url":"http://localhost:8085/sse"}}}' ~/.gemini/settings.json > ~/.gemini/settings.json.tmp && mv ~/.gemini/settings.json.tmp ~/.gemini/settings.json
fi

Relaunch the CLI from your project folder and confirm Gitea is wired up:

cd ~/agentverse-developer/playground
gemini
/mcp

With Gitea visible, you can now do version control with plain English:

Create a new Gitea repository named 'my-profile' with description
'My first AI-built website'. Don't add any content yet.
Using the Gitea tool, push index.html and styles.css to the
'my-profile' repository.
File an issue in the my-profile repo titled "Profile image is missing".
Use the Gitea tool and the 'dev' user account.
Close issue #1 in the my-profile repo. Use the 'dev' user account.

That’s the leap the codelab is really showing off: the AI stops being a chatbot and becomes an active participant in your workflow — creating repos, pushing commits, filing and closing issues.

Extensions vs. raw MCP: editing settings.json by hand is the “raw” way — useful for understanding the plumbing. In real life you’d usually install an extension (gemini extensions install …), which bundles the MCP server, custom slash-commands, and context into one installable package. The codelab uses this approach later for an image-generation extension called Nano Banana.

Step 3: Forge the actual agent with ADK

This is the heart of the lab. You move from “AI helps me write code” to “I build an AI thing that runs on its own.” The framework is Google’s Agent Development Kit (ADK).

First, lay down the rules

Before generating any agent code, you write a GEMINI.md file. The CLI loads it automatically and treats it as persistent, project-level instructions — coding standards, naming conventions, a persona, hard constraints:

cd ~/agentverse-developer/shadowblade
. ~/agentverse-developer/set_env.sh
cat << 'EOF' > GEMINI.md
### Coding Rules for This Project
- Use Python 3 with type hints on every function.
- Every function needs a docstring explaining what it does.
- Use snake_case for variables and functions, PascalCase for classes.
- Keep code clean and readable.
EOF

This is context engineering layer two. The hierarchy is worth remembering:

  1. ~/.gemini/settings.json — global user settings
  2. GEMINI.md — project rules, always loaded
  3. Agent Skills (.gemini/skills/) — specialized knowledge loaded only when relevant

That third layer (progressive disclosure) is what keeps the agent fast: a repo can hold dozens of niche skills, but the AI only pulls the one that matches the task at hand.

The agent itself

The codelab has you generate agent.py from a design doc, then — because LLM output is unpredictable — swap in the known-good version:

cp ~/agentverse-developer/working_code/agent.py ~/agentverse-developer/shadowblade/
cp ~/agentverse-developer/working_code/mcp_server.py ~/agentverse-developer/shadowblade/

At its core, the agent is an LlmAgent with a model, a clear instruction block, and a list of tools wired up through an MCPToolset. The “weapons” it can wield are just @mcp.tool()-decorated Python functions in mcp_server.py — each one a small, focused tool with a descriptive docstring the model reads to decide when to use it.

Run it

cd ~/agentverse-developer
python -m venv env
source env/bin/activate
pip install --upgrade pip
pip install -r shadowblade/requirements.txt
adk run shadowblade

Then give it a command. The agent reads the “monster’s weakness,” picks the matching tool, and reports the outcome:

We're stuck against 'Perfectionism'. Its weakness is 'Elegant
Sufficiency'. Break us out!
'Dogma' blocks our path. Its weakness is 'Revolutionary Rewrite'. Take it down.

Strip away the theme and this is exactly how a real support or ops agent works: read the situation, choose the correct internal tool, execute, summarize.

Step 4: Test it (because an untested agent is a liability)

Agents are harder to test than scripts because their behavior emerges from an LLM’s multi-step reasoning. You care about two things: did it produce the right final answer, and did it take the right path (use the right tools)?

ADK gives you two complementary methods:

adk eval runs the agent against a set of predefined cases in a JSON “evalset.” Each case defines the input, the expected response, and — crucially — the expected tool_uses. A neat trick the lab teaches here is synthetic test data: you hand the AI one template case and ask it to generate dozens of varied ones, scaling your test coverage cheaply.

pytest wraps the same AgentEvaluator in code, which is what makes it CI-ready:

cp ~/agentverse-developer/working_code/test_agent_initiative.py ~/agentverse-developer/shadowblade/
source ~/agentverse-developer/env/bin/activate
cd ~/agentverse-developer
. ~/agentverse-developer/set_env.sh
pytest test_agent_initiative.py

A passing run (1 passed) means the agent follows its protocol and is ready to drop into an automated pipeline. The scoring criteria split cleanly into tool_trajectory_avg_score (did it do the right thing) and response_match_score (did it say the right thing).

The lab also introduces hooks — scripts that fire at specific points in the agent loop (BeforeTool, AfterTool, etc.) so you can validate, audit, or block actions during a run without touching the agent’s code. Great for security and compliance gates.

Step 5: Deploy to Cloud Run, then clean up

Build a container image and ship it as a live, autoscaling service:

. ~/agentverse-developer/set_env.sh
# create the artifact repo (ignore error if it already exists)
gcloud artifacts repositories create $REPO_NAME
--repository-format=docker
--location=$REGION
--description="Agent repo" 2>/dev/null || echo "Already exists, moving on"
# grant the service account the roles it needs
for ROLE in artifactregistry.admin cloudbuild.builds.editor run.admin
iam.serviceAccountUser aiplatform.user logging.logWriter logging.viewer; do
gcloud projects add-iam-policy-binding $PROJECT_ID
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"
--role="roles/$ROLE" --quiet
done
# prep the Dockerfile, then build and deploy
sed -i 's|COPY ./shadowblade|COPY .|g' ~/agentverse-developer/shadowblade/Dockerfile
sed -i 's|COPY shadowblade|COPY .|g' ~/agentverse-developer/shadowblade/Dockerfile
cd ~/agentverse-developer
gcloud builds submit ./shadowblade
--tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/my-agent:latest
gcloud run deploy my-agent 
--image=${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/my-agent:latest
--region=${REGION}
--allow-unauthenticated
--set-env-vars="A2A_HOST=0.0.0.0,A2A_PORT=8080,GOOGLE_GENAI_USE_VERTEXAI=TRUE"
--min-instances=1
--project=${PROJECT_ID}

Visit your service URL with /.well-known/agent-card.json appended to confirm the agent is live and describing itself:

https://my-agent-xxxxx-uc.a.run.app/.well-known/agent-card.json

Don’t skip cleanup — this is what stops a free-credit project from quietly billing you:

. ~/agentverse-developer/set_env.sh
gcloud run services delete my-agent --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet
rm -rf ~/agentverse-developer ~/.gemini
rm -f ~/project_id.txt

The five ideas worth keeping

Setting the theme aside, here’s what this codelab actually teaches:

  1. Intent-driven development — describe the outcome, let the AI generate the code, then verify it. The verification habit matters as much as the generation.
  2. MCP servers turn a chatbot into a doer — the moment the CLI can touch Git, a database, or an API, it becomes part of your real workflow.
  3. Context engineering is layered — global settings, persistent project rules (GEMINI.md), and on-demand skills. Good context beats clever one-off prompts.
  4. Agents need real testing — judge both the final answer and the path taken. Synthetic data lets you scale that testing cheaply.
  5. Ship it like software — containerize, set IAM roles, deploy to Cloud Run, and tear it down when you’re done.

The story makes it memorable; the workflow makes it useful. Both are worth keeping.

Want to go through it yourself? The full codelab is “Agentverse: The Shadowblade’s Codex” on Google Codelabs, and the starter code lives at github.com/weimeilin79/agentverse-developer. I’ve also collected every command from this tutorial in a quick-reference file on my own GitHub: github.com/estherirawati/agentverse.


How to Build and Deploy an AI Agent with Gemini CLI and Google ADK: A was originally published in Google Developer Experts on Medium, where people are continuing the conversation by highlighting and responding to this story.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

These two founders left Goldman and Meta to build voice AI for markets everyone else overlooked

Next Post

Building a Multimodal Indonesian Fake-News Detector with JAX, Flax, and Keras Kinetic on Cloud TPU

Related Posts