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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:25:13 +08:00
commit ec2b666284
2231 changed files with 491535 additions and 0 deletions
@@ -0,0 +1,46 @@
# ADK Workflow Loop Sample
## Overview
This sample demonstrates how to create a feedback loop between different nodes in **ADK Workflows**.
It takes a user-provided topic and uses the `generate_headline` agent to write a headline. The `evaluate_headline` agent then grades the headline as either "tech-related" or "unrelated", providing feedback if it's unrelated. The `route_headline` function checks this grade. If the headline is "unrelated", the workflow loops back to the `generate_headline` agent, passing the feedback so it can try again. This process repeats until a "tech-related" headline is generated.
In ADK Workflows, loops allow for iterative refinement and evaluation by conditionally routing execution back to an earlier node in the sequence.
## Sample Inputs
- `flower`
- `quantum mechanics`
- `renewable energy`
## Graph
```mermaid
graph TD
START --> process_input
process_input --> generate_headline
generate_headline --> evaluate_headline
evaluate_headline --> route_headline
route_headline -->|unrelated| generate_headline
route_headline -->|tech-related| END[Loop ends]
```
## How To
1. Define a node (like `route_headline`) that yields an `Event` with a specific route based on a condition:
```python
def route_headline(node_input: Feedback):
return Event(route=node_input.grade)
```
1. In the `Workflow` edges definition, create a conditional edge that connects the routing node back to a previous node in the workflow, using a routing map dict:
```python
(route_headline, {"unrelated": generate_headline})
```
This creates the cycle. If the route yielded by `route_headline` is "unrelated", execution jumps back to `generate_headline`.
@@ -0,0 +1,80 @@
# 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 typing import Literal
from google.adk import Agent
from google.adk import Event
from google.adk import Workflow
from pydantic import BaseModel
from pydantic import Field
class Feedback(BaseModel):
grade: Literal["tech-related", "unrelated"] = Field(
description=(
"Decide if the headline is related to technology or software"
" engineering."
),
)
feedback: str = Field(
description=(
"If the headline is unrelated to technology, provide feedback on how"
" to make it more tech-focused."
),
)
def process_input(node_input: str):
"""Puts user input in the state."""
return Event(state={"topic": node_input})
generate_headline = Agent(
name="generate_headline",
instruction="""
Write a headline about the topic "{topic}".
If feedback is provided, take it into account.
The feedback: {feedback?}
""",
)
evaluate_headline = Agent(
name="evaluate_headline",
instruction="""
Grade whether the headline is related to technology or software engineering.
""",
output_schema=Feedback,
output_key="feedback",
)
def route_headline(node_input: Feedback):
return Event(route=node_input.grade)
root_agent = Workflow(
name="root_agent",
edges=[
(
"START",
process_input,
generate_headline,
evaluate_headline,
route_headline,
),
(route_headline, {"unrelated": generate_headline}),
],
)
@@ -0,0 +1,94 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "computer"
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"actions": {
"stateDelta": {
"topic": "computer"
}
},
"author": "root_agent",
"id": "e-2",
"invocationId": "i-1",
"nodeInfo": {
"path": "root_agent@1/process_input@1"
}
},
{
"author": "generate_headline",
"content": {
"parts": [
{
"text": "Computers: Shaping Our World"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-3",
"invocationId": "i-1",
"nodeInfo": {
"messageAsOutput": true,
"outputFor": [
"root_agent@1/generate_headline@1"
],
"path": "root_agent@1/generate_headline@1"
}
},
{
"actions": {
"stateDelta": {
"feedback": {
"feedback": "This headline is clearly tech-related as it directly discusses computers.",
"grade": "tech-related"
}
}
},
"author": "evaluate_headline",
"content": {
"parts": [
{
"text": "{\"grade\": \"tech-related\", \"feedback\": \"This headline is clearly tech-related as it directly discusses computers.\"}"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-1",
"nodeInfo": {
"messageAsOutput": true,
"outputFor": [
"root_agent@1/evaluate_headline@1"
],
"path": "root_agent@1/evaluate_headline@1"
}
},
{
"actions": {
"route": "tech-related"
},
"author": "root_agent",
"id": "e-5",
"invocationId": "i-1",
"nodeInfo": {
"path": "root_agent@1/route_headline@1"
}
}
]
}
@@ -0,0 +1,168 @@
{
"appName": "loop",
"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": "generate_headline",
"content": {
"parts": [
{
"text": "\"Petal Power: The Timeless Allure of Flowers\""
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-3",
"invocationId": "i-1",
"nodeInfo": {
"messageAsOutput": true,
"outputFor": [
"root_agent@1/generate_headline@1"
],
"path": "root_agent@1/generate_headline@1"
}
},
{
"actions": {
"stateDelta": {
"feedback": {
"feedback": "To make this headline more tech-focused, consider incorporating elements like AI for plant recognition, robotics in gardening, biotechnology in horticulture, or data analytics related to flower cultivation and sales. For example, 'AI-Driven Botany: The Tech Unlocking Petal Power' or 'Smart Gardens: Engineering the Timeless Allure of Flowers'.",
"grade": "unrelated"
}
}
},
"author": "evaluate_headline",
"content": {
"parts": [
{
"text": "{\"grade\": \"unrelated\", \"feedback\": \"To make this headline more tech-focused, consider incorporating elements like AI for plant recognition, robotics in gardening, biotechnology in horticulture, or data analytics related to flower cultivation and sales. For example, 'AI-Driven Botany: The Tech Unlocking Petal Power' or 'Smart Gardens: Engineering the Timeless Allure of Flowers'.\"}"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-1",
"nodeInfo": {
"messageAsOutput": true,
"outputFor": [
"root_agent@1/evaluate_headline@1"
],
"path": "root_agent@1/evaluate_headline@1"
}
},
{
"actions": {
"route": "unrelated"
},
"author": "root_agent",
"id": "e-5",
"invocationId": "i-1",
"nodeInfo": {
"path": "root_agent@1/route_headline@1"
}
},
{
"author": "generate_headline",
"content": {
"parts": [
{
"text": "AI-Powered Petals: The Tech Revolution Blooming in Modern Floriculture"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-6",
"invocationId": "i-1",
"nodeInfo": {
"messageAsOutput": true,
"outputFor": [
"root_agent@1/generate_headline@2"
],
"path": "root_agent@1/generate_headline@2"
}
},
{
"actions": {
"stateDelta": {
"feedback": {
"feedback": "This headline is strongly tech-related, explicitly mentioning 'AI-Powered' and 'Tech Revolution'. It effectively combines a traditional field (floriculture) with advanced technology.",
"grade": "tech-related"
}
}
},
"author": "evaluate_headline",
"content": {
"parts": [
{
"text": "{\"grade\": \"tech-related\", \"feedback\": \"This headline is strongly tech-related, explicitly mentioning 'AI-Powered' and 'Tech Revolution'. It effectively combines a traditional field (floriculture) with advanced technology.\"}"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-7",
"invocationId": "i-1",
"nodeInfo": {
"messageAsOutput": true,
"outputFor": [
"root_agent@1/evaluate_headline@2"
],
"path": "root_agent@1/evaluate_headline@2"
}
},
{
"actions": {
"route": "tech-related"
},
"author": "root_agent",
"id": "e-8",
"invocationId": "i-1",
"nodeInfo": {
"path": "root_agent@1/route_headline@2"
}
}
],
"id": "2779014d-3ee3-429e-951d-e69756ddf789",
"state": {
"__session_metadata__": {
"displayName": "flower"
},
"feedback": {
"feedback": "This headline is already strongly tech-focused due to the explicit mention of AI and 'Tech Revolution'.",
"grade": "tech-related"
},
"topic": "flower"
},
"userId": "user"
}