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,224 @@
# Runner Debug Helper Example
This example demonstrates the `run_debug()` helper method that simplifies agent interaction for debugging and experimentation in ADK.
## Overview
The `run_debug()` method reduces agent interaction boilerplate from 7-8 lines to just 2 lines, making it ideal for:
- Quick debugging sessions
- Jupyter notebooks
- REPL experimentation
- Writing examples
- Initial agent development
## Files Included
- `agent.py` - Agent with 2 tools: weather and stock price
- `main.py` - 8 examples demonstrating all features
- `README.md` - This documentation
## Setup
### Prerequisites
Set your Google API key:
```bash
export GOOGLE_API_KEY="your-api-key"
```
### Running the Example
```bash
python -m contributing.samples.runner_debug_example.main
```
## Features Demonstrated
1. **Minimal Usage**: Simple 2-line agent interaction
1. **Multiple Messages**: Processing multiple messages in sequence
1. **Session Persistence**: Maintaining conversation context
1. **Separate Sessions**: Managing multiple user sessions
1. **Tool Calls**: Displaying tool invocations and results
1. **Event Capture**: Collecting events for programmatic inspection
1. **Advanced Configuration**: Using RunConfig for custom settings
1. **Comparison**: Before/after boilerplate reduction
## Part Types Supported
The `run_debug()` method properly displays all ADK part types:
| Part Type | Display Format | Use Case |
| ----------------------- | ---------------------------------------- | ---------------------- |
| `text` | `agent > {text}` | Regular text responses |
| `function_call` | `agent > [Calling tool: {name}({args})]` | Tool invocations |
| `function_response` | `agent > [Tool result: {response}]` | Tool results |
| `executable_code` | `agent > [Executing {language} code...]` | Code blocks |
| `code_execution_result` | `agent > [Code output: {output}]` | Code execution results |
| `inline_data` | `agent > [Inline data: {mime_type}]` | Images, files, etc. |
| `file_data` | `agent > [File: {uri}]` | File references |
## Tools Available in Example
The example agent includes 2 tools to demonstrate tool handling:
1. **`get_weather(city)`** - Returns mock weather data for major cities
1. **`get_stock_price(ticker)`** - Returns mock stock prices for major tech companies
## Key Benefits
### Before (7-8 lines)
```python
from google.adk.sessions import InMemorySessionService
from google.genai import types
APP_NAME = "default"
USER_ID = "default"
session_service = InMemorySessionService()
runner = Runner(agent=agent, app_name=APP_NAME, session_service=session_service)
session = await session_service.create_session(
app_name=APP_NAME, user_id=USER_ID, session_id="default"
)
content = types.Content(role="user", parts=[types.Part.from_text("Hi")])
async for event in runner.run_async(
user_id=USER_ID, session_id=session.id, new_message=content
):
if event.content and event.content.parts:
print(event.content.parts[0].text)
```
### After (2 lines)
```python
runner = InMemoryRunner(agent=agent)
await runner.run_debug("Hi")
```
## API Reference
```python
async def run_debug(
self,
user_messages: str | list[str],
*,
user_id: str = 'debug_user_id',
session_id: str = 'debug_session_id',
run_config: Optional[RunConfig] = None,
quiet: bool = False,
verbose: bool = False,
) -> List[Event]:
```
### Parameters
- `user_messages`: Single message string or list of messages (required)
- `user_id`: User identifier for session tracking (default: 'debug_user_id')
- `session_id`: Session identifier for conversation continuity (default: 'debug_session_id')
- `run_config`: Optional advanced configuration
- `quiet`: Whether to suppress output to console (default: False)
- `verbose`: Whether to show detailed tool calls and responses (default: False)
### Usage Examples
```python
# Minimal usage
runner = InMemoryRunner(agent=agent)
await runner.run_debug("What's the weather?")
# Multiple queries
await runner.run_debug(["Query 1", "Query 2", "Query 3"])
# Custom session
await runner.run_debug(
"Hello",
user_id="alice",
session_id="debug_session"
)
# Capture events without printing
events = await runner.run_debug(
"Process this",
quiet=True
)
# Show tool calls with verbose mode
await runner.run_debug(
"What's the weather?",
verbose=True # Shows [Calling tool: ...] and [Tool result: ...]
)
# With custom configuration
from google.adk.agents.run_config import RunConfig
config = RunConfig(support_cfc=False)
await runner.run_debug("Query", run_config=config)
```
## Troubleshooting
### Common Issues and Solutions
1. **Tool calls not showing in output**
- **Issue**: Tool invocations and responses are not displayed
- **Solution**: Set `verbose=True` to see detailed tool interactions:
```python
await runner.run_debug("Query", verbose=True)
```
1. **Import errors when running tests**
- **Issue**: `ModuleNotFoundError: No module named 'google.adk'`
- **Solution**: Ensure you're using the virtual environment:
```bash
source .venv/bin/activate
python -m pytest tests/
```
1. **Session state not persisting between calls**
- **Issue**: Agent doesn't remember previous interactions
- **Solution**: Use the same `user_id` and `session_id` across calls:
```python
await runner.run_debug("First query", user_id="alice", session_id="debug")
await runner.run_debug("Follow-up", user_id="alice", session_id="debug")
```
1. **Output truncation issues**
- **Issue**: Long tool responses are truncated with "..."
- **Solution**: This is by design to keep debug output readable. For full responses, use:
```python
events = await runner.run_debug("Query", quiet=True)
# Process events programmatically for full content
```
1. **API key errors**
- **Issue**: Authentication failures or missing API key
- **Solution**: Ensure your Google API key is set:
```bash
export GOOGLE_API_KEY="your-api-key"
```
## Important Notes
`run_debug()` is designed for debugging and experimentation only. For production use requiring:
- Custom session/memory services (Spanner, Cloud SQL)
- Fine-grained event processing
- Error recovery and resumability
- Performance optimization
Use the standard `run_async()` method instead.
@@ -0,0 +1,17 @@
# 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.
"""Runner debug example demonstrating simplified agent interaction."""
from . import agent
@@ -0,0 +1,90 @@
# 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.
"""Example agent for demonstrating run_debug helper method."""
from google.adk import Agent
from google.adk.tools.tool_context import ToolContext
def get_weather(city: str, tool_context: ToolContext) -> str:
"""Get weather information for a city.
Args:
city: Name of the city to get weather for.
tool_context: Tool context for session state.
Returns:
Weather information as a string.
"""
# Store query history in session state
if "weather_queries" not in tool_context.state:
tool_context.state["weather_queries"] = [city]
else:
tool_context.state["weather_queries"] = tool_context.state[
"weather_queries"
] + [city]
# Mock weather data for demonstration
weather_data = {
"San Francisco": "Foggy, 15°C (59°F)",
"New York": "Sunny, 22°C (72°F)",
"London": "Rainy, 12°C (54°F)",
"Tokyo": "Clear, 25°C (77°F)",
"Paris": "Cloudy, 18°C (64°F)",
}
return weather_data.get(
city, f"Weather data not available for {city}. Try a major city."
)
def get_stock_price(ticker: str) -> str:
"""Get the current stock price for a given ticker symbol.
This tool demonstrates how function calls are displayed in run_debug().
Args:
ticker: Stock ticker symbol (e.g., GOOGL, AAPL, MSFT).
Returns:
Stock price information as a string.
"""
prices = {
"GOOGL": "175.50 USD",
"AAPL": "225.00 USD",
"MSFT": "420.00 USD",
"AMZN": "190.00 USD",
"NVDA": "125.00 USD",
}
ticker = ticker.upper()
if ticker in prices:
return f"Price for {ticker}: {prices[ticker]}"
return f"Stock ticker {ticker} not found in database."
root_agent = Agent(
model="gemini-2.5-flash-lite",
name="agent",
description="A helpful assistant demonstrating run_debug() helper method",
instruction="""You are a helpful assistant that can:
1. Provide weather information for major cities
2. Provide stock prices for major tech companies
3. Remember previous queries in the conversation
When users ask about weather, use the get_weather tool.
When users ask for stock prices, use the get_stock_price tool.
Be friendly and conversational.""",
tools=[get_weather, get_stock_price],
)
@@ -0,0 +1,261 @@
# 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.
"""Demonstrates the run_debug() helper method for simplified agent interaction."""
import asyncio
from google.adk.runners import InMemoryRunner
from . import agent
async def example_minimal():
"""Minimal usage - just 2 lines for debugging."""
print("------------------------------------")
print("Example 1: Minimal Debug Usage")
print("------------------------------------")
# Create runner
runner = InMemoryRunner(agent=agent.root_agent)
# Debug with just 2 lines
await runner.run_debug("What's the weather in San Francisco?")
async def example_multiple_messages():
"""Debug with multiple messages in sequence."""
print("\n------------------------------------")
print("Example 2: Multiple Messages")
print("------------------------------------")
runner = InMemoryRunner(agent=agent.root_agent)
# Pass multiple messages as a list
await runner.run_debug([
"Hi there!",
"What's the weather in Tokyo?",
"How about New York?",
"What's the stock price of GOOGL?",
])
async def example_conversation_persistence():
"""Demonstrate conversation persistence during debugging."""
print("\n------------------------------------")
print("Example 3: Session Persistence")
print("------------------------------------")
runner = InMemoryRunner(agent=agent.root_agent)
# First interaction
await runner.run_debug("Hi, I'm planning a trip to Europe")
# Second interaction - continues same session
await runner.run_debug("What's the weather in Paris?")
# Third interaction - agent remembers context
await runner.run_debug("And London?")
# Fourth interaction - referring to previous messages
await runner.run_debug("Which city had better weather?")
async def example_separate_sessions():
"""Debug with multiple separate sessions."""
print("\n------------------------------------")
print("Example 4: Separate Sessions")
print("------------------------------------")
runner = InMemoryRunner(agent=agent.root_agent)
# Alice's session
print("\n-- Alice's session --")
await runner.run_debug(
"What's the weather in San Francisco?",
user_id="alice",
session_id="alice_debug",
)
# Bob's session (separate)
print("\n-- Bob's session --")
await runner.run_debug(
"What is the price of AAPL?", user_id="bob", session_id="bob_debug"
)
# Continue Alice's session
print("\n-- Back to Alice's session --")
await runner.run_debug(
"Should I bring an umbrella?",
user_id="alice",
session_id="alice_debug",
)
async def example_with_tools():
"""Demonstrate tool calls and responses with verbose flag."""
print("\n------------------------------------")
print("Example 5: Tool Calls (verbose flag)")
print("------------------------------------")
runner = InMemoryRunner(agent=agent.root_agent)
print("\n-- Default (verbose=False) - Clean output --")
# Without verbose: Only shows final agent responses
await runner.run_debug([
"What's the weather in Tokyo?",
"Check MSFT stock price",
])
print("\n-- With verbose=True - Detailed output --")
# With verbose: Shows tool calls as [Calling tool: ...] and [Tool result: ...]
await runner.run_debug(
[
"What's the weather in Paris?",
"What's the stock price of NVDA?",
],
verbose=True,
)
async def example_capture_events():
"""Capture events for inspection during debugging."""
print("\n------------------------------------")
print("Example 6: Capture Events (No Print)")
print("------------------------------------")
runner = InMemoryRunner(agent=agent.root_agent)
# Capture events without printing for inspection
events = await runner.run_debug(
["Get weather for London", "Get stock price of AMZN"],
quiet=True,
)
# Inspect the captured events
print(f"Captured {len(events)} events")
for i, event in enumerate(events):
if event.content and event.content.parts:
for part in event.content.parts:
if part.text:
print(f" Event {i+1}: {event.author} - Text: {len(part.text)} chars")
elif part.function_call:
print(
f" Event {i+1}: {event.author} - Tool call:"
f" {part.function_call.name}"
)
elif part.function_response:
print(f" Event {i+1}: {event.author} - Tool response received")
async def example_with_run_config():
"""Demonstrate using RunConfig for advanced settings."""
print("\n------------------------------------")
print("Example 7: Advanced Configuration")
print("------------------------------------")
from google.adk.agents.run_config import RunConfig
runner = InMemoryRunner(agent=agent.root_agent)
# Custom configuration - RunConfig supports:
# - support_cfc: Control function calling behavior
# - response_modalities: Output modalities (for LIVE API)
# - speech_config: Speech settings (for LIVE API)
config = RunConfig(
support_cfc=False, # Disable controlled function calling
)
await runner.run_debug(
"Explain what tools you have available", run_config=config
)
async def example_comparison():
"""Show before/after comparison of boilerplate reduction."""
print("\n------------------------------------")
print("Example 8: Before vs After Comparison")
print("------------------------------------")
print("\nBefore (7-8 lines of boilerplate):")
print("""
from google.adk.sessions import InMemorySessionService
from google.genai import types
APP_NAME = "default"
USER_ID = "default"
session_service = InMemorySessionService()
runner = Runner(agent=agent, app_name=APP_NAME, session_service=session_service)
session = await session_service.create_session(
app_name=APP_NAME, user_id=USER_ID, session_id="default"
)
content = types.Content(role="user", parts=[types.Part.from_text("Hi")])
async for event in runner.run_async(
user_id=USER_ID, session_id=session.id, new_message=content
):
if event.content and event.content.parts:
print(event.content.parts[0].text)
""")
print("\nAfter (just 2 lines):")
print("""
runner = InMemoryRunner(agent=agent)
await runner.run_debug("Hi")
""")
print("\nThat's a 75% reduction in boilerplate.")
async def main():
"""Run all debug examples."""
print("ADK run_debug() Helper Method Examples")
print("=======================================")
print("Demonstrating all capabilities:\n")
print("1. Minimal usage (2 lines)")
print("2. Multiple messages")
print("3. Session persistence")
print("4. Separate sessions")
print("5. Tool calls")
print("6. Event capture")
print("7. Advanced configuration")
print("8. Before/after comparison")
await example_minimal()
await example_multiple_messages()
await example_conversation_persistence()
await example_separate_sessions()
await example_with_tools()
await example_capture_events()
await example_with_run_config()
await example_comparison()
print("\n=======================================")
print("All examples completed.")
print("\nHow different part types appear:")
print(" Text: agent > Hello world (always shown)")
print("\nWith verbose=True only:")
print(
" Tool call: agent > [Calling tool: get_stock_price({'ticker':"
" 'GOOGL'})]"
)
print(" Tool result: agent > [Tool result: Price for GOOGL: 175.50 USD]")
print("\nNote: When models have code execution enabled (verbose=True):")
print(" Code exec: agent > [Executing python code...]")
print(" Code output: agent > [Code output: Result: 42]")
print(" Inline data: agent > [Inline data: image/png]")
print(" File ref: agent > [File: gs://bucket/file.pdf]")
if __name__ == "__main__":
asyncio.run(main())
@@ -0,0 +1,83 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "What's the stock price of GOOGL?"
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "agent",
"content": {
"parts": [
{
"functionCall": {
"args": {
"ticker": "GOOGL"
},
"id": "fc-1",
"name": "get_stock_price"
}
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"longRunningToolIds": [],
"nodeInfo": {
"path": "agent@1"
}
},
{
"author": "agent",
"content": {
"parts": [
{
"functionResponse": {
"id": "fc-1",
"name": "get_stock_price",
"response": {
"result": "Price for GOOGL: 175.50 USD"
}
}
}
],
"role": "user"
},
"id": "e-3",
"invocationId": "i-1",
"nodeInfo": {
"path": "agent@1"
}
},
{
"author": "agent",
"content": {
"parts": [
{
"text": "The current stock price for GOOGL is 175.50 USD."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-1",
"nodeInfo": {
"path": "agent@1"
}
}
]
}
@@ -0,0 +1,83 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "What's the stock price of NVDA?"
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "agent",
"content": {
"parts": [
{
"functionCall": {
"args": {
"ticker": "NVDA"
},
"id": "fc-1",
"name": "get_stock_price"
}
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"longRunningToolIds": [],
"nodeInfo": {
"path": "agent@1"
}
},
{
"author": "agent",
"content": {
"parts": [
{
"functionResponse": {
"id": "fc-1",
"name": "get_stock_price",
"response": {
"result": "Price for NVDA: 125.00 USD"
}
}
}
],
"role": "user"
},
"id": "e-3",
"invocationId": "i-1",
"nodeInfo": {
"path": "agent@1"
}
},
{
"author": "agent",
"content": {
"parts": [
{
"text": "The current stock price for NVDA is 125.00 USD."
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-1",
"nodeInfo": {
"path": "agent@1"
}
}
]
}
@@ -0,0 +1,90 @@
{
"events": [
{
"author": "user",
"content": {
"parts": [
{
"text": "What is the weather in San Francisco?"
}
],
"role": "user"
},
"id": "e-1",
"invocationId": "i-1",
"nodeInfo": {
"path": ""
}
},
{
"author": "agent",
"content": {
"parts": [
{
"functionCall": {
"args": {
"city": "San Francisco"
},
"id": "fc-1",
"name": "get_weather"
}
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-2",
"invocationId": "i-1",
"longRunningToolIds": [],
"nodeInfo": {
"path": "agent@1"
}
},
{
"actions": {
"stateDelta": {
"weather_queries": [
"San Francisco"
]
}
},
"author": "agent",
"content": {
"parts": [
{
"functionResponse": {
"id": "fc-1",
"name": "get_weather",
"response": {
"result": "Foggy, 15\u00b0C (59\u00b0F)"
}
}
}
],
"role": "user"
},
"id": "e-3",
"invocationId": "i-1",
"nodeInfo": {
"path": "agent@1"
}
},
{
"author": "agent",
"content": {
"parts": [
{
"text": "The weather in San Francisco is foggy, with a temperature of 15\u00b0C (59\u00b0F). Is there anything else I can help you with?"
}
],
"role": "model"
},
"finishReason": "STOP",
"id": "e-4",
"invocationId": "i-1",
"nodeInfo": {
"path": "agent@1"
}
}
]
}