To use ADK tools, users can specify the tool name in a skill object's `additional_tools` and pass the tool in when initializing a SkillToolset.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 879230409
This change introduces several improvements to the BigQuery Agent Analytics Plugin:
* **Fix 1 (High):** Error callbacks (`on_model_error_callback`, `on_tool_error_callback`) now emit `status="ERROR"` instead of defaulting to `"OK"`.
* **Fix 2 (Medium):** Schema upgrade now detects missing sub-fields in nested RECORD columns via a new recursive helper. The version label is now stamped only after the `update_table` call succeeds, ensuring failures can be retried.
* **Fix 3 (Medium):** Multi-loop `shutdown()` now drains batch processors on non-current event loops using `run_coroutine_threadsafe` before closing transports.
* **Fix 4 (Medium):** Session state is truncated before logging to prevent oversized payloads.
* **Fix 5 (Low):** String system prompts are now truncated during content parsing.
* **Fix 6 (Low):** Removed the unused `_HITL_TOOL_NAMES` frozenset.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 879147684
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:
Problem:
The agent's specific version wasn't being tracked in our telemetry data, limiting our ability to trace issues to specific agent versions. This change introduces the gen_ai.agent.version attribute to span context, defaulting to an empty string if omitted for backwards compatibility.
Solution:
We want to capture the specific version of an agent during execution by adding an optional version field to the base agent configurations (BaseAgent, BaseAgentConfig).
This solution was chosen because exposing this field directly to OpenTelemetry span attributes (gen_ai.agent.version) ensures the version is automatically recorded alongside other existing metadata (like name and description) during invocation. Defaulting the value to an empty string ensures backwards compatibility without breaking existing agent implementations that do not specify a version.
Testing Plan
- Added test_trace_agent_invocation_with_version to verify that the gen_ai.agent.version attribute is correctly captured when agent.version is populated.
- Updated existing telemetry span tests to ensure gen_ai.agent.version safely defaults to an empty string ('') when no version is provided.
Unit Tests:
- I have added or updated unit tests for my change.
- All unit tests pass locally.
Manual End-to-End (E2E) Tests:
- Tested on Agent Engine and in a local deployment.
Checklist
[x] I have read the 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.
Additional context
Add any other context or screenshots about the feature request here.
Co-authored-by: Achuth Narayan Rajagopal <achuthr@google.com>
PiperOrigin-RevId: 878835568
Merge https://github.com/google/adk-python/pull/4648
**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: #4647
- Related: #3429, #3430
**2. Or, if no issue exists, describe the change:**
**Problem:**
`AgentLoader.list_agents()` returns every non-hidden subdirectory in the agents directory, regardless of whether it contains a valid agent definition. This causes non-agent directories (e.g. `tmp/`, `data/`, `utils/`) to appear in the `/list-apps` API response. This affects both the ADK web UI agent selector and any production deployment depending on this API.
**Solution:**
Reuse the existing `_determine_agent_language()` method inside `list_agents()` to verify each candidate directory contains at least one recognized agent file (`root_agent.yaml`, `agent.py`, or `__init__.py`). Directories that fail this check are excluded from the result. This avoids introducing any new methods or abstractions and keeps the check lightweight (filesystem only, no agent imports).
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
27 passed in 2.85s:
pytest tests/unittests/cli/utils/test_agent_loader.py -v
======================= 27 passed, 14 warnings in 2.85s ========================
Added `test_list_agents_excludes_non_agent_directories` which creates a temp directory with three valid agent types (package with `__init__.py`, module with `agent.py`, YAML with `root_agent.yaml`) and three non-agent directories, and asserts only the valid agents are listed.
**Screenshots / Video:**
| Before (non-agent directories listed) | After (only valid agents listed) |
|----------------------------------------|----------------------------------|
|<img width="566" height="553" alt="Image" src="https://github.com/user-attachments/assets/0f50084b-319f-480e-8d8a-051c28d4a7e7" />|<img width="567" height="532" alt="Image" src="https://github.com/user-attachments/assets/52d3543f-4c4c-4ff3-a6dd-7d5ce3f19bb2" />|
**Manual End-to-End (E2E) Tests:**
1. Create a project directory containing both valid agent subdirectories and non-agent subdirectories
2. Run `adk web .`
3. Open the web UI and verify only valid agents appear in the agent selector
4. See screenshots below for before/after comparison
### 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.
- [ ] Any dependent changes have been merged and published in downstream modules.
### Additional context
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4648 from markadelnawar:fix/list-agents-filter-non-agents-dirs 041895610fa0c52f2bf3cf7ba0d072a5c580c1b6
PiperOrigin-RevId: 878674609
The `_extract_reasoning_value` function now checks for both 'reasoning_content' and 'reasoning' fields in LiteLLM messages, with 'reasoning_content' taking precedence
Close#3694
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 878668213
Merge https://github.com/google/adk-python/pull/4618
## Summary
Fixes#4564
When using `output_key` with a `temp:` prefix (e.g. `output_key='temp:result'`) in a `SequentialAgent`, the output was silently lost. Agent-2 could never read the temp state written by agent-1.
## Root Cause
Two issues in `append_event`:
1. `_trim_temp_delta_state()` removed temp keys from the event delta **before** `_update_session_state()` could apply them to the in-memory session
2. `_update_session_state()` also explicitly skipped `temp:`-prefixed keys
```python
# Before (broken ordering):
async def append_event(self, session, event):
event = self._trim_temp_delta_state(event) # temp keys gone!
self._update_session_state(session, event) # nothing to apply
```
## Fix
Introduce `_apply_temp_state()` which writes temp-scoped keys to the in-memory `session.state` **before** the event delta is trimmed:
```python
# After:
async def append_event(self, session, event):
self._apply_temp_state(session, event) # temp keys → session.state
event = self._trim_temp_delta_state(event) # temp keys removed from delta
self._update_session_state(session, event) # non-temp keys applied
```
This ensures:
- ✅ Temp state is available to subsequent agents within the same invocation
- ✅ Temp state is still stripped from event deltas (not persisted to storage)
- ✅ All three session services (InMemory, Database, SQLite) behave consistently
## Files Changed
- `src/google/adk/sessions/base_session_service.py`: Added `_apply_temp_state()`, reordered `append_event` logic, removed temp-skip in `_update_session_state`
- `src/google/adk/sessions/database_session_service.py`: Added `_apply_temp_state()` call before trim
- `src/google/adk/sessions/sqlite_session_service.py`: Added `_apply_temp_state()` call before trim
- `tests/unittests/sessions/test_session_service.py`: Updated existing test + added new test for sequential agent scenario
## Testing
All 67 session service tests pass across InMemory, Database, and SQLite backends.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4618 from stakeswky:fix/temp-state-output-key b9fc737e7a6dc07e06e99af3271a8fc026acae4a
PiperOrigin-RevId: 878499263
This change introduces compatibility of the remote_a2a_agent with the new a2a_agent_executor.
New Event Converters:
`to_adk_event.py`= Defines a new set of default converters for transforming A2A types (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) into ADK Event objects.
Configurable Remote Agent:
The A2aRemoteAgentConfig object allows users to override the default event converters with custom ones.
New AgentExecutor Compatibility:
RemoteA2aAgent now checks for `agent_executor_v2` metadata in A2A responses.
If detected, it delegates response handling to a new `_handle_a2a_response_impl` method, which utilizes the modular converters defined in the configuration.
PiperOrigin-RevId: 878487448
Previous rollback CL - cl/872951141
This change introduces a new search_catalog tool within the BigQuery toolset, enabling users to search for BigQuery assets across projects using the Dataplex Catalog API.
Key changes include:
- Adding google-cloud-dataplex as a dependency in pyproject.toml.
- Updating BigQuery credentials to include the Dataplex scope.
- Implementing get_dataplex_catalog_client in client.py to create Dataplex API clients.
- Creating search_tool.py with the search_catalog function, which constructs and executes Dataplex search queries.
- Adding extensive unit tests for the new Dataplex client and the search_catalog tool, covering various scenarios including query filtering and error handling.
- Updating the BigQuery toolset to include the new search_catalog tool.
- Updating the BigQuery samples README to mention the new tool.
PiperOrigin-RevId: 878435463
This change introduces new implementation files for the A2aAgentExecutor and event converters. The existing A2aAgentExecutor now acts as a wrapper, allowing a switch between the legacy and new implementations. The new implementation includes support for execution interceptors and a dedicated executor context.
Main Changes=
`a2a_agent_executor_impl.py` = the new implementation of the AgentExecutor differs from the legacy one (`a2a_agent_executor.py`) for the removal of the TaskResultAggregator and the explicit `InvocationContext` creation. Instead, it uses `ExecutorContext` and delegates event conversion to the new logic that supports streaming. It maintains an `agents_artifact` state map to handle partial updates and emits TaskArtifactUpdateEvents for content. The `long_running_functions.py` is used to keep track of the LongRunning FunctionCalls and respective FunctionResponse, to emit them at the end of the generation loop in a `TaskStateUpdateEvent(input-required/auth-required)`.
`from_adk_event.py` = this file replaces the conversion functions in the `event_converter.py` used to convert the adk events into a2a events, estrapolating them in a dedicated file. The main changes in the methods are the introduction of TaskArtifactUpdateEvent to handle content parts, allowing for true artifact streaming and chunking. It utilizes an `agents_artifacts` dictionary to track artifact IDs across partial events to correctly handle append operations.
PiperOrigin-RevId: 878399140
This change introduces an `ensure_part` helper function that normalizes input to `types.Part`. This allows `save_artifact` methods in `FileArtifactService`, `GcsArtifactService`, and `InMemoryArtifactService` to accept dictionaries, including those with camelCase keys as used by Agentspace, and convert them into proper `types.Part` instances before saving
Close#2886
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 878131948
This change enables round-tripping of EventCompaction data by storing it within the event's custom_metadata under the key "_compaction" when appending events. When retrieving events, the "_compaction" data is extracted from custom_metadata and used to populate the EventActions.compaction field. This is a temporary measure until the Vertex AI SDK's SessionEvent model supports a dedicated compaction field.
Close#3465
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 878128265
Only acquire FOR UPDATE locks on app and user state rows when the event's state_delta contains changes for those specific scopes. This avoids unnecessary locking on state rows that are not being modified, improving concurrency.
Close#4655
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 878108562
details:
* Uses GEPA (https://gepa-ai.github.io/gepa/) to optimize the instructions for the root agent. Can be extended to sub-agents and other components in the future.
* GEPA package is imported dynamically; you do not need to install it along with ADK unless you plan to use this optimizer.
Co-authored-by: Keyur Joshi <keyurj@google.com>
PiperOrigin-RevId: 878009649
Refactor ToolResultBlockParam content handling to use json.dumps for dict/list results.
Implement _generate_content_streaming to handle Anthropic's streaming API
Close#3250
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 877613612
- **Fork-safety (#4636):** Adds PID tracking to `BigQueryAgentAnalyticsPlugin` so that forked child processes detect stale gRPC channels and re-initialize instead of deadlocking. Uses the standard `os.getpid()` pattern (same as SQLAlchemy, gRPC-python).
- **Auto-create views (#4639):** After ensuring the `agent_events` table exists, automatically creates 15 per-event-type BigQuery views (`v_llm_request`, `v_tool_completed`, etc.) that unnest JSON columns into typed, queryable columns. Controlled by `BigQueryLoggerConfig.create_views` (default `True`), idempotent via `CREATE OR REPLACE VIEW`.
- **Trace-ID continuity & o11y alignment (#4645):** Fixes trace_id fracture between early events (USER_MESSAGE_RECEIVED, INVOCATION_STARTING) and later events (AGENT_STARTING onwards) when no ambient OTel span exists. Also aligns BQ rows with Cloud Trace span IDs when o11y is active.
- **Span-ID consistency under ambient OTel (#4640 review):** Fixes `*_STARTING` / `*_COMPLETED` events producing mismatched span IDs when an ambient OTel span is active. Completion callbacks now check for ambient spans and defer to `_resolve_ids` Layer 2 instead of overriding with plugin-synthetic IDs.
- **Stack leak safety (#4640 review):** Adds `TraceManager.clear_stack()` and makes `ensure_invocation_span()` clear stale records from *different* invocations, preventing span stack leaks across invocations. Uses `_active_invocation_id_ctx` to distinguish stale leak vs same-invocation re-entry.
- **Root agent name staleness fix:** `init_trace()` now refreshes `_root_agent_name_ctx` unconditionally on each invocation (previously set-once-on-None). `after_run_callback` resets it alongside other invocation cleanup.
- **Exception-safe cleanup:** `after_run_callback` uses `try/finally` to guarantee invocation state (`clear_stack`, `_active_invocation_id_ctx`, `_root_agent_name_ctx`) is always reset, even if `_log_event` raises.
- **`on_tool_error_callback` span fix:** Previously discarded the span_id from `pop_span()`, causing TOOL_ERROR events to get the wrong span. Now captures and uses the popped span_id.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 877580395
This change updates the part_converter to ensure that the name field in a2a_types.FileWithUri and a2a_types.FileWithBytes is correctly mapped to the display_name field in genai_types.FileData and genai_types.Blob, respectively, during conversions between A2A and Genai Part types. Tests are updated to verify this propagation in both directions.
PiperOrigin-RevId: 877507283
LiteLlm provides built-in handling for tool and response format compatibility across different providers, allowing output schemas to be used reliably with tools for any LiteLlm instance
Close#3969
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 877471153
When handling a /run_sse request that includes a functionCallEventId, do not split events that contain both content and artifactDelta
Close#4487
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 877435561
Escape Click’s Wrapping in `adk deploy agent_engine` example
Merge https://github.com/google/adk-python/pull/4337
### Link to Issue or Description of Change
**2. Or, if no issue exists, describe the change:**
**Problem:**
`adk deploy agent_engine` help message loses newlines in docstring formatting
<img width="749" height="257" alt="スクリーンショット 2026-01-31 13 29 18" src="https://github.com/user-attachments/assets/ede7d9e7-609d-4412-acce-c80e24ec1e2f" />
**Solution:**
Add `\b` on a line by itself before the formatted block
### Testing Plan
This is format improvement of help message, so I think there is no need to add test case.
**Unit Tests:**
- [ ] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
```
% pytest tests/unittests/cli # Python 3.13.8
======================= 260 passed, 140 warnings in 7.73s ========================
```
**Manual End-to-End (E2E) Tests:**
Ran `adk deploy agent_engine --help`, then saw
```
Example:
# With Express Mode API Key
adk deploy agent_engine --api_key=[api_key] my_agent
# With Google Cloud Project and Region
adk deploy agent_engine --project=[project] --region=[region]
--display_name=[app_name] my_agent
```
### 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.
### Additional context
Same solution as #4258
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4337 from ftnext:escape-wrapping-deploy-agent-engine-example 09440380dd5b1e14a48151eba1b808def8ae3b6a
PiperOrigin-RevId: 877205878
Merge https://github.com/google/adk-python/pull/4462
**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
**2. Or, if no issue exists, describe the change:**
**Problem:**
I found a typo: arethemselves
>/.../adk-python/src/google/adk/a2a/converters/event_converter.py:245: UserWarning: [EXPERIMENTAL] convert_a2a_message_to_event: ADK Implementation for A2A support (A2aAgentExecutor, RemoteA2aAgent and corresponding supporting components etc.) is in experimental mode and is subjected to breaking changes. A2A protocol and SDK arethemselves not experimental. Once it's stable enough the experimental mode will be removed. Your feedback is welcome.
**Solution:**
Just fix
### Testing Plan
This is typo fix
**Unit Tests:**
N/A
**Manual End-to-End (E2E) Tests:**
N/A
### 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.
- [ ] I have manually tested my changes end-to-end.
- [ ] Any dependent changes have been merged and published in downstream modules.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4462 from ftnext:fix-typo-a2a-experimental-warning a117314eb524dd93351e17f2183eea080225e43e
PiperOrigin-RevId: 877095788
1. For prototyping and testing purposes, sandbox name can be provided, and it will be used for all requests across the lifecycle of an agent
2. If no sandbox name is provided, agent engine name will be provided, and we will automatically create one sandbox per session, and the sandbox has TTL set for a year.
If the sandbox stored in the session hits the TTL, it will not be in "STATE_RUNNING" so a new sandbox will be created.
Co-authored-by: Lusha Wang <lusha@google.com>
PiperOrigin-RevId: 876450610
details:
* Enables the use of ADK evaluations via LocalEvalService for optimizing agents.
* Provides flexibility in choosing eval sets and eval cases for training and validation.
* Converts ADK eval results into a compact format useful for whitebox agent optimization.
Co-authored-by: Keyur Joshi <keyurj@google.com>
PiperOrigin-RevId: 875818012
Merge https://github.com/google/adk-python/pull/4572
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #4496
**2. Or, if no issue exists, describe the change:**
**Problem:**
`LoggingPlugin` overrides 12 callback methods from `BasePlugin` but none use the `@override` decorator. Every other plugin in the package (`DebugLoggingPlugin`, `ReplayPlugin`, `RecordingsPlugin`, `EnsureRetryOptionsPlugin`, `_RequestIntercepterPlugin`) already follows this practice. With `mypy --strict` enabled in `pyproject.toml`, missing `@override` means renamed or removed base-class methods would be silently missed in `LoggingPlugin` while being caught everywhere else.
**Solution:**
Import `override` from `typing_extensions` and decorate all 12 overridden callbacks. Purely additive: one import line and 12 decorators. No behavioral, API, or runtime change.
### Testing Plan
**Unit Tests:**
- [ ] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
No new tests are required — `@override` is a static-analysis-only decorator with no runtime effect. Ran `mypy` on the file before and after the change: same preexisting warnings, no new errors introduced. CI will validate via the existing test suite and linting checks.
**Manual End-to-End (E2E) Tests:**
Not applicable. This change adds only decorators with no runtime behavior. Verified by comparing `mypy` output before and after — no new errors.
### 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.
- [ ] 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.
- [ ] I have manually tested my changes end-to-end.
- [ ] Any dependent changes have been merged and published in downstream modules.
### Additional context
I am the author of the original issue (#4496). A previous PR (#4544) was opened but is pending clarification, so I'm
submitting this complete PR as the original issue author.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4572 from cchinchilla-dev:feat/add_override_decorators_to_loggingplugin_4496 142ed872bee39db782c1dccb84f40906ee849bb8
PiperOrigin-RevId: 875811966
This change adds a new `a2a` subpackage with configuration and utility functions for intercepting requests and responses in `RemoteA2aAgent`. The `RemoteA2aAgent` now accepts an `A2aRemoteAgentConfig` to register `RequestInterceptor` instances, allowing custom logic to be executed before and after the A2A message send.
PiperOrigin-RevId: 875559286
invocation_id is no longer required in resuming case, unless no new_message is provided.
Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 875432024
This change makes DEFAULT_SKILL_SYSTEM_INSTRUCTION raise a UserWarning when accessed, indicating that its content is experimental and subject to change in minor/patch releases. The constant is also made "private" internally.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 875288217
Merge https://github.com/google/adk-python/pull/4531
**Problem:**
JSON Schema allows `true` and `false` as valid boolean schemas, where `true` accepts any value and `false` rejects all values. Some MCP servers use this pattern for unconstrained fields. E.g. [mcp-grafana](https://github.com/grafana/mcp-grafana) - see [grafana-mcp-list-tools.json](https://github.com/user-attachments/files/25392430/grafana-mcp-list-tools.json) which was obtained from `tools/list`
The schema sanitizer previously passed booleans through unchanged, causing a Pydantic ValidationError when `_ExtendedJSONSchema` tried to validate them as schema objects.
```
1 validation error for _ExtendedJSONSchema
properties.data.items.properties.model
Input should be a valid dictionary or object to extract fields from [type=model_attributes_type, input_value=True, input_type=bool]
For further information visit https://errors.pydantic.dev/2.12/v/model_attributes_type
Traceback (most recent call last):
...
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 561, in run_async
async for event in agen:
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 549, in _run_with_trace
async for event in agen:
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 778, in _exec_with_plugin
async for event in agen:
...<64 lines>...
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 538, in execute
async for event in agen:
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/agents/base_agent.py", line 294, in run_async
async for event in agen:
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/agents/llm_agent.py", line 468, in _run_async_impl
async for event in agen:
...<5 lines>...
should_pause = True
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 427, in run_async
async for event in agen:
last_event = event
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 446, in _run_one_step_async
async for event in agen:
yield event
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 578, in _preprocess_async
await tool.process_llm_request(
tool_context=tool_context, llm_request=llm_request
)
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/tools/base_tool.py", line 129, in process_llm_request
llm_request.append_tools([self])
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/models/llm_request.py", line 255, in append_tools
declaration = tool._get_declaration()
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/tools/mcp_tool/mcp_tool.py", line 200, in _get_declaration
parameters = _to_gemini_schema(input_schema)
File "/.foo/.venv/lib/python3.13/site-packages/google/adk/tools/_gemini_schema_util.py", line 218, in _to_gemini_schema
json_schema=_ExtendedJSONSchema.model_validate(sanitized_schema),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "/.foo/.venv/lib/python3.13/site-packages/pydantic/main.py", line 716, in model_validate
return cls.__pydantic_validator__.validate_python(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
obj,
^^^^
...<5 lines>...
by_name=by_name,
^^^^^^^^^^^^^^^^
)
^
pydantic_core._pydantic_core.ValidationError: 1 validation error for _ExtendedJSONSchema
properties.data.items.properties.model
Input should be a valid dictionary or object to extract fields from [type=model_attributes_type, input_value=True, input_type=bool]
For further information visit https://errors.pydantic.dev/2.12/v/model_attributes_type
```
**Solution:**
Convert boolean schemas to `{"type": "object"}` as the closest approximation available in Gemini's schema model.
Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4531 from onematchfox:fix-gemini-schema-bool 383ac0c0c3ab78d77be4503f5d6b9ad26c41b0db
PiperOrigin-RevId: 875219362
When converting an A2A TextPart to a GenAI Part, extract the 'thought' field from the TextPart's metadata and include it in the GenAI Part.
PiperOrigin-RevId: 875129430
Introduces RunSkillScriptTool to execute scripts located in a skill's scripts/ directory.
The execution logic is isolated within a dedicated SkillScriptCodeExecutor wrapper instantiated by RunSkillScriptTool. This wrapper manages script materialization in a temporary directory and executes Python (via runpy) or Shell scripts (returning standard output or JSON-encoded envelopes).
This isolation eliminates the need to modify the underlying `BaseCodeExecutor` interface or implementations (`unsafe_local_code_executor`, etc.) to support working directories or file paths.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 875012237
This change introduces a new `client` parameter to the `Gemini` model's constructor. When provided, this preconfigured `google.genai.Client` instance is used for all API calls, offering fine-grained control over authentication, project, and location settings
Close#2560
PiperOrigin-RevId: 874752355
1. For prototyping and testing purposes, sandbox name can be provided, and it will be used for all requests across the lifecycle of an agent
2. If no sandbox name is provided, agent engine name will be provided, and we will automatically create one sandbox per session, and the sandbox has TTL set for a year.
If the sandbox stored in the session hits the TTL, it will not be in "STATE_RUNNING" so a new sandbox will be created.
PiperOrigin-RevId: 874705260
Adds use_id_token and audience fields to ServiceAccount so that
ServiceAccountCredentialExchanger can produce ID tokens instead of
access tokens. This is required for authenticating to Cloud Run, Cloud
Functions, and other Google Cloud services that verify caller identity.
Close#4458
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 874630210
This change introduces a new `client` parameter to the `Gemini` model's constructor. When provided, this preconfigured `google.genai.Client` instance is used for all API calls, offering fine-grained control over authentication, project, and location settings
Close#2560
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 874628604
1. For prototyping and testing purposes, sandbox name can be provided, and it will be used for all requests across the lifecycle of an agent
2. If no sandbox name is provided, agent engine name will be provided, and we will automatically create one sandbox per session, and the sandbox has TTL set for a year.
If the sandbox stored in the session hits the TTL, it will not be in "STATE_RUNNING" so a new sandbox will be created.
Co-authored-by: Lusha Wang <lusha@google.com>
PiperOrigin-RevId: 874415933
Get agents API design is being updated to return full AgentCard instead of agent card url - while it's being rolled out, update get agents method to instantiate agent card from existing fields.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 874285065
This change introduces a recursive function to transform JSON schemas to meet OpenAI's strict mode requirements, including adding "additionalProperties: false" to all object schemas, making all properties required, and stripping sibling keywords from $ref nodes. The schema conversion uses deep copies to not mutating the original input
Close#4573
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 874174994
This change allows users to provide a custom PushNotificationConfigStore when converting an ADK agent to an A2A Starlette application. If no custom store is provided, an InMemoryPushNotificationConfigStore is used by default, thios now lets A2A push notification configuration RPCs
Close#4126
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 874118109
The migration from requests to httpx in v1.24.0 broke ApplicationIntegrationToolset because httpx replaces the URL query string when a `params` dict is passed, even if empty. The requests library merged them instead. This extracts any query parameters embedded in the URL path into the explicit params dict before passing to httpx.
Close#4555
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 874112143
This change introduces an interceptor mechanism allowing custom logic to be executed before agent runs, after each event, and after the agent run completes. New dependencies are added to support these features.
PiperOrigin-RevId: 873952199
The default table ID for the BigQueryAgentAnalyticsPlugin is changed from "agent_events_v2" to "agent_events". The class docstring is also updated to remove the "v2.0" reference.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 873485931
This CL adds four enhancements to the BigQuery Agent Analytics plugin and fixes a span hierarchy corruption bug.
- **Schema Auto-Upgrade:** Additive-only schema migration that automatically adds missing columns to existing BQ tables on startup. A `adk_schema_version` label on the table (starting at `"1"`, bumped with each schema change) makes the check idempotent — the diff runs at most once per version. Enabled by default (`auto_schema_upgrade=True`) because upgrades are additive-only and fail-safe. Pre-versioning tables (no label) are treated as outdated, diffed, and stamped. No previous schema versions need to be stored; the logic diffs actual columns against the current canonical schema.
- **Tool Provenance:** Adds `tool_origin` to TOOL_* event content, distinguishing six origin types — `LOCAL` (FunctionTool), `MCP` (McpTool), `A2A` (AgentTool wrapping RemoteA2aAgent), `SUB_AGENT` (AgentTool), `TRANSFER_AGENT` (TransferToAgentTool), and `UNKNOWN` (fallback) — via `isinstance()` checks with lazy imports to avoid circular dependencies.
- **HITL Tracing:** Emits dedicated HITL event types (`HITL_CONFIRMATION_REQUEST`, `HITL_CREDENTIAL_REQUEST`, `HITL_INPUT_REQUEST` + `_COMPLETED` variants) for human-in-the-loop interactions. Detection lives in `on_event_callback` (for synthetic `adk_request_*` FunctionCall events emitted by the framework) and `on_user_message_callback` (for `adk_request_*` FunctionResponse completions sent by the user), not in tool callbacks — because `adk_request_*` names are synthetic function calls that bypass `before_tool_callback`/`after_tool_callback` entirely.
- **Span Hierarchy Fix (#4561):** Removes `context.attach()`/`context.detach()` calls from `TraceManager.push_span()`, `attach_current_span()`, and `pop_span()`. The plugin was injecting its spans into the shared OTel context, which corrupted the framework's span hierarchy when an external exporter (e.g. `opentelemetry-instrumentation-vertexai`) was active — causing `call_llm` to be re-parented under `llm_request` and parent spans to show shorter durations than children. The plugin now tracks span_id/parent_span_id via its internal contextvar stack without mutating ambient OTel context.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 873114688
Updates _model_response_to_chunk to better handle LiteLLM's streaming delta/message structure, including prioritizing delta when it contains meaningful content and preserving reasoning_content
Close#4225
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 873097502
Client library for the Agent Registry API that allows users to discover, look up, and connect to agents and MCP servers cataloged in the registry.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 873073675
In live mode, when the model calls an unregistered tool, ADK now runs on_tool_error_callback before failing. If the callback returns a response, ADK emits
that function response and continues; otherwise it keeps the old ValueError
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 872996178
Previously we resolved tools sequentially by awaiting _convert_tool_union_to_tools() in a loop -- reduce the latency by resolving tools concurrently.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 872979105
Merge https://github.com/google/adk-python/pull/4171
**Problem:**
The BigQuery ADK tools currently lack the ability to search for and discover BigQuery assets using the Dataplex Catalog. Users cannot leverage Dataplex's search capabilities within the ADK to find relevant data assets before querying them.
**Solution:**
This PR integrates a new search_catalog_tool into the BigQuery ADK. This tool utilizes the dataplex catalog client library to interact with the Dataplex API, allowing users to search the catalog.
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
Added the screenshots of the manual adk web UI tests - https://docs.google.com/document/d/1c_lMW7NYGKuLAvPFmSkLehbqySeNyXQIhzQlvo3ixmQ/edit?usp=sharing
### 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.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4171 from sahaajaaa:sahaajaaa-bq-adk 3dbbaa4f909cb25259e8e7d73a00a58fbe9c2f09
PiperOrigin-RevId: 872951141
This change allows `add_memory` to use the `memories.generate` API with `direct_memories_source` when `custom_metadata["enable_consolidation"]` is set to True. This enables server-side consolidation of the provided memories
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 872554004
The `add_memory` methods in `Context` and `BaseMemoryService` now accept `MemoryEntry` objects in addition to strings. The Vertex AI Memory Bank service implementation is updated to handle these new types
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 872108561
* use last-release-sha to locate the previous release commit in main for CHANGELOG generating.
* release tag can now use the commit sha in release branch
Co-authored-by: Wei Sun (Jack) <weisun@google.com>
PiperOrigin-RevId: 871909085
## Problem
When performing authentication flows via `OAUTH2` or `OPEN_ID_CONNECT`, the native `OAuth2Token` response from identity providers, like Google OAuth, often includes an `id_token` alongside the `access_token` and `refresh_token`. [MCP Toolbox](https://googleapis.github.io/genai-toolbox/resources/authservices/google/) implements authentication through ID Tokens and [integrates with ADK](https://google.github.io/adk-docs/integrations/mcp-toolbox-for-databases/) to provide easy tools management for the end-users.
However, the ADK's `update_credential_with_tokens` utility explicitly drops the `id_token`, preventing agents and tools from verifying user identity or extracting OIDC claims securely. Furthermore, the `OAuth2Auth` model does not have a designated field for `id_token`.
## Solution
1. Added an `id_token: Optional[str] = None` field to the `OAuth2Auth` pydantic model in `auth_credential.py`.
2. Updated `update_credential_with_tokens` in `oauth2_credential_util.py` to correctly extract and map `tokens.get("id_token")` into the `OAuth2Auth` credential object.
3. Updated the relevant unit tests to ensure `id_token` is asserted and preserved during credential updates.
### Testing Plan
- I have added or updated unit tests for my change.
- All unit tests pass locally.
PiperOrigin-RevId: 871801313
The list_skills method is not for model tool listing, but for giving the developer flexibility to load the skill name/description at runtime (from discussion in go/orcas-rfc-555)
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 871406905
This CL fixes several bugs in the BigQuery Agent Analytics plugin and refactors the internal data-passing pattern for better type safety and maintainability.
- **Stale Loop State Validation:** Use `loop.is_closed()` — a public, reliable API — to detect and clean up stale asyncio loop states in `_batch_processor_prop`, `_get_loop_state`, and `flush`. The previous approach used `asyncio.Queue._loop` which is `None` on Python 3.10+, causing the check to always treat states as stale.
- **Quota Project ID Fallback:** Remove the `or project_id` fallback when setting `quota_project_id` on `BigQueryWriteAsyncClient`. This fixes Workload Identity Federation flows where the federated identity lacks `serviceusage.services.use` on the quota project.
- **Kwargs Passthrough:** Pass `**kwargs` through to `_log_event` in all callbacks. Previously only model callbacks forwarded them, causing custom attributes (e.g. `customer_id`) to silently drop for agent, tool, run, and error events.
- **State Delta Logging:** Replace the dead `on_state_change_callback` (never invoked by the framework) with `on_event_callback`, which is already dispatched by the runner for every event. Remove duplicate `STATE_DELTA` logging from `after_tool_callback`.
- **EventData Dataclass:** Replace the `**kwargs`-as-data-bus pattern in `_log_event` with an explicit `EventData` dataclass. This makes the interface self-documenting, catches typos at construction time, and eliminates shared dict mutation across `_resolve_span_ids`, `_extract_latency`, and `_enrich_attributes`. All 12 callback call sites now construct typed `EventData` instances.
- **Multi-Subagent Tool Logging Tests:** Add `TestMultiSubagentToolLogging` (6 tests) verifying that tool events are correctly attributed to subagents in multi-turn, multi-agent scenarios. Total tests: 111 (up from 60).
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 871381533
When we added the session_lock_map, it resulted in pickling errors during Agent Engine deployment. To fix, we implemented custom getstate and setstate methods to exclude the lock map lock and session lock map from pickling. Closes https://github.com/google/adk-python/issues/4486.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 871056554
meanwhile also centralize input-stream creation in registration
Move the LiveRequestQueue stream creation from _call_live
(function_tool.py) to the lazy registration block in
_process_function_live_helper (functions.py). This centralizes the
input_stream: LiveRequestQueue annotation check and stream creation
in one place, and ensures the stream is also recreated on
re-invocation after stop_streaming resets it to None.
_call_live now simply passes the existing .stream if set, without
needing to know about LiveRequestQueue at all.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 869935204
add_events_to_memory now supports memory_write_mode to select generate (event-based extraction/consolidation) or create (direct raw fact writes via memory_facts). This now lets custom memory pipelines while keeping generate as the default path
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 869897256
Using one lock and checking for tables creation instead of schema version.
Closes issue #4445
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 869808097
Merge https://github.com/google/adk-python/pull/4185
**Description**
This PR resolves#4100 by making the `new_message` field optional in the `RunAgentRequest` model.
**The Problem:**
When attempting to resume an agent session via the FastAPI web server, the request would fail with a `422 Unprocessable Entity` if `new_message` was omitted. This prevented "resume-only" workflows where a user just wants to wake up an existing session.
**The Solution:**
Updated `RunAgentRequest.new_message` to be `Optional[types.Content] = None`. The underlying `runner.run_async` logic already supports `None` for resuming purposes, so no further logic changes were required.
**Verification:**
Verified that `RunAgentRequest` now validates successfully when `new_message` is missing, defaulting the field to `None`.
Co-authored-by: Liang Wu <wuliang@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4185 from Akshat8510:fix/fastapi-resume-4100 b6d252636aa5f96186507fccf47a278fe733a362
PiperOrigin-RevId: 869761179
previously we only register streaming tool that accept stream input at runner, now uniformly register all streaming tool at runner.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 869447996
currently we started to relay live request to streaming tool even when the tool was not called yet.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 869421826
`_update_type_string` lowercases Gemini-style type strings (e.g.
"STRING" -> "string") for Anthropic API compatibility. It already
recursed into `items` (arrays) and `items.properties` (arrays of
objects), but not into top-level `properties` of object types. This
caused tool schemas with nested object parameters (e.g. Pydantic
models) to produce invalid JSON Schema with uppercase type strings,
resulting in Anthropic API 400 errors.
Recurse into `properties` at every level, which also subsumes the
existing `items.properties` handling.
This can fix unit test github action error by removing `--extra eval`. `--extra a2a` is not needed because it's included in `test`. All tests are still passing.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 869014318
This allows users to load skills from a directory and pass it into the SkillToolset constructor.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 868929937
Merge https://github.com/google/adk-python/pull/4455
**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._
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4455 from google:release/candidate f660ec82ff4140ef1deea95182e6e0cc62100f89
PiperOrigin-RevId: 868877872
This enables to re-use the ADK web interface in other contexts more easily.
For example, when having an own run-time the web interface can be exposed
for visualization during development.
Also add documentation for function.
PiperOrigin-RevId: 868848338
Remove the release-please GitHub App config files and add an Actions-based
release pipeline with candidate branch strategy. This includes workflows for
cutting releases, running release-please, finalizing releases, publishing to
PyPI, and cherry-picking fixes to release candidates.
Co-authored-by: Wei Sun (Jack) <weisun@google.com>
PiperOrigin-RevId: 868825704
Merge https://github.com/google/adk-python/pull/3926
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Related: #3916
**2. Or, if no issue exists, describe the change:**
**Problem:**
While `DatabaseSessionService` already supports PostgreSQL through SQLAlchemy, there is no documentation or sample code showing users how to configure and use it.
**Solution:**
Add a comprehensive sample under `contributing/samples/postgres_session_service/` that demonstrates:
- How to configure `DatabaseSessionService` with PostgreSQL
- The auto-generated database schema (sessions, events, app_states, user_states tables)
- Connection URL format and configuration options
- A working sample agent with session persistence
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
This is a documentation-only change (new sample), so no new unit tests are required. Existing tests continue to pass.
**Manual End-to-End (E2E) Tests:**
Tested locally with the following steps:
1. Started PostgreSQL using `docker compose up -d`
2. Set environment variables:
```bash
export POSTGRES_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/adk_sessions
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
export GOOGLE_CLOUD_LOCATION=us-central1
export GOOGLE_GENAI_USE_VERTEXAI=true
```
3. Ran `pip install google-adk asyncpg greenlet` to install the required packages
4. Ran `python main.py` - session created successfully
5. Ran `python main.py` again - previous session resumed with event history
6. Verified tables and rows created in PostgreSQL (sessions, events, app_states, user_states)
### Checklist
- [x] I have read the 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.
### Additional context
This PR adds documentation and a working sample for an already-supported feature. The DatabaseSessionService class already handles PostgreSQL through its DynamicJSON type decorator which uses JSONB for PostgreSQL.
Files added:
- contributing/samples/postgres_session_service/README.md - Comprehensive guide
- contributing/samples/postgres_session_service/agent.py - Sample agent
- contributing/samples/postgres_session_service/main.py - Usage example
- contributing/samples/postgres_session_service/compose.yml - Local PostgreSQL setup
- contributing/samples/postgres_session_service/\_\_init\_\_.py - Package init
Co-authored-by: Liang Wu <wuliang@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3926 from hiroakis:feat-support-pg-for-conversation a5279d4fb2a63699f384c670928d77d882c25a25
PiperOrigin-RevId: 868816317
Merge https://github.com/google/adk-python/pull/4435
### Link to Issue or Description of Change
- Closes: #4302
**Problem:**
`VertexAiSessionService.list_sessions()` only returns the first ~100 sessions. The `sessions_iterator` from `api_client.agent_engines.sessions.list()` is an `AsyncPager` — it implements `__aiter__`/`__anext__` for fetching subsequent pages, but the code uses a plain `for` loop which only calls `__iter__`/`__next__`, so it never fetches beyond the first page.
**Solution:**
Changed `for api_session in sessions_iterator` to `async for api_session in sessions_iterator` so the `AsyncPager` actually paginates. Updated the test mock to return an `AsyncIterableList` (supports both sync and async iteration) instead of a bare list, so the tests properly simulate real `AsyncPager` behaviour.
### Testing Plan
**Unit Tests:**
```
$ pytest tests/unittests/sessions/
115 passed, 1 warning in 2.25s
```
The existing `test_list_sessions`, `test_list_sessions_with_pagination`, and `test_list_sessions_all_users` all continue to pass with the updated mock.
Co-authored-by: Liang Wu <wuliang@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4435 from anmolg1997:fix/vertex-ai-session-service-pagination 14c71b607ecbf2215f4b9ba6eb4b0ff6b9eaf740
PiperOrigin-RevId: 868466166
Sessions were being erroneously cached and reused across different asyncio event loops, causing "Event loop is closed" in environments with transient loops. This updates the session caching to be loop-aware: before reusing a cached session, check that the stored loop matches the current loop. Also, if session is disconnected and loops do not match, discard the cached entry without calling aclose().
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 868380746
Merge https://github.com/google/adk-python/pull/4288
**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: #4274
**2. Or, if no issue exists, describe the change:**
N/A - Issue exists
### 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:**
- [X] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
$ pytest tests/unittests/cli/ -v
============================= test session starts ==============================
platform darwin -- Python 3.11.14, pytest-9.0.2, pluggy-1.6.0
collected 246 items
...
====================== 246 passed, 147 warnings in 21.38s ======================
**Manual End-to-End (E2E) Tests:**
1. Verify CLI flag is recognized:
$ adk api_server --help | grep auto_create_session --auto_create_session
Automatically create a session if it doesn't exist when calling /run.
2. Start server with flag enabled:
$ adk api_server --auto_create_session
3. Test /run endpoint without pre-creating session:
$ curl -X POST http://localhost:8000/run \
-H "Content-Type: application/json" \
-d '{"app_name": "my_agent", "user_id": "user1", "session_id": "new_session", "new_message": {"role": "user", "parts": [{"text": "Hello"}]}}'
Expected: Session auto-created, request succeeds (no 404 error).
### 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.
### Additional context
This PR exposes the existing Runner.auto_create_session functionality (added in commit 8e69a58 / ADK v1.23.0) through the adk api_server CLI command.
Files changed (3 files, ~15 lines):
src/google/adk/cli/cli_tools_click.py - Add --auto_create_session CLI option
src/google/adk/cli/fast_api.py - Pass parameter through get_fast_api_app()
src/google/adk/cli/adk_web_server.py - Store and use in _create_runner()
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4288 from ekimcodes:main 3c8d299a88b21789431dbda488befba7ee3ace81
PiperOrigin-RevId: 868361303
Merge https://github.com/google/adk-python/pull/3975
### Link to Issue or Description of Change
Fixing various typos: see commit diffs for details
**1. Link to an existing issue (if applicable):**
- Closes: N/A
- Related: N/A
**2. Or, if no issue exists, describe the change:**
Fixing various typos: see commit diffs for details
**Problem:**
Improve quality of repo
**Solution:**
Pull this P/R
### Testing Plan
N/A
**Unit Tests:**
- [N/A] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
**Manual End-to-End (E2E) Tests:**
N/A
### 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.
- [N/A] I have commented my code, particularly in hard-to-understand areas.
- [N/A] 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.
- [N/A] I have manually tested my changes end-to-end.
- [N/A] Any dependent changes have been merged and published in downstream modules.
### Additional context
N/A
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3975 from didier-durand:fix-typos-b ca1cba4e7afe99bb60efffb4de79a2bfe8522ea8
PiperOrigin-RevId: 868308215
Adds optional token_limit and event_retention_size fields to EventsCompactionConfig. When the latest prompt token count meets/exceeds the threshold, ADK compacts older raw events after the invocation and keeps the last N events un-compacted. Updates prompt history building to apply compaction ranges correctly so retained events remain visible.
Close#4146
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 868297968
These endpoints provide basic health checks and version information for the running ADK server, including the ADK version and Python runtime details. The version information will be used to generate ADK conformance test report.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 868283421
Adds BaseMemoryService.add_events_to_memory(session, events=..., custom_metadata=...) and CallbackContext.add_events_to_memory(events=..., custom_metadata=...) so callers can add memories from an explicit subset of ADK events.
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 868261578
Adds a logger.exception call to capture traceback and error details when an exception occurs during the execution of a coroutine within an MCP session, before re-raising it as a ConnectionError.
PiperOrigin-RevId: 868253547
Merge https://github.com/google/adk-python/pull/3944
### 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:** fixing various typos in multiple files: see commit diffs for details
**Problem:**
Discovered typos while reading ADK repo
**Solution:**
Submitted this PR to fix them
### Testing Plan
N/A: changes only in comments, .md and docstrings.
**Unit Tests:**
- [N/A ] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
**Manual End-to-End (E2E) Tests:**
N/A
### 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.
- [N/A] I have commented my code, particularly in hard-to-understand areas.
- [N/A] 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.
- [N/A] I have manually tested my changes end-to-end.
- [N/A] Any dependent changes have been merged and published in downstream modules.
### Additional context
N/A
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3944 from didier-durand:fix-typos-a 02378a488d9a87ac9b6b7397fe9ad7c393faf16a
PiperOrigin-RevId: 868245940
This change introduces new FastAPI endpoints in adk_web_server.py and corresponding client methods in adk_web_server_client.py to allow fetching metadata for artifact versions without downloading the artifact content
Close#3710
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 868217569
Merge https://github.com/google/adk-python/pull/4365
## Summary
- Fixes `DataError` when using PostgreSQL with `asyncpg` for session storage
- PostgreSQL's default `TIMESTAMP` type is `WITHOUT TIME ZONE`, which cannot accept timezone-aware datetime objects
- The existing code handled this for SQLite but not PostgreSQL - this fix applies the same timezone stripping
## Error
When creating a session with PostgreSQL + asyncpg, the following error occurs:
```
sqlalchemy.dialects.postgresql.asyncpg.Error: <class 'asyncpg.exceptions.DataError'>:
invalid input for query argument $5: datetime.datetime(2026, 2, 3, 21, 32, 50, 353909,
tzinfo=datetime.timezone.utc) (can't subtract offset-naive and offset-aware datetimes)
```
During the INSERT:
```sql
INSERT INTO sessions (app_name, user_id, id, state, create_time, update_time)
VALUES ($1, $2, $3, $4, $5, $6)
```
Where `$5` and `$6` are timezone-aware datetimes being inserted into `TIMESTAMP WITHOUT TIME ZONE` columns.
## Root Cause
Commit 1063fa53 changed from database-generated timestamps (`func.now()`) to explicit Python datetimes (`datetime.now(timezone.utc)`). The SQLite case was handled by stripping the timezone, but PostgreSQL was overlooked.
## Test plan
- [x] Verified fix resolves the error when creating sessions with PostgreSQL + asyncpg
- [ ] Existing unit tests pass
Fixes regression from #1733
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4365 from filipecaixeta:fix-postgresql-timestamp-timezone 9d788ba99e7167a53962d93e59a80f78af091ca9
PiperOrigin-RevId: 867800330
This change introduces an in-process `asyncio.Lock` per session to serialize `append_event` calls for the same session ID within a single process. For supported database dialects (MySQL, PostgreSQL, MariaDB), it also uses `SELECT ... FOR UPDATE` to acquire row-level locks on the session, app state, and user state records, preventing race conditions across different processes or database connections. A new test case verifies that concurrent updates to stale session objects correctly merge all state changes.
Close#1049
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 867752676
Merge https://github.com/google/adk-python/pull/3462
**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:**
**Problem:**
When using adk in streaming mode, `usage_metadata.prompt_token_count` may be `None` which will emit log
```Invalid type NoneType for attribute 'gen_ai.usage.input_tokens' value. Expected one of ['bool', 'str', 'bytes', 'int', 'float'] or a sequence of those types```
**Solution:**
Skip setting span attribute if prompt token count is None
**Unit Tests:**
- [x] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
### 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.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3462 from wsa-2002:prompt-token-count-may-be-none-in-streaming-mode 94666862f70ed2577d5c55485e67f6da36a57bc6
PiperOrigin-RevId: 867693355
Function call and response IDs generated by ADK are now preserved in the LLM request contents when the agent is using a Gemini model with `use_interactions_api` enabled
Close#4381
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 867675945
This change updates the VertexAiMemoryBankService to utilize the asynchronous interface provided by `vertexai.Client().aio`. This involves:
- Retrieving the async client via `_get_api_client().aio`.
- Awaiting calls to `generate` and `retrieve`.
- Using `async for` to iterate over the results of the `retrieve` method, as it now returns an async iterator
Close#4386
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 867675311
The schema sanitization utility now recursively processes list items, ensuring that properties with list values (e.g., "required") are correctly handled and not altered.
Close#4363
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 867663267
Merge https://github.com/google/adk-python/pull/4324
**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: #4320
**2. Or, if no issue exists, describe the change:**
**Problem:**
Was using print instead of logger for warning message
**Solution:*
Refactored
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
**Manual End-to-End (E2E) Tests:**
### 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.
- [ ] Any dependent changes have been merged and published in downstream modules.
### Additional context
_Add any other context or screenshots about the feature request here._
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4324 from DineshThumma9:logger_in_mcp_session_clean 5eaa9bdc8c3c6697e75b0e876f043d496dd8ee95
PiperOrigin-RevId: 867601662
If the user specifies use_mcp_resources=True in their MCPToolset, the agent will be able to load resources with the load_mcp_resource_tool.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 866539602
The definition of an "invocation" for context filtering has been updated. An invocation now starts with a user message and can include multiple model turns (like the tool calls and responses) until the next user message. The filtering logic has been rewritten to identify invocation start points based on human user messages
Close#4296
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 866023290
The `tzlocal` library and the logging of the local timezone were not used in the `DatabaseSessionService` logic.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 865677320
Merge https://github.com/google/adk-python/pull/4338
### Link to Issue or Description of Change
**2. Or, if no issue exists, describe the change:**
**Problem:**
Click collapses intended bullet lists in the service URI options.
<img width="709" height="267" alt="image" src="https://github.com/user-attachments/assets/5f74d8a6-f343-41a4-ba6d-570ed0076932" />
**Solution:**
Add `\b` on a line by itself before the formatted block to preserve blank lines.
### Testing Plan
This is format improvement of help message, so I think there is no need to add test case.
**Unit Tests:**
- [ ] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
```
% pytest tests/unittests/cli # Python 3.13.8
===================================== 260 passed, 140 warnings in 9.30s ======================================
```
**Manual End-to-End (E2E) Tests:**
`adk web --help`
```
--session_service_uri TEXT Optional. The URI of the session service. If set, ADK uses this service.
If unset, ADK chooses a default session service (see
--use_local_storage).
- Use 'agentengine://<agent_engine>' to connect to Agent Engine
sessions. <agent_engine> can either be the full qualified resource
name 'projects/abc/locations/us-central1/reasoningEngines/123' or
the resource id '123'.
- Use 'memory://' to run with the in-memory session service.
- Use 'sqlite://<path_to_sqlite_file>' to connect to a SQLite DB.
- See https://docs.sqlalchemy.org/en/20/core/engines.html#backend-specific-urls
for supported database URIs.
```
### 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.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4338 from ftnext:escape-wrapping-web-options-bullet-list 9466731aff293d241cc7ae5728bc3c34c5c89dd6
PiperOrigin-RevId: 865533252
Merge https://github.com/google/adk-python/pull/4335
Fixed 'the the' typos and grammatical errors in README, docstrings, and sample agents.
**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: N/A
- Related: N/A
**2. Or, if no issue exists, describe the change:**
**Problem:**
While exploring the repository, I noticed a few minor writing errors that impact professional readability:
1. **Grammar:** A subject-verb agreement error in `README.md` and `llms.txt` ("guide the agents works together").
2. **Duplicate Words:** Several instances of stuttering typos (repeating "the the" or "but the the") in docstrings within `src/` and the `contributing/samples/` directories.
**Solution:**
I have applied the following fixes to improve documentation quality:
* Corrected phrasing to "guide the agents to work together" in the README.
* Removed redundant instances of "the" in `eval_metrics.py`, `spanner/settings.py`, and the sample agent docstrings.
* **No functional code or logic was altered.**
### Testing Plan
**Unit Tests:**
- [x] All unit tests pass locally.
_Summary:_
Since this PR is strictly limited to documentation, comments, and docstrings, no new tests were required. I ran the standard test suite to ensure no syntax errors were accidentally introduced, and everything passed successfully.
**Manual End-to-End (E2E) Tests:**
N/A — This is a static documentation fix.
### 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. (N/A)
- [ ] I have added tests that prove my fix is effective or that my feature works. (N/A - Doc fix only)
- [x] New and existing unit tests pass locally with my changes.
- [ ] I have manually tested my changes end-to-end. (N/A)
- [x] Any dependent changes have been merged and published in downstream modules.
### Additional context
_None._
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4335 from 88448844:fix-typos-and-docs 200668dad0c216b81d7008d9d6625ac135c9006e
PiperOrigin-RevId: 865530036
The /run_live websocket endpoint now accepts proactive_audio, enable_affective_dialog, and enable_session_resumption as query parameters. These parameters control the corresponding settings within the RunConfig used for the live session
Close#4263
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 865441673
Relax version constraints for opentelemetry-api and opentelemetry-sdk to allow versions between 1.36.0 and 1.40.0
Close#4229
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 864896212
This change sets `pool_pre_ping=True` in SQLAlchemy engine kwargs for database backends other than SQLite. This helps ensure that connections from the pool are still valid before being used, preventing issues with stale or disconnected connections. Tests are added to verify the default behavior and that explicit overrides are respected
Close#4211
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 864886767
This change updates the credential key generation to use a stable hash (SHA256) instead of Python's built-in hash, which can vary based on PYTHONHASHSEED. It also makes sure that temporary or exchanged OAuth2 fields are excluded from the key calculation. I also added when saving credentials, a copy of the AuthConfig is used to avoid modifying the original shared AuthConfig instance with user-specific exchanged credentials.
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 864599326
This property is a compatibility alias that returns the update timestamp as a POSIX timestamp. It infers whether the database is SQLite using sqlalchemy.inspect to call get_update_timestamp correctly
Close#4334
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 864595914
Problem: The test test_openapi_json_schema_accessible was failing because Pydantic couldn't generate a JSON schema for mcp.client.session.ClientSession, which is part of genai_types.ToolListUnion.
Root Cause: The AgentDetails model in src/google/adk/evaluation/app_details.py:37 had tool_declarations: genai_types.ToolListUnion, and ToolListUnion includes mcp.client.session.ClientSession which doesn't have Pydantic core schema support. This model is used in the FastAPI app through EvalCase → Invocation → AppDetails → AgentDetails, causing OpenAPI schema generation to fail.
Solution: Changed the type annotation from genai_types.ToolListUnion to list[Any] in two places:
AgentDetails.tool_declarations
_ToolDeclarations.tool_declarations
This allows Pydantic to generate the OpenAPI schema while maintaining runtime compatibility (the field still accepts the same values).
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 863765002
Update existing toolsets to utilize the new toolset authentication framework. Key changes:
- McpToolset: Add _auth_config instance variable, _get_auth_headers()
method to build auth headers from exchanged credentials, and
get_auth_config() override. Auth headers are now included when
creating MCP sessions.
- OpenAPIToolset: Add _auth_config and get_auth_config() to expose
auth configuration to the framework.
- ApplicationIntegrationToolset: Add _auth_config and get_auth_config().
- APIHubToolset: Add _auth_config and get_auth_config().
When ADK resolves toolset auth before calling get_tools(), it populates exchanged_auth_credential on the auth_config. Toolsets can then use this credential when making authenticated requests.
Also update test fixtures in test_apihub_toolset.py to use real auth objects instead of mocks that fail pydantic validation.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 863764941
This change adds framework-level support for resolving toolset authentication before calling get_tools(). Key changes:
- Add _resolve_toolset_auth() method in BaseLlmFlow that iterates
through toolsets, checks for auth config, and resolves credentials
via CredentialManager before tool listing
- Add TOOLSET_AUTH_CREDENTIAL_ID_PREFIX constant for identifying
toolset auth requests
- Add skip logic in auth_preprocessor to not resume function calls
for toolset auth (they do not need it)
- Add get_auth_response() method to CallbackContext for retrieving
auth credentials from session state
- Update CredentialManager to accept CallbackContext instead of
requiring ToolContext
When a toolset needs authentication but credentials are not available, the flow yields an adk_request_credential event and interrupts the invocation, allowing the user to complete the OAuth flow before retrying.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 863543036
This seems a breaking change, but actually credential manager is used internally only and also it won't work if some one call it using callback context
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 863534476
The ADK web server's /run_sse endpoint now yields a JSON object like {"error": "..."} when an exception occurs during event generation. The adk_web_server_client is updated to detect this error payload and raise a RuntimeError.
Close#4291
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 863475838
The `_part_has_payload` helper now returns False for parts containing a function response, preventing the addition of fallback user content when a user turn consists solely of tool outputs.
Close#4249
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 863319497
For providers that typically require file IDs (like OpenAI and Azure), if a file URI is an HTTP/HTTPS URL and the MIME type is image, video, or audio, convert it to the corresponding URL-based content type (e.g., "image_url") instead of using the generic "file" type
Close#4112
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 863311703
This change introduces a new function, _validate_agent_import, which attempts to import the user's agent.py file before the deployment process begins. This helps catch common issues such as missing dependencies, incorrect relative imports, or syntax errors in the agent code early, providing more informative error messages to the user.
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 863310033
This CL enhances asyncio event loop management and test isolation.
- **BigQuery Analytics Plugin:** Ensure the asyncio event loop is consistently closed within the BigQuery analytics plugin. This prevents potential resource leaks. Add checks to handle potential deadlocks in Python 3.13+ when creating loops during interpreter shutdown.
- **Test Thread Pool Cleanup:** Introduce a pytest fixture (`cleanup_thread_pools`) to automatically shut down and clear all tool-related thread pools after each test run in `test_functions_thread_pool.py`. This improves test isolation and prevents order-dependent test failures.
- **Streaming Test Loop Restoration:** Refactor event loop handling in `test_streaming.py`. A new `_run_with_loop` method is introduced in the custom test runners to create a temporary event loop for each test execution, run the coroutine, and crucially, restore the original event loop afterwards. This prevents tests from interfering with each other's loop state.
- **Resource Closure:** Ensure services are closed properly in tests by adding `await service.close()` in `test_service_factory.py` and using `async with session_service` in `test_session_service.py`.
PiperOrigin-RevId: 863305565
Improves test reliability by guaranteeing the BigQueryAgentAnalyticsPlugin is shut down after each test execution. This is achieved by wrapping test logic in try/finally blocks, using a yield fixture, or employing a new asynccontextmanager to ensure the plugin.shutdown() method is always called, preventing potential resource leaks between tests.
PiperOrigin-RevId: 862951816
Since we will save MCP resource contents to the artifact service, no need to do post-processing based on mime type. Also fixed the implementation; the correct method to call is session.read_resource(uri).
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 862885513
Merge https://github.com/google/adk-python/pull/4276
This adds 2 mypy GitHub Actions checks:
* `mypy.yml` runs mypy on every PR. This will list all errors, so it shouldn't block until errors are resolved.
* `mypy-new-errors.yml` compares the PR branch to `main` to ensure no new mypy errors are introduced. This check can be made blocking now and can be removed once all errors are resolved in favor of `mypy.yml`.
### 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.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4276 from sararob:mypy-gh-actions 63130773c4862e90e352d4cb79221d78a6b9f5fd
PiperOrigin-RevId: 862226296
This allows users to access MCP resources on their own within agent logic / using custom tools. I plan on also later adding it to the agent state.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 861910520
* The main fix is in eval_metrics.py
* Removed some deprecated paths in the FastAPI server
* Added a unit test to catch future breakages
* Bump fastapi version to be 0.124.1 to capture the fix in https://github.com/fastapi/fastapi/pull/14482
* Removed the upper-bound restriction on fastapi version which was used to temporarily fix the issue
Fixes#3173
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 861867708
Details:
* The Sampler allows ADK agent optimizers to request evals and receive detailed eval results that can be used to guide agent optimization.
* This interface allows developers to run custom evaluations if needed for their agent. An implementation to interface with the inbuilt LocalEvalService shall be published shortly in a follow-up PR.
* The AgentOptimizer interface describes the general framework for an ADK agent optimizer that uses the Sampler interface to optimize an ADK agent.
* data_types.py contains generic types and base classes to allow intercommunication between the AgentOptimizer, Sampler, and developer code.
Co-authored-by: Keyur Joshi <keyurj@google.com>
PiperOrigin-RevId: 861849691
This changes the behavior of how we handle stale session, instead of reject the transaction entirely, we aggresively refresh the session.
Removed synchronous inspect(self).session calls within StorageSession.update_timestamp_tz and _dialect_name. This introspection was causing deadlocks/hangs when used with sqlalchemy.ext.asyncio in Python 3.13.
Closes issue: https://github.com/google/adk-python/issues/1733
Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 861353058
The generated agent deployment script now uses os.path.join and os.path.dirname(__file__) to construct the path to root_agent.yaml. This prevents issues where backslashes in Windows paths could be misinterpreted as Python escape sequences within the f-string, leading to syntax error
Close#4223
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 860236820
This change introduces a new `unittests.sh` script to simplify running unit tests. The script automatically sets up a minimal test environment, runs `pytest`, and then restores the previous development environment. The CONTRIBUTING.md has been updated to include instructions on using this new script.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 860222798
This change updates the feature request issue template to include required and recommended sections. New questions are added to gather more details on the problem, impact, willingness to contribute, and potential API/implementation ideas. Existing questions are rephrased for clarity
PiperOrigin-RevId: 860199885
Merge https://github.com/google/adk-python/pull/4221
### Link to Issue or Description of Change
N/A
**2. Or, if no issue exists, describe the change:**
Fixing various typos in .py files to improve quality: see commit diffs for details
**Problem:**
See above
**Solution:**
Fixing the typos
### Testing Plan
N/A
**Unit Tests:**
N/A
**Manual End-to-End (E2E) Tests:**
N/A
### 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.
- [N/A] I have commented my code, particularly in hard-to-understand areas.
- [N/A ] I have added tests that prove my fix is effective or that my feature works.
- [N/A] New and existing unit tests pass locally with my changes.
- [N/A] I have manually tested my changes end-to-end.
- [N/A ] Any dependent changes have been merged and published in downstream modules.
### Additional context
N/A
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4221 from didier-durand:fix-typos-e 1bcc8e05cdc116451222dd7fd7b0657745f769c1
PiperOrigin-RevId: 859332402
Merge https://github.com/google/adk-python/pull/4136
**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):**
Allow google search tool to set different model #4135
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
Currently, the Google Search tool inherits and uses the same LLM model set from the parent agent for processing and summarizing search results. This creates a limitation for users who wish to decouple the agent's reasoning model from the model used for search summarization (e.g., for cost optimization or using a lightweight model for simpler summarization tasks).
**Solution:**
I have updated the Google Search tool to accept an optional LLM model parameter.
Custom Model: Users can now explicitly specify which model should be used for processing search results.
Default Behavior: If no model is specified, the tool defaults to the parent agent's model, ensuring backward compatibility.
```
# If a custom model is specified, use it instead of the original model
if self.model is not None:
llm_request.model = self.model
```
### Testing Plan
Added a new test case test_process_llm_request_with_custom_model in [test_google_search_tool.py] that verifies:
When a custom model parameter is provided to GoogleSearchTool, it overrides the model from the incoming llm_request during process_llm_request
The tool correctly uses the custom model for LLM calls while maintaining other request parameters
**Unit Tests:**
- [X] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
(base) wanglu2:adk-python/ (feature/allow-google-search-tool-set-different-llm✗) $ uv run pytest ./tests/unittests/tools/test_google_search_tool.py [22:07:32]
======================================================================== test session starts ========================================================================
platform darwin -- Python 3.13.1, pytest-9.0.2, pluggy-1.6.0
rootdir: /Users/wanglu2/Documents/Git/adk-python
configfile: pyproject.toml
plugins: mock-3.15.1, anyio-4.12.0, xdist-3.8.0, asyncio-1.3.0, langsmith-0.6.0
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 21 items
tests/unittests/tools/test_google_search_tool.py ..................... [100%]
======================================================================== 21 passed in 7.91s =========================================================================
### 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.
- [ ] Any dependent changes have been merged and published in downstream modules.
### Additional context
Co-authored-by: Kathy Wu <wukathy@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4136 from lwangverizon:feature/allow-google-search-tool-set-different-llm 239ea9577bd7befc9a3574aca48dc8243d55192c
PiperOrigin-RevId: 859265757
This change introduces a `flush` method to the `BigQueryAgentAnalyticsPlugin`. This ensures that all pending log events are written to BigQuery before the agent's run completes.
Key changes:
- Added `flush()` method to `BigQueryAgentAnalyticsPlugin` to force write of pending events.
PiperOrigin-RevId: 859263853
Update the litellm version constraint in both project dependencies and dev dependencies to exclude versions 1.81.0 and higher because unit test breakages in GitHub actions introduced by it.
This is a stopgap before the actual fix is added. Close#4225
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 859239880
Bug: In live streaming mode, when function_call and function_response events
arrive during active transcription, they are correctly buffered but never
yielded to the caller. This causes callers to miss these events even though
they are saved to the session.
Fix: Add yield buffered_event after appending buffered events to the session
when transcription ends.
Testing:
- Added unit test: test_live_streaming_buffered_function_call_yielded_during_transcription
- Test verifies buffered events are yielded by:
1. Simulating partial transcription (triggers buffering)
2. Sending function_call during transcription (gets buffered)
3. Ending transcription (should yield buffered events)
4. Asserting both function_call and function_response are in yielded events
Test results:
- With fix: PASSED
- Without fix (yield commented out): FAILED with "Buffered function_call event was not yielded"
- Example event flow after fix:
EVENT: partial=True, input_transcription="Show me the weather"
EVENT: function_call=get_weather, args={'location': 'NYC'} <- Now yielded
EVENT: function_response=get_weather, response={...} <- Now yielded
EVENT: partial=False, input_transcription="Show me the weather for today"
PiperOrigin-RevId: 859158546
This refactors the BigQueryAgentAnalyticsPlugin to use the standard OpenTelemetry API for trace and span ID generation and propagation, replacing the custom ContextVar implementation.
Key changes:
- Utilizes `opentelemetry.trace` for starting/ending spans.
- Correctly uses `opentelemetry.context` for context attachment and detachment.
- Span information is now derived from the OpenTelemetry context when available.
- Added a fallback mechanism to ensure span_id and parent_span_id are still populated if the OpenTelemetry SDK is not initialized.
To get standard OpenTelemetry trace information in BigQuery logs, users should install `opentelemetry-sdk` and initialize a global `TracerProvider` in their application *before* initializing ADK components.
Example minimal initialization:
```python
# Install: pip install opentelemetry-sdk
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
trace.set_tracer_provider(TracerProvider())
```
PiperOrigin-RevId: 858965562
Merge https://github.com/google/adk-python/pull/4175
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
N/A: just fixing typos discovered while reading the repo
**2. Or, if no issue exists, describe the change:**
No code change, just typo fixes: see commit diffs for all details
**Problem:**
Trying to improve overall repo quality
**Solution:**
Fixing typos as they get discovered
### Testing Plan
N/A
**Unit Tests:**
N/A
**Manual End-to-End (E2E) Tests:**
N/A
### 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.
- [X] 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.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4175 from didier-durand:fix-typos-c 16e93ed2d9bc153fa0332ab1ae39633fcc5056e9
PiperOrigin-RevId: 858751240
LiteLLM defaults to DEV mode, which automatically loads environment variables from a local `.env` file. This change sets LITELLM_MODE to PRODUCTION to prevent LiteLLM from implicitly loading `.env` files when used within ADK.
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 858723362
This change introduces a helper function `_redact_uri_for_log` to sanitize URIs before logging. It removes user credentials from the netloc and redacts the values of query parameters, ensuring that sensitive information like passwords is not exposed in log outputs. The function is applied to all log statements and error messages that include service URIs for session, memory, and artifact services
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 858703465
The migration tool uses synchronous SQLAlchemy engines but users often provide async driver URLs (e.g., postgresql+asyncpg://) since that's what ADK requires at runtime.
This fix:
- Makes `to_sync_url()` public in `_schema_check_utils.py` for reuse
- Updates `migrate_from_sqlalchemy_pickle.py` to convert async URLs
- Updates `migrate_from_sqlalchemy_sqlite.py` to convert async URLs
- Adds comprehensive unit tests for `to_sync_url()` function
- Adds integration test for migration with async driver URLs
Fixes#4176
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 858359061
Right now the regex is over-matching and is returning true for references like these:
from ..utils._client_labels_utils import EVAL_CLIENT_LABEL
Co-authored-by: Ankur Sharma <ankusharma@google.com>
PiperOrigin-RevId: 857255767
### 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/4117
**Overview**
This PR implements the feature request in #4108 to allow `thinking_config` to be set directly within `generate_content_config`, bringing the Python SDK in line with the Go implementation.
**Changes**
- **llm_agent.py**: Relaxed the validation logic in `validate_generate_content_config` to remove the `ValueError` for `thinking_config`.
- **Precedence Warning**: Added an override of `model_post_init` in `LlmAgent` to issue a `UserWarning` if both a `planner` and a manual `thinking_config` are provided.
- **built_in_planner.py**: Updated `apply_thinking_config` to log an `INFO` message when the planner overwrites an existing configuration on the `LlmRequest`.
**Testing**
Verified with a reproduction script covering:
1. Successful initialization of an agent with direct `thinking_config`.
2. Validation of `UserWarning` during initialization when conflicting configurations are present.
3. Confirmation of logger output when the planner performs an overwrite.
Closes: #4108
Tagging @invictus2010 for visibility.
Co-authored-by: Liang Wu <wuliang@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4117 from Akshat8510:feat/allow-thinking-config-4108 5deeb893799379c681d6822dc4a1e42f86d3ed01
PiperOrigin-RevId: 856821447
Currently only tool calling supports MCP auth. This refactors the auth logic into a auth_utils file and uses it for tool listing as well. Fixes https://github.com/google/adk-python/issues/2168.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 856798589
Merge https://github.com/google/adk-python/pull/4059
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #3961
**Problem:**
Excessive notifications from periodic workflow runs (every 6 hours for triage, daily for stale-bot and docs upload) in forks where they are not needed.
**Solution:**
Add repository checks to prevent scheduled workflows from running in forked repositories.
The workflows will now only run in the main google/adk-python repository.
### Testing Plan
I think that unit tests and E2E are not needed because this change is for GitHub Actions (not ADK source code).
_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
- [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.
- [ ] 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.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4059 from ftnext:disable-fork-actions 991cc94674cd5cef2e3c2aacf243ba7dae7b88ad
PiperOrigin-RevId: 856691019
Merge https://github.com/google/adk-python/pull/3988
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: https://github.com/google/adk-python/issues/3987
- Related: https://github.com/google/adk-python/issues/3596
**2. Or, if no issue exists, describe the change:**
**Problem:**
Idea about my use case
I'm building the report generation system using google-ask (1.18.0) and building multiple subagents here, I'm passing the one subagent Agent as a tool to another Parent Agent. Note: Sub-agent can do web search.
here, parent agent triggers multiple sub-agent (same agent) multiple times according to use case or complexity of the user input
Describe the bug
here, the bug sometimes sub agents doesn't provide the proper output and resulted in the
```
merged_text = '\n'.join(p.text for p in last_content.parts if p.text)
^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not iterable
and it's breaking the system of Agents workflow
```
**Solution:**
Creating fallback if there is no **last_content.parts** it will return the empty parts so we won't face the NoneType issue
### Testing Plan
Created a unit test file for this issue
test_google_search_agent_tool_repro.py
**Unit Tests:**
- [X] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
3677 passed, 2208 warnings in 42.64s
**Manual End-to-End (E2E) Tests:**
N/A
### 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.
- [ ] Any dependent changes have been merged and published in downstream modules.
### Additional context
N/A
Co-authored-by: Liang Wu <wuliang@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3988 from ananthanarayanan-28:none-type-issue e6ba948345adfc5ac73a5e39d11c68236f117179
PiperOrigin-RevId: 856515019
Original codes use tool.__name__ to register streaming tools, this is problemetic, it only works with python function passed as tools directly, if they are wrapped in FunctionTool, then FunctionTool doesn't have "__name__" property. canonical_tools wrap python function in FunctionTool uniformly thus we can use tool.name uniformly
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 856472936
Merge https://github.com/google/adk-python/pull/4025
**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:
- #3950
- #3731
- #3708
**2. Or, if no issue exists, describe the change:**
**Problem:**
- `ClientSession` of https://github.com/modelcontextprotocol/python-sdk uses AnyIO for async task management.
- AnyIO TaskGroup requires its start and close must happen in a same task.
- Since `McpSessionManager` does not create task per client, the client might be closed by different task, cause the error: `Attempted to exit cancel scope in a different task than it was entered in`.
**Solution:**
I Suggest 2 changes:
Handling the `ClientSession` in a single task
- To start and close `ClientSession` by the same task, we need to wrap the whole lifecycle of `ClientSession` to a single task.
- `SessionContext` wraps the initialization and disposal of `ClientSession` to a single task, ensures that the `ClientSession` will be handled only in a dedicated task.
Add timeout for `ClientSession`
- Since now we are using task per `ClientSession`, task should never be leaked.
- But `McpSessionManager` does not deliver timeout directly to `ClientSession` when the type is not STDIO.
- There is only timeout for `httpx` client when MCP type is SSE or StreamableHTTP.
- But the timeout applys only to `httpx` client, so if there is an issue in MCP client itself(e.g. https://github.com/modelcontextprotocol/python-sdk/issues/262), a tool call waits the result **FOREVER**!
- To overcome this issue, I propagated the `sse_read_timeout` to `ClientSession`.
- `timeout` is too short for timeout for tool call, since its default value is only 5s.
- `sse_read_timeout` is originally made for read timeout of SSE(default value of 5m or 300s), but actually most of SSE implementations from server (e.g. FastAPI, etc.) sends ping periodically(about 15s I assume), so in a normal circumstances this timeout is quite useless.
- If the server does not send ping, the timeout is equal to tool call timeout. Therefore, it would be appropriate to use `sse_read_timeout` as tool call timeout.
- Most of tool calls should finish within 5 minutes, and sse timeout is adjustable if not.
- If this change is not acceptable, we could make a dedicate parameter for tool call timeout(e.g. `tool_call_timeout`).
### Testing Plan
- Although this does not change the interface itself, it changes its own session management logics, some existing tests are no longer valid.
- I made changes to those tests, especially those of which validate session states(e.g. checking whether `initialize()` called).
- Since now session is encapsulated with `SessionContext`, we cannot validate the initialized state of the session in `TestMcpSessionManager`, should validate it at `TestSessionContext`.
- Added a simple test for reproducing the issue(`test_create_and_close_session_in_different_tasks`).
- Also made a test for the new component: `SessionContext`.
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
```plaintext
=================================================================================== 3689 passed, 1 skipped, 2205 warnings in 63.39s (0:01:03) ===================================================================================
```
**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
- [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.
- [ ] ~~Any dependent changes have been merged and published in downstream modules.~~ `no deps has been changed`
### Additional context
This PR is related to https://github.com/modelcontextprotocol/python-sdk/pull/1817 since it also fixes endless tool call awaiting.
Co-authored-by: Kathy Wu <wukathy@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4025 from challenger71498:feat/task-based-mcp-session-manager f7f7cd0c9c96840361c30499d08c33a189f57d86
PiperOrigin-RevId: 856438147
1. Convert A2A responses containing a DataPart to ADK events. By default, this is done by serializing the DataPart to JSON and embedding it within the inline_data field of a GenAI Part, wrapped with custom tags (<a2a_datapart_json> and </a2a_datapart_json>).
2. Convert ADK events back to A2A requests. Specifically, messages stored in inline_data with the text/plain mime type and content wrapped within the custom tags (<a2a_datapart_json> and </a2a_datapart_json>) are deserialized from JSON back into an A2A DataPart
PiperOrigin-RevId: 856426615
audio is transcribed thus no need to be sent, but other blob(e.g. image) should still be sent.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 856422986
Introduces a function to map LiteLLM finish reason strings to the internal types.FinishReason enum and populates the finish_reason field in LlmResponse. Removes custom logic for handling file URIs, including special casing for different providers, and updates tests accordingly
Close#4125
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 856421317
There was an extra test_mcp_toolset in the tools/ directory with only one test; I moved it into the main file.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 856419611
The LoadArtifactsTool now checks if an artifact's inline data MIME type is supported by Gemini. If not, it attempts to convert the artifact content into a text Part
Close#4028
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 856404510
Explicitly pass the log_level parameter to uvicorn.Config in both
adk web and adk api_server commands. This ensures that Uvicorn's
internal logging respects the configured log level.
Closes#4139
feature/auto-create-new-session
Merge https://github.com/google/adk-python/pull/4072
**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
**2. Or, if no issue exists, describe the change:**
**Problem:**
When building frontend applications with ADK, there's a limitation where frontends cannot always guarantee that `create_session` is called before initiating a conversation. This creates friction in the user experience because:
- Users may refresh the page or navigate directly to a conversation URL with a specific session_id
- Frontend state management may lose track of whether a session was already created
- Mobile apps or single-page applications have complex lifecycle management where ensuring `create_session` is called first adds unnecessary complexity
- This forces developers to implement additional logic to check session existence before every conversation
Currently, if `get_session` is called with a non-existent session_id, it returns `None`, requiring the frontend to explicitly handle this case and call `create_session` separately.
**Solution:**
Modified the `get_session` method in `DatabaseSessionService` to automatically create a session if it doesn't exist in the database. This "get or create" pattern is common in many frameworks and provides a more developer-friendly API.
The implementation:
1. Attempts to fetch the session from the database
2. If the session doesn't exist (returns `None`), automatically calls `create_session` with the provided parameters
3. Retrieves and returns the newly created session
4. Maintains backward compatibility - existing code continues to work without changes
This allows frontends to simply call `get_session` with a session_id and be confident that the session will be available, regardless of whether it was previously created.
**Benefits:**
- Simplifies frontend integration by removing the need to track session creation state
- Reduces API calls (no need to check existence before calling get_session)
- Follows the principle of least surprise - getting a session with an ID should work reliably
- No breaking changes to existing code that checks for `None` return values
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
**pytest results:**
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4072 from lwangverizon:feature/auto-create-new-session 5475c6ae91d12332598d521302736eb1db79a8be
PiperOrigin-RevId: 856019482
LlmResponse so far doesn't expose generation_complete signal, removing the dead codes.
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 855835802
### Description of Change
**Problem:**
The `ToolboxToolset` was implemented directly within `adk-python`, leading to code duplication and potential drift from the core `toolbox-adk` implementation.
**Solution:**
Refactored `ToolboxToolset` to act as a rigorous wrapper around the `toolbox-adk` package, which delegates all functionality to `toolbox_adk.ToolboxToolset`.
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
Summary:
- Verified initialization flows through to `toolbox-adk`.
- Verified `auth_token_getters` are correctly propagated.
- Verified type hints are static-analysis friendly.
**Manual End-to-End (E2E) Tests:**
Manually verified standard toolbox loading and execution with the new wrapper:
```python
from google.adk.tools import ToolboxToolset
from toolbox_adk import CredentialStrategy
# Loading with toolset_name
ts = ToolboxToolset(
server_url='http://localhost:8080',
toolset_name='calculator',
credentials=CredentialStrategy.toolbox_identity()
)
tools = await ts.get_tools()
print(f'Loaded {len(tools)} 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: 855798474
Merge https://github.com/google/adk-python/pull/3756
move event iteration inside api_client context in get_session
Move event iteration inside the api_client context manager in VertexAiSessionService.get_session() to prevent client closure during multi-page event fetching.
**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: #3757
**2. Or, if no issue exists, describe the change:**
**Problem:**
When a session contains more than 100 events (requiring pagination), `VertexAiSessionService.get_session()` fails with:
```
RuntimeError: Cannot send a request, as the client has been closed.
```
The root cause is that the `events_iterator` is consumed **outside** the `async with self._get_api_client() as api_client:` context block. When the iterator needs to fetch page 2, 3, etc., the API client has already been closed because the `async with` block has exited.
```python
# Current buggy flow:
async with self._get_api_client() as api_client:
get_session_response, events_iterator = await asyncio.gather(...)
# ← Client closed here
async for event in events_iterator: # ← Fails on page 2+ (client closed)
session.events.append(...)
```
**Solution:**
Move the session creation, user validation, and event iteration **inside** the `async with` block so the API client remains open during the entire pagination process:
```python
async with self._get_api_client() as api_client:
get_session_response, events_iterator = await asyncio.gather(...)
# Validation and session creation...
async for event in events_iterator: # ← Now works for all pages
session.events.append(...)
# Client closed after all events are fetched
```
### Testing Plan
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
```bash
pytest tests/unittests/sessions/test_vertex_ai_session_service.py -v
```
**Added regression test:** `test_get_session_pagination_keeps_client_open`
- Creates a `MockAsyncClientWithPagination` that tracks whether it's inside the `async with` context
- Raises `RuntimeError` if iteration happens outside the context (matching real httpx behavior)
- Simulates 3 pages of events (100 + 100 + 50 = 250 events)
- Verifies all 250 events are successfully retrieved
**Manual End-to-End (E2E) Tests:**
1. Deploy an ADK agent to Vertex AI Agent Engine
2. Create a session and send 100+ messages to accumulate >100 events
3. Verify `get_session()` successfully retrieves all events without error
**Before fix:**
```
RuntimeError: Cannot send a request, as the client has been closed.
```
**After fix:**
- Session with 201 events (3 pages) loads successfully
- All events are retrieved and appended to the session
### 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.
### Additional context
This bug affects any production deployment where users have extended conversations. Sessions accumulating >100 events (which triggers pagination) become completely unusable as the agent cannot load the session to process new messages.
The fix is minimal and maintains backward compatibility - it only changes the scope of the `async with` block without altering any logic or return values.
**Affected versions:** Tested on google-adk 1.19.0, but the bug exists in earlier versions as well.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3756 from AlexisMarasigan:fix/vertex-ai-session-service-paginatio 01fbafa6524312f24f7c9feaffb07bff0ad49b77
PiperOrigin-RevId: 855451813
* **Async Safety:** Improved TraceManager context variable handling to ensure correct context isolation in concurrent asynchronous operations. This was achieved by using immutable tuples for the span stack and making copies of context dictionaries before modification.
* **Enhanced Logging:** The BigQueryAgentAnalyticsPlugin now captures richer metadata, including:
* Root agent name (via a new context variable).
* LLM model name and version.
* Usage metadata from LLM requests and responses.
* **Serialization Fix:** Updated BigQueryAgentAnalyticsPlugin to prevent JSON serialization errors when logging custom objects (e.g., Dataclasses). These are now automatically converted to dictionaries or string representations to ensure successful insertion into BigQuery.
PiperOrigin-RevId: 855415320
2026-01-12 15:46:12 -08:00
1284 changed files with 62741 additions and 10233 deletions
# - Issues labeled with "planned" (need owner assignment)
if:>-
github.event_name == 'schedule' ||
github.event.action == 'opened' ||
github.event.label.name == 'planned'
github.repository == 'google/adk-python' && (
github.event_name == 'schedule' ||
github.event.action == 'opened' ||
github.event.label.name == 'planned'
)
permissions:
issues:write
contents:read
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.