Lab 17: Building a Market Analyst with Deterministic Edges
Goal
In this lab, you will build a structured workflow that analyzes currency conversion requests. You will use a Deterministic Workflow with explicit edges to create a pipeline that classifies a request and routes it to a specific specialist tool.
This demonstrates how to create predictable AI pipelines in ADK 2.0 with just a few lines of routing glue code, instead of hand-writing full if/else orchestration for every branch.
Step 1: Create the Project
- Create a new project:
uv run adk create market_analyst - Navigate into the directory:
cd market_analyst
Step 2: Define the Specialist Nodes
Open agent.py. We will create three main components:
- A Classifier Agent: To detect the target currency.
- Specialist Tools: To handle the "market analysis" (simulated).
from __future__ import annotations
from pydantic import BaseModel
from google.adk import Agent, Workflow, Context
from google.adk.workflow import node
from typing import Literal
# 1. Define the Classification Schema
class MarketRoute(BaseModel):
currency: Literal["USD", "EUR", "GBP"]
# 2. Create the Classifier Node
# TODO: Define the 'classifier' agent.
# Use MarketRoute as output_schema.
# Write instructions to extract the currency (USD, EUR, or GBP).
classifier = ...
# 3. Create Specialist Agents (Nodes)
# TODO: Define usd_analyst, eur_analyst, and gbp_analyst.
# Give each one a brief, unique instruction for their currency.
usd_analyst = ...
eur_analyst = ...
gbp_analyst = ...
# 4. Wrap the classifier so it can set ctx.route.
# A plain Agent never sets ctx.route on its own -- not even with a Pydantic
# output_schema -- so a small @node wrapper is what makes the Router
# Dictionary below actually work.
# TODO: Complete this function:
# a. Call `await ctx.run_node(classifier, node_input)` and store the result.
# Note: the result comes back as a plain dict, e.g. {"currency": "EUR"},
# even though MarketRoute is a Pydantic model.
# b. Set `ctx.route` to the "currency" value from that dict.
# c. Return node_input (unchanged) so the chosen specialist still receives
# the original user request.
@node(rerun_on_resume=True)
async def classify_and_route(ctx: Context, node_input: str):
...
Step 3: Build the Deterministic Workflow
Exercise: Complete the root_agent definition using the edges parameter.
You need to:
- Connect
"START"toclassify_and_route(notclassifierdirectly -- it's the wrapper that setsctx.route). - Create a Router Dictionary that connects
classify_and_routeto the three specialist agents based on the route it set.
# TODO: Complete the Workflow definition
root_agent = Workflow(
name="MarketSystem",
edges=[
# Edge 1: Start at the classify_and_route node
("START", ...),
# Edge 2: Route based on ctx.route
(classify_and_route, {
"USD": ...,
"EUR": ...,
"GBP": ...
})
]
)
Step 4: Run and Test
- Launch the Dev UI:
uv run adk web . - Test the routing:
- "What is happening with the Dollar?" -> Should run
usd_analyst. - "Give me news on the Euro." -> Should run
eur_analyst.
- "What is happening with the Dollar?" -> Should run
- Inspect the Graph: Observe how ADK 2.0 visualizes the deterministic paths in the Graph View.
Lab Summary
You have successfully built a deterministic workflow!
- You used Pydantic to ensure the classifier's output is one of your router keys.
- You learned that Router Dictionaries match against
ctx.route, not a node's raw output -- and that a plainAgentneeds a small@nodewrapper to set it. - You defined explicit edges to create a transparent execution graph, where only the classifier needed custom code and the specialist branches stayed fully declarative.
Self-Reflection Questions
- What happens if
classify_and_routesetsctx.routeto a value that isn't in your dictionary (e.g., "JPY")? - Can you add an
"other"key to the dictionary to handle unknown inputs? classify_and_routeis a@nodefunction, just like in Module 18 -- so what's actually different about this pattern compared to a full Dynamic Workflow?
🕵️ Hidden Solution 🕵️
Looking for the solution? Here's a hint (Base64 decode me):
L2RvYy1hZGstdHJhaW5pbmcvbW9kdWxlMTctc3RydWN0dXJlZC1yb3V0aW5nL2xhYi1zb2x1dGlvbg==
The direct link is: Lab Solution