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,69 @@
|
||||
# ADK Workflow Parallel Worker Sample
|
||||
|
||||
## Overview
|
||||
|
||||
This sample demonstrates how to use **parallel workers** in ADK Workflows.
|
||||
|
||||
It takes a user-provided topic, uses an agent to find a list of related topics. The workflow engine will automatically fan-out execution across multiple concurrently running nodes when given an iterable of inputs. First, it dynamically spins up multiple instances of the `make_upper_case` function in parallel to capitalize the topics. Then, it dynamically spins up parallel instances of the `explain_topic` agent to explain each related topic concurrently. Finally, an `aggregate` function collects and formats all the parallel explanations into a single response.
|
||||
|
||||
## Sample Inputs
|
||||
|
||||
- `machine learning`
|
||||
|
||||
- `renewable energy`
|
||||
|
||||
- `space exploration`
|
||||
|
||||
## Graph
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
START --> process_input
|
||||
process_input --> find_related_topics
|
||||
find_related_topics --> make_upper_case[make_upper_case <br/>parallel_worker=True]
|
||||
|
||||
make_upper_case --> worker1[worker 1]
|
||||
make_upper_case --> worker2[worker 2]
|
||||
make_upper_case --> workerN[worker N]
|
||||
|
||||
worker1 --> explain_topic[explain_topic <br/>parallel_worker=True]
|
||||
worker2 --> explain_topic
|
||||
workerN --> explain_topic
|
||||
|
||||
explain_topic --> eworker1[worker 1]
|
||||
explain_topic --> eworker2[worker 2]
|
||||
explain_topic --> eworkerN[worker N]
|
||||
|
||||
eworker1 --> aggregate
|
||||
eworker2 --> aggregate
|
||||
eworkerN --> aggregate
|
||||
```
|
||||
|
||||
## How To
|
||||
|
||||
Both agents and functions can be designed as parallel workers in an ADK Workflow.
|
||||
|
||||
1. Ensure the preceding node in the workflow outputs an iterable (e.g., a `list`). The workflow engine will automatically fan-out and execute the parallel worker node concurrently for each item in the iterable.
|
||||
|
||||
1. To define an **Agent** as a parallel worker, use the `parallel_worker=True` parameter:
|
||||
|
||||
```python
|
||||
explain_topic = Agent(
|
||||
name="explain_topic",
|
||||
instruction="""Explain how the following topic relates to the original topic: "{topic}".""",
|
||||
parallel_worker=True,
|
||||
output_schema=TopicExplanation,
|
||||
)
|
||||
```
|
||||
|
||||
1. To define a **Python function** as a parallel worker, decorate it with `@node(parallel_worker=True)`:
|
||||
|
||||
```python
|
||||
from google.adk.workflow import node
|
||||
|
||||
@node(parallel_worker=True)
|
||||
def make_upper_case(node_input: str):
|
||||
yield node_input.upper()
|
||||
```
|
||||
|
||||
1. The subsequent node in the workflow will receive the results from all parallel executions as a single aggregated list (e.g., `list[TopicExplanation]`).
|
||||
@@ -0,0 +1,79 @@
|
||||
# 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 google.adk import Agent
|
||||
from google.adk import Event
|
||||
from google.adk import Workflow
|
||||
from google.adk.workflow import node
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class TopicExplanation(BaseModel):
|
||||
topic: str
|
||||
explanation: str
|
||||
|
||||
|
||||
def process_input(node_input: str):
|
||||
"""Puts user input in the state."""
|
||||
return Event(state={"topic": node_input})
|
||||
|
||||
|
||||
find_related_topics = Agent(
|
||||
name="find_related_topics",
|
||||
instruction=(
|
||||
'Given the specific topic "{topic}", generate a list of 3 '
|
||||
"related topics."
|
||||
),
|
||||
output_schema=list[str],
|
||||
)
|
||||
|
||||
|
||||
@node(parallel_worker=True)
|
||||
def make_upper_case(node_input: str):
|
||||
yield node_input.upper()
|
||||
|
||||
|
||||
explain_topic = Agent(
|
||||
name="explain_topic",
|
||||
instruction=(
|
||||
"Explain how the following topic relates the the original topic: "
|
||||
'"{topic}".'
|
||||
),
|
||||
parallel_worker=True,
|
||||
output_schema=TopicExplanation,
|
||||
)
|
||||
|
||||
|
||||
def aggregate(node_input: list[TopicExplanation]):
|
||||
return Event(
|
||||
message="\n\n---\n\n".join(
|
||||
f"{explanation.topic}: {explanation.explanation}"
|
||||
for explanation in node_input
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
root_agent = Workflow(
|
||||
name="root_agent",
|
||||
edges=[
|
||||
(
|
||||
"START",
|
||||
process_input,
|
||||
find_related_topics,
|
||||
make_upper_case,
|
||||
explain_topic,
|
||||
aggregate,
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,225 @@
|
||||
{
|
||||
"appName": "parallel_worker",
|
||||
"events": [
|
||||
{
|
||||
"author": "user",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "flower"
|
||||
}
|
||||
],
|
||||
"role": "user"
|
||||
},
|
||||
"id": "e-1",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"path": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"actions": {
|
||||
"stateDelta": {
|
||||
"topic": "flower"
|
||||
}
|
||||
},
|
||||
"author": "root_agent",
|
||||
"id": "e-2",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"path": "root_agent@1/process_input@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "find_related_topics",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "[\"gardening\", \"plants\", \"botany\"]"
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-3",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/find_related_topics@1"
|
||||
],
|
||||
"path": "root_agent@1/find_related_topics@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"branch": "make_upper_case@1",
|
||||
"id": "e-4",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"outputFor": [
|
||||
"root_agent@1/make_upper_case@1/make_upper_case@1"
|
||||
],
|
||||
"path": "root_agent@1/make_upper_case@1/make_upper_case@1"
|
||||
},
|
||||
"output": "GARDENING"
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"branch": "make_upper_case@2",
|
||||
"id": "e-5",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"outputFor": [
|
||||
"root_agent@1/make_upper_case@1/make_upper_case@2"
|
||||
],
|
||||
"path": "root_agent@1/make_upper_case@1/make_upper_case@2"
|
||||
},
|
||||
"output": "PLANTS"
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"branch": "make_upper_case@3",
|
||||
"id": "e-6",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"outputFor": [
|
||||
"root_agent@1/make_upper_case@1/make_upper_case@3"
|
||||
],
|
||||
"path": "root_agent@1/make_upper_case@1/make_upper_case@3"
|
||||
},
|
||||
"output": "BOTANY"
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"id": "e-7",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"outputFor": [
|
||||
"root_agent@1/make_upper_case@1"
|
||||
],
|
||||
"path": "root_agent@1/make_upper_case@1"
|
||||
},
|
||||
"output": [
|
||||
"GARDENING",
|
||||
"PLANTS",
|
||||
"BOTANY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"author": "explain_topic",
|
||||
"branch": "explain_topic@1",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "{\"topic\": \"GARDENING\", \"explanation\": \"Gardening is the practice of growing and cultivating plants, and flowers are a central element in many gardening practices. Gardeners often plant, nurture, and arrange flowers for their aesthetic beauty, fragrance, or to attract pollinators, making flowers an integral part of the gardening world.\"}"
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-8",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/explain_topic@1/explain_topic@1"
|
||||
],
|
||||
"path": "root_agent@1/explain_topic@1/explain_topic@1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "explain_topic",
|
||||
"branch": "explain_topic@2",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "{\"topic\": \"PLANTS\", \"explanation\": \"A flower is a reproductive part of many types of plants. Plants are the larger biological kingdom to which flowers belong, as flowers grow on and are integral components of flowering plants (angiosperms).\"}"
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-9",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/explain_topic@1/explain_topic@2"
|
||||
],
|
||||
"path": "root_agent@1/explain_topic@1/explain_topic@2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "explain_topic",
|
||||
"branch": "explain_topic@3",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "{\"topic\": \"BOTANY\", \"explanation\": \"Botany is the scientific study of plants, including their structure, growth, reproduction, metabolism, development, diseases, and chemical properties. Flowers are the reproductive organs of many plants, specifically angiosperms, and are therefore a primary subject of study within botany, with botanists analyzing their morphology, physiology, ecology, and evolutionary significance.\"}"
|
||||
}
|
||||
],
|
||||
"role": "model"
|
||||
},
|
||||
"finishReason": "STOP",
|
||||
"id": "e-10",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"messageAsOutput": true,
|
||||
"outputFor": [
|
||||
"root_agent@1/explain_topic@1/explain_topic@3"
|
||||
],
|
||||
"path": "root_agent@1/explain_topic@1/explain_topic@3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"id": "e-11",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"outputFor": [
|
||||
"root_agent@1/explain_topic@1"
|
||||
],
|
||||
"path": "root_agent@1/explain_topic@1"
|
||||
},
|
||||
"output": [
|
||||
{
|
||||
"explanation": "Gardening is the practice of growing and cultivating plants, and flowers are a central element in many gardening practices. Gardeners often plant, nurture, and arrange flowers for their aesthetic beauty, fragrance, or to attract pollinators, making flowers an integral part of the gardening world.",
|
||||
"topic": "GARDENING"
|
||||
},
|
||||
{
|
||||
"explanation": "A flower is a reproductive part of many types of plants. Plants are the larger biological kingdom to which flowers belong, as flowers grow on and are integral components of flowering plants (angiosperms).",
|
||||
"topic": "PLANTS"
|
||||
},
|
||||
{
|
||||
"explanation": "Botany is the scientific study of plants, including their structure, growth, reproduction, metabolism, development, diseases, and chemical properties. Flowers are the reproductive organs of many plants, specifically angiosperms, and are therefore a primary subject of study within botany, with botanists analyzing their morphology, physiology, ecology, and evolutionary significance.",
|
||||
"topic": "BOTANY"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"author": "root_agent",
|
||||
"content": {
|
||||
"parts": [
|
||||
{
|
||||
"text": "GARDENING: Gardening is the practice of growing and cultivating plants, and flowers are a central element in many gardening practices. Gardeners often plant, nurture, and arrange flowers for their aesthetic beauty, fragrance, or to attract pollinators, making flowers an integral part of the gardening world.\n\n---\n\nPLANTS: A flower is a reproductive part of many types of plants. Plants are the larger biological kingdom to which flowers belong, as flowers grow on and are integral components of flowering plants (angiosperms).\n\n---\n\nBOTANY: Botany is the scientific study of plants, including their structure, growth, reproduction, metabolism, development, diseases, and chemical properties. Flowers are the reproductive organs of many plants, specifically angiosperms, and are therefore a primary subject of study within botany, with botanists analyzing their morphology, physiology, ecology, and evolutionary significance."
|
||||
}
|
||||
],
|
||||
"role": "user"
|
||||
},
|
||||
"id": "e-12",
|
||||
"invocationId": "i-1",
|
||||
"nodeInfo": {
|
||||
"path": "root_agent@1/aggregate@1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "70e3790b-df94-4567-93c9-3c60abc6a4e6",
|
||||
"state": {
|
||||
"__session_metadata__": {
|
||||
"displayName": "flower"
|
||||
},
|
||||
"topic": "flower"
|
||||
},
|
||||
"userId": "user"
|
||||
}
|
||||
Reference in New Issue
Block a user