Compare commits

..

8 Commits

Author SHA1 Message Date
Xuan Yang b8644ef32c Make additional_headers kwargs 2025-10-21 12:44:50 -07:00
Xuan Yang ace3e5a3a5 Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-20 09:58:15 -07:00
Xuan Yang 37179a6e1f Format conditional statement for setting headers 2025-10-20 09:36:25 -07:00
Parham Alizadeh d8ded07eb3 addressing comments - tidy ups 2025-10-20 10:18:27 +01:00
Parham MohammadAlizadeh a09dd4d31f Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-18 12:09:45 +01:00
Parham MohammadAlizadeh 71999b0ef7 Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-17 16:37:23 +01:00
Parham MohammadAlizadeh 3d6d6132cd Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-17 16:23:25 +01:00
Parham Alizadeh 78e4d81579 feat(tools): support additional headers for google api toolset #non-breaking 2025-10-17 16:22:55 +01:00
467 changed files with 6991 additions and 38898 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ Steps to reproduce the behavior:
1. Install '...'
2. Run '....'
3. Open '....'
4. Provide error or stacktrace
4. Provie error or stacktrace
**Expected behavior**
A clear and concise description of what you expected to happen.
-52
View File
@@ -1,52 +0,0 @@
**Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) before creating a pull request.**
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #_issue_number_
- Related: #_issue_number_
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
_A clear and concise description of what the problem is._
**Solution:**
_A clear and concise description of what you want to happen and why you choose
this solution._
### Testing Plan
_Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes._
**Unit Tests:**
- [ ] I have added or updated unit tests for my change.
- [ ] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
**Manual End-to-End (E2E) Tests:**
_Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix._
### Checklist
- [ ] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document.
- [ ] I have performed a self-review of my own code.
- [ ] I have commented my code, particularly in hard-to-understand areas.
- [ ] I have added tests that prove my fix is effective or that my feature works.
- [ ] New and existing unit tests pass locally with my changes.
- [ ] I have manually tested my changes end-to-end.
- [ ] Any dependent changes have been merged and published in downstream modules.
### Additional context
_Add any other context or screenshots about the feature request here._
+1 -1
View File
@@ -89,7 +89,7 @@ jobs:
- name: Check for import from cli package in certain changed Python files
run: |
git fetch origin ${{ github.base_ref }}
CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only origin/${{ github.base_ref }}...HEAD | grep -E '\.py$' | grep -v -E 'cli/.*|src/google/adk/tools/apihub_tool/apihub_toolset.py|tests/.*|contributing/samples/' || true)
CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only origin/${{ github.base_ref }}...HEAD | grep -E '\.py$' | grep -v -E 'cli/.*|tests/.*|contributing/samples/' || true)
if [ -n "$CHANGED_FILES" ]; then
echo "Changed Python files to check:"
echo "$CHANGED_FILES"
-134
View File
@@ -1,134 +0,0 @@
name: Copybara PR Handler
on:
push:
branches:
- main
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to close (for testing)'
required: true
type: string
commit_sha:
description: 'Commit SHA reference (optional, for testing)'
required: false
type: string
jobs:
close-imported-pr:
runs-on: ubuntu-latest
permissions:
pull-requests: write
issues: write
contents: read
steps:
- name: Check for Copybara commits and close PRs
uses: actions/github-script@v7
with:
github-token: ${{ secrets.ADK_TRIAGE_AGENT }}
script: |
// Check if this is a manual test run
const isManualRun = context.eventName === 'workflow_dispatch';
let prsToClose = [];
if (isManualRun) {
// Manual testing mode
const prNumber = parseInt(context.payload.inputs.pr_number);
const commitSha = context.payload.inputs.commit_sha || context.sha.substring(0, 7);
console.log('=== MANUAL TEST MODE ===');
console.log(`Testing with PR #${prNumber}, commit ${commitSha}`);
prsToClose.push({ prNumber, commitSha });
} else {
// Normal mode: process commits from push event
const commits = context.payload.commits || [];
console.log(`Found ${commits.length} commit(s) in this push`);
// Process each commit
for (const commit of commits) {
const sha = commit.id;
const committer = commit.committer.name;
const message = commit.message;
console.log(`\n--- Processing commit ${sha.substring(0, 7)} ---`);
console.log(`Committer: ${committer}`);
// Check if this is a Copybara commit
if (committer !== 'Copybara-Service') {
console.log('Not a Copybara commit, skipping');
continue;
}
// Extract PR number from commit message
// Pattern: "Merge https://github.com/google/adk-python/pull/3333"
const prMatch = message.match(/Merge https:\/\/github\.com\/google\/adk-python\/pull\/(\d+)/);
if (!prMatch) {
console.log('No PR number found in Copybara commit message');
continue;
}
const prNumber = parseInt(prMatch[1]);
const commitSha = sha.substring(0, 7);
prsToClose.push({ prNumber, commitSha });
}
}
// Process PRs to close
for (const { prNumber, commitSha } of prsToClose) {
console.log(`\n--- Processing PR #${prNumber} ---`);
// Get PR details to check if it's open
let pr;
try {
pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
} catch (error) {
console.log(`PR #${prNumber} not found or inaccessible:`, error.message);
continue;
}
// Only close if PR is still open
if (pr.data.state !== 'open') {
console.log(`PR #${prNumber} is already ${pr.data.state}, skipping`);
continue;
}
const author = pr.data.user.login;
try {
// Add comment with commit reference
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: `Thank you @${author} for your contribution! 🎉\n\nYour changes have been successfully imported and merged via Copybara in commit ${commitSha}.\n\nClosing this PR as the changes are now in the main branch.`
});
// Close the PR
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
state: 'closed'
});
console.log(`Successfully closed PR #${prNumber}`);
} catch (error) {
console.log(`Error closing PR #${prNumber}:`, error.message);
}
}
if (isManualRun) {
console.log('\n=== TEST COMPLETED ===');
} else {
console.log('\n--- Finished processing all commits ---');
}
-17
View File
@@ -98,20 +98,3 @@ Thumbs.db
*.bak
*.tmp
*.temp
# AI Coding Tools - Project-specific configs
# Developers should symlink or copy AGENTS.md and add their own overrides locally
.claude/
CLAUDE.md
.cursor/
.cursorrules
.cursorignore
.windsurfrules
.aider*
.continue/
.codeium/
.githubnext/
.roo/
.rooignore
.bolt/
.v0/
+40 -364
View File
@@ -1,59 +1,15 @@
# AI Coding Assistant Context
# Gemini CLI / Gemini Code Assist Context
This document provides context for AI coding assistants (Claude Code, Gemini CLI, GitHub Copilot, Cursor, etc.) to understand the ADK Python project and assist with development.
This document provides context for the Gemini CLI and Gemini Code Assist to understand the project and assist with development.
## Project Overview
The Agent Development Kit (ADK) is an open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control. 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.
### Key Components
- **Agent** - Blueprint defining identity, instructions, and tools (`LlmAgent`, `LoopAgent`, `ParallelAgent`, `SequentialAgent`, etc.)
- **Runner** - Execution engine that orchestrates the "Reason-Act" loop, manages LLM calls, executes tools, and handles multi-agent coordination
- **Tool** - Functions/capabilities agents can call (Python functions, OpenAPI specs, MCP tools, Google API tools)
- **Session** - Conversation state management (in-memory, Vertex AI, Spanner-backed)
- **Memory** - Long-term recall across sessions
## Project Architecture
Please refer to [ADK Project Overview and Architecture](https://github.com/google/adk-python/blob/main/contributing/adk_project_overview_and_architecture.md) for details.
### Source Structure
```
src/google/adk/
├── agents/ # Agent implementations (LlmAgent, LoopAgent, ParallelAgent, etc.)
├── runners.py # Core Runner orchestration class
├── tools/ # Tool ecosystem (50+ files)
│ ├── google_api_tool/
│ ├── bigtable/, bigquery/, spanner/
│ ├── openapi_tool/
│ └── mcp_tool/ # Model Context Protocol
├── models/ # LLM integrations (Gemini, Anthropic, LiteLLM)
├── sessions/ # Session management (in-memory, Vertex AI, Spanner)
├── memory/ # Long-term memory services
├── evaluation/ # Evaluation framework (47 files)
├── cli/ # CLI tools and web UI
├── flows/ # Execution flow orchestration
├── a2a/ # Agent-to-Agent protocol
├── telemetry/ # Observability and tracing
└── utils/ # Utility functions
```
### Test Structure
```
tests/
├── unittests/ # 2600+ unit tests across 236+ files
│ ├── agents/
│ ├── tools/
│ ├── models/
│ ├── evaluation/
│ ├── a2a/
│ └── ...
└── integration/ # Integration tests
```
### ADK Live (Bidi-streaming)
- ADK live feature can be accessed from runner.run_live(...) and corresponding FAST api endpoint.
@@ -65,129 +21,6 @@ tests/
- User audio or model audio should be saved into artifacts with a reference in Event to it.
- Tests are in [tests/unittests/streaming](https://github.com/google/adk-python/tree/main/tests/unittests/streaming).
### Agent Structure Convention (Required)
**All agent directories must follow this structure:**
```
my_agent/
├── __init__.py # MUST contain: from . import agent
└── agent.py # MUST define: root_agent = Agent(...) OR app = App(...)
```
**Choose one pattern based on your needs:**
**Option 1 - Simple Agent (for basic agents without plugins):**
```python
from google.adk.agents import Agent
from google.adk.tools import google_search
root_agent = Agent(
name="search_assistant",
model="gemini-2.5-flash",
instruction="You are a helpful assistant.",
description="An assistant that can search the web.",
tools=[google_search]
)
```
**Option 2 - App Pattern (when you need plugins, event compaction, custom configuration):**
```python
from google.adk import Agent
from google.adk.apps import App
from google.adk.plugins import ContextFilterPlugin
root_agent = Agent(
name="my_agent",
model="gemini-2.5-flash",
instruction="You are a helpful assistant.",
tools=[...],
)
app = App(
name="my_app",
root_agent=root_agent,
plugins=[
ContextFilterPlugin(num_invocations_to_keep=3),
],
)
```
**Rationale:** This structure allows the ADK CLI (`adk web`, `adk run`, etc.) to automatically discover and load agents without additional configuration.
## Development Setup
### Requirements
**Minimum requirements:**
- Python 3.10+ (**Python 3.11+ strongly recommended** for best performance)
- `uv` package manager (**required** - faster than pip/venv)
**Install uv if not already installed:**
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
### Setup Instructions
**Standard setup for development:**
```bash
# Create virtual environment with Python 3.11
uv venv --python "python3.11" ".venv"
source .venv/bin/activate
# Install all dependencies for development
uv sync --all-extras
```
**Minimal setup for testing only (matches CI):**
```bash
uv sync --extra test --extra eval --extra a2a
```
**Virtual Environment Usage (Required):**
- **Always use** `.venv/bin/python` or `.venv/bin/pytest` directly
- **Or activate** with `source .venv/bin/activate` before running commands
- **Never use** `python -m venv` - always create with `uv venv` if missing
**Rationale:** `uv` is significantly faster and ensures consistent dependency resolution across the team.
### Building
```bash
# Build wheel
uv build
# Install local build for testing
pip install dist/google_adk-<version>-py3-none-any.whl
```
### Running Agents Locally
**For interactive development and debugging:**
```bash
# Launch web UI (recommended for development)
adk web path/to/agents_dir
```
**For CLI-based testing:**
```bash
# Interactive CLI (prompts for user input)
adk run path/to/my_agent
```
**For API/production mode:**
```bash
# Start FastAPI server
adk api_server path/to/agents_dir
```
**For running evaluations:**
```bash
# Run evaluation set against agent
adk eval path/to/my_agent path/to/eval_set.json
```
## ADK: Style Guides
### Python Style Guide
@@ -204,68 +37,48 @@ The project follows the Google Python Style Guide. Key conventions are enforced
* **Imports**: Organized and sorted.
* **Error Handling**: Specific exceptions should be caught, not general ones like `Exception`.
### Autoformat (Required Before Committing)
### Autoformat
We have autoformat.sh to help solve import organize and formatting issues.
**Always run** before committing code:
```bash
./autoformat.sh
# Run in open_source_workspace/
$ ./autoformat.sh
```
**Manual formatting** (if needed):
```bash
# Format imports
isort src/ tests/ contributing/
# Format code style
pyink --config pyproject.toml src/ tests/ contributing/
```
**Check formatting** without making changes:
```bash
pyink --check --diff --config pyproject.toml src/
isort --check src/
```
**Formatting Standards (Enforced by CI):**
- **Formatter:** `pyink` (Google-style Python formatter)
- **Line length:** 80 characters maximum
- **Indentation:** 2 spaces (never tabs)
- **Import sorter:** `isort` with Google profile
- **Linter:** `pylint` with Google Python Style Guide
**Rationale:** Consistent formatting eliminates style debates and makes code reviews focus on logic rather than style.
### In ADK source
Below styles applies to the ADK source code (under `src/` folder of the GitHub repo).
Below styles applies to the ADK source code (under `src/` folder of the Github.
repo).
#### Use relative imports (Required)
#### Use relative imports
```python
# DO - Use relative imports
# DO
from ..agents.llm_agent import LlmAgent
# DON'T - No absolute imports
# DON'T
from google.adk.agents.llm_agent import LlmAgent
```
**Rationale:** Relative imports make the code more maintainable and avoid circular import issues in large codebases.
#### Import from module, not from `__init__.py` (Required)
#### Import from module, not from `__init__.py`
```python
# DO - Import directly from module
# DO
from ..agents.llm_agent import LlmAgent
# DON'T - Import from __init__.py
from ..agents import LlmAgent
# DON'T
from ..agents import LlmAgent # import from agents/__init__.py
```
**Rationale:** Direct module imports make dependencies explicit and improve IDE navigation and refactoring.
#### Always do `from __future__ import annotations`
#### Always do `from __future__ import annotations` (Required)
```python
# DO THIS, right after the open-source header.
from __future__ import annotations
```
**Rule:** Every source file must include `from __future__ import annotations` immediately after the license header, before any other imports.
Like below:
```python
# Copyright 2025 Google LLC
@@ -282,67 +95,39 @@ from ..agents import LlmAgent
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations # REQUIRED - Always include this
from __future__ import annotations
# ... rest of imports ...
# ... the rest of the file.
```
**Rationale:** This enables forward-referencing classes without quotes, improving code readability and type hint support (PEP 563).
This allows us to forward-reference a class without quotes.
Check out go/pep563 for details.
### In ADK tests
#### Use absolute imports (Required)
#### Use absolute imports
**Rule:** Test code must use absolute imports (`google.adk.*`) to match how users import ADK.
In tests, we use `google.adk` same as how our users uses.
```python
# DO - Use absolute imports
# DO
from google.adk.agents.llm_agent import LlmAgent
# DON'T - No relative imports in tests
# DON'T
from ..agents.llm_agent import LlmAgent
```
**Rationale:** Tests should exercise the same import paths that users will use, catching issues with the public API.
## ADK: Local testing
## ADK: Local Testing
### Unit tests
### Unit Tests
Run below command:
**Quick start:** Run all tests with:
```bash
pytest tests/unittests
$ pytest tests/unittests
```
**Recommended:** Match CI configuration before submitting PRs:
```bash
uv sync --extra test --extra eval --extra a2a && pytest tests/unittests
```
**Additional options:**
```bash
# Run tests in parallel for faster execution
pytest tests/unittests -n auto
# Run a specific test file during development
pytest tests/unittests/agents/test_llm_agent.py
```
### Testing Philosophy
**Use real code over mocks:** ADK tests should use real implementations as much as possible instead of mocking. Only mock external dependencies like network calls or cloud services.
**Test interface behavior, not implementation details:** Tests should verify that the public API behaves correctly, not how it's implemented internally. This makes tests resilient to refactoring and ensures the contract with users remains intact.
**Test Requirements:**
- Fast and isolated tests where possible
- Use real ADK components; mock only external dependencies (LLM APIs, cloud services, etc.)
- Focus on testing public interfaces and behavior, not internal implementation
- Descriptive test names that explain what behavior is being tested
- High coverage for new features, edge cases, and error conditions
- Location: `tests/unittests/` following source structure
## Docstring and comments
### Comments - Explaining the Why, Not the What
@@ -428,118 +213,9 @@ The following changes are considered breaking and necessitate a MAJOR version
- Dependency Removal: Removing support for a previously integrated third-party
library or tool type.
## Commit Message Format (Required)
## Commit Message Format
**All commits must** follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format.
**Format:**
```
<type>(<scope>): <description>
[optional body]
[optional footer]
```
**Common types:** `feat`, `fix`, `refactor`, `docs`, `test`, `chore`
**Examples:**
```
feat(agents): Add support for App pattern with plugins
fix(sessions): Prevent memory leak in session cleanup
refactor(tools): Unify environment variable enabled checks
```
**Rationale:** Conventional commits enable automated changelog generation and version management.
## Key Files and Locations
Quick reference to important project files:
- **Main config:** `pyproject.toml` (uses `flit_core` build backend)
- **Dependencies:** `uv.lock` (managed by `uv`)
- **Linting:** `pylintrc` (Google Python Style Guide)
- **Auto-format:** `autoformat.sh` (runs isort + pyink)
- **CLI entry point:** `src/google/adk/cli/cli_tools_click.py`
- **Web UI backend:** `src/google/adk/cli/adk_web_server.py`
- **Main exports:** `src/google/adk/__init__.py` (exports Agent, Runner)
- **Examples:** `contributing/samples/` (100+ agent implementations)
## Additional Resources
- **Documentation:** https://google.github.io/adk-docs
- **Samples:** https://github.com/google/adk-samples
- **Architecture Details:** `contributing/adk_project_overview_and_architecture.md`
- **Contributing Guide:** `CONTRIBUTING.md`
- **LLM Context:** `llms.txt` (summarized), `llms-full.txt` (comprehensive)
## Python Tips
### General Python Best Practices
* **Constants:** Use immutable global constant collections (tuple, frozenset, immutabledict) to avoid hard-to-find bugs. Prefer constants over wild string/int literals, especially for dictionary keys, pathnames, and enums.
* **Naming:** Name mappings like `value_by_key` to enhance readability in lookups (e.g., `item = item_by_id[id]`).
* **Readability:** Use f-strings for concise string formatting, but use lazy-evaluated `%`-based templates for logging. Use `repr()` or `pprint.pformat()` for human-readable debug messages. Use `_` as a separator in numeric literals to improve readability.
* **Comprehensions:** Use list, set, and dict comprehensions for building collections concisely.
* **Iteration:** Iterate directly over containers without indices. Use `enumerate()` when you need the index, `dict.items()` for keys and values, and `zip()` for parallel iteration.
* **Built-ins:** Leverage built-in functions like `all()`, `any()`, `reversed()`, `sum()`, etc., to write more concise and efficient code.
* **Flattening Lists:** Use `itertools.chain.from_iterable()` to flatten a list of lists efficiently without unnecessary copying.
* **String Methods:** Use `startswith()` and `endswith()` with a tuple of strings to check for multiple prefixes or suffixes at once.
* **Decorators:** Use decorators to add common functionality (like logging, timing, caching) to functions without modifying their core logic. Use `functools.wraps()` to preserve the original function's metadata.
* **Context Managers:** Use `with` statements and context managers (from `contextlib` or custom classes with `__enter__`/`__exit__`) to ensure resources are properly initialized and torn down, even in the presence of exceptions.
* **Else Clauses:** Utilize the `else` clause in `try/except` blocks (runs if no exception), and in `for/while` loops (runs if the loop completes without a `break`) to write more expressive and less error-prone code.
* **Single Assignment:** Prefer single-assignment form (assign to a variable once) over assign-and-mutate to reduce bugs and improve readability. Use conditional expressions where appropriate.
* **Equality vs. Identity:** Use `is` or `is not` for singleton comparisons (e.g., `None`, `True`, `False`). Use `==` for value comparison.
* **Object Comparisons:** When implementing custom classes, be careful with `__eq__`. Return `NotImplemented` for unhandled types. Consider edge cases like subclasses and hashing. Prefer using `attrs` or `dataclasses` to handle this automatically.
* **Hashing:** If objects are equal, their hashes must be equal. Ensure attributes used in `__hash__` are immutable. Disable hashing with `__hash__ = None` if custom `__eq__` is implemented without a proper `__hash__`.
* **`__init__()` vs. `__new__()`:** `__new__()` creates the object, `__init__()` initializes it. For immutable types, modifications must happen in `__new__()`.
* **Default Arguments:** NEVER use mutable default arguments. Use `None` as a sentinel value instead.
* **`__add__()` vs. `__iadd__()`:** `x += y` (in-place add) can modify the object in-place if `__iadd__` is implemented (like for lists), while `x = x + y` creates a new object. This matters when multiple variables reference the same object.
* **Properties:** Use `@property` to create getters and setters only when needed, maintaining a simple attribute access syntax. Avoid properties for computationally expensive operations or those that can fail.
* **Modules for Namespacing:** Use modules as the primary mechanism for grouping and namespacing code elements, not classes. Avoid `@staticmethod` and methods that don't use `self`.
* **Argument Passing:** Python is call-by-value, where the values are object references (pointers). Assignment binds a name to an object. Modifying a mutable object through one name affects all names bound to it.
* **Keyword/Positional Arguments:** Use `*` to force keyword-only arguments and `/` to force positional-only arguments. This can prevent argument transposition errors and make APIs clearer, especially for functions with multiple arguments of the same type.
* **Type Hinting:** Annotate code with types to improve readability, debuggability, and maintainability. Use abstract types from `collections.abc` for container annotations (e.g., `Sequence`, `Mapping`, `Iterable`). Annotate return values, including `None`. Choose the most appropriate abstract type for function arguments and return types.
* **`NewType`:** Use `typing.NewType` to create distinct types from primitives (like `int` or `str`) to prevent argument transposition and improve type safety.
* **`__repr__()` vs. `__str__()`:** Implement `__repr__()` for unambiguous, developer-focused string representations, ideally evaluable. Implement `__str__()` for human-readable output. `__str__()` defaults to `__repr__()`.
* **F-string Debug:** Use `f"{expr=}"` for concise debug printing, showing both the expression and its value.
### Libraries and Tools
* **`collections.Counter`:** Use for efficiently counting hashable objects in an iterable.
* **`collections.defaultdict`:** Useful for avoiding key checks when initializing dictionary values, e.g., appending to lists.
* **`heapq`:** Use `heapq.nlargest()` and `heapq.nsmallest()` for efficiently finding the top/bottom N items. Use `heapq.merge()` to merge multiple sorted iterables.
* **`attrs` / `dataclasses`:** Use these libraries to easily define simple classes with boilerplate methods like `__init__`, `__repr__`, `__eq__`, etc., automatically generated.
* **NumPy:** Use NumPy for efficient array computing, element-wise operations, math functions, filtering, and aggregations on numerical data.
* **Pandas:** When constructing DataFrames row by row, append to a list of dicts and call `pd.DataFrame()` once to avoid inefficient copying. Use `TypedDict` or `dataclasses` for intermediate row data.
* **Flags:** Use libraries like `argparse` or `click` for command-line flag parsing. Access flag values in a type-safe manner.
* **Serialization:** For cross-language serialization, consider JSON (built-in), Protocol Buffers, or msgpack. For Python serialization with validation, use `pydantic` for runtime validation and automatic (de)serialization, or `cattrs` for performance-focused (de)serialization with `dataclasses` or `attrs`.
* **Regular Expressions:** Use `re.VERBOSE` to make complex regexes more readable with whitespace and comments. Choose the right method (`re.search`, `re.fullmatch`). Avoid regexes for simple string checks (`in`, `startswith`, `endswith`). Compile regexes used multiple times with `re.compile()`.
* **Caching:** Use `functools.lru_cache` with care. Prefer immutable return types. Be cautious when memoizing methods, as it can lead to memory leaks if the instance is part of the cache key; consider `functools.cached_property`.
* **Pickle:** Avoid using `pickle` due to security risks and compatibility issues. Prefer JSON, Protocol Buffers, or msgpack for serialization.
* **Multiprocessing:** Be aware of potential issues with `multiprocessing` on some platforms, especially concerning `fork`. Consider alternatives like threads (`concurrent.futures.ThreadPoolExecutor`) or `asyncio` for I/O-bound tasks.
* **Debugging:** Use `IPython.embed()` or `pdb.set_trace()` to drop into an interactive shell for debugging. Use visual debuggers if available. Log with context, including inputs and exception info using `logging.exception()` or `exc_info=True`.
* **Property-Based Testing & Fuzzing:** Use `hypothesis` for property-based testing that generates test cases automatically. For coverage-guided fuzzing, consider `atheris` or `python-afl`.
### Testing
* **Assertions:** Use pytest's native `assert` statements with informative expressions. Pytest automatically provides detailed failure messages showing the values involved. Add custom messages with `assert condition, "helpful message"` when the expression alone isn't clear.
* **Custom Assertions:** Write reusable helper functions (not methods) for repeated complex checks. Use `pytest.fail("message")` to explicitly fail a test with a custom message.
* **Parameterized Tests:** Use `@pytest.mark.parametrize` to reduce duplication when running the same test logic with different inputs. This is more idiomatic than the `parameterized` library.
* **Fixtures:** Use pytest fixtures (with `@pytest.fixture`) for test setup, teardown, and dependency injection. Fixtures are cleaner than class-based setup methods and can be easily shared across tests.
* **Mocking:** Use `mock.create_autospec()` with `spec_set=True` to create mocks that match the original object's interface, preventing typos and API mismatch issues. Use context managers (`with mock.patch(...)`) to manage mock lifecycles and ensure patches are stopped. Prefer injecting dependencies via fixtures over patching.
* **Asserting Mock Calls:** Use `mock.ANY` and other matchers for partial argument matching when asserting mock calls (e.g., `assert_called_once_with`).
* **Temporary Files:** Use pytest's `tmp_path` and `tmp_path_factory` fixtures for creating isolated and automatically cleaned-up temporary files/directories. These are preferred over the `tempfile` module in pytest tests.
* **Avoid Randomness:** Do not use random number generators to create inputs for unit tests. This leads to flaky, hard-to-debug tests. Instead, use deterministic, easy-to-reason-about inputs that cover specific behaviors.
* **Test Invariants:** Focus tests on the invariant behaviors of public APIs, not implementation details.
* **Test Organization:** Prefer simple test functions over class-based tests unless you need to share fixtures across multiple test methods in a class. Use descriptive test names that explain the behavior being tested.
### Error Handling
* **Re-raising Exceptions:** Use a bare `raise` to re-raise the current exception, preserving the original stack trace. Use `raise NewException from original_exception` to chain exceptions, providing context. Use `raise NewException from None` to suppress the original exception's context.
* **Exception Messages:** Always include a descriptive message when raising exceptions.
* **Converting Exceptions to Strings:** `str(e)` can be uninformative. `repr(e)` is often better. For full details including tracebacks and chained exceptions, use functions from the `traceback` module (e.g., `traceback.format_exception(e)`, `traceback.format_exc()`).
* **Terminating Programs:** Use `sys.exit()` for expected terminations. Uncaught non-`SystemExit` exceptions should signal bugs. Avoid functions that cause immediate, unclean exits like `os.abort()`.
* **Returning None:** Be consistent. If a function can return a value, all paths should return a value (use `return None` explicitly). Bare `return` is only for early exit in conceptually void functions (annotated with `-> None`).
- Please use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)
format.
- If it's not a breaking change, please add #non-breaking tag. If it's a
breaking change, please add #breaking.
+17 -202
View File
@@ -1,191 +1,5 @@
# Changelog
## [1.18.0](https://github.com/google/adk-python/compare/v1.17.0...v1.18.0) (2025-11-05)
### Features
* **[ADK Visual Agent Builder]**
* Core Features
* Visual workflow designer for agent creation
* Support for multiple agent types (LLM, Sequential, Parallel, Loop, Workflow)
* Agent tool support with nested agent tools
* Built-in and custom tool integration
* Callback management for all ADK callback types (before/after agent, model, tool)
* Assistant to help you build your agents with natural language
* Assistant proposes and writes agent configuration yaml files for you
* Save to test with chat interfaces as normal
* Build and debug at the same time in adk web!
* **[Core]**
* Add support for extracting cache-related token counts from LiteLLM usage ([4f85e86](https://github.com/google/adk-python/commit/4f85e86fc3915f0e67312a39fe22451968d4f1b1))
* Expose the Python code run by the code interpreter in the logs ([a2c6a8a](https://github.com/google/adk-python/commit/a2c6a8a85cf4f556e9dacfe46cf384d13d964208))
* Add run_debug() helper method for quick agent experimentation ([0487eea](https://github.com/google/adk-python/commit/0487eea2abcd05d7efd123962d17b8c6c9a9d975))
* Allow injecting a custom Runner into `agent_to_a2a` ([156d235](https://github.com/google/adk-python/commit/156d23547915e8f7f5c6ba55e0362f4b133c3968))
* Support MCP prompts via the McpInstructionProvider class ([88032cf](https://github.com/google/adk-python/commit/88032cf5c56bb2d81842353605f9f5ab4b2206ff))
* **[Models]**
* Add model tracking to LiteLlm and introduce a LiteLLM with fallbacks demo ([d4c63fc](https://github.com/google/adk-python/commit/d4c63fc5629e7d70ad8b8185be09243a01e3428f))
* Add ApigeeLlm as a model that lets ADK Agent developers to connect with an Apigee proxy ([87dcb3f](https://github.com/google/adk-python/commit/87dcb3f7ba344a2ba7d9edfc4817c9e792d90bfc))
* **[Integrations]**
* Add example and fix for loading and upgrading old ADK session databases ([338c3c8](https://github.com/google/adk-python/commit/338c3c89c6bce7f3406f729013cedcd78b809a56))
* Add support for specifying logging level for adk eval cli command ([b1ff85f](https://github.com/google/adk-python/commit/b1ff85fb2347e3402eedd42e3673be7093a99548))
* Propagate LiteLLM finish_reason to LlmResponse for use in callbacks ([71aa564](https://github.com/google/adk-python/commit/71aa5645f6c3d91fd0e0ddb1ed564188c6727080))
* Allow LLM request to override the model used in the generate content async method in LiteLLM ([ce8f674](https://github.com/google/adk-python/commit/ce8f674a287368439ba11be3285902671e9bc75a))
* Add api key argument to Vertex Session and Memory services for Express Mode support ([9014a84](https://github.com/google/adk-python/commit/9014a849eab9f77b82db4a7f2053fb2a96282f03))
* Added support for enums as arguments for function tools ([240ef5b](https://github.com/google/adk-python/commit/240ef5beea9389911e8c03a6039b353befc716ac))
* Implement artifact_version related methods in GcsArtifactService ([e194ebb](https://github.com/google/adk-python/commit/e194ebb33c62bc40403ea852a88f77a9511b61a4))
* **[Services]**
* Add support for Vertex AI Express Mode when deploying to Agent Engine ([d4b2a8b](https://github.com/google/adk-python/commit/d4b2a8b49f98a9991cb44ac7ec6e538b81a08664))
* Remove custom polling logic for Vertex AI Session Service since LRO polling is supported in express mode ([546c2a6](https://github.com/google/adk-python/commit/546c2a68165f54e694664d5b6b6740566301782b))
* Make VertexAiSessionService fully asynchronous ([f7e2a7a](https://github.com/google/adk-python/commit/f7e2a7a40ef248dd6fbba9669503b0828a12f0cc))
* **[Tools]**
* Add Bigquery detect_anomalies tool ([9851340](https://github.com/google/adk-python/commit/9851340ad1df86d6f5c21e8984199573f239bb2b))
* Extend Bigquery detect_anomalies tool to support future data anomaly detection ([38ea749](https://github.com/google/adk-python/commit/38ea749c9cec8e65f5e768f49fd2de79b5545571))
* Add get_job_info tool to BigQuery toolset ([6429457](https://github.com/google/adk-python/commit/64294572c1c93590aa3c221015a5cb9b440ee948))
* **[Evals]**
* Add "final_session_state" to the EvalCase data model ([2274c4f](https://github.com/google/adk-python/commit/2274c4f3040b20da3690aa03272155776ca330c1))
* Marked expected_invocation as optional field on evaluator interface ([b17c8f1](https://github.com/google/adk-python/commit/b17c8f19e5fc67180d1bdc621f84cd43e357571c))
* Adds LLM-backed user simulator ([54c4ecc](https://github.com/google/adk-python/commit/54c4ecc73381cffa51cff01c7fb8a2ac59308c53))
* **[Observability]**
* Add BigQueryLoggingPlugin for event logging to BigQuery ([b7dbfed](https://github.com/google/adk-python/commit/b7dbfed4a3d4a0165e2c6e51594d1f547bec89d3))
* **[Live]**
* Add token usage to live events for bidi streaming ([6e5c0eb](https://github.com/google/adk-python/commit/6e5c0eb6e0474f5b908eb9df20328e7da85ebed9))
### Bug Fixes
* Reduce logging spam for MCP tools without authentication ([11571c3](https://github.com/google/adk-python/commit/11571c37ab948d43cbaa3a1d82522256dfe4d467))
* Fix typo in several files ([d2888a3](https://github.com/google/adk-python/commit/d2888a3766b87df2baaaa1a67a2235b1b80f138f))
* Disable SetModelResponseTool workaround for Vertex AI Gemini 2+ models ([6a94af2](https://github.com/google/adk-python/commit/6a94af24bf3367c05a5d405b7e7b79810a1fac4e))
* Bug when callback_context_invocation_context is missing in GlobalInstructionPlugin ([f81ebdb](https://github.com/google/adk-python/commit/f81ebdb622211031945eb06c3f00ff5208d94f9b))
* Support models slash prefix in model name extraction ([8dff850](https://github.com/google/adk-python/commit/8dff85099d67623dd6f4a707fb932ea55b8aaf9b))
* Do not consider events with state delta and no content as final response ([1ee93c8](https://github.com/google/adk-python/commit/1ee93c8bcb7ccd6f33658dc76b2095dd7e58aac9))
* Parameter filtering for CrewAI functions with **kwargs ([74a3500](https://github.com/google/adk-python/commit/74a3500fc5d4b07e80f914d83a0d91face28086c))
* Do not treat FinishReason.STOP as error case for LLM responses containing candidates with empty contents ([2f72ceb](https://github.com/google/adk-python/commit/2f72ceb49b452c5a1f257bce6adb004fa5d54472))
* Fixes null check for reflect_retry plugin sample ([86f0155](https://github.com/google/adk-python/commit/86f01550bd1b52d6d160e8bc54cecc6c4fe8611c))
* Creates evalset directory on evalset create ([6c3882f](https://github.com/google/adk-python/commit/6c3882f2d66f169d393171be280b6e6218b52a7c))
* Add ADK_DISABLE_LOAD_DOTENV environment variable that disables automatic loading of .env when running ADK cli, if set to true or 1 ([15afbcd](https://github.com/google/adk-python/commit/15afbcd1587d4102a4dc5c07c0c493917df9d6ea))
* Allow tenacity 9.0.0 ([ee8acc5](https://github.com/google/adk-python/commit/ee8acc58be7421a3e8eab07b051c45f9319f80dc))
* Output file uploading to artifact service should handle both base64 encoded and raw bytes ([496f8cd](https://github.com/google/adk-python/commit/496f8cd6bb36d3ba333d7ab1e94e7796d2960300))
* Correct message part ordering in A2A history ([5eca72f](https://github.com/google/adk-python/commit/5eca72f9bfd05c7c28a3d738391138a59a31167d))
* Change instruction insertion to respect tool call/response pairs ([1e6a9da](https://github.com/google/adk-python/commit/1e6a9daa63050936ab421f1f684935927aebc63e))
* DynamicPickleType to support MySQL dialect ([fc15c9a](https://github.com/google/adk-python/commit/fc15c9a0c3c043c0a61dce625b8cd1ee121b4baf))
* Enable usage metadata in LiteLLM streaming ([f9569bb](https://github.com/google/adk-python/commit/f9569bbb1afbc7f0e8b6e68599590471fd112b9f))
* Fix issue with MCP tools throwing an error ([1a4261a](https://github.com/google/adk-python/commit/1a4261ad4b66cdeb39d39110a086bd6112b17516))
* Remove redundant `format` field from LiteLLM content objects ([489c39d](https://github.com/google/adk-python/commit/489c39db01465e38ecbc2c7f32781c349b8cddc9))
* Update the contribution analysis tool to use original write mode ([54db3d4](https://github.com/google/adk-python/commit/54db3d4434e0706b83a589fa2499d11d439a6e4e))
* Fix agent evaluations detailed output rows wrapping issue([4284c61](https://github.com/google/adk-python/commit/4284c619010b8246c1ecaa011f14b6cc9de512dd))
* Update dependency version constraints to be based on PyPI versions([0b1784e](https://github.com/google/adk-python/commit/0b1784e0e493a0e2df1edfe37e5ed5f4247e7d9d))
### Improvements
* Add Community Repo section to README ([432d30a](https://github.com/google/adk-python/commit/432d30af486329aa83f89c5d5752749a85c0b843))
* Undo adding MCP tools output schema to FunctionDeclaration ([92a7d19](https://github.com/google/adk-python/commit/92a7d1957367d498de773761edd142d8c108d751))
* Refactor ADK README for clarity and consistency ([b0017ae](https://github.com/google/adk-python/commit/b0017aed4472c73c3b07e71f1d65ae97a5293547))
* Add support for reversed proxy in adk web ([a0df75b](https://github.com/google/adk-python/commit/a0df75b6fa35d837086decb8802dbf1c0a6637ad))
* Avoid rendering empty columns as part of detailed results rendering of eval results ([5cb35db](https://github.com/google/adk-python/commit/5cb35db921bf86b5ad0012046bd19fa7cc1e6abb))
* Clear the behavior of disallow_transfer_to_parent ([48ddd07](https://github.com/google/adk-python/commit/48ddd078941f9240b10f052b6de171c310bc2bc6))
* Disable the scheduled execution for issue triage workflow ([a02f321](https://github.com/google/adk-python/commit/a02f321f1bdb8be9ad1873db804e0e8393268dc3))
* Include delimiter when matching events from parent nodes in content processor ([b8a2b6c](https://github.com/google/adk-python/commit/b8a2b6c57080ae29d7a02df7d9fcc2f961d422d2))
* Improve Tau-bench ADK colab stability ([04dbc42](https://github.com/google/adk-python/commit/04dbc42e50ce40ef3924d1c259e425215e12c2e7))
* Implement ADK-based agent factory for Tau-bench ([c0c67c8](https://github.com/google/adk-python/commit/c0c67c8698d70ddb9ed958416661f232ef9a5ed8))
* Add util to run ADK LLM Agent with simulation environment ([87f415a](https://github.com/google/adk-python/commit/87f415a7c36a1f3b6ab84d1fe939726c6ef7f34e))
* Demonstrate CodeExecutor customization for environment setup ([8eeff35](https://github.com/google/adk-python/commit/8eeff35b35d7e1538a5c9662cc8369f6ff7962f8))
* Add sample agent for VertexAiCodeExecutor ([edfe553](https://github.com/google/adk-python/commit/edfe5539421d196ca4da14d3a37fac7b598f8c8d))
* Adds a new sample agent that demonstrates how to integrate PostgreSQL databases using the Model Context Protocol (MCP) ([45a2168](https://github.com/google/adk-python/commit/45a2168e0e6773e595ecfb825d7e4ab0a38c3a38))
* Add example for using ADK with Fast MCP sampling ([d3796f9](https://github.com/google/adk-python/commit/d3796f9b33251d28d05e6701f11e80f02a2a49e1))
* Refactor gepa sample code and clean-up user demo colab([63353b2](https://github.com/google/adk-python/commit/63353b2b74e23e97385892415c5a3f2a59c3504f))
## [1.17.0](https://github.com/google/adk-python/compare/v1.16.0...v1.17.0) (2025-10-22)
### Features
* **[Core]**
* Add a service registry to provide a generic way to register custom service implementations to be used in FastAPI server. See [short instruction](https://github.com/google/adk-python/discussions/3175#discussioncomment-14745120). ([391628f](https://github.com/google/adk-python/commit/391628fcdc7b950c6835f64ae3ccab197163c990))
* Add the ability to rewind a session to before a previous invocation ([9dce06f](https://github.com/google/adk-python/commit/9dce06f9b00259ec42241df4f6638955e783a9d1))
* Support resuming a parallel agent with multiple branches paused on tool confirmation requests ([9939e0b](https://github.com/google/adk-python/commit/9939e0b087094038b90d86c2fd35c26dd63f1157))
* Support content union as static instruction ([cc24d61](https://github.com/google/adk-python/commit/cc24d616f80c0eba2b09239b621cf3d176f144ea))
* **[Evals]**
* ADK cli allows developers to create an eval set and add an eval case ([ae139bb](https://github.com/google/adk-python/commit/ae139bb461c2e7c6be154b04f3f2c80919808d31))
* **[Integrations]**
* Allow custom request and event converters in A2aAgentExecutor ([a17f3b2](https://github.com/google/adk-python/commit/a17f3b2e6d2d48c433b42e27763f3d6df80243ca))
* **[Observability]**
* Env variable for disabling llm_request and llm_response in spans ([e50f05a](https://github.com/google/adk-python/commit/e50f05a9fc94834796876f7f112f344f788f202e))
* **[Services]**
* Allow passing extra kwargs to create_session of VertexAiSessionService ([6a5eac0](https://github.com/google/adk-python/commit/6a5eac0bdc9adc6907a28f65a3d4d7234e863049))
* Implement new methods in in-memory artifact service to support custom metadata, artifact versions, etc. ([5a543c0](https://github.com/google/adk-python/commit/5a543c00df2f7a66018df8a67efcf4ce44d4e0e4))
* Add create_time and mime_type to ArtifactVersion ([2c7a342](https://github.com/google/adk-python/commit/2c7a34259395b1294319118d0f3d1b3b867b44d6))
* Support returning all sessions when user id is none ([141318f](https://github.com/google/adk-python/commit/141318f77554ae4eb5a360bea524e98eff4a086c))
* **[Tools]**
* Support additional headers for Google API toolset ([ed37e34](https://github.com/google/adk-python/commit/ed37e343f0c997d3ee5dc98888c5e0dbd7f2a2b6))
* Introduces a new AgentEngineSandboxCodeExecutor class that supports executing agent-generated code using the Vertex AI Code Execution Sandbox API ([ee39a89](https://github.com/google/adk-python/commit/ee39a891106316b790621795b5cc529e89815a98))
* Support dynamic per-request headers in MCPToolset ([6dcbb5a](https://github.com/google/adk-python/commit/6dcbb5aca642290112a7c81162b455526c15cd14))
* Add `bypass_multi_tools_limit` option to GoogleSearchTool and VertexAiSearchTool ([9a6b850](https://github.com/google/adk-python/commit/9a6b8507f06d8367488aac653efecf665619516c), [6da7274](https://github.com/google/adk-python/commit/6da727485898137948d72906d86d78b6db6331ac))
* Extend `ReflectAndRetryToolPlugin` to support hallucinating function calls ([f51380f](https://github.com/google/adk-python/commit/f51380f9ea4534591eda76bef27407c0aa7c3fae))
* Add require_confirmation param for MCP tool/toolset ([78e74b5](https://github.com/google/adk-python/commit/78e74b5bf2d895d72025a44dbcf589f543514a50))
* **[UI]**
* Granular per agent speech configuration ([409df13](https://github.com/google/adk-python/commit/409df1378f36b436139aa909fc90a9e9a0776b3a))
### Bug Fixes
* Returns dict as result from McpTool to comply with BaseTool expectations ([4df9263](https://github.com/google/adk-python/commit/4df926388b6e9ebcf517fbacf2f5532fd73b0f71))
* Fixes the identity prompt to be one line ([7d5c6b9](https://github.com/google/adk-python/commit/7d5c6b9acf0721dd230f08df919c7409eed2b7d0))
* Fix the broken langchain importing caused their 1.0.0 release ([c850da3](https://github.com/google/adk-python/commit/c850da3a07ec1441037ced1b654d8aacacd277ab))
* Fix BuiltInCodeExecutor to support visualizations ([ce3418a](https://github.com/google/adk-python/commit/ce3418a69de56570847d45f56ffe7139ab0a47aa))
* Relax runner app-name enforcement and improve agent origin inference ([dc4975d](https://github.com/google/adk-python/commit/dc4975dea9fb79ad887460659f8f397a537ee38f))
* Improve error message when adk web is run in wrong directory ([4a842c5](https://github.com/google/adk-python/commit/4a842c5a1334c3ee01406f796651299589fe12ab))
* Handle App objects in eval and graph endpoints ([0b73a69](https://github.com/google/adk-python/commit/0b73a6937bd84a41f79a9ada3fc782dca1d6fb11))
* Exclude `additionalProperties` from Gemini schemas ([307896a](https://github.com/google/adk-python/commit/307896aeceeb97efed352bc0217bae10423e5da6))
* Overall eval status should be NOT_EVALUATED if no invocations were evaluated ([9fbed0b](https://github.com/google/adk-python/commit/9fbed0b15afb94ec8c0c7ab60221bbc97e481b06))
* Create context cache only when prefix matches with previous request ([9e0b1fb](https://github.com/google/adk-python/commit/9e0b1fb62b06de7ecb79bf77d54a999167d001e1))
* Handle `App` instances returned by `agent_loader.load_agent` ([847df16](https://github.com/google/adk-python/commit/847df1638cbf1686aa43e8e094121d4e23e40245))
* Add support for file URIs in LiteLLM content conversion ([85ed500](https://github.com/google/adk-python/commit/85ed500871ff55c74d16e809ddae0d4db66cbc3a))
* Only exclude scores that are None ([998264a](https://github.com/google/adk-python/commit/998264a5b1b98ac660fcc1359fb2d25c84fa0d87))
* Better handling the A2A streaming tasks ([bddc70b](https://github.com/google/adk-python/commit/bddc70b5d004ba5304fe05bcbf6e08210f0e6131))
* Correctly populate context_id in remote_a2a_agent library ([2158b3c](https://github.com/google/adk-python/commit/2158b3c91531e9125761f211f125d9ab41a55e10))
* Remove unnecessary Aclosing ([2f4f561](https://github.com/google/adk-python/commit/2f4f5611bdb30bd5eb2fdb3a70f43d748371392f))
* Fix pickle data was truncated error in database session using MySql ([36c96ec](https://github.com/google/adk-python/commit/36c96ec5b356109b7c874c85d8bb24f0bf6c050d))
### Improvements
* Improve hint message in agent loader ([fe1fc75](https://github.com/google/adk-python/commit/fe1fc75c15a7983829bbe0b023f4b612b1e5c018))
* Fixes MCPToolset --> McpToolset in various places ([d4dc645](https://github.com/google/adk-python/commit/d4dc6454783f747120d407d0dc2cb78f53598d83))
* Add span for context caching handling and new cache creation ([a2d9f13](https://github.com/google/adk-python/commit/a2d9f13fa1d31e00ba9493fba321ca151cdd9366))
* Checks gemini version for `2 and above` for gemini-builtin tools ([0df6759](https://github.com/google/adk-python/commit/0df67599c0eb54a9a5df51af06483b40058953bf))
* Refactor and fix state management in the session service ([8b3ed05](https://github.com/google/adk-python/commit/8b3ed059c24903e8aca0a09d9d503b48af7df850))
* Update agent builder instructions and remove run command details ([89344da](https://github.com/google/adk-python/commit/89344da81364d921f778c8bbea93e1df6ad1097e))
* Clarify how to use adk built-in tool in instruction ([d22b8bf](https://github.com/google/adk-python/commit/d22b8bf8907e723f618dfd18e90dd0a5dbc9518c))
* Delegate the agent state reset logic to LoopAgent ([bb1ea74](https://github.com/google/adk-python/commit/bb1ea74924127d65d763a45b869da3d4ff4d5c5a))
* Adjust the instruction about default model ([214986e](https://github.com/google/adk-python/commit/214986ebeb53b2ef34c8aa37cd6403106de82c1b))
* Migrate invocation_context to callback_context ([e2072af](https://github.com/google/adk-python/commit/e2072af69f40474431b6749b7b9dc22fbcbc7730))
* Correct the callback signatures ([fa84bcb](https://github.com/google/adk-python/commit/fa84bcb5756773eadff486b99c9bd416b4faa9c6))
* Set default for `bypass_multi_tools_limit` to False for GoogleSearchTool and VertexAiSearchTool ([6da7274](https://github.com/google/adk-python/commit/6da727485898137948d72906d86d78b6db6331ac))
* Add more clear instruction to the doc updater agent about one PR for each recommended change ([b21d0a5](https://github.com/google/adk-python/commit/b21d0a50d610407be2f10b73a91274840ffdfe18))
* Add a guideline to avoid content deletion ([16b030b](https://github.com/google/adk-python/commit/16b030b2b25a9b0b489e47b4b148fc4d39aeffcb))
* Add a sample agent for the `ReflectAndRetryToolPlugin` ([9b8a4aa](https://github.com/google/adk-python/commit/9b8a4aad6fe65ef37885e5c3368d2799a2666534))
* Improve error message when adk web is run in wrong directory ([4a842c5](https://github.com/google/adk-python/commit/4a842c5a1334c3ee01406f796651299589fe12ab))
* Add span for context caching handling and new cache creation ([a2d9f13](https://github.com/google/adk-python/commit/a2d9f13fa1d31e00ba9493fba321ca151cdd9366))
* Disable the scheduled execution for issue triage workflow ([bae2102](https://github.com/google/adk-python/commit/bae21027d9bd7f811bed638ecce692262cb33fe5))
* Correct the callback signatures ([fa84bcb](https://github.com/google/adk-python/commit/fa84bcb5756773eadff486b99c9bd416b4faa9c6))
### Documentation
* Format README.md for samples ([0bdba30](https://github.com/google/adk-python/commit/0bdba3026345872fb907aedd1ed75e4135e58a30))
* Bump models in llms and llms-full to Gemini 2.5 ([ce46386](https://github.com/google/adk-python/commit/ce4638651f376fb6579993d8468ae57198134729))
* Update gemini_llm_connection.py - typo spelling correction ([e6e2767](https://github.com/google/adk-python/commit/e6e2767c3901a14187f5527540f318317dd6c8e3))
* Announce the first ADK Community Call in the README ([731bb90](https://github.com/google/adk-python/commit/731bb9078d01359ae770719a8f5c003680ed9f3e))
## [1.16.0](https://github.com/google/adk-python/compare/v1.15.1...v1.16.0) (2025-10-08)
### Features
@@ -204,7 +18,7 @@
* Add `dry_run` functionality to BigQuery `execute_sql` tool ([960eda3](https://github.com/google/adk-python/commit/960eda3d1f2f46dc93a365eb3de03dc3483fe9bb))
* Add BigQuery analyze_contribution tool ([4bb089d](https://github.com/google/adk-python/commit/4bb089d386d4e8133e9aadbba5c42d31ff281cf6))
* Spanner ADK toolset supports customizable template SQL and parameterized SQL ([da62700](https://github.com/google/adk-python/commit/da62700d739cb505149554962a8bcfb30f9428cc))
* Support OAuth2 client credentials grant type ([5c6cdcd](https://github.com/google/adk-python/commit/5c6cdcd197a6780fc86d9183fa208f78c8a975d9))
* Support Oauth2 client credentials grant type ([5c6cdcd](https://github.com/google/adk-python/commit/5c6cdcd197a6780fc86d9183fa208f78c8a975d9))
* Add `ReflectRetryToolPlugin` to reflect from errors and retry with different arguments when tool errors ([e55b894](https://github.com/google/adk-python/commit/e55b8946d6a2e01aaf018d6a79d11d13c5286152))
* Support using `VertexAiSearchTool` built-in tool with other tools in the same agent ([4485379](https://github.com/google/adk-python/commit/4485379a049a5c84583a43c85d444ea1f1ba6f12))
* Support using google search built-in tool with other tools in the same agent ([d3148da](https://github.com/google/adk-python/commit/d3148dacc97f0a9a39b6d7a9640f7b7b0d6f9a6c))
@@ -285,7 +99,7 @@
* Add endpoint to generate memory from session ([2595824](https://github.com/google/adk-python/commit/25958242db890b4d2aac8612f7f7cfbb561727fa))
* **[Tools]**
* Add Google Maps Grounding Tool to ADK ([6b49391](https://github.com/google/adk-python/commit/6b493915469ecb42068e24818ab547b0856e4709))
* **MCP:** Initialize tool_name_prefix in MCPToolset ([86dea5b](https://github.com/google/adk-python/commit/86dea5b53ac305367283b7e353b60d0f4515be3b))
* **MCP:** Initialize tool_name_prefix in MCPToolse ([86dea5b](https://github.com/google/adk-python/commit/86dea5b53ac305367283b7e353b60d0f4515be3b))
* **[Evals]**
* Data model for storing App Details and data model for steps ([01923a9](https://github.com/google/adk-python/commit/01923a9227895906ca8ae32712d65b178e2cd7d5))
* Adds Rubric based final response evaluator ([5a485b0](https://github.com/google/adk-python/commit/5a485b01cd64cb49735e13ebd5e7fa3da02cd85f))
@@ -352,7 +166,7 @@
* Fix discussion answering github action workflow to escape the quote in the discussion content JSON [43c9681](https://github.com/google/adk-python/commit/43c96811da891a5b0c9cf1be525665e65f346a13)
* Send full MIME types for image/video/pdf in get_content [e45c3be](https://github.com/google/adk-python/commit/e45c3be23895b5ec68908ad9ee19bd622dcbd003)
* Fix flaky unit tests: tests/unittests/flows/llm_flows/test_functions_simple.py [b92b288](https://github.com/google/adk-python/commit/b92b288c978a9b3d1a76c8bcb96cc8f439ce610b)
* Make UT of a2a consistent about how tests should be skipped when python version < 3.10 [98b0426](https://github.com/google/adk-python/commit/98b0426cd2dc5e28014ead22b22dbf50d42d0a9a)
* Make UT of a2a consistent about how tests should be skipped when python verison < 3.10 [98b0426](https://github.com/google/adk-python/commit/98b0426cd2dc5e28014ead22b22dbf50d42d0a9a)
### Improvements
@@ -443,7 +257,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
* Using base event's invocation id when merge multiple function response event ([279e4fe](https://github.com/google/adk-python/commit/279e4fedd0b1c0d1499c0f9a4454357af7da490e))
* Avoid crash when there is no candidates_token_count, which is Optional ([22f34e9](https://github.com/google/adk-python/commit/22f34e9d2c552fbcfa15a672ef6ff0c36fa32619))
* Fix the packaging version comparison logic in adk cli ([a2b7909](https://github.com/google/adk-python/commit/a2b7909fc36e7786a721f28e2bf75a1e86ad230d))
* Add Spanner admin scope to Spanner tool default OAuth scopes ([b66054d](https://github.com/google/adk-python/commit/b66054dd0d8c5b3d6f6ad58ac1fbd8128d1da614))
* Add Spanner admin scope to Spanner tool default Oauth scopes ([b66054d](https://github.com/google/adk-python/commit/b66054dd0d8c5b3d6f6ad58ac1fbd8128d1da614))
* Fixes SequentialAgent.config_type type hint ([8a9a271](https://github.com/google/adk-python/commit/8a9a271141678996c9b84b8c55d4b539d011391c))
* Fixes the host in the ansi bracket of adk web ([cd357bf](https://github.com/google/adk-python/commit/cd357bf5aeb01f1a6ae2a72349a73700ca9f1ed2))
* Add spanner tool name prefix ([a27927d](https://github.com/google/adk-python/commit/a27927dc8197c391c80acb8b2c23d610fba2f887))
@@ -455,7 +269,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
* Update `openai` dependency version, based on correct OPENAI release ([bb8ebd1](https://github.com/google/adk-python/commit/bb8ebd15f90768b518cd0e21a59b269e30d6d944))
* Add the missing license header for core_callback_config init file ([f8fd6a4](https://github.com/google/adk-python/commit/f8fd6a4f09ab520b8ecdbd8f9fe48228dbff7ebe))
* Creates yaml_utils.py in utils to allow adk dump yaml in the same style ([1fd58cb](https://github.com/google/adk-python/commit/1fd58cb3633992cd88fa7e09ca6eda0f9b34236f))
* Return explicit None type for DELETE endpoints ([f03f167](https://github.com/google/adk-python/commit/f03f1677790c0a9e59b6ba6f46010d0b7b64be50))
* Return explict None type for DELETE endpoints ([f03f167](https://github.com/google/adk-python/commit/f03f1677790c0a9e59b6ba6f46010d0b7b64be50))
* Add _config suffix to all yaml-based agent examples ([43f302c](https://github.com/google/adk-python/commit/43f302ce1ab53077ee8f1486d5294540678921e6))
* Rename run related method and request to align with the conventions ([ecaa7b4](https://github.com/google/adk-python/commit/ecaa7b4c9847b478c7cdc37185b1525f733bb403))
* Update models in samples/ folder to be gemini 2.0+ ([6c217ba](https://github.com/google/adk-python/commit/6c217bad828edf62b41ec06b168f8a6cb7ece2ed))
@@ -480,7 +294,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
### Bug Fixes
* A2A RPC URL got overridden by host and port param of adk api server ([52284b1](https://github.com/google/adk-python/commit/52284b1bae561e0d6c93c9d3240a09f210551b97))
* A2A RPC URL got overriden by host and port param of adk api server ([52284b1](https://github.com/google/adk-python/commit/52284b1bae561e0d6c93c9d3240a09f210551b97))
* Aclose all async generators to fix OTel tracing context ([a30c63c](https://github.com/google/adk-python/commit/a30c63c5933a770b960b08a6e2f8bf13eece8a22))
* Use PreciseTimestamp for create and update time in database session service to improve precision ([585141e](https://github.com/google/adk-python/commit/585141e0b7dda20abb024c7164073862c8eea7ae))
* Ignore AsyncGenerator return types in function declarations ([e2518dc](https://github.com/google/adk-python/commit/e2518dc371fe77d7b30328d8d6f5f864176edeac))
@@ -508,7 +322,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
* Group FastAPI endpoints with tags ([c323de5](https://github.com/google/adk-python/commit/c323de5c692223e55372c3797e62d4752835774d))
* Allow implementations to skip defining a close method on Toolset ([944e39e](https://github.com/google/adk-python/commit/944e39ec2a7c9ad7f20c08fd66bf544de94a23d7))
* Add sample agent to test support of output_schema and tools at the same time for gemini model ([f2005a2](https://github.com/google/adk-python/commit/f2005a20267e1ee8581cb79c37aa55dc8e18c0ea))
* Add GitHub workflow config for uploading ADK docs to knowledge store ([5900273](https://github.com/google/adk-python/commit/59002734559d49a46940db9822b9c5f490220a8c))
* Add Github workflow config for uploading ADK docs to knowledge store ([5900273](https://github.com/google/adk-python/commit/59002734559d49a46940db9822b9c5f490220a8c))
* Update ADK Answering agent to reference doc site instead of adk-docs repo ([b5a8bad](https://github.com/google/adk-python/commit/b5a8bad170e271b475385dac440c7983ed207df8))
### Documentation
@@ -540,7 +354,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
### Improvements
* Add GitHub workflow config for the ADK Answering agent ([8dc0c94](https://github.com/google/adk-python/commit/8dc0c949afb9024738ff7ac1b2c19282175c3200))
* Add Github workflow config for the ADK Answering agent ([8dc0c94](https://github.com/google/adk-python/commit/8dc0c949afb9024738ff7ac1b2c19282175c3200))
* Import AGENT_CARD_WELL_KNOWN_PATH from adk instead of from a2a directly ([37dae9b](https://github.com/google/adk-python/commit/37dae9b631db5060770b66fce0e25cf0ffb56948))
* Make `LlmRequest.LiveConnectConfig` field default to a factory ([74589a1](https://github.com/google/adk-python/commit/74589a1db7df65e319d1ad2f0676ee0cf5d6ec1d))
* Update the prompt to make the ADK Answering Agent more objective ([2833030](https://github.com/google/adk-python/commit/283303032a174d51b8d72f14df83c794d66cb605))
@@ -599,13 +413,14 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
### Features
* [Core]Add agent card builder ([18f5bea](https://github.com/google/adk-python/commit/18f5bea411b3b76474ff31bfb2f62742825b45e5))
* [Core]Add a to_a2a util to convert adk agent to A2A ASGI application ([a77d689](https://github.com/google/adk-python/commit/a77d68964a1c6b7659d6117d57fa59e43399e0c2))
* [Core]Add an to_a2a util to convert adk agent to A2A ASGI application ([a77d689](https://github.com/google/adk-python/commit/a77d68964a1c6b7659d6117d57fa59e43399e0c2))
* [Core]Add camel case converter for agents ([0e173d7](https://github.com/google/adk-python/commit/0e173d736334f8c6c171b3144ac6ee5b7125c846))
* [Evals]Use LocalEvalService to run all evals in cli and web ([d1f182e](https://github.com/google/adk-python/commit/d1f182e8e68c4a5a4141592f3f6d2ceeada78887))
* [Evals]Enable FinalResponseMatchV2 metric as an experiment ([36e45cd](https://github.com/google/adk-python/commit/36e45cdab3bbfb653eee3f9ed875b59bcd525ea1))
* [Models]Add support for `model-optimizer-*` family of models in vertex ([ffe2bdb](https://github.com/google/adk-python/commit/ffe2bdbe4c2ea86cc7924eb36e8e3bb5528c0016))
* [Services]Added a sample for History Management ([67284fc](https://github.com/google/adk-python/commit/67284fc46667b8c2946762bc9234a8453d48a43c))
* [Services]Support passing fully qualified agent engine resource name when constructing session service and memory service ([2e77804](https://github.com/google/adk-python/commit/2e778049d0a675e458f4e35fe4104ca1298dbfcf))
* [Services]Support passing fully qualified agent engine resource name when constructing session service and memory service ([2e77804](https://github.com/google/adk-python/commit/2e778049d0a675e458f4e
35fe4104ca1298dbfcf))
* [Tools]Add ComputerUseToolset ([083dcb4](https://github.com/google/adk-python/commit/083dcb44650eb0e6b70219ede731f2fa78ea7d28))
* [Tools]Allow toolset to process llm_request before tools returned by it ([3643b4a](https://github.com/google/adk-python/commit/3643b4ae196fd9e38e52d5dc9d1cd43ea0733d36))
* [Tools]Support input/output schema by fully-qualified code reference ([dfee06a](https://github.com/google/adk-python/commit/dfee06ac067ea909251d6fb016f8331065d430e9))
@@ -718,7 +533,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
### Documentation
* Update the a2a example link in README.md [d0fdfb8](https://github.com/google/adk-python/commit/d0fdfb8c8e2e32801999c81de8d8ed0be3f88e76)
* Update the a2a exmaple link in README.md [d0fdfb8](https://github.com/google/adk-python/commit/d0fdfb8c8e2e32801999c81de8d8ed0be3f88e76)
* Adds AGENTS.md to provide relevant project context for the Gemini CLI [37108be](https://github.com/google/adk-python/commit/37108be8557e011f321de76683835448213f8515)
* Update CONTRIBUTING.md [ffa9b36](https://github.com/google/adk-python/commit/ffa9b361db615ae365ba62c09a8f4226fb761551)
* Add adk project overview and architecture [28d0ea8](https://github.com/google/adk-python/commit/28d0ea876f2f8de952f1eccbc788e98e39f50cf5)
@@ -913,7 +728,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
* Fix typos in README for sample bigquery_agent and oauth_calendar_agent ([9bdd813](https://github.com/google/adk-python/commit/9bdd813be15935af5c5d2a6982a2391a640cab23))
* Make tool_call one span for telemetry and renamed to execute_tool ([999a7fe](https://github.com/google/adk-python/commit/999a7fe69d511b1401b295d23ab3c2f40bccdc6f))
* Use media type in chat window. Remove isArtifactImage and isArtifactAudio reference ([1452dac](https://github.com/google/adk-python/commit/1452dacfeb6b9970284e1ddeee6c4f3cb56781f8))
* Set output_schema correctly for LiteLlm ([6157db7](https://github.com/google/adk-python/commit/6157db77f2fba4a44d075b51c83bff844027a147))
* Set output_schema correctly for LiteLllm ([6157db7](https://github.com/google/adk-python/commit/6157db77f2fba4a44d075b51c83bff844027a147))
* Update pending event dialog style ([1db601c](https://github.com/google/adk-python/commit/1db601c4bd90467b97a2f26fe9d90d665eb3c740))
* Remove the gap between event holder and image ([63822c3](https://github.com/google/adk-python/commit/63822c3fa8b0bdce2527bd0d909c038e2b66dd98))
@@ -941,7 +756,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
## 1.1.1
### Features
* Add [BigQuery first-party tools](https://github.com/google/adk-python/commit/d6c6bb4b2489a8b7a4713e4747c30d6df0c07961).
* Add BigQuery first-party tools. See [here](https://github.com/google/adk-python/commit/d6c6bb4b2489a8b7a4713e4747c30d6df0c07961) for more details.
## 1.1.0
@@ -1077,7 +892,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
* Fix google search reading undefined for `renderedContent`.
### Miscellaneous Chores
* Docstring improvements, typo fixings, github action to enforce code styles on formatting and imports, etc.
* Docstring improvements, typo fixings, github action to enfore code styles on formatting and imports, etc.
## 0.3.0
@@ -1116,7 +931,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
### âš  BREAKING CHANGES
* Fix typo in method name in `Event`: has_trailing_code_execution_result --> has_trailing_code_execution_result.
* Fix typo in method name in `Event`: has_trailing_code_exeuction_result --> has_trailing_code_execution_result.
### Features
@@ -1146,7 +961,7 @@ with Bigtable for building AI Agent applications(experimental feature) ([a953807
### Miscellaneous Chores
* Adds unit tests in GitHub action.
* Adds unit tests in Github action.
* Improves test coverage.
* Various typo fixes.
+4 -6
View File
@@ -57,9 +57,7 @@ information on using pull requests.
### Requirement for PRs
- All PRs, other than small documentation or typo fixes, should have a Issue
associated. If a relevant issue doesn't exist, please create one first or
you may instead describe the bug or feature directly within the PR
description, following the structure of our issue templates.
associated. If not, please create one.
- Small, focused PRs. Keep changes minimal—one concern per PR.
- For bug fixes or features, please provide logs or screenshot after the fix
is applied to help reviewers better understand the fix.
@@ -145,7 +143,7 @@ part before or alongside your code PR.
3. **Create and activate a virtual environment:**
**NOTE**: ADK supports Python 3.10+. Python 3.11 and above is strongly
**NOTE**: ADK supports Python 3.9+. Python 3.11 and above is strongly
recommended.
Create a workspace venv using uv.
@@ -234,6 +232,6 @@ has resources that is helpful for contributors.
## Vibe Coding
If you want to contribute by leveraging vibe coding, the AGENTS.md
If you want to contribute by leveraging viber coding, the AGENTS.md
(https://github.com/google/adk-python/tree/main/AGENTS.md) could be used as
context to your LLM.
context to your LLM.
+44 -29
View File
@@ -11,38 +11,63 @@
<img src="https://raw.githubusercontent.com/google/adk-python/main/assets/agent-development-kit.png" width="256"/>
</h2>
<h3 align="center">
An open-source, code-first Python framework for building, evaluating, and deploying sophisticated AI agents with flexibility and control.
An open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.
</h3>
<h3 align="center">
Important Links:
<a href="https://google.github.io/adk-docs/">Docs</a>,
<a href="https://github.com/google/adk-samples">Samples</a>,
<a href="https://github.com/google/adk-java">Java ADK</a>,
<a href="https://github.com/google/adk-go">Go ADK</a> &
<a href="https://github.com/google/adk-java">Java ADK</a> &
<a href="https://github.com/google/adk-web">ADK Web</a>.
</h3>
</html>
Agent Development Kit (ADK) is a flexible and modular framework that applies
software development principles to AI agent creation. It is designed to
simplify building, deploying, and orchestrating agent workflows, from simple
tasks to complex systems. While optimized for Gemini, ADK is model-agnostic,
deployment-agnostic, and compatible with other frameworks.
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.
---
## 🔥 ADK's very first community call on Oct 15
Join our ADK Community Call! Our first virtual community call is on Oct 15!
Meet our team, and talk with us about our roadmap and how to contribute.
First Call Details:
Topic: ADK Roadmap
Date: October 15, 2025
Time: 9:30-10:30am PST
Meeting link:
[Join the call](http://meet.google.com/gjm-gfim-ctz)
Add to your calendar
[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), [ADK Community Call RSVP](https://google.qualtrics.com/jfe/form/SV_3K0RJZ64H1BexqS)
Agenda:
[Julia] ADK Roadmap
[ Bo & Hangfei] Eng Deep Dive: Context Caching
[Kris] How to Contribute
[Shubham] Upcoming Events
---
## 🔥 What's new
- **Custom Service Registration**: Add a service registry to provide a generic way to register custom service implementations to be used in FastAPI server. See [short instruction](https://github.com/google/adk-python/discussions/3175#discussioncomment-14745120). ([391628f](https://github.com/google/adk-python/commit/391628fcdc7b950c6835f64ae3ccab197163c990))
- **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).
- **Rewind**: Add the ability to rewind a session to before a previous invocation ([9dce06f](https://github.com/google/adk-python/commit/9dce06f9b00259ec42241df4f6638955e783a9d1)).
- **Resumability**: Support pause and resume an invocation in ADK.
- **New CodeExecutor**: Introduces a new AgentEngineSandboxCodeExecutor class that supports executing agent-generated code using the Vertex AI Code Execution Sandbox API ([ee39a89](https://github.com/google/adk-python/commit/ee39a891106316b790621795b5cc529e89815a98))
- **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.
- **Search tool**: Support using Google built-in search and built-in `VertexAiSearchTool` with other tools in the same agent.
## ✨ Key Features
- **Rich Tool Ecosystem**: Utilize pre-built tools, custom functions,
OpenAPI specs, MCP tools or integrate existing tools to give agents diverse
OpenAPI specs, or integrate existing tools to give agents diverse
capabilities, all for tight integration with the Google ecosystem.
- **Code-First Development**: Define agent logic, tools, and orchestration
@@ -59,6 +84,13 @@ deployment-agnostic, and compatible with other frameworks.
- **Deploy Anywhere**: Easily containerize and deploy agents on Cloud Run or
scale seamlessly with Vertex AI Agent Engine.
## 🤖 Agent2Agent (A2A) Protocol and ADK Integration
For remote agent-to-agent communication, ADK integrates with the
[A2A protocol](https://github.com/google-a2a/A2A/).
See this [example](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents)
for how they can work together.
## 🚀 Installation
### Stable Release (Recommended)
@@ -82,13 +114,6 @@ pip install git+https://github.com/google/adk-python.git@main
Note: The development version is built directly from the latest code commits. While it includes the newest fixes and features, it may also contain experimental changes or bugs not present in the stable release. Use it primarily for testing upcoming changes or accessing critical fixes before they are officially released.
## 🤖 Agent2Agent (A2A) Protocol and ADK Integration
For remote agent-to-agent communication, ADK integrates with the
[A2A protocol](https://github.com/google-a2a/A2A/).
See this [example](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents)
for how they can work together.
## 📚 Documentation
Explore the full documentation for detailed guides on building, evaluating, and
@@ -156,20 +181,10 @@ We welcome contributions from the community! Whether it's bug reports, feature r
- [General contribution guideline and flow](https://google.github.io/adk-docs/contributing-guide/).
- Then if you want to contribute code, please read [Code Contributing Guidelines](./CONTRIBUTING.md) to get started.
## Community Repo
We have [adk-python-community repo](https://github.com/google/adk-python-community)that is home to a growing ecosystem of community-contributed tools, third-party
service integrations, and deployment scripts that extend the core capabilities
of the ADK.
## Vibe Coding
If you are to develop agent via vibe coding the [llms.txt](./llms.txt) and the [llms-full.txt](./llms-full.txt) can be used as context to LLM. While the former one is a summarized one and the later one has the full information in case your LLM has big enough context window.
## Community Events
- [Completed] ADK's 1st community meeting on Wednesday, October 15, 2025. Remember to [join our group](https://groups.google.com/g/adk-community) to get access to the [recording](https://drive.google.com/file/d/1rpXDq5NSH8-MyMeYI6_5pZ3Lhn0X9BQf/view), and [deck](https://docs.google.com/presentation/d/1_b8LG4xaiadbUUDzyNiapSFyxanc9ZgFdw7JQ6zmZ9Q/edit?slide=id.g384e60cdaca_0_658&resourcekey=0-tjFFv0VBQhpXBPCkZr0NOg#slide=id.g384e60cdaca_0_658).
## đź“„ License
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.
@@ -46,7 +46,7 @@ root_agent = Agent(
Use the provided tools to conduct various operations on users' data in Google BigQuery.
Scenario 1:
The user wants to query their bigquery datasets
The user wants to query their biguqery datasets
Use bigquery_datasets_list to query user's datasets
Scenario 2:
@@ -99,7 +99,7 @@ Agent: âś… Great news! Your reimbursement has been approved by the manager. Proc
The human-in-the-loop process follows this pattern:
1. **Initial Call**: Root agent delegates approval request to remote approval agent for amounts >$100
2. **Pending Response**: Remote approval agent returns immediate response with `status: "pending"` and ticket ID and surface the approval request to root agent
2. **Pending Response**: Remote approval agent returns immediate response with `status: "pending"` and ticket ID and serface the approval request to root agent
3. **Agent Acknowledgment**: Root agent informs user about pending approval status
4. **Human Interaction**: Human manager interacts with root agent to review and approve/reject the request
5. **Updated Response**: Root agent receives updated tool response with approval decision and send it to remote agent
@@ -15,8 +15,6 @@
"""Agent factory for creating Agent Builder Assistant with embedded schema."""
from pathlib import Path
import textwrap
from typing import Any
from typing import Callable
from typing import Optional
from typing import Union
@@ -28,6 +26,7 @@ from google.adk.tools import AgentTool
from google.adk.tools import FunctionTool
from google.genai import types
from .sub_agents.adk_knowledge_agent import create_adk_knowledge_agent
from .sub_agents.google_search_agent import create_google_search_agent
from .sub_agents.url_context_agent import create_url_context_agent
from .tools.cleanup_unused_files import cleanup_unused_files
@@ -35,7 +34,6 @@ from .tools.delete_files import delete_files
from .tools.explore_project import explore_project
from .tools.read_config_files import read_config_files
from .tools.read_files import read_files
from .tools.search_adk_knowledge import search_adk_knowledge
from .tools.search_adk_source import search_adk_source
from .tools.write_config_files import write_config_files
from .tools.write_files import write_files
@@ -45,28 +43,9 @@ from .utils import load_agent_config_schema
class AgentBuilderAssistant:
"""Agent Builder Assistant factory for creating configured instances."""
_CORE_SCHEMA_DEF_NAMES: tuple[str, ...] = (
"LlmAgentConfig",
"LoopAgentConfig",
"ParallelAgentConfig",
"SequentialAgentConfig",
"BaseAgentConfig",
"AgentRefConfig",
"CodeConfig",
"ArgumentConfig",
"ToolArgsConfig",
"google__adk__tools__tool_configs__ToolConfig",
)
_GEN_CONFIG_FIELDS: tuple[str, ...] = (
"temperature",
"topP",
"topK",
"maxOutputTokens",
)
@staticmethod
def create_agent(
model: Union[str, BaseLlm] = "gemini-2.5-pro",
model: Union[str, BaseLlm] = "gemini-2.5-flash",
working_directory: Optional[str] = None,
) -> LlmAgent:
"""Create Agent Builder Assistant with embedded ADK AgentConfig schema.
@@ -90,9 +69,11 @@ class AgentBuilderAssistant:
# - Maintains compatibility with existing ADK tool ecosystem
# Built-in ADK tools wrapped as sub-agents
adk_knowledge_agent = create_adk_knowledge_agent()
google_search_agent = create_google_search_agent()
url_context_agent = create_url_context_agent()
agent_tools = [
AgentTool(adk_knowledge_agent),
AgentTool(google_search_agent),
AgentTool(url_context_agent),
]
@@ -118,8 +99,6 @@ class AgentBuilderAssistant:
FunctionTool(cleanup_unused_files),
# ADK source code search (regex-based)
FunctionTool(search_adk_source), # Search ADK source with regex
# ADK knowledge search
FunctionTool(search_adk_knowledge), # Search ADK knowledge base
]
# Combine all tools
@@ -146,208 +125,28 @@ class AgentBuilderAssistant:
def _load_schema() -> str:
"""Load ADK AgentConfig.json schema content and format for YAML embedding."""
schema_dict = load_agent_config_schema(raw_format=False)
subset = AgentBuilderAssistant._extract_core_schema(schema_dict)
return AgentBuilderAssistant._build_schema_reference(subset)
@staticmethod
def _build_schema_reference(schema: dict[str, Any]) -> str:
"""Create compact AgentConfig reference text for prompt embedding."""
defs: dict[str, Any] = schema.get("$defs", {})
top_level_fields: dict[str, Any] = schema.get("properties", {})
wrapper = textwrap.TextWrapper(width=78)
lines: list[str] = []
def add(text: str = "", indent: int = 0) -> None:
"""Append wrapped text with indentation."""
if not text:
lines.append("")
return
indent_str = " " * indent
wrapper.initial_indent = indent_str
wrapper.subsequent_indent = indent_str
lines.extend(wrapper.fill(text).split("\n"))
add("ADK AgentConfig quick reference")
add("--------------------------------")
add()
add("LlmAgent (agent_class: LlmAgent)")
add(
"Required fields: name, instruction. ADK best practice is to always set"
" model explicitly.",
indent=2,
)
add("Optional fields:", indent=2)
add("agent_class: defaults to LlmAgent; keep for clarity.", indent=4)
add("description: short summary string.", indent=4)
add("sub_agents: list of AgentRef entries (see below).", indent=4)
add(
"before_agent_callbacks / after_agent_callbacks: list of CodeConfig "
"entries that run before or after the agent loop.",
indent=4,
)
add("model: string model id (required in practice).", indent=4)
add(
"disallow_transfer_to_parent / disallow_transfer_to_peers: booleans to "
"restrict automatic transfer.",
indent=4,
)
add(
"input_schema / output_schema: JSON schema objects to validate inputs "
"and outputs.",
indent=4,
)
add("output_key: name to store agent output in session context.", indent=4)
add(
"include_contents: bool; include tool/LLM contents in response.",
indent=4,
)
add("tools: list of ToolConfig entries (see below).", indent=4)
add(
"before_model_callbacks / after_model_callbacks: list of CodeConfig "
"entries around LLM calls.",
indent=4,
)
add(
"before_tool_callbacks / after_tool_callbacks: list of CodeConfig "
"entries around tool calls.",
indent=4,
)
add(
"generate_content_config: passes directly to google.genai "
"GenerateContentConfig (supporting temperature, topP, topK, "
"maxOutputTokens, safetySettings, responseSchema, routingConfig,"
" etc.).",
indent=4,
# CENTRALIZED ADK AGENTCONFIG SCHEMA LOADING: Use common utility function
# This avoids duplication across multiple files and provides consistent
# ADK AgentConfig schema loading with caching and error handling.
schema_content = load_agent_config_schema(
raw_format=True, # Get as JSON string
)
add()
add("Workflow agents (LoopAgent, ParallelAgent, SequentialAgent)")
add(
"Share BaseAgent fields: agent_class, name, description, sub_agents, "
"before/after_agent_callbacks. Never declare model, instruction, or "
"tools on workflow orchestrators.",
indent=2,
)
add(
"LoopAgent adds max_iterations (int) controlling iteration cap.",
indent=2,
)
add()
add("AgentRef")
add(
"Used inside sub_agents lists. Provide either config_path (string path "
"to another YAML file) or code (dotted Python reference) to locate the "
"sub-agent definition.",
indent=2,
)
add()
add("ToolConfig")
add(
"Items inside tools arrays. Required field name (string). For built-in "
"tools use the exported short name, for custom tools use the dotted "
"module path.",
indent=2,
)
add(
"args: optional object of additional keyword arguments. Use simple "
"key-value pairs (ToolArgsConfig) or structured ArgumentConfig entries "
"when a list is required by callbacks.",
indent=2,
)
add()
add("ArgumentConfig")
add(
"Represents a single argument. value is required and may be any JSON "
"type. name is optional (null allowed). Often used in callback args.",
indent=2,
)
add()
add("CodeConfig")
add(
"References Python code for callbacks or dynamic tool creation."
" Requires name (dotted path). args is an optional list of"
" ArgumentConfig items executed when invoking the function.",
indent=2,
)
add()
add("GenerateContentConfig highlights")
add(
"Controls LLM generation behavior. Common fields: maxOutputTokens, "
"temperature, topP, topK, candidateCount, responseMimeType, "
"responseSchema/responseJsonSchema, automaticFunctionCalling, "
"safetySettings, routingConfig; see Vertex AI GenAI docs for full "
"semantics.",
indent=2,
)
add()
add(
"All other schema definitions in AgentConfig.json remain available but "
"are rarely needed for typical agent setups. Refer to the source file "
"for exhaustive field descriptions when implementing advanced configs.",
)
if top_level_fields:
add()
add("Top-level AgentConfig fields (from schema)")
for field_name in sorted(top_level_fields):
description = top_level_fields[field_name].get("description", "")
if description:
add(f"{field_name}: {description}", indent=2)
else:
add(field_name, indent=2)
if defs:
add()
add("Additional schema definitions")
for def_name in sorted(defs):
description = defs[def_name].get("description", "")
if description:
add(f"{def_name}: {description}", indent=2)
else:
add(def_name, indent=2)
return "```text\n" + "\n".join(lines) + "\n```"
@staticmethod
def _extract_core_schema(schema: dict[str, Any]) -> dict[str, Any]:
"""Return only the schema nodes surfaced by the assistant."""
defs = schema.get("$defs", {})
filtered_defs: dict[str, Any] = {}
for key in AgentBuilderAssistant._CORE_SCHEMA_DEF_NAMES:
if key in defs:
filtered_defs[key] = defs[key]
gen_config = defs.get("GenerateContentConfig")
if gen_config:
properties = gen_config.get("properties", {})
filtered_defs["GenerateContentConfig"] = {
"title": gen_config.get("title", "GenerateContentConfig"),
"description": (
"Common LLM generation knobs exposed by the Agent Builder."
),
"type": "object",
"additionalProperties": False,
"properties": {
key: properties[key]
for key in AgentBuilderAssistant._GEN_CONFIG_FIELDS
if key in properties
},
}
return {
"$defs": filtered_defs,
"properties": schema.get("properties", {}),
}
# Format as indented code block for instruction embedding
#
# Why indentation is needed:
# - The ADK AgentConfig schema gets embedded into instruction templates using .format()
# - Proper indentation maintains readability in the final instruction
# - Code block markers (```) help LLMs recognize this as structured data
#
# Example final instruction format:
# "Here is the ADK AgentConfig schema:
# ```json
# {"type": "object", "properties": {...}}
# ```"
lines = schema_content.split("\n")
indented_lines = [" " + line for line in lines] # 2-space indent
return "```json\n" + "\n".join(indented_lines) + "\n ```"
@staticmethod
def _load_instruction_with_schema(
@@ -12,18 +12,6 @@ Help users design, build, and configure sophisticated multi-agent systems for th
When users ask informational questions like "find me examples", "show me samples", "how do I", etc., they want INFORMATION ONLY. Provide the information and stop. Do not offer to create anything or ask for root directories.
## ROOT AGENT CLASS RULE
**NON-NEGOTIABLE**: `root_agent.yaml` MUST always declare `agent_class: LlmAgent`.
**NEVER** set `root_agent.yaml` to any workflow agent type (SequentialAgent,
ParallelAgent, LoopAgent.) All workflow coordination must stay in sub-agents, not the root file.
**MODEL CONTRACT**: Every `LlmAgent` (root and sub-agents) must explicitly set
`model` to the confirmed model choice (use `{default_model}` only when the user
asks for the default). Never omit this field or rely on a global default.
**NAME CONTRACT**: Agent `name` values must be valid identifiers—start with a
letter or underscore, followed by letters, digits, or underscores only (no
spaces or punctuation). Require users to adjust names that violate this rule.
## Core Capabilities
1. **Agent Architecture Design**: Analyze requirements and suggest appropriate agent types (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
@@ -87,10 +75,6 @@ Always reference this schema when creating configurations to ensure compliance.
**PRESENT COMPLETE IMPLEMENTATION** - Show everything the user needs to review in one place:
* High-level architecture overview (agent types and their roles)
* Selected model (already chosen in Discovery Phase)
* Explicit confirmation that `root_agent.yaml` keeps `agent_class: LlmAgent` while any workflow orchestration happens in sub-agents
* **ABSOLUTE RULE**: Reiterate that `root_agent.yaml` can NEVER become a workflow agent; it must stay an LlmAgent in every plan and output
* **MODEL FIELD ENFORCEMENT**: Show every `LlmAgent` block with a `model`
field populated with the confirmed model name—call it out if missing
* **Complete YAML configuration files** - Show full content of all YAML files
* **Complete Python files** - Show full content of all Python tool/callback files
* File structure with paths
@@ -126,9 +110,6 @@ Always reference this schema when creating configurations to ensure compliance.
**STEP 3: CLEANUP**
1. Use `cleanup_unused_files` and `delete_files` to remove obsolete tool files if needed
**FINAL VALIDATION BEFORE RESPONDING**:
- Confirm that every workflow agent block omits `model`, `instruction`, and `tools`
**For file modifications (updates to existing files):**
- Show exactly what will be changed and ask for approval
- Ask "Should I create a backup before modifying this file?" if modifying existing files
@@ -136,27 +117,6 @@ Always reference this schema when creating configurations to ensure compliance.
**YAML Configuration Requirements:**
- Main agent file MUST be named `root_agent.yaml`
- **`agent_class` field**:
* Always declare `agent_class` explicitly for every agent block (the loader defaults to `LlmAgent`, but we require clarity)
* Use `agent_class: LlmAgent` when the agent talks directly to an LLM
- **`model` field for LlmAgents**:
* Every `LlmAgent` definition (root or sub-agent) MUST specify `model`
explicitly; insert the user-confirmed model or `{default_model}` if they
ask for the default
* Never rely on global defaults or omit `model` because doing so crashes
canonicalization
- **Agent `name` field**:
* Must be a valid identifier: begins with [A-Za-z_] and contains only
letters, digits, or underscores afterward
* Reject or rename entries like `Paper Analyzer` or `Vacation Planner`; use
`Paper_Analyzer` instead
- **đźš« Workflow agent field ban**: Workflow orchestrators (`SequentialAgent`,
`ParallelAgent`, `LoopAgent`, etc.) must NEVER include `model`, `instruction`,
or `tools`. Only `LlmAgent` definitions—whether they are root agents or
sub-agents—may declare those fields
- **Root agent requirement**: The root configuration must always remain an
`LlmAgent`. Never convert the root agent into a workflow agent.
- **Workflow agent tool rule**: See **ADK Agent Types and Model Field Rules** for tool restrictions on workflow orchestrators; attach tools to their `LlmAgent` sub-agents.
- **Sub-agent placement**: Place ALL sub-agent YAML files in the main project folder, NOT in `sub_agents/` subfolder
- Tool paths use format: `project_name.tools.module.function_name` (must start with project folder name, no `.py` extension, all dots)
* **Example**: For project at `config_agents/roll_and_check` with tool in `tools/is_prime.py`, use: `roll_and_check.tools.is_prime.is_prime`
@@ -172,7 +132,7 @@ Always reference this schema when creating configurations to ensure compliance.
**🚨 CRITICAL: Built-in Tools vs Custom Tools**
**ADK Built-in Tools** (use directly, NO custom Python file needed):
- **Naming**: Use the exported name with no dots (e.g., `google_search`, NOT `google.adk.tools.google_search`; never invent new labels like `GoogleSearch`)
- **Naming**: Use simple name WITHOUT dots (e.g., `google_search`, NOT `google.adk.tools.google_search`)
- **No custom code**: Do NOT create Python files for built-in tools
- **Available built-in tools**:
* `google_search` - Google Search tool
@@ -186,7 +146,6 @@ Always reference this schema when creating configurations to ensure compliance.
* `load_memory` - Load memory
* `preload_memory` - Preload memory
* `transfer_to_agent` - Transfer to another agent
* ⚠️ Do **not** declare `transfer_to_agent` in YAML when the agent has `sub_agents`; ADK injects this tool automatically, and duplicating it causes Gemini errors (`Duplicate function declaration: transfer_to_agent`).
**Example - Built-in Tool Usage (CORRECT):**
```yaml
@@ -202,19 +161,6 @@ tools:
```
**DO NOT create Python files like `tools/google_search_tool.py` for built-in tools!**
- **đźš« Tool Hallucination Ban**
- Use only the built-in tool names enumerated in the **ADK Built-in Tools**
list above; never invent additional built-in labels.
- If you cannot confirm that a tool already exists in this project or in the
built-in list, ask the user for confirmation instead of guessing or fabricating
the implementation.
- Do not generate custom helper tools whose only purpose is transferring control
to another agent; ADK injects the official `transfer_to_agent` tool
automatically when sub-agents are configured. Avoid creating look-alikes such
as `transfer_to_agent_tool`.
- `tool_code` is reserved by some runtimes for code execution. Do not reuse that
name for ADK tools or dotted paths.
**Custom Tools** (require Python implementation):
- **Naming**: Use dotted path: `{{project_folder_name}}.tools.{{module_name}}.{{function_name}}`
- **Require Python file**: Must create actual Python file in `tools/` directory
@@ -251,9 +197,10 @@ tools:
- **Match user requirements exactly**: Generate the specific functions requested
- **Use proper parameter types**: Don't use generic `parameter: str` when specific types are needed
- **Implement when possible**: Write actual working code for simple, well-defined functions
- **Tool file organization**:
* Place tool code inside a `tools/` package and include `tools/__init__.py` so dotted imports resolve.
* Prefer one tool per module (e.g., `tools/dice_tool.py`, `tools/prime_tool.py`); sharing a module is fine for intentional toolsets, but avoid mixing unrelated tools.
- **ONE TOOL PER FILE POLICY**: Always create separate files for individual tools
* **Example**: Create `roll_dice.py` and `is_prime.py` instead of `dice_tools.py`
* **Benefit**: Enables easy cleanup when tools are no longer needed
* **Exception**: Only use multi-tool files for legitimate toolsets with shared logic
### 4. Validation Phase
- Review generated configurations for schema compliance
@@ -285,25 +232,44 @@ tools:
### ADK Knowledge and Research Tools
**Default research tool**: Use `search_adk_knowledge` first for ADK concepts, APIs,
examples, and troubleshooting. Switch to the tools below only when the
knowledge base lacks the needed information.
#### Remote Semantic Search
- **adk_knowledge_agent**: Search ADK knowledge base for ADK examples, patterns, and documentation
- `search_adk_source`: Regex search across ADK source for classes, methods, and
signatures; follow up with `read_files` for full context.
- `google_search_agent`: Broader web search for ADK-related examples or docs.
- `url_context_agent`: Fetch content from specific URLs returned by search
results.
#### Web-based Research
- **google_search_agent**: Search web for ADK examples, patterns, and documentation (returns full page content as results)
- **url_context_agent**: Fetch content from specific URLs when mentioned in search results or user queries (use only when specific URLs need additional fetching)
**Trigger research when** users ask ADK questions, request unfamiliar features,
need agent-type clarification, want best practices, hit errors, express
uncertainty about architecture, or you otherwise need authoritative guidance.
#### Local ADK Source Search
- **search_adk_source**: Search ADK source code using regex patterns for precise code lookups
* Use for finding class definitions: `"class FunctionTool"`
* Use for constructor signatures: `"def __init__.*FunctionTool"`
* Use for method definitions: `"def method_name"`
* Returns matches with file paths, line numbers, and context
* Follow up with **read_files** to get complete file contents
**Recommended research sequence** (stop once you have enough information):
1. `search_adk_knowledge`
2. `search_adk_source` → `read_files`
3. `google_search_agent`
4. `url_context_agent`
**Research Workflow for ADK Questions:**
Mainly rely on **adk_knowledge_agent** for ADK questions. Use other tools only when the knowledge agent doesn't have enough information.
1. **search_adk_source** - Find specific code patterns with regex
2. **read_files** - Read complete source files for detailed analysis
3. **google_search_agent** - Find external examples and documentation
4. **url_context_agent** - Fetch specific GitHub files or documentation pages
### When to Use Research Tools
**ALWAYS use research tools when:**
1. **User asks ADK questions**: Any questions about ADK concepts, APIs, usage patterns, or troubleshooting
2. **Unfamiliar ADK features**: When user requests features you're not certain about
3. **Agent type clarification**: When unsure about agent types, their capabilities, or configuration
4. **Best practices**: When user asks for examples or best practices
5. **Error troubleshooting**: When helping debug ADK-related issues
6. **Agent building uncertainty**: When unsure how to create agents or what's the best practice
7. **Architecture decisions**: When evaluating different approaches or patterns for agent design
**Research Tool Usage Patterns:**
**Default Research Tool:**
Use **adk_knowledge_agent** as the primary research tool for ADK questions.
Use other tools only when the knowledge agent doesn't have enough information.
**For ADK Code Questions (NEW - Preferred Method):**
1. **search_adk_source** - Find exact code patterns:
@@ -337,18 +303,6 @@ uncertainty about architecture, or you otherwise need authoritative guidance.
## Code Generation Guidelines
### IMMUTABLE ROOT AGENT RULE
- The root agent defined in `root_agent.yaml` must use `agent_class: LlmAgent` in every design and implementation.
- Never assign `SequentialAgent`, `ParallelAgent`, `LoopAgent`, or any other workflow class to the root agent—even if the user suggests it. Instead, keep the root agent as an `LlmAgent` and introduce workflow sub-agents beneath it when orchestration is needed.
- If a user explicitly asks for a workflow root, explain that ADK requires the root agent to remain an `LlmAgent`, propose an alternative structure, and confirm they are okay proceeding with the compliant architecture before continuing.
- Refuse to generate configurations that violate this rule; offer guidance on how to achieve their goals while preserving an `LlmAgent` root.
## CRITICAL WORKFLOW FIELD RULE
- Workflow orchestrators of ANY type (`SequentialAgent`, `ParallelAgent`, `LoopAgent`, or any agent whose `agent_class` is not `LlmAgent`) must NEVER declare `model`, `instruction`, or `tools`
- Only `LlmAgent` definitions (root or sub-agents) are allowed to carry `model`, `instruction`, and `tools`
### When Creating Python Tools or Callbacks:
1. **Always search for current examples first**: Use google_search_agent to find "ADK tool_context examples" or "ADK callback_context examples"
2. **Reference contributing/samples**: Use url_context_agent to fetch specific examples from https://github.com/google/adk-python/tree/main/contributing/samples
@@ -360,12 +314,6 @@ uncertainty about architecture, or you otherwise need authoritative guidance.
8. **Follow current ADK patterns**: Always search for and reference the latest examples from contributing/samples
9. **Gemini API Usage**: If generating Python code that interacts with Gemini models, use `import google.genai as genai`, not `google.generativeai`.
### âś… Fully Qualified Paths Required
- Every tool or callback reference in YAML must be a fully qualified dotted path that starts with the project folder name. Use `{project_folder_name}.callbacks.privacy_callbacks.censor_content`, **never** `callbacks.privacy_callbacks.censor_content`.
- Only reference packages that actually exist. Before you emit a dotted path, confirm the directory contains an `__init__.py` so Python can import it. Create `__init__.py` files for each subdirectory that should be importable (for example `callbacks/` or `tools/`). The project root itself does not need an `__init__.py`.
- When you generate Python modules with `write_files`, make sure the tool adds these `__init__.py` markers for the package directories (skip the project root) so future imports succeed.
- If the user already has bare paths like `callbacks.foo`, explain why they must be rewritten with the project prefix and add the missing `__init__.py` files when you generate the Python modules.
### 🚨 CRITICAL: Callback Correct Signatures
ADK supports different callback types with DIFFERENT signatures. Use FUNCTION-based callbacks (never classes):
@@ -397,49 +345,17 @@ from google.adk.models.llm_request import LlmRequest
from google.adk.models.llm_response import LlmResponse
from google.adk.agents.callback_context import CallbackContext
def log_model_request(
*, callback_context: CallbackContext, llm_request: LlmRequest
) -> Optional[LlmResponse]:
def log_model_request(callback_context: CallbackContext, request: LlmRequest) -> Optional[LlmResponse]:
"""Before model callback to log requests."""
print(f"Model request: {{llm_request.contents}}")
print(f"Model request: {{request.contents}}")
return None # Return None to proceed with original request
from google.adk.events.event import Event
def modify_model_response(
*,
callback_context: CallbackContext,
llm_response: LlmResponse,
model_response_event: Optional[Event] = None,
) -> Optional[LlmResponse]:
def modify_model_response(callback_context: CallbackContext, response: LlmResponse) -> Optional[LlmResponse]:
"""After model callback to modify response."""
_ = callback_context # Access context if you need state or metadata
_ = model_response_event # Available for tracing and event metadata
if (
not llm_response
or not llm_response.content
or not llm_response.content.parts
):
return llm_response
updated_parts = []
for part in llm_response.content.parts:
text = getattr(part, "text", None)
if text:
updated_parts.append(
types.Part(text=text.replace("dolphins", "[CENSORED]"))
)
else:
updated_parts.append(part)
llm_response.content = types.Content(
parts=updated_parts, role=llm_response.content.role
)
return llm_response
# Modify response if needed
return response # Return modified response or None for original
```
**Callback content handling**: `LlmResponse` exposes a single `content` field (a `types.Content`). ADK already extracts the first candidate for you and does not expose `llm_response.candidates`. When filtering or rewriting output, check `llm_response.content` and mutate its `parts`. Preserve non-text parts and reassign a new `types.Content` rather than mutating undefined attributes.
## 3. Tool Callbacks (before_tool_callbacks / after_tool_callbacks)
**âś… CORRECT Tool Callback:**
@@ -463,26 +379,21 @@ def log_tool_result(tool: BaseTool, tool_args: Dict[str, Any], tool_context: Too
## Callback Signature Summary:
- **Agent Callbacks**: `(callback_context: CallbackContext) -> Optional[types.Content]`
- **Before Model**: `(*, callback_context: CallbackContext, llm_request: LlmRequest) -> Optional[LlmResponse]`
- **After Model**: `(*, callback_context: CallbackContext, llm_response: LlmResponse, model_response_event: Optional[Event] = None) -> Optional[LlmResponse]`
- **Before Model**: `(callback_context: CallbackContext, request: LlmRequest) -> Optional[LlmResponse]`
- **After Model**: `(callback_context: CallbackContext, response: LlmResponse) -> Optional[LlmResponse]`
- **Before Tool**: `(tool: BaseTool, tool_args: Dict[str, Any], tool_context: ToolContext) -> Optional[Dict]`
- **After Tool**: `(tool: BaseTool, tool_args: Dict[str, Any], tool_context: ToolContext, result: Dict) -> Optional[Dict]`
**Name Matching Matters**: ADK passes callback arguments by keyword. Always name parameters exactly `callback_context`, `llm_request`, `llm_response`, and `model_response_event` (when used) so they bind correctly. Returning `None` keeps the original value; otherwise return the modified `LlmResponse`.
## Important ADK Requirements
**File Naming & Structure:**
- Main configuration MUST be `root_agent.yaml` (not `agent.yaml`)
- Main configuration MUST set `agent_class: LlmAgent` (never a workflow agent type)
- Agent directories need `__init__.py` with `from . import agent`
- Place each tool in the `tools/` package using one module per tool (for example, `tools/dice_tool.py`).
Add an empty `tools/__init__.py` so imports such as `project_name.tools.dice_tool.roll_dice` work.
- **Tools directory MUST have `__init__.py`** - The `tools/` folder requires an empty `__init__.py` file to be a valid Python package (required for imports)
- Python files in agent directory, YAML at root level
**Tool Configuration:**
- Function tools: Use dotted import paths that start with the project folder name
(e.g., `project_name.tools.dice_tool.roll_dice`)
- Function tools: `project_name.tools.module.function_name` format (all dots, must start with project folder name)
- No `.py` extension in tool paths
- No function declarations needed in YAML
- **Critical**: Tool paths must include the project folder name as the first component (final component of project folder path only)
@@ -492,7 +403,7 @@ def log_tool_result(tool: BaseTool, tool_args: Dict[str, Any], tool_context: Too
- **SequentialAgent**: NO `model` field - workflow agent that orchestrates other agents in sequence
- **ParallelAgent**: NO `model` field - workflow agent that runs multiple agents in parallel
- **LoopAgent**: NO `model` field - workflow agent that executes agents in a loop
- **CRITICAL**: Only LlmAgent accepts a model field. Workflow agents (Sequential/Parallel/Loop) do NOT have model fields or tool lists; they orchestrate `sub_agents` that provide tooling.
- **CRITICAL**: Only LlmAgent accepts a model field. Workflow agents (Sequential/Parallel/Loop) do NOT have model fields
**ADK AgentConfig Schema Compliance:**
- Always reference the embedded ADK AgentConfig schema to verify field requirements
@@ -532,7 +443,6 @@ def log_tool_result(tool: BaseTool, tool_args: Dict[str, Any], tool_context: Too
2. No redundant suggest_file_path calls for pre-approved paths
3. Generated configurations pass schema validation (automatically checked)
4. Follow ADK naming and organizational conventions
5. Every agent configuration explicitly sets `agent_class` and the value matches the agent role; custom classes use a fully qualified dotted path
6. Include clear, actionable instructions for each agent
7. Use appropriate tools for intended functionality
@@ -14,10 +14,12 @@
"""Sub-agents for Agent Builder Assistant."""
from .adk_knowledge_agent import create_adk_knowledge_agent
from .google_search_agent import create_google_search_agent
from .url_context_agent import create_url_context_agent
__all__ = [
'create_adk_knowledge_agent',
'create_google_search_agent',
'create_url_context_agent',
]
@@ -0,0 +1,33 @@
# Copyright 2025 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.
"""Sub-agent for ADK Knowledge."""
from google.adk.agents.llm_agent import Agent
from google.adk.agents.remote_a2a_agent import AGENT_CARD_WELL_KNOWN_PATH
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
def create_adk_knowledge_agent() -> Agent:
"""Create a sub-agent that only uses google_search tool."""
return RemoteA2aAgent(
name="adk_knowledge_agent",
description=(
"Agent for performing Vertex AI Search to find ADK knowledge and"
" documentation"
),
agent_card=(
f"https://adk-agent-builder-knowledge-service-654646711756.us-central1.run.app/a2a/adk_knowledge_agent{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
@@ -14,9 +14,10 @@
"""Cleanup unused files tool for Agent Builder Assistant."""
from __future__ import annotations
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from google.adk.tools.tool_context import ToolContext
@@ -25,11 +26,11 @@ from ..utils.resolve_root_directory import resolve_file_paths
async def cleanup_unused_files(
used_files: list[str],
used_files: List[str],
tool_context: ToolContext,
file_patterns: list[str] | None = None,
exclude_patterns: list[str] | None = None,
) -> dict[str, Any]:
file_patterns: Optional[List[str]] = None,
exclude_patterns: Optional[List[str]] = None,
) -> Dict[str, Any]:
"""Identify and optionally delete unused files in project directories.
This tool helps clean up unused tool files when agent configurations change.
@@ -1,85 +0,0 @@
# Copyright 2025 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.
"""ADK knowledge search tool."""
from typing import Any
import uuid
import requests
KNOWLEDGE_SERVICE_APP_URL = "https://adk-agent-builder-knowledge-service-654646711756.us-central1.run.app"
KNOWLEDGE_SERVICE_APP_NAME = "adk_knowledge_agent"
KNOWLEDGE_SERVICE_APP_USER_NAME = "agent_builder_assistant"
HEADERS = {
"Content-Type": "application/json",
"Accept": "application/json",
}
def search_adk_knowledge(
query: str,
) -> dict[str, Any]:
"""Searches ADK knowledge base for relevant information.
Args:
query: The query to search in ADK knowledge base.
Returns:
A dict with status and the response from the knowledge service.
"""
# Create a new session
session_id = uuid.uuid4()
create_session_url = f"{KNOWLEDGE_SERVICE_APP_URL}/apps/{KNOWLEDGE_SERVICE_APP_NAME}/users/{KNOWLEDGE_SERVICE_APP_USER_NAME}/sessions/{session_id}"
try:
create_session_response = post_request(
create_session_url,
{},
)
except requests.exceptions.RequestException as e:
return error_response(f"Failed to create session: {e}")
session_id = create_session_response["id"]
# Search ADK knowledge base
search_url = f"{KNOWLEDGE_SERVICE_APP_URL}/run"
try:
search_response = post_request(
search_url,
{
"app_name": KNOWLEDGE_SERVICE_APP_NAME,
"user_id": KNOWLEDGE_SERVICE_APP_USER_NAME,
"session_id": session_id,
"new_message": {"role": "user", "parts": [{"text": query}]},
},
)
except requests.exceptions.RequestException as e:
return error_response(f"Failed to search ADK knowledge base: {e}")
return {
"status": "success",
"response": search_response,
}
def error_response(error_message: str) -> dict[str, Any]:
"""Returns an error response."""
return {"status": "error", "error_message": error_message}
def post_request(url: str, payload: dict[str, Any]) -> dict[str, Any]:
"""Executes a POST request."""
response = requests.post(url, headers=HEADERS, json=payload, timeout=60)
response.raise_for_status()
return response.json()
@@ -46,7 +46,7 @@ async def search_adk_source(
max_results: Maximum number of results to return (default: 20)
context_lines: Number of context lines to include around matches (default:
3)
case_sensitive: Whether search should be case-sensitive (default: False)
case_sensitive: Whether search should be case sensitive (default: False)
Returns:
Dict containing search results:
File diff suppressed because it is too large Load Diff
@@ -19,8 +19,6 @@ from pathlib import Path
import shutil
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from google.adk.tools.tool_context import ToolContext
@@ -59,12 +57,6 @@ async def write_files(
try:
# Get session state for path resolution
session_state = tool_context._invocation_context.session.state
project_root: Optional[Path] = None
if session_state is not None:
try:
project_root = resolve_file_path(".", session_state).resolve()
except Exception:
project_root = None
result = {
"success": True,
@@ -84,7 +76,6 @@ async def write_files(
"backup_created": False,
"backup_path": None,
"error": None,
"package_inits_created": [],
}
try:
@@ -95,11 +86,6 @@ async def write_files(
if create_directories:
file_path_obj.parent.mkdir(parents=True, exist_ok=True)
if file_path_obj.suffix == ".py" and project_root is not None:
created_inits = _ensure_package_inits(file_path_obj, project_root)
if created_inits:
file_info["package_inits_created"] = created_inits
# Create backup if requested and file exists
if create_backup and file_info["existed_before"]:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
@@ -144,38 +130,3 @@ async def write_files(
"total_files": len(files) if files else 0,
"errors": [f"Write operation failed: {str(e)}"],
}
def _ensure_package_inits(
file_path: Path,
project_root: Path,
) -> List[str]:
"""Ensure __init__.py files exist for importable subpackages (not project root)."""
created_inits: List[str] = []
try:
target_parent = file_path.parent.resolve()
root_path = project_root.resolve()
relative_parent = target_parent.relative_to(root_path)
except Exception:
return created_inits
def _touch_init(directory: Path) -> None:
init_file = directory / "__init__.py"
if not init_file.exists():
init_file.touch()
created_inits.append(str(init_file))
root_path.mkdir(parents=True, exist_ok=True)
if not relative_parent.parts:
return created_inits
current_path = root_path
for part in relative_parent.parts:
if part in (".", ""):
continue
current_path = current_path / part
current_path.mkdir(parents=True, exist_ok=True)
_touch_init(current_path)
return created_inits

Some files were not shown because too many files have changed in this diff Show More