### Description of Change
**Problem:**
The `ToolboxToolset` was relying on the legacy `toolbox-core` package. Users wanting to use the Toolbox features were forced to install the heavy `[extensions]` group, lacking a granular installation option. Additionally, `ToolboxToolset` had a validation check enforcing either `toolset_name` or `tool_names` to be present, preventing the default behavior of loading all tools (which `toolbox-adk` supports).
**Solution:**
* Refactored `ToolboxToolset` to delegate to `toolbox-adk`.
* Added a new `toolbox` optional dependency group in `pyproject.toml`.
* Users can now run `pip install google-adk[toolbox]` to install only the necessary dependencies.
* Updated the `extensions` dependency group to replace `toolbox-core` with `toolbox-adk`.
* This ensures existing users of `[extensions]` are not broken upon upgrade.
* Removed the restrictive validation check to allow default loading of all tools.
* Updated the `ImportError` message to guide users toward the new granular installation command.
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
**Manual End-to-End (E2E) Tests:**
- Verified that the sample agent runs correctly with `toolbox-adk` locally.
- Verified that `ToolboxToolset` can now be instantiated without arguments to load all tools.
### Checklist
- [x] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document.
- [x] I have performed a self-review of my own code.
- [x] I have commented my code, particularly in hard-to-understand areas.
- [x] I have added tests that prove my fix is effective or that my feature works.
- [x] New and existing unit tests pass locally with my changes.
- [x] I have manually tested my changes end-to-end.
- [x] Any dependent changes have been merged and published in downstream modules.
PiperOrigin-RevId: 857171811
Merge https://github.com/google/adk-python/pull/4041
## Description
This PR fixes false positive stale labels in the `adk_stale_agent`.
Previously, the agent was incorrectly identifying the issue as "stale" because it treated `adk-bot` (acting via PAT) as a human maintainer. Since the username lacks the `[bot]` suffix, administrative alerts (e.g., "Notification: The author has updated...") were counted as maintainer activity, inadvertently triggering the stale logic immediately after an author's edit.
## Changes Made
- **Hardcoded Bot Exclusion:** Added `BOT_NAME = "adk-bot"` and updated history parsing loops (comments, edits, timeline) to explicitly ignore this actor.
- **Bot Alert Skip:** Added logic to `continue` (skip) processing the bot's specific "Notification" comment so it is not recorded as the last activity on the timeline.
Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4041 from ryanaiagent:fix/stale-bot-logic f1500a94cb8c9d5090e9b1ef29690506120f7749
PiperOrigin-RevId: 852365962
This gcloud authentication header is required as a project override when using google ADC credentials. It is required for all OneMCP servers. Originally I manually put it in the big query sample, but since it is used for all OneMCP, it makes sense to just add it to the core API Registry logic. I also refactored the auth header logic a bit to deduplicate.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 845967178
Merge https://github.com/google/adk-python/pull/3937
**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
Not applicable
**Problem:**
Several markdown files contained typos, grammatical errors (e.g., "search youtubes"), and awkward phrasing.
**Solution:**
Performed a comprehensive quality assurance pass on the documentation.
- Fixed typos in README.md and AGENTS.md.
- Improved grammar and phrasing in CONTRIBUTING.md and sample READMEs.
### Testing Plan
This is a documentation and typo fix PR.
**Unit Tests:**
- [ ] I have added or updated unit tests for my change.
- [ ] All unit tests pass locally.
N/A - Documentation changes only.
**Manual End-to-End (E2E) Tests:**
This is a documentation and typo fix PR.
### Checklist
- [x] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document.
- [x] 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.
- [x] I have manually tested my changes end-to-end.
- [ ] Any dependent changes have been merged and published in downstream modules.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3937 from Goodnight77:docs/fix-typos a0cf4db6741f19c77eeb0746c9db524dd02121ac
PiperOrigin-RevId: 845599254
LiteLLM's `ollama_chat` provider does not accept array-based content in messages. This change flattens multipart content by joining text parts or JSON-serializing non-text parts before sending the request to the LiteLLM completion API. This ensures compatibility with Ollama's chat endpoint.
Close#3727
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 843382361
Merge https://github.com/google/adk-python/pull/3875
# Problem
The example in `contributing/samples/human_in_loop/README.md` shows:
```python
await runner.run_async(...)
```
However, `run_async` returns an **async generator**, so awaiting it raises:
```
TypeError: object async_generator can't be used in 'await' expression
```
Additionally, the example payload uses `"ticket-id"` while ADK tools and other examples use `"ticketId"`, creating a mismatch that breaks copy/paste usage.
# Solution
- Updated the snippet to consume the async generator correctly:
```python
async for event in runner.run_async(...):
...
```
- Aligned the payload key from `"ticket-id"` → `"ticketId"` for consistency with ADK schema and other examples.
These changes make the example runnable and consistent with the API’s actual behavior.
# Testing Plan
This PR is a **small documentation correction**, so no unit tests are required per contribution guidelines.
- Verified the corrected snippet manually to ensure it no longer raises `TypeError`.
# Checklist
- [x] I have read the CONTRIBUTING.md document.
- [x] I have performed a self-review of my own code.
- [ ] I have commented my code, particularly in hard-to-understand areas. *(N/A – docs only)*
- [ ] I have added tests that prove my fix is effective or that my feature works. *(N/A – docs only)*
- [ ] New and existing unit tests pass locally with my changes. *(N/A – docs only)*
- [x] I have manually tested my changes end-to-end.
- [ ] Any dependent changes have been merged and published in downstream modules. *(N/A)*
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3875 from krishna-dhulipalla:docs/fix-adk-run_async-example 83fc5b430690b63b8b7bf1025ef03b0761264751
PiperOrigin-RevId: 842952362
Context: many issues related to local mult-agent system is tagged with a2a
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 842397159
Add using the execute sql query return result as list of dictionaries.
In each dictionary the key is the column name and the value is the value of
the that column in a given row.
PiperOrigin-RevId: 840909555
This change introduces `Gemma3Ollama`, a new LLM model class for running Gemma 3 models locally via Ollama, leveraging LiteLLM. The function calling logic previously in the `Gemma` class has been refactored into a `GemmaFunctionCallingMixin` and is now used by both `Gemma` and `Gemma3Ollama`. A new sample application, `hello_world_gemma3_ollama`, is added to demonstrate using `Gemma3Ollama` with an agent. Unit tests for `Gemma3Ollama` are also included.
Merge: https://github.com/google/adk-python/pull/3120
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 839996879
The vector_store_similarity_search tool performs similarity search against data in a Spanner vector store table, using the provided Spanner tool settings for configuration.
PiperOrigin-RevId: 839352057
The Gemini API may not always send an explicit transcription finished signal. This change ensures that any buffered input or output transcription text is yielded as a finished transcription when a turn is completed, generation is complete, or the session is interrupted.
Also, refined the check for `event.partial` in runners.py to be more explicit.
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 839008606
Merge https://github.com/google/adk-python/pull/3700
### Description
This PR refactors the `adk_stale_agent` to address `429 RESOURCE_EXHAUSTED` errors encountered during workflow execution. The previous implementation was inefficient in fetching issue history (using pagination over the REST API) and lacked server-side filtering, causing excessive API calls and huge token consumption that breached Gemini API quotas.
The new implementation switches to a **GraphQL-first approach**, implements server-side filtering via the Search API, adds robust concurrency controls, and significantly improves code maintainability through modular refactoring.
### Root Cause of Failure
The previous workflow failed with the following error due to passing too much context to the LLM and processing too many irrelevant issues:
```text
google.genai.errors.ClientError: 429 RESOURCE_EXHAUSTED.
Quota exceeded for metric: generativelanguage.googleapis.com/generate_content_paid_tier_input_token_count
```
### Key Changes
#### 1. Optimization: REST → GraphQL (`agent.py`)
* **Old:** Fetched issue comments and timeline events using multiple paginated REST API calls (`/timeline`).
* **New:** Implemented `get_issue_state` using a single **GraphQL** query. This fetches comments, `userContentEdits`, and specific timeline events (Labels, Renames) in one network request.
* **Refactoring:** The complex analysis logic has been decomposed into focused helper functions (_fetch_graphql_data, _build_history_timeline, _replay_history_to_find_state) for better readability and testing.
* **Configurable:** Added GRAPHQL_COMMENT_LIMIT and GRAPHQL_TIMELINE_LIMIT settings to tune context depth
* **Impact:** Drastically reduces the data payload size and eliminates multiple API round-trips, significantly lowering the token count sent to the LLM.
#### 2. Optimization: Server-Side Filtering (`utils.py`)
* **Old:** Fetched *all* open issues via REST and filtered them in Python memory.
* **New:** Uses the GitHub Search API (`get_old_open_issue_numbers`) with `created:<DATE` syntax.
* **Impact:** Only fetches issue numbers that actually meet the age threshold, preventing the agent from wasting cycles and tokens on brand-new issues.
#### 3. Concurrency & Rate Limiting (`main.py` & `settings.py`)
* **Old:** Sequential execution loop.
* **New:** Implemented `asyncio.gather` with a configurable `CONCURRENCY_LIMIT` (set to 3).
* **New:** Added `urllib3` retry strategies (exponential backoff) in `utils.py` to handle GitHub API rate limits (HTTP 429) gracefully.
#### 4. Logic Improvements ("Ghost Edits")
* **New Feature:** The agent now detects "Ghost Edits" (where an author updates the issue description without posting a new comment).
* **Action:** If a silent edit is detected on a stale candidate, the agent now alerts maintainers instead of marking it stale, preventing false positives.
### File Comparison Summary
| File | Change |
| :--- | :--- |
| `main.py` | Switched from `InMemoryRunner` loop to `asyncio` chunked processing. Added execution timing and API usage logging. |
| `agent.py` | Replaced REST logic with GraphQL query. Added logic to handle silent body edits. Decomposed giant get_issue_state into helper functions with docstrings. Added _format_days helper. |
| `utils.py` | Added `HTTPAdapter` with Retries. Added `get_old_open_issue_numbers` using Search API. |
| `settings.py` | Removed `ISSUES_PER_RUN`; added configuration for CONCURRENCY_LIMIT, SLEEP_BETWEEN_CHUNKS, and GraphQL limits. |
| `PROMPT_INSTRUCTIONS.txt` | Simplified decision tree; removed date calculation responsibility from LLM. |
### Verification
The new logic minimizes token usage by offloading date calculations to Python and strictly limiting the context passed to the LLM to semantic intent analysis (e.g., "Is this a question?").
* **Metric Check:** The workflow now tracks API calls per issue to ensure we stay within limits.
* **Safety:** Silent edits by users now correctly reset the "Stale" timer.
* **Maintainability:** All complex logic is now isolated in typed helper functions with comprehensive docstrings.
Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3700 from ryanaiagent:feat/improve-stale-agent 888064eff125ae74f7c3a9ad6c74f98de80243a2
PiperOrigin-RevId: 838885530
This calls the cloudapiregistry.googleapis.com API to get MCP tools from the project's registry, and adds them to ADK.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 837166909
Merge https://github.com/google/adk-python/pull/3572
**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):**
N/A
**2. Or, if no issue exists, describe the change:**
**Problem:**
Docs 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.
Co-authored-by: Hangfei Lin <hangfei@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3572 from issacg:patch-1 b7c7ed46ff0fb018f4da1537535eff27c323daf5
PiperOrigin-RevId: 834864431
It also enables the ADK triaging agent to run periodically on planned but not triaged issues.
Co-authored-by: Xuan Yang <xygoogle@google.com>
PiperOrigin-RevId: 834489103
Updates type annotations to use built-in types like `list` and `dict`, and uses `| None` for optional types, along with adding `from __future__ import annotations`
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 832522395
This change:
* Deprecates the `save_live_audio` configuration option in `RunConfig`, introducing `save_live_blob` as its replacement. A warning is issued if `save_live_audio` is used.
* Updates `base_llm_flow.py` to use the new `save_live_blob` flag.
* Ensures that audio events generated by `audio_cache_manager.py` are properly appended to the session service.
* Adds a utility script `pcm_audio_player.py` for playing raw PCM audio files.
Input sample event: 14a5859f-6b6c-46ed-9f28-e5008793b1c6|live_bidi_streaming_multi_agent|user|1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c|e-7a28a060-29bf-4483-bc5c-17248698a897|1762916981.5932|{"content":{"parts":[{"file_data":{"file_uri":"artifact://live_bidi_streaming_multi_agent/user/1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c/_adk_live/adk_live_audio_storage_input_audio_1762916981593.pcm#0","mime_type":"audio/pcm"}}],"role":"user"},"invocation_id":"e-7a28a060-29bf-4483-bc5c-17248698a897","author":"user","actions":{"state_delta":{},"artifact_delta":{},"requested_auth_configs":{},"requested_tool_confirmations":{}},"id":"14a5859f-6b6c-46ed-9f28-e5008793b1c6","timestamp":1762916981.5932002}
output sample event:
506c9df4-e143-4ebc-90a5-2f5b2eb26754|live_bidi_streaming_multi_agent|user|1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c|e-7a28a060-29bf-4483-bc5c-17248698a897|1762916986.10579|{"content":{"parts":[{"file_data":{"file_uri":"artifact://live_bidi_streaming_multi_agent/user/1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c/_adk_live/adk_live_audio_storage_output_audio_1762916986105.pcm;rate=24000#0","mime_type":"audio/pcm;rate=24000"}}],"role":"model"},"invocation_id":"e-7a28a060-29bf-4483-bc5c-17248698a897","author":"model","actions":{"state_delta":{},"artifact_delta":{},"requested_auth_configs":{},"requested_tool_confirmations":{}},"id":"506c9df4-e143-4ebc-90a5-2f5b2eb26754","timestamp":1762916986.105794}
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 831512074
This change introduces a mechanism for users to register their own custom backend services for sessions, memory, and artifacts without modifying the ADK framework. This enhances the extensibility of ADK.
Two methods of registration are supported, both by placing a file in the parent directory of the agents.
**YAML Configuration (services.yaml or .yml)**
This is the recommended approach for simple services that can be instantiated with a constructor like MyService(uri="...", **kwargs).
Example services.yaml:
```
services:
- scheme: mysession
type: session
class: my_package.my_module.MyCustomSessionService
```
**Python Registration (services.py)**
For services requiring more complex initialization logic, users can define factory functions in a services.py file.
Example services.py
```
from google.adk.cli.service_registry import get_service_registry
from my_package.my_module import MyCustomSessionService
def my_session_factory(uri: str, **kwargs):
# custom initialization logic
return MyCustomSessionService(...)
get_service_registry().register_session_service("mysession", my_session_factory)
```
ADK will load services from services.yaml/.yml first, and then from services.py. If the same service scheme is defined in both, the registration in services.py will take precedence.
To use a registered service, specify its URI via the corresponding command-line flag, e.g., `--session_service_uri=mysession://....`
Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 831211371
The agent's instructions are updated to guide it to guess a positive integer, starting from 50 and decreasing, using the `guess_number_tool` until the target is found. The maximum number of retries for the `CustomRetryPlugin` is increased from 6 to 10.
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 830984481
Enhanced `save_artifact` in `callback_context.py` to accept `custom_metadata` and added `get_artifact_version` to retrieve artifact details.
Introduced a new sample, `context_offloading_with_artifact`, demonstrating how to use ADK artifacts to offload large data from the LLM context. The sample includes:
- `QueryLargeDataTool`: Generates mock sales reports, saves them as artifacts with custom metadata, and injects the artifact content into the LLM request immediately after creation.
- `CustomLoadArtifactsTool`: Provides summaries of available artifacts to the LLM based on metadata and loads artifact content on demand when `load_artifacts` is called.
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 830592786