Step 1 · Connect the agents in a workflow (12 min)¶
Goal: Make the SRE agent run its two ADK agents one after the other, with a code step between them.
Builds on: ADK basics: 4. Workflow, 5. Runner, session and events.
The idea: an ADK workflow is a graph¶
The SRE agent (sre_agent/src/sre_agent/sre_workflow.py) uses the
Agent Development Kit (ADK). It has two agents:
| Agent | Input | Output |
|---|---|---|
🕵️ trace_analyzer |
The recent failing and slow requests | One trace ID |
🩺 log_correlator |
The spans and logs of that trace | The root cause and a mitigation plan |
Between the two agents, a plain Python function, fetch_telemetry, gets the spans, the logs and
the project topology for the trace ID. A model is not necessary for this task, so it is code.
An ADK Workflow connects these nodes. A node can be an agent or a function. A tuple in
edges is a chain: each node gets the output of the node before it.
flowchart TB
S([START]) --> TA["🕵️ trace_analyzer"]
TA -->|trace ID| FT["fetch_telemetry (Python)"]
FT -->|spans + logs| LC["🩺 log_correlator"]
At this time, the chain stops after trace_analyzer. The trace ID goes nowhere, and the report
has no root-cause analysis.
No API key? The agents still run¶
Without GEMINI_API_KEY, the agents use SimulatedLlm (sre_agent/src/sre_agent/simulated_llm.py).
This is an ADK model class that answers with fixed rules, not with a neural network. The workflow,
the agents and the tool calls are real ADK. Only the text comes from rules. With a key, the same
agents use Gemini.
Your task¶
-
Find the TODO:
git grep -n "TODO(step-1)" -
In
_run_adk_diagnostics, changeedgesto the chainSTART → trace_analyzer → fetch_telemetry → log_correlator.
Run it¶
-
Do these commands:
uv run workshop/check.py 1 uv run simulate_incident.py --engine-only -
Find the new sections at the start of the report: Root Cause Analysis, Observability Metrics and Recommended Mitigation. The
log_correlatorwrote them. - Look at Observability Metrics. It says
Not checked: this agent has no query_metrics tool. Step 2 fixes this.
With a GEMINI_API_KEY, Gemini writes its own text: the sections can have other titles, and
there is no Not checked line. The agent has no tools yet, so it can only guess the cause from
the spans and logs.
The cascade table and the post-mortem come after the agents' text. The workflow adds them from the tools, so they are always correct.
Discuss¶
- Why is
fetch_telemetrya function and not an agent? A model is slow, costs money and can make mistakes. Use a model only for the decisions that need one. - Why does
trace_analyzerreturn only a trace ID? A small, exact output is easy to check: the workflow makes sure that the ID is one of the candidates.
Stuck? Run uv run workshop/step.py hint 1, or ask the workshop coach in Antigravity. To apply
the solution: uv run workshop/step.py solve 1.
Hint and solution¶
Try the step first. Open the hint when you are stuck, and the solution only after the hint.
Hint: where to change the code
File: sre_agent/src/sre_agent/sre_workflow.py, in _run_adk_diagnostics(). The TODO says:
# TODO(step-1): The workflow stops after the TraceAnalyzer. Make it a chain of 4 nodes:
# START -> trace_analyzer -> fetch_telemetry -> log_correlator.
# A tuple in `edges` is a chain: each node gets the output of the node before it. Thus
# fetch_telemetry gets the trace ID, and log_correlator gets the spans and logs.
Solution
--- a/sre_agent/src/sre_agent/sre_workflow.py
+++ b/sre_agent/src/sre_agent/sre_workflow.py
@@ -272,11 +272,9 @@
try:
# Define the ADK 2.0 graph workflow
- # TODO(step-1): The workflow stops after the TraceAnalyzer. Make it a chain of 4 nodes:
- # START -> trace_analyzer -> fetch_telemetry -> log_correlator.
- # A tuple in `edges` is a chain: each node gets the output of the node before it. Thus
- # fetch_telemetry gets the trace ID, and log_correlator gets the spans and logs.
- sre_diagnostics_workflow = AdkWorkflow(name="sre_diagnostics_workflow", edges=[(START, trace_analyzer)])
+ sre_diagnostics_workflow = AdkWorkflow(
+ name="sre_diagnostics_workflow", edges=[(START, trace_analyzer, fetch_telemetry, log_correlator)]
+ )
session_service = InMemorySessionService()
runner = Runner(node=sre_diagnostics_workflow, app_name="sre_diagnostics", session_service=session_service)
To apply it to your code: uv run workshop/step.py solve 1.