Commit Graph

915 Commits

Author SHA1 Message Date
Haiyuan Cao ea034877ec fix: Improve BigQuery Agent Analytics plugin reliability and code quality
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
2026-02-17 10:24:34 -08:00
Google Team Member 6a808c60b3 feat: Introduce User Personas to the ADK evaluation framework
PiperOrigin-RevId: 871366815
2026-02-17 09:54:23 -08:00
Xiang (Sean) Zhou 976a238544 refactor: Extract reusable private methods
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 871359399
2026-02-17 09:36:25 -08:00
Google Team Member 42eeaef2b3 refactor: Extract reusable private methods
PiperOrigin-RevId: 871151624
2026-02-17 00:05:25 -08:00
Xiang (Sean) Zhou 706f9fe74d refactor: Extract reusable private methods
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 871128393
2026-02-16 22:52:47 -08:00
Kathy Wu 4e2d6159ae fix: Fix pickling lock errors in McpSessionManager
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
2026-02-16 18:50:30 -08:00
Ke Wang 21be6adcb8 feat: Make skill instruction optimizable and can adapt to user tasks
PiperOrigin-RevId: 869971535
2026-02-13 18:44:46 -08:00
Xiang (Sean) Zhou d56cb4142c fix: Check both input_stream parameter name and its annotation to decide whether it's a streaming tool that accept input stream
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
2026-02-13 16:33:26 -08:00
George Weale 811e50a0cb feat: add generate/create modes for Vertex AI Memory Bank writes
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
2026-02-13 14:46:45 -08:00
Anmol Jaiswal d5332f4434 feat: Expand LiteLlm supported models and add registry tests
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 869873309
2026-02-13 13:47:13 -08:00
Liang Wu fbe9eccd05 fix: race condition in table creation for DatabaseSessionService
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
2026-02-13 11:07:15 -08:00
Akshat8510 30b2ed3ef8 fix(web): allow session resume without new message
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
2026-02-13 09:11:51 -08:00
Xiang (Sean) Zhou ede925b502 chore: Lazy register all streaming tools
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 869480442
2026-02-12 18:50:43 -08:00
Xiang (Sean) Zhou 5269a6b1d6 chore: Register all streaming tool at runner
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
2026-02-12 16:59:36 -08:00
Xiang (Sean) Zhou b53bc555cc fix: Only relay the LiveRequest after tools is invoked
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
2026-02-12 15:52:45 -08:00
Xuan Yang 647d3b16a3 chore: Unify CallbackContext and ToolContext into the Context class
Co-authored-by: Xuan Yang <xygoogle@google.com>
PiperOrigin-RevId: 869400758
2026-02-12 15:01:51 -08:00
Google Team Member d85932faa3 chore: Add X-Goog-API-Client header to GDA API requests
PiperOrigin-RevId: 869372484
2026-02-12 13:58:05 -08:00
Kathy Wu 9f7d5b3f14 feat: Add load_skill_from_dir() method
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
2026-02-11 18:10:54 -08:00
Xuan Yang b7f9110b52 chore: Introduce a unified Context
Co-authored-by: Xuan Yang <xygoogle@google.com>
PiperOrigin-RevId: 868890552
2026-02-11 16:16:24 -08:00
George Weale 079f7a38be fix: Support escaped curly braces in instruction templates
Close #3527

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 868875061
2026-02-11 15:38:53 -08:00
Leon Ziyang Zhang bcbfeba953 feat: pass trace context in MCP tool call's _meta field with Otel propagator
PiperOrigin-RevId: 868841079
2026-02-11 14:18:22 -08:00
Liang Wu 61c329f8ce ci: match the environment with internal ones for pyink/isort/unittest
Previously submitted change is causing [Pyink error](https://github.com/google/adk-python/actions/runs/21884351396/job/63176122118) in repo because Pyink recently updated to 25.12.0.

Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 868806575
2026-02-11 13:01:32 -08:00
Anmol Jaiswal 758d337c76 fix(sessions): use async iteration for VertexAiSessionService.list_sessions pagination
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
2026-02-10 21:18:51 -08:00
Google Team Member 3cf43e3842 feat: Enhance google credentials config to support externally passed access token
PiperOrigin-RevId: 868390961
2026-02-10 17:21:38 -08:00
Kathy Wu 4aa475145f fix: Fix event loop closed bug in McpSessionManager
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
2026-02-10 16:50:53 -08:00