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
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