Files
google--adk-python/docs/guides/workflow/graph/index.md
T
wehub-resource-sync ec2b666284
Continuous Integration / Pre-commit Linter (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.10) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.11) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.12) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.10) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.11) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.12) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.14) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Waiting to run
Copybara PR Handler / close-imported-pr (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:25:13 +08:00

134 lines
6.0 KiB
Markdown

# Workflow Graphs
In ADK 2.0, workflows are represented as directed graphs where execution flows from node to node along defined edges. This guide explains the core concepts of **nodes**, **edges**, and **graphs**, how to define them, and the validation rules enforced by the framework.
## Introduction
A workflow graph defines the execution plan for your multi-step agent interactions. It specifies:
- What tasks to run (Nodes).
- The order of execution (Edges).
- How data flows and how branches fork or merge.
The graph structure is compiled and validated when you instantiate the `Workflow` class.
## Core Concepts
### Nodes (`NodeLike`)
A node represents a single unit of execution in the workflow. In ADK, you can use several types of objects as nodes (collectively referred to as `NodeLike`):
1. **Python Functions**: Sync or async functions (and generators) decorated with `@node`. They are automatically wrapped in a `FunctionNode`.
2. **Agents**: `LlmAgent` instances (typically in `single_turn` mode). They are automatically wrapped in an internal `_LlmAgentWrapper`.
3. **Tools**: `BaseTool` instances. They are wrapped in a `ToolNode`.
4. **Workflows**: A `Workflow` is itself a `BaseNode` and can be nested as a child node in another workflow.
5. **`START`**: A special sentinel node that marks the entry point of the workflow. Every graph must have exactly one edge starting from `START`.
### Edges (`Edge`)
An edge defines a transition from a source node (`from_node`) to a destination node (`to_node`).
#### Unconditional Edges
By default, edges are unconditional. When the source node completes, execution immediately transitions to the destination node.
#### Conditional Edges (Routing)
An edge can be associated with one or more **routes** (a string, integer, or boolean). The edge is only followed if the source node explicitly emits a matching route.
To emit a route, the source node must yield an `Event(route="my_route")` (or return/yield an object that maps to that route).
#### Default Route
You can define a fallback edge using `DEFAULT_ROUTE` (imported as `from google.adk.workflow import DEFAULT_ROUTE` or using `"__DEFAULT__"`). This edge is followed if the source node emits a route, but no specific conditional edge matches it.
---
## Defining the Graph (Syntax)
You define the graph structure by passing a list of `edges` to the `Workflow` constructor. ADK supports two syntax styles:
### 1. Chain Tuples (Recommended)
Chain tuples provide a concise way to define sequential, parallel, and conditional transitions using Python tuples.
* **Sequential Chain**:
```python
edges=[
(START, step_a, step_b, step_c),
]
```
This defines: `START -> step_a -> step_b -> step_c`.
* **Parallel Fan-Out**: Use a tuple of nodes to split execution into parallel branches.
```python
edges=[
(START, step_a, (step_b, step_c)),
]
```
This defines: `START -> step_a`, and then `step_a -> step_b` AND `step_a -> step_c` in parallel.
* **Conditional Routing**: Use a dictionary (Routing Map) to define conditional branches.
```python
from google.adk.workflow import DEFAULT_ROUTE
edges=[
(START, step_a, {
"success": step_b,
"failure": step_c,
DEFAULT_ROUTE: fallback_step,
}),
]
```
If `step_a` yields `Event(route="success")`, it goes to `step_b`. If it yields `"failure"`, it goes to `step_c`. Any other route goes to `fallback_step`.
### 2. Explicit Edge Objects
For complex graphs or when you prefer explicit declarations, you can use `Edge` objects:
```python
from google.adk.workflow import Edge, START
edges=[
Edge(from_node=START, to_node=step_a),
Edge(from_node=step_a, to_node=step_b, route="success"),
Edge(from_node=step_a, to_node=step_c, route="failure"),
]
```
---
## Graph Validation
When a `Workflow` is initialized, it builds an internal `Graph` representation and runs `validate_graph()` to catch structural errors early. The following rules are strictly enforced:
### 1. Unique Node Names
All distinct node objects in the graph must have unique names.
* *Error*: If you have two different function nodes named `process_data`, validation will fail.
* *Solution*: Ensure unique names, or reuse the exact same object instance if you want to route back to the same node.
### 2. Single START Entry Point
The graph must contain the `START` node, and `START` must not have any incoming edges.
* *Error*: A graph without `START` or with an edge pointing back to `START` will fail validation.
### 3. Connectivity (Reachability)
All nodes in the graph must be reachable from the `START` node.
* *Error*: If you define a node but do not connect it to the rest of the graph, validation will fail.
### 4. No Duplicate Edges
You cannot define duplicate edges between the same two nodes.
* *Error*: `Edge(from_node=A, to_node=B)` and `Edge(from_node=A, to_node=B)` in the same list will fail.
### 5. Default Route Constraints
- A node can have at most one outgoing `DEFAULT_ROUTE` edge.
- `DEFAULT_ROUTE` cannot be combined with other routes in a list (e.g., `route=["success", DEFAULT_ROUTE]` is invalid).
### 6. No Unconditional Cycles
The graph must not contain cycles consisting entirely of unconditional edges (edges with no route).
* *Allowed*: Conditional loops are allowed (e.g., `A -> B -> A` where `B -> A` is conditional on a route).
* *Forbidden*: Unconditional loops (`A -> B -> A` with no routes) are rejected to prevent infinite execution loops.
### 7. Static Schema Matching
If a node defines an `output_schema` and its successor defines an `input_schema`, they must match exactly.
* *Error*: Schema mismatch on transition edges will fail validation.
### 8. Chat Agent Wiring
`LlmAgent` instances configured with `mode='chat'` are only allowed to follow the `START` node.
* *Reason*: Chat-mode agents manage their own conversational history and cannot consume direct inputs from preceding nodes in a workflow chain. For sequential steps, use `mode='single_turn'`.