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