Lab 21.6 Solution: Market Analyst with Deterministic Edges
Goal
This file contains the complete code for the agent.py script using the ADK 2.0 Deterministic Workflow pattern.
market_analyst/agent.py
from __future__ import annotations
from pydantic import BaseModel
from google.adk import Agent, Workflow
from typing import Literal
# 1. Define the Classification Schema
# Using Pydantic is CRITICAL here because the Workflow router
# matches the node's output against the dictionary keys.
class MarketRoute(BaseModel):
currency: Literal["USD", "EUR", "GBP"]
# 2. Create the Classifier Node
classifier = Agent(
name="classifier",
model="gemini-3.5-flash",
instruction="Extract the currency (USD, EUR, or GBP) from the user's request. Return ONLY the JSON.",
output_schema=MarketRoute
)
# 3. Create Specialist Agents (Nodes)
usd_analyst = Agent(
name="usd_analyst",
model="gemini-3.5-flash",
instruction="Provide a brief, bullish outlook for the US Dollar."
)
eur_analyst = Agent(
name="eur_analyst",
model="gemini-3.5-flash",
instruction="Provide a brief, cautious outlook for the Euro."
)
gbp_analyst = Agent(
name="gbp_analyst",
model="gbp_analyst", # Tip: Use name as a string or the variable
model="gemini-3.5-flash",
instruction="Provide a brief, neutral outlook for the British Pound."
)
# 4. Build the Deterministic Workflow
# The 'edges' list defines the explicit structure of the graph.
root_agent = Workflow(
name="MarketSystem",
edges=[
# Rule 1: The workflow always starts by running the classifier.
("START", classifier),
# Rule 2: Route the output of the classifier to a specialist.
# ADK 2.0 automatically looks at the 'currency' field of the
# MarketRoute object returned by the classifier.
(classifier, {
"USD": usd_analyst,
"EUR": eur_analyst,
"GBP": gbp_analyst
})
]
)
Self-Reflection Answers
-
What happens if the
classifierreturns a value that isn't in your dictionary (e.g., "JPY")?- Answer: The workflow will fail with a routing error because the graph engine doesn't know where to go next. This is why using
Literalin Pydantic is so important—it forces the LLM to choose from your defined paths.
- Answer: The workflow will fail with a routing error because the graph engine doesn't know where to go next. This is why using
-
Can you add an
"other"key to the dictionary to handle unknown inputs?- Answer: Yes! You could update your
MarketRouteschema to include"OTHER"and then add a corresponding entry in theedgesdictionary to point to a general-purpose agent.
- Answer: Yes! You could update your
-
How does this approach compare to the
@nodedynamic workflow in terms of code complexity?- Answer: The deterministic
Workflowis much more concise for simple routing. You don't have to writeasync def, handleContext, or manually callawait ctx.run_node(). The framework handles all the plumbing for you. However, it is less flexible if you need complex Python logic (like loops) between nodes.
- Answer: The deterministic