Skip to content

Commit 980f463

Browse files
authored
Merge branch 'main' into feat/function-tools-enum-support
2 parents fdc13e8 + bddc70b commit 980f463

57 files changed

Lines changed: 2346 additions & 680 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* Update remote_a2a_agent to better handle streaming events and avoid duplicate responses ([8e5f361](https://github.com/google/adk-python/commit/8e5f36126498f751171bb2639c7f5a9e7dca2558))
5050
* Update the load_artifacts tool so that the model can reliably call it for follow up questions about the same artifact ([238472d](https://github.com/google/adk-python/commit/238472d083b5aa67551bde733fc47826ff062679))
5151
* Fix VertexAiSessionService base_url override to preserve initialized http_options ([8110e41](https://github.com/google/adk-python/commit/8110e41b36cceddb8b92ba17cffaacf701706b36), [c51ea0b](https://github.com/google/adk-python/commit/c51ea0b52e63de8e43d3dccb24f9d20987784aa5))
52+
* Handle `App` instances returned by `agent_loader.load_agent` ([847df16](https://github.com/google/adk-python/commit/847df1638cbf1686aa43e8e094121d4e23e40245))
5253

5354
### Improvements
5455

README.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,44 @@
2525
Agent Development Kit (ADK) is a flexible and modular framework for developing and deploying AI agents. While optimized for Gemini and the Google ecosystem, ADK is model-agnostic, deployment-agnostic, and is built for compatibility with other frameworks. ADK was designed to make agent development feel more like software development, to make it easier for developers to create, deploy, and orchestrate agentic architectures that range from simple tasks to complex workflows.
2626

2727

28+
---
29+
## 🔥 ADK's very first community call on Oct 15
30+
31+
Join our ADK Community Call! Our first virtual community call is on Oct 15!
32+
Meet our team, and talk with us about our roadmap and how to contribute.
33+
34+
First Call Details:
35+
36+
Topic: ADK Roadmap
37+
38+
Date: October 15, 2025
39+
40+
Time: 9:30-10:30am PST
41+
42+
Meeting link:
43+
[Join the call](http://meet.google.com/gjm-gfim-ctz)
44+
45+
Add to your calendar
46+
[Event calendar invite](https://calendar.google.com/calendar/event?action=TEMPLATE&tmeid=MDUydWo1dHV1dHFtNzJuM3E0bmEyMW12ZnZfMjAyNTEwMTVUMTYzMDAwWiBjXzljNWVjODhhMmQyYWU5YjY5Mzk4ODU1MGZkNDA5MjVmYjgxYjM4MTI1NGNjYTgzNmRkMjMwNzRiMjNmYzcyZDVAZw&tmsrc=c_9c5ec88a2d2ae9b693988550fd40925fb81b381254cca836dd23074b23fc72d5%40group.calendar.google.com), [.ics file](https://calendar.google.com/calendar/ical/c_9c5ec88a2d2ae9b693988550fd40925fb81b381254cca836dd23074b23fc72d5%40group.calendar.google.com/public/basic.ics), [ADK community calendar](https://calendar.google.com/calendar/embed?src=c_9c5ec88a2d2ae9b693988550fd40925fb81b381254cca836dd23074b23fc72d5%40group.calendar.google.com&ctz=America%2FLos_Angeles)
47+
48+
Agenda:
49+
[Julia] ADK Roadmap
50+
[ Bo & Hangfei] Eng Deep Dive: Context Caching
51+
[Kris] How to Contribute
52+
53+
[Shubham] Upcoming Events
54+
2855
---
2956

3057
## 🔥 What's new
3158

32-
- **Agent Config**: Build agents without code. Check out the
33-
[Agent Config](https://google.github.io/adk-docs/agents/config/) feature.
59+
- **Context compaction**: Supports context compaction to reduce context length. Here is a [sample](https://github.com/google/adk-python/blob/main/contributing/samples/hello_world_app/agent.py#L156) and [compaction config](https://github.com/google/adk-python/blob/main/src/google/adk/apps/app.py#L51).
60+
61+
- **Resumability**: Support pause and resume an invocation in ADK.
62+
63+
- **ReflectRetryToolPlugin**: Add [`ReflectRetryToolPlugin`](https://github.com/google/adk-python/blob/main/src/google/adk/plugins/reflect_retry_tool_plugin.py) to reflect from errors and retry with different arguments when tool errors.
3464

35-
- **Tool Confirmation**: A [tool confirmation flow(HITL)](https://google.github.io/adk-docs/tools/confirmation/) that can guard tool execution with explicit confirmation and custom input
65+
- **Search tool**: Support using Google built-in search and built-in `VertexAiSearchTool` with other tools in the same agent.
3666

3767
## ✨ Key Features
3868

@@ -43,6 +73,11 @@ Agent Development Kit (ADK) is a flexible and modular framework for developing a
4373
- **Code-First Development**: Define agent logic, tools, and orchestration
4474
directly in Python for ultimate flexibility, testability, and versioning.
4575

76+
- **Agent Config**: Build agents without code. Check out the
77+
[Agent Config](https://google.github.io/adk-docs/agents/config/) feature.
78+
79+
- **Tool Confirmation**: A [tool confirmation flow(HITL)](https://google.github.io/adk-docs/tools/confirmation/) that can guard tool execution with explicit confirmation and custom input.
80+
4681
- **Modular Multi-Agent Systems**: Design scalable applications by composing
4782
multiple specialized agents into flexible hierarchies.
4883

contributing/samples/adk_pr_triaging_agent/agent.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from pathlib import Path
1616
from typing import Any
1717

18-
from adk_pr_triaging_agent.settings import BOT_LABEL
1918
from adk_pr_triaging_agent.settings import GITHUB_BASE_URL
2019
from adk_pr_triaging_agent.settings import IS_INTERACTIVE
2120
from adk_pr_triaging_agent.settings import OWNER
@@ -178,7 +177,7 @@ def add_label_and_reviewer_to_pr(pr_number: int, label: str) -> dict[str, Any]:
178177
label_url = (
179178
f"{GITHUB_BASE_URL}/repos/{OWNER}/{REPO}/issues/{pr_number}/labels"
180179
)
181-
label_payload = [label, BOT_LABEL]
180+
label_payload = [label]
182181

183182
try:
184183
response = post_request(label_url, label_payload)

contributing/samples/adk_pr_triaging_agent/settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
OWNER = os.getenv("OWNER", "google")
2929
REPO = os.getenv("REPO", "adk-python")
30-
BOT_LABEL = os.getenv("BOT_LABEL", "bot triaged")
3130
PULL_REQUEST_NUMBER = os.getenv("PULL_REQUEST_NUMBER")
3231

3332
IS_INTERACTIVE = os.environ.get("INTERACTIVE", "1").lower() in ["true", "1"]

contributing/samples/adk_triaging_agent/agent.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
from typing import Any
1616

17-
from adk_triaging_agent.settings import BOT_LABEL
1817
from adk_triaging_agent.settings import GITHUB_BASE_URL
1918
from adk_triaging_agent.settings import IS_INTERACTIVE
2019
from adk_triaging_agent.settings import OWNER
@@ -103,7 +102,7 @@ def add_label_and_owner_to_issue(
103102
label_url = (
104103
f"{GITHUB_BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}/labels"
105104
)
106-
label_payload = [label, BOT_LABEL]
105+
label_payload = [label]
107106

108107
try:
109108
response = post_request(label_url, label_payload)

contributing/samples/adk_triaging_agent/settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
OWNER = os.getenv("OWNER", "google")
2828
REPO = os.getenv("REPO", "adk-python")
29-
BOT_LABEL = os.getenv("BOT_LABEL", "bot triaged")
3029
EVENT_NAME = os.getenv("EVENT_NAME")
3130
ISSUE_NUMBER = os.getenv("ISSUE_NUMBER")
3231
ISSUE_TITLE = os.getenv("ISSUE_TITLE")

contributing/samples/human_tool_confirmation/agent.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# limitations under the License.
1414

1515
from google.adk import Agent
16+
from google.adk.apps import App
17+
from google.adk.apps import ResumabilityConfig
1618
from google.adk.tools.function_tool import FunctionTool
1719
from google.adk.tools.tool_confirmation import ToolConfirmation
1820
from google.adk.tools.tool_context import ToolContext
@@ -88,3 +90,12 @@ def request_time_off(days: int, tool_context: ToolContext):
8890
],
8991
generate_content_config=types.GenerateContentConfig(temperature=0.1),
9092
)
93+
94+
app = App(
95+
name='human_tool_confirmation',
96+
root_agent=root_agent,
97+
# Set the resumability config to enable resumability.
98+
resumability_config=ResumabilityConfig(
99+
is_resumable=True,
100+
),
101+
)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Reflect And Retry Tool Plugin
2+
3+
`ReflectAndRetryToolPlugin` provides self-healing, concurrent-safe error
4+
recovery for tool failures.
5+
6+
**Key Features:**
7+
8+
- **Concurrency Safe:** Uses locking to safely handle parallel tool
9+
executions
10+
- **Configurable Scope:** Tracks failures per-invocation (default) or globally
11+
using the `TrackingScope` enum.
12+
- **Extensible Scoping:** The `_get_scope_key` method can be overridden to
13+
implement custom tracking logic (e.g., per-user or per-session).
14+
- **Granular Tracking:** Failure counts are tracked per-tool within the
15+
defined scope. A success with one tool resets its counter without affecting
16+
others.
17+
- **Custom Error Extraction:** Supports detecting errors in normal tool
18+
responses that don't throw exceptions, by overriding the
19+
`extract_error_from_result` method.
20+
21+
## Samples
22+
23+
Here are some sample agents to demonstrate the usage of the plugin.
24+
25+
### Basic Usage
26+
27+
This is a hello world example to show the basic usage of the plugin. The
28+
`guess_number_tool` is hacked with both Exceptions and error responses. With the
29+
help of the `CustomRetryPlugin`, both above error types can lead to retries.
30+
31+
For example, here is the output from agent:
32+
33+
```
34+
I'll guess the number 50. Let's see how it is!
35+
My guess of 50 was too high! I'll try a smaller number this time. Let's go with 25.
36+
My guess of 25 was still too high! I'm going smaller. How about 10?
37+
Still too high! My guess of 10 was also too large. I'll try 5 this time.
38+
My guess of 5 is "almost valid"! That's good news, it means I'm getting very close. I'll try 4.
39+
My guess of 4 is still "almost valid," just like 5. It seems I'm still hovering around the right answer. Let's try 3!
40+
I guessed the number 3, and it is valid! I found it!
41+
```
42+
43+
You can run the agent with:
44+
45+
```bash
46+
$ adk web contributing/samples/plugin_reflect_tool_retry
47+
```
48+
49+
You can provide the following prompt to see the agent retrying tool calls:
50+
51+
```
52+
Please guess a number! Tell me what number you guess and how is it.
53+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from . import agent
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from typing import Any
16+
17+
from google.adk.agents import LlmAgent
18+
from google.adk.apps.app import App
19+
from google.adk.plugins import LoggingPlugin
20+
from google.adk.plugins import ReflectAndRetryToolPlugin
21+
22+
APP_NAME = "basic"
23+
USER_ID = "test_user"
24+
25+
26+
def guess_number_tool(query: int) -> dict[str, Any]:
27+
"""A tool that guesses a number.
28+
29+
Args:
30+
query: The number to guess.
31+
32+
Returns:
33+
A dictionary containing the status and result of the tool execution.
34+
"""
35+
target_number = 3
36+
if query == target_number:
37+
return {"status": "success", "result": "Number is valid."}
38+
39+
if abs(query - target_number) <= 2:
40+
return {"status": "error", "error_message": "Number is almost valid."}
41+
42+
if query > target_number:
43+
raise ValueError("Number is too large.")
44+
45+
if query < target_number:
46+
raise ValueError("Number is too small.")
47+
48+
raise ValueError("Number is invalid.")
49+
50+
51+
class CustomRetryPlugin(ReflectAndRetryToolPlugin):
52+
53+
async def extract_error_from_result(
54+
self, *, tool, tool_args, tool_context, result
55+
):
56+
return result if result.get("status") == "error" else None
57+
58+
59+
root_agent = LlmAgent(
60+
name="hello_world",
61+
description="Helpful agent",
62+
instruction="""Use guess_number_tool to guess a number.""",
63+
model="gemini-2.5-flash",
64+
tools=[guess_number_tool],
65+
)
66+
67+
68+
app = App(
69+
name=APP_NAME,
70+
root_agent=root_agent,
71+
plugins=[
72+
CustomRetryPlugin(
73+
max_retries=6, throw_exception_if_retry_exceeded=False
74+
),
75+
LoggingPlugin(),
76+
],
77+
)

0 commit comments

Comments
 (0)