chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# ADK Workflow Nested Workflow Sample
|
||||
|
||||
## Overview
|
||||
|
||||
This sample demonstrates how to compose workflows by embedding one workflow inside another as a single node in **ADK Workflows**.
|
||||
|
||||
It takes a 4-digit year as input and performs two tasks in parallel:
|
||||
|
||||
1. **Historical Event (`find_historical_event`)**: A straightforward Agent node that generates a 2-sentence description of an event that happened that year.
|
||||
1. **Famous Person (`find_famous_person`)**: A nested Workflow that first finds a person born in that year (`find_name`), and then forwards that name to another agent to write a biography (`generate_bio`).
|
||||
|
||||
From the perspective of the `root_agent` workflow, `find_famous_person` is just another node. The root workflow doesn't need to know the internal steps; it just waits for the parallel branches to finish, then synchronizes their outputs using a `JoinNode` before formatting them in `aggregate_results`.
|
||||
|
||||
## Sample Inputs
|
||||
|
||||
- `1969`
|
||||
|
||||
- `2000`
|
||||
|
||||
- `1984`
|
||||
|
||||
## Graph
|
||||
|
||||
### Root Workflow (`root_agent`)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
START --> process_input
|
||||
process_input --> find_historical_event[find_historical_event <br/>AGENT]
|
||||
process_input --> find_famous_person[find_famous_person <br/>WORKFLOW]
|
||||
find_historical_event --> join_for_aggregation[join_for_aggregation <br/>JOIN]
|
||||
find_famous_person --> join_for_aggregation
|
||||
join_for_aggregation --> aggregate_results
|
||||
```
|
||||
|
||||
### Nested Workflow (`find_famous_person`)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
START --> find_name
|
||||
find_name --> generate_bio
|
||||
```
|
||||
|
||||
## How To
|
||||
|
||||
1. Define your sub-workflow just like any regular workflow. Ensure it accepts the required state (e.g., `year`) and outputs the expected state (e.g., `person_bio`).
|
||||
|
||||
```python
|
||||
find_famous_person = Workflow(
|
||||
name="find_famous_person",
|
||||
edges=[("START", find_name, generate_bio)],
|
||||
)
|
||||
```
|
||||
|
||||
1. Treat the sub-workflow as a normal node when defining the edges of the parent workflow. To run them concurrently, place the nodes in a tuple, then use a `JoinNode` to synchronize their parallel executions before the final aggregation.
|
||||
|
||||
```python
|
||||
root_agent = Workflow(
|
||||
name="root_agent",
|
||||
edges=[
|
||||
("START", process_input, (find_famous_person, find_historical_event), join_for_aggregation, aggregate_results),
|
||||
],
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright 2026 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import agent
|
||||
@@ -0,0 +1,92 @@
|
||||
# Copyright 2026 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import re
|
||||
|
||||
from google.adk import Agent
|
||||
from google.adk import Event
|
||||
from google.adk import Workflow
|
||||
from google.adk.workflow import JoinNode
|
||||
|
||||
|
||||
def process_input(node_input: str):
|
||||
"""Validates the input is a valid 4-digit year."""
|
||||
match = re.search(r"\b\d{4}\b", node_input)
|
||||
if not match:
|
||||
yield Event(message="Please provide a valid 4-digit year (e.g., 1955).")
|
||||
raise ValueError("Invalid year format.")
|
||||
|
||||
yield Event(state={"year": match.group(0)})
|
||||
|
||||
|
||||
find_name = Agent(
|
||||
name="find_name",
|
||||
instruction="""
|
||||
Find the name of one famous person who was born in this year: {year}.
|
||||
Return ONLY their name, nothing else.
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
generate_bio = Agent(
|
||||
name="generate_bio",
|
||||
instruction="""
|
||||
Write a short, engaging 3-sentence biography for the specified person.
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
# Sub-workflow that acts as a single node in the parent workflow
|
||||
find_famous_person = Workflow(
|
||||
name="find_famous_person",
|
||||
edges=[("START", find_name, generate_bio)],
|
||||
)
|
||||
|
||||
|
||||
find_historical_event = Agent(
|
||||
name="find_historical_event",
|
||||
instruction="""
|
||||
Describe one highly significant historical event that occurred in this year: {year}.
|
||||
Keep the description to 2 sentences.
|
||||
""",
|
||||
)
|
||||
|
||||
join_for_aggregation = JoinNode(name="join_for_aggregation")
|
||||
|
||||
|
||||
def aggregate_results(node_input: dict[str, str], year: str):
|
||||
"""Combines outputs from parallel branches found in context state."""
|
||||
|
||||
combined_message = (
|
||||
f"# Year: {year}\n\n"
|
||||
"## Famous Person Bio:\n\n"
|
||||
f"{node_input['find_famous_person']}\n\n"
|
||||
"## Historical Event:\n\n"
|
||||
f"{node_input['find_historical_event']}"
|
||||
)
|
||||
yield Event(message=combined_message)
|
||||
|
||||
|
||||
root_agent = Workflow(
|
||||
name="root_agent",
|
||||
edges=[
|
||||
(
|
||||
"START",
|
||||
process_input,
|
||||
(find_famous_person, find_historical_event),
|
||||
join_for_aggregation,
|
||||
aggregate_results,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"appName": "nested_workflow",
|
||||
"events": [
|
||||
{
|
||||
"author": "user",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "1984"
|
||||
}
|
||||
],
|
||||
"role": "user"
|
||||
},
|
||||
"id": "e-1",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"path": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"actions": {
|
||||
"stateDelta": {
|
||||
"year": "1984"
|
||||
}
|
||||
},
|
||||
"author": "root_agent",
|
||||
"id": "e-2",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"path": "root_agent@1/process_input@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "find_name",
|
||||
"branch": "find_famous_person@1",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "Scarlett Johansson"
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-3",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/find_famous_person@1/find_name@1"
|
||||
],
|
||||
"path": "root_agent@1/find_famous_person@1/find_name@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "generate_bio",
|
||||
"branch": "find_famous_person@1",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "Scarlett Johansson is an acclaimed actress renowned for her distinctive voice and versatile performances across a wide range of genres. From her captivating early roles in films like \"Lost in Translation\" to her iconic portrayal of Black Widow in the Marvel Cinematic Universe, she has consistently delivered powerful performances. A four-time Golden Globe nominee and two-time Academy Award nominee, she remains one of Hollywood's most bankable and respected stars."
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-4",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/find_famous_person@1/generate_bio@1",
|
||||
"root_agent@1/find_famous_person@1"
|
||||
],
|
||||
"path": "root_agent@1/find_famous_person@1/generate_bio@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "find_historical_event",
|
||||
"branch": "find_historical_event@1",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "In December 1984, the Union Carbide chemical plant in Bhopal, India, experienced a catastrophic gas leak, releasing deadly methyl isocyanate. This disaster killed thousands instantly and caused hundreds of thousands of injuries, becoming one of the world's worst industrial accidents and a lasting symbol of corporate negligence."
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-5",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/find_historical_event@1"
|
||||
],
|
||||
"path": "root_agent@1/find_historical_event@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"id": "e-6",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"outputFor": [
|
||||
"root_agent@1/join_for_aggregation@1"
|
||||
],
|
||||
"path": "root_agent@1/join_for_aggregation@1"
|
||||
},
|
||||
"output": {
|
||||
"find_famous_person": "Scarlett Johansson is an acclaimed actress renowned for her distinctive voice and versatile performances across a wide range of genres. From her captivating early roles in films like \"Lost in Translation\" to her iconic portrayal of Black Widow in the Marvel Cinematic Universe, she has consistently delivered powerful performances. A four-time Golden Globe nominee and two-time Academy Award nominee, she remains one of Hollywood's most bankable and respected stars.",
|
||||
"find_historical_event": "In December 1984, the Union Carbide chemical plant in Bhopal, India, experienced a catastrophic gas leak, releasing deadly methyl isocyanate. This disaster killed thousands instantly and caused hundreds of thousands of injuries, becoming one of the world's worst industrial accidents and a lasting symbol of corporate negligence."
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "# Year: 1984\n\n## Famous Person Bio:\n\nScarlett Johansson is an acclaimed actress renowned for her distinctive voice and versatile performances across a wide range of genres. From her captivating early roles in films like \"Lost in Translation\" to her iconic portrayal of Black Widow in the Marvel Cinematic Universe, she has consistently delivered powerful performances. A four-time Golden Globe nominee and two-time Academy Award nominee, she remains one of Hollywood's most bankable and respected stars.\n\n## Historical Event:\n\nIn December 1984, the Union Carbide chemical plant in Bhopal, India, experienced a catastrophic gas leak, releasing deadly methyl isocyanate. This disaster killed thousands instantly and caused hundreds of thousands of injuries, becoming one of the world's worst industrial accidents and a lasting symbol of corporate negligence."
|
||||
}
|
||||
],
|
||||
"role": "user"
|
||||
},
|
||||
"id": "e-7",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"path": "root_agent@1/aggregate_results@1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "b7848178-784d-4fe3-a11f-568b3419acb7",
|
||||
"state": {
|
||||
"__session_metadata__": {
|
||||
"displayName": "1984"
|
||||
}
|
||||
},
|
||||
"userId": "user"
|
||||
}
|
||||
Reference in New Issue
Block a user