A robust, stateful "Agentic Loop" architecture for building interactive AI applications using the Google Gen AI Agent Development Kit (ADK). This template is vibe-coded to get you up and running with modern agentic workflows instantly.
Blog -> Building a Dummy Agentic System and My Naive Lens on AI Agents
| State 0: Initial State | State 1: Add Triangle & Move Square | State 2: Remove Circle |
|---|---|---|
![]() |
![]() |
![]() |
You need a Google Cloud Project with the Gemini API enabled.
export GOOGLE_API_KEY="your-api-key"# Clone the template
cd agent-starter-template
# Install Backend Dependencies (using uv)
cd backend
uv venv
source .venv/bin/activate
uv sync# From the backend directory (ensure environment is activated)
source .venv/bin/activate
uvicorn main:app --reloadServer runs at http://localhost:8000.
Simply open frontend/index.html in your browser.
You can also test with curl:
curl -X POST "http://localhost:8000/api/chat" \
-H "Content-Type: application/json" \
-d '{
"query": "Add a new item called Task 1 with value Urgent",
"user_id": "test_user",
"session_id": "session_1",
"state": {}
}'agent-starter-template/
├── backend/ # PYTHON SERVER (ADK)
│ ├── core/ # Configuration & Models
│ │ ├── config.py
│ │ └── models.py
│ │
│ ├── agent/ # ADK AGENT LOGIC
│ │ ├── runner.py # Agent, Runner, Session setup
│ │ ├── tools.py # Tools (manipulate state)
│ │ └── detector.py # Diff Engine
│ │
│ ├── api/ # API ENDPOINTS
│ │ └── chat.py # Orchestrator
│ │
│ ├── domain/ # DOMAIN TYPES
│ │ └── types.py
│ │
│ ├── main.py # Entry Point
│ └── pyproject.toml # Dependencies (uv)
│
└── frontend/ # JAVASCRIPT CLIENT
├── css/
├── js/
│ ├── chat.js # API Client & Chat UI
│ └── app_bridge.js
└── index.html
- Frontend as Source of Truth: The client sends its current
statewith every request. - ADK Runner: The backend uses
google-adkto run the agent loop. - State Modification: The agent uses tools (
agent/tools.py) to modify the session state. - Sync: The backend returns the new state and a diff (
ActionMetadata) to the frontend.
sequenceDiagram
participant User
participant Frontend as Frontend (AgentChat)
participant API as Backend (FastAPI)
participant Session as ADK Session Service
participant Runner as ADK Agent Runner
participant Agent as Agent (LLM)
Note over User, Frontend: 1. Interaction
User->>Frontend: Enters query (e.g., "Add item 'Task 1'")
Frontend->>Frontend: Capture Current App State (Snapshot)
Note over Frontend, API: 2. Request
Frontend->>API: POST /api/chat {query, state_snapshot}
Note over API, Session: 3. Sync State (Source of Truth)
API->>Session: Get or Create Session
API->>Session: Update Session State with Snapshot
Session-->>API: Session Ready
Note over API, Runner: 4. Execution
API->>API: Capture PrevState (DeepCopy)
API->>Runner: run_agent_loop(query)
loop Agent Loop
Runner->>Agent: Process Query
Agent->>Agent: Determine Tool Call
alt Tool Usage
Agent->>Runner: Call Tool (e.g., tool_add_item)
Runner->>Session: Execute Tool (Modifies Session State)
Session-->>Runner: Return Tool Result
Runner-->>Agent: Observation
end
end
Agent-->>Runner: Final Text Response
Runner-->>API: Completion
Note over API, Frontend: 5. Response Construction
API->>Session: Get NewState
API->>API: detect_changes(PrevState, NewState) -> ActionMeta
API->>Frontend: Return {response, state: NewState, action: ActionMeta}
Note over Frontend, User: 6. Update
Frontend->>Frontend: Update App UI with NewState
Frontend->>User: Display Agent Response
- Tools: Add new functions in
backend/agent/tools.py. Decorate with@tool_safeand register inbackend/agent/runner.py. - Prompt: Edit
_load_instruction()inbackend/agent/runner.py. - State Model: Edit
backend/domain/types.pyto define your data model. - Frontend: Implement
getAppState()andonStateUpdate()hooks in your app code to connect tochat.js.
- Beyond the Dev-UI: How to Build an Interface for an ADK agent
- Google Agent Development Kit (ADK)
- The Anatomy of Tool Calling - Python functions and tool calling.
- How to Build an Agent - Our canvas editing agent can be viewed similarly as code editing agent.


