Skip to content

Commit 6e88953

Browse files
Merge branch 'main' into add-agent-registry-support
2 parents 0bb7560 + 953304d commit 6e88953

56 files changed

Lines changed: 3498 additions & 1452 deletions

Some content is hidden

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

.agents/skills/adk-git/SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Self-check before committing: read your subject line and ask "does this tell me
7373
4. **50 char limit** on subject line when possible, max 72.
7474
5. **Use body for context** - Add a blank line then explain _why_,
7575
not _how_, when the subject alone isn't enough.
76+
6. **Reference GitHub issues** - If the commit fixes a GitHub issue, include "Fixes #<issue-number>" or "Closes #<issue-number>" (or the full issue URL if cross-repository) in the commit message body.
7677

7778
### Examples
7879

.agents/skills/adk-issue/SKILL.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
name: adk-issue
3+
description: Analyze and triage GitHub issues for the adk-python repository. Use this skill when the user provides an issue number or link to investigate whether the issue is legitimate, whether it should be fixed, and if there is an existing PR addressing it. Triggers on "analyze issue", "issue #", "github issue", "github.com/google/adk-python/issues/".
4+
---
5+
6+
# ADK Issue Analyzer & Triager
7+
8+
This skill provides a structured workflow for analyzing, verifying, and triaging GitHub issues from the `google/adk-python` repository. When a user provides a GitHub issue number or link, use this skill to perform deep investigation and report your findings.
9+
10+
## Issue Triage Workflow
11+
12+
Follow this 3-step process to analyze the issue:
13+
14+
### Step 1: Retrieve and Parse the Issue
15+
1. **Extract the issue number**: Parse the number from the link or prompt (e.g., `https://github.com/google/adk-python/issues/5882` -> `5882`).
16+
2. **Fetch issue details**: Use the `gh` CLI tool to fetch issue details in JSON format:
17+
```bash
18+
gh issue view <issue_number> --repo google/adk-python --json number,title,body,state,labels,comments,assignees,createdAt,closedAt
19+
```
20+
*If the `gh` CLI is not available or errors out, use `read_url_content` to fetch the public GitHub issue page:*
21+
```
22+
https://github.com/google/adk-python/issues/<issue_number>
23+
```
24+
25+
---
26+
27+
### Step 2: Deep Investigation & Analysis
28+
Address the following four critical questions and present your findings in a structured, premium report.
29+
30+
#### 1. What is broken?
31+
Explain the root cause of the issue or failure:
32+
- **Trace the execution flow**: Identify which components, classes, or functions are malfunctioning.
33+
- **Pinpoint the bug**: Detail why the system is behaving incorrectly and where the failure originates (e.g. incorrect logic, missing configuration, unhandled states).
34+
35+
#### 2. Is the issue legitimate?
36+
Inspect the codebase to confirm if the issue represents a real problem:
37+
- **Examine the description**: Identify the component, class, function, or file referenced.
38+
- **Search the codebase**: Use `grep_search` to locate the relevant files/functions in the local workspace.
39+
- **Inspect the code**: Open the files using `view_file` to analyze the code's current logic.
40+
- **Verify the bug**:
41+
- Is the reported problem actually present in the code?
42+
- Does it produce the reported error or behavior under the current version (ADK 2.0)?
43+
- Is it a documentation typo, setup discrepancy, or a genuine code/logic bug?
44+
- **Document your code evidence**: Reference specific file paths and line ranges (using clickable markdown file links, e.g., `[skill_toolset.py](file:///path/to/file#L123)`) in your report.
45+
46+
#### 3. Should we fix it?
47+
Formulate a recommendation on whether the issue should be addressed:
48+
- **Assess the impact**:
49+
- Does it break core functionality?
50+
- Does it affect standard developer workflows or introduce brittle workarounds?
51+
- Is it a high-priority bug or a low-impact cosmetic/feature request?
52+
- **Check alignment**:
53+
- Does the suggested solution align with `adk-architecture` and `adk-style`?
54+
- Is it consistent with Python idioms and Pydantic validation rules?
55+
- **Evaluate workarounds**: Is there a clean workaround, or is a core fix necessary?
56+
- **Final Recommendation**: Clearly declare whether we should fix it, along with the reasoning and estimated complexity/scope of the fix.
57+
58+
#### 4. Is there a linked PR that fixes this issue?
59+
Search for any existing pull requests that attempt to resolve the issue:
60+
- **Search PRs**: Run `gh pr list --repo google/adk-python --search "<issue_number>"` to list pull requests mentioning the issue number in the branch name, title, or body.
61+
- **Verify the PR details**: If PRs are found, fetch their details:
62+
```bash
63+
gh pr view <pr_number> --repo google/adk-python --json number,title,state,url,body,author
64+
```
65+
- **Analyze progress**: Check if the PR is open, merged, or closed, and if it successfully fixes the issue according to the repository's testing patterns.
66+
- **Offer to create a fix**: If no existing PR is found, you MUST explicitly ask the user: "Would you like me to create and implement a fix for this issue in the workspace? (Note: The changes and tests will be created in a new branch but NOT committed, so you can review and iterate on them.)"
67+
68+
---
69+
70+
### Step 3: Report & Propose Fix
71+
1. **Present the structured report**: Follow the **Report Template** below to format your findings.
72+
2. **Propose a fix**: If there is no existing PR addressing the issue, explicitly ask the user if they would like you to implement the fix in the workspace. When implementing the fix:
73+
- **Do NOT commit the changes**: Leave them uncommitted in the workspace so the user can review and iterate on them.
74+
- **Base the branch on remote HEAD**: When creating the new branch, ensure it is based on the remote tracking branch HEAD (`origin/main`), not the current local branch. For example:
75+
```bash
76+
git checkout -b fix/<issue_number>-<desc> origin/main
77+
```
78+
- **Follow these implementation steps**:
79+
1. **Create the fix**: Modify the necessary source files implementing clean, robust logic following `adk-style` and `adk-architecture`.
80+
2. **Add or update unittests**: Write comprehensive unit tests to verify the behavior and prevent regressions.
81+
3. **Update documentation**: Update `/docs/design` and `/docs/guides` if applicable to the changes.
82+
4. **Update samples**: Update `/contributing/samples` if applicable to demonstrate the new capability or updated behavior.
83+
84+
---
85+
86+
## Report Template
87+
88+
Present your final analysis as a high-quality markdown response using the following structure:
89+
90+
```markdown
91+
# GitHub Issue #<issue_number> Analysis: <Issue Title>
92+
93+
## Detailed Analysis
94+
95+
### 1. Root Cause Analysis ("What is broken?")
96+
- Explanation of the failure or bug (what is failing and why).
97+
- Pinpoint the exact file, function, or design component that is malfunctioning.
98+
99+
### 2. Legitimacy Analysis
100+
- **Status**: [Legitimate Bug / Feature Request / Duplicate / Invalid / Not Reproducible]
101+
- **Evidence**:
102+
- Code references: [filename.py](file:///absolute/path/to/file#L100-L120)
103+
- Analysis of code behavior and why the issue occurs.
104+
105+
### 3. Fix Recommendation
106+
- **Recommendation**: [Should Fix (High Priority) / Should Fix (Medium/Low Priority) / Won't Fix / Needs Discussion]
107+
- **Rationale**:
108+
- Impact on user experience, workflows, or architecture.
109+
- Implementation complexity and risk of side effects.
110+
111+
### 4. Existing Pull Requests
112+
- **Linked PR**: [None / Pull Request #<pr_number> - <PR Title> (<state>)]
113+
- **PR URL**: <PR URL>
114+
- **Analysis**: Brief summary of the PR's approach and status (e.g., "Fixes the bug by implementing X in Y, currently awaiting review").
115+
116+
---
117+
118+
## Executive Summary
119+
1. **What is broken?** [Brief explanation of the root cause or error]
120+
2. **Is the issue legitimate?** [Yes / No - brief explanation]
121+
3. **Should we fix it?** [Yes / No / Needs Discussion - priority & brief reasoning]
122+
4. **Is there a linked PR that fixes this issue?** [None / Yes, PR #<pr_number> - <state>]
123+
```
124+
125+
---
126+
127+
## Tips & Best Practices
128+
> [!TIP]
129+
> Always use explicit repository qualifiers (`--repo google/adk-python`) when running `gh` commands to avoid failures due to custom internal or local git remotes.
130+
131+
> [!IMPORTANT]
132+
> When presenting code files and lines, always use markdown file links that point directly to the files in the workspace. Make sure the link is clickable and formatted as `[filename.py](file:///absolute/path/to/file#L100-L120)` without surrounding backticks around the brackets.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Abort Agent Sample
2+
3+
## Overview
4+
5+
This sample demonstrates a standalone ADK agent designed specifically to showcase cooperative task cancellation on client disconnections.
6+
7+
The agent leverages a custom tool that counts from 1 to a target number requested by the user, pausing 1 second between each count and printing the progress directly to the server's stdout terminal. This delay allows you to easily trigger connection drops (by cancelling client requests mid-execution) and visually observe that background agent execution halts immediately in the server terminal, resolving resource leaks.
8+
9+
## Sample Inputs
10+
11+
- `Count to 10 seconds`
12+
13+
The agent will call the `count_seconds` tool with a target count of 10, pausing 1 second between each increment.
14+
15+
- `Please count up to 20`
16+
17+
The agent will invoke the tool to count to 20. If you close the client connection (such as pressing `Ctrl+C` in a cURL window or closing your browser tab) while the loop is running, counting halts immediately.
18+
19+
## Graph
20+
21+
```mermaid
22+
graph TD
23+
START --> AbortAgent
24+
AbortAgent --> |"Invoke Tool"| count_seconds
25+
count_seconds --> |"Abort if Disconnected / Done"| AbortAgent
26+
AbortAgent --> ANSWER
27+
```
28+
29+
## How To
30+
31+
### 1. Running Locally via the CLI
32+
33+
To interact with the agent in your local shell terminal:
34+
35+
```bash
36+
adk run contributing/samples/core/abort/
37+
```
38+
39+
Type `count to 10` at the `[user]:` prompt. Pressing `Ctrl+C` mid-run will abort counting and exit.
40+
41+
### 2. Running via HTTP Server and cURL
42+
43+
To verify connection-drop abortion over network protocols (e.g. simple HTTP REST request):
44+
45+
1. Start the local development server to watch the sample workspace:
46+
```bash
47+
adk web --allow_origins=http://localhost:4200 contributing/samples/
48+
```
49+
1. In a separate terminal, register the test session (local CLI development servers run with `--auto_create_session` set to `False` by default):
50+
```bash
51+
curl -X POST http://localhost:8000/apps/abort_agent/users/user/sessions \
52+
-H "Content-Type: application/json" \
53+
-d '{"session_id": "8b24e6ed-1fff-4f0c-a06a-e065692a446e"}'
54+
```
55+
1. Initiate the count request (this blocks waiting for a response):
56+
```bash
57+
curl -X POST http://localhost:8000/run \
58+
-H "Content-Type: application/json" \
59+
-d '{
60+
"app_name": "abort_agent",
61+
"user_id": "user",
62+
"session_id": "8b24e6ed-1fff-4f0c-a06a-e065692a446e",
63+
"new_message": {
64+
"role": "user",
65+
"parts": [{"text": "count to 100"}]
66+
}
67+
}'
68+
```
69+
1. Observe your `adk web` terminal window. You will see the counting progress logging.
70+
1. **Trigger the Abort**: Press `Ctrl+C` in your cURL terminal window to close the client connection.
71+
1. Observe the server console window. Counting halts instantly and prints:
72+
```text
73+
[Counting Tool] Count was ABORTED mid-run at progress: X/100 (Client Disconnected)!
74+
```
75+
76+
### 3. Running and Testing via ADK Web (Dev UI)
77+
78+
To observe cooperative aborts interactively in the web-based developer interface:
79+
80+
1. Start the local development server:
81+
```bash
82+
adk web --allow_origins=http://localhost:4200 contributing/samples/
83+
```
84+
1. Open the ADK Web interface (`http://localhost:4200`) in your web browser.
85+
1. Select the **`abort_agent`** app from the left sidebar panel.
86+
1. Type `count to 100` in the message input box and click submit.
87+
1. **Trigger the Abort**: Simply close your browser tab, refresh the page, or navigate away from the chat panel.
88+
1. Observe the server's stdout terminal console. You will see that counting halts immediately and logs:
89+
```text
90+
[Counting Tool] Count was ABORTED mid-run (Client Disconnected)!
91+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2026 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: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright 2026 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+
import asyncio
16+
import logging
17+
18+
from google.adk import Agent
19+
20+
logger = logging.getLogger("google_adk." + __name__)
21+
22+
23+
async def count_seconds(target: int) -> str:
24+
"""Counts from 1 to the target number, pausing 1 second between counts, and prints each count.
25+
26+
Args:
27+
target: The target number to count to.
28+
"""
29+
logger.info("Starting count from 1 to %d...", target)
30+
print(
31+
f"\n[Counting Tool] Starting counting up to {target} in console...",
32+
flush=True,
33+
)
34+
35+
i = 0
36+
try:
37+
for i in range(1, target + 1):
38+
await asyncio.sleep(1)
39+
# Print to standard stdout so it shows directly in the server terminal
40+
print(f"[Counting Tool] Progress: {i}/{target}", flush=True)
41+
logger.info("Counted: %d/%d", i, target)
42+
43+
print(
44+
f"[Counting Tool] Finished counting up to {target}.\n",
45+
flush=True,
46+
)
47+
return f"Successfully counted from 1 to {target} in the console."
48+
except asyncio.CancelledError:
49+
print(
50+
f"\n[Counting Tool] Count was ABORTED mid-run at progress: {i}/{target}"
51+
" (Client Disconnected)!\n",
52+
flush=True,
53+
)
54+
logger.warning("Counting tool was cancelled mid-run.")
55+
raise
56+
57+
58+
root_agent = Agent(
59+
name="abort_agent",
60+
description=(
61+
"An agent designed to demonstrate how ADK handles client disconnects"
62+
" and aborts agent executions mid-run using a counting loop with a"
63+
" 1-second delay."
64+
),
65+
instruction="""You are an abort coordinator.
66+
Your goal is to demonstrate cooperative task abortion.
67+
When asked to count to a number (or count for a number of seconds), invoke the `count_seconds` tool with the target number.
68+
Do not try to count by yourself; always delegate counting to the `count_seconds` tool so that progress is accurately printed and logs can show task cancellation when a disconnect happens.""",
69+
tools=[count_seconds],
70+
)

contributing/samples/models/interactions_api/agent.py

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

1515
"""Agent definition for testing the Interactions API integration.
16-
17-
NOTE: The Interactions API does NOT support mixing custom function calling tools
18-
with built-in tools in the same agent. To work around this limitation, we use
19-
bypass_multi_tools_limit=True on GoogleSearchTool, which converts the built-in
20-
google_search to a function calling tool (via GoogleSearchAgentTool).
21-
22-
The bypass is only triggered when len(agent.tools) > 1, so we include multiple
23-
tools in the agent (GoogleSearchTool + get_current_weather).
24-
25-
With bypass_multi_tools_limit=True and multiple tools, all tools become function
26-
calling tools, which allows mixing google_search with custom function tools.
2716
"""
2817

2918
from google.adk.agents.llm_agent import Agent
@@ -74,16 +63,13 @@ def get_current_weather(city: str) -> dict:
7463
}
7564

7665

77-
# Main agent with google_search (via bypass) and custom function tools
78-
# Using bypass_multi_tools_limit=True converts google_search to a function calling tool.
79-
# We need len(tools) > 1 to trigger the bypass, so we include get_current_weather directly.
80-
# This allows mixing google_search with custom function tools via the Interactions API.
66+
# Main agent with google_search built-in tool and custom function tools
8167
#
8268
# NOTE: code_executor is not compatible with function calling mode because the model
8369
# tries to call a function (e.g., run_code) instead of outputting code in markdown.
8470
root_agent = Agent(
8571
model=Gemini(
86-
model="gemini-3-flash-preview",
72+
model="gemini-3.1-flash-lite",
8773
use_interactions_api=True,
8874
),
8975
name="interactions_test_agent",
@@ -99,7 +85,7 @@ def get_current_weather(city: str) -> dict:
9985
Be concise and helpful in your responses. Always confirm what you did.
10086
""",
10187
tools=[
102-
GoogleSearchTool(bypass_multi_tools_limit=True),
88+
GoogleSearchTool(),
10389
get_current_weather,
10490
],
10591
)

0 commit comments

Comments
 (0)