Two ADK source files import third-party packages that are not declared
in [project] dependencies, leaving bare `pip install google-adk` one
transitive resolver change away from breaking on `from google.adk import
Runner`:
* utils/model_name_utils.py and cli/cli_deploy.py do
`from packaging.version import …` at module top level. Reachable from
the canonical import chain (runners.py -> telemetry.tracing ->
utils.model_name_utils) and from `adk --help`. Reproduced today by
uninstalling packaging from a fresh venv.
* tools/environment_simulation/environment_simulation_config.py does
`from pydantic_core import ValidationError`. pydantic-core ships with
pydantic, so this works at runtime, but the dep is undeclared. pydantic
re-exports ValidationError, so swap the import.
Adds packaging>=21.0 to main deps and switches the env_simulation import
to pydantic. Includes guard tests in tests/unittests/test_release_
dependencies.py that pin the contract.
Change-Id: Idab2bffe8ae1d66aa049801fbfff9569af7b7687
Added a new unit test test_event_serialization_always_camel_case in test_workflow_events.py. The test recursively verifies that all keys in a serialized Event model use camelCase, ensuring consistency with frontend expectations and catching accidental additions of snake_case fields.
Change-Id: I12ff59079b59ad5fd421e659c80450cf10c15bbb
Add alias_generator and populate_by_name to RequestInput model_config to match frontend naming conventions and other event models.
Change-Id: I5eb4a55185d0113d86407c119050bb9885a7962b
Replace asyncio.timeout() (3.11+) with asyncio.wait_for() so node
timeouts work on Python 3.10. Fix typing.Self import in telemetry
tests with a 3.10-compatible fallback. Update pyproject.toml to
declare >=3.10 and add the 3.10 classifier.
Change-Id: Ibe1dcf4a1d44014891aa487aac6e160203c38a58
BaseNode.run() wrapped raw yields into Event(output=item) without
calling _validate_output_data(), so output_schema was never enforced
by the runtime for custom nodes. Moved validation into run() so it
applies centrally to all yields — both raw values and Event objects
with output. Updated tests to remove manual _validate_output_data()
calls and added tests proving runtime enforcement.
Change-Id: I4a984e71ae0027daa5cdfb9e3ba7936688743488
This change introduces a new query parameter `save_live_blob` to the `/run_live` WebSocket endpoint in the ADK web server. When set to true, this parameter enables saving of live blobs during the session. The default value is false. Unit tests are updated to cover this new parameter.
Closes issue #4707
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 901280577
Change-Id: I1359cb831c5bb7ddfa11e5d1d4ebed18080d00f2
New metrics added:
- gen_ai.agent.invocation.duration
- gen_ai.tool.execution.duration
- gen_ai.agent.request.size
- gen_ai.agent.response.size
- gen_ai.agent.workflow.steps
New metrics and attributes are in line with OTel semantic conventions where possible, and will be formally to the semconv later.
PiperOrigin-RevId: 901156576
Change-Id: I0d6afc50287e643245d6fc7690d9841d9f22eaab
Default is True to match existing behavior. Setting it to False prevents the model from loading artifact directly from a provided canonical URI, and makes the behavior consistent between InMemoryArtifactService and other services with canonical URIs.
PiperOrigin-RevId: 901061080
Change-Id: I3079a3cd57e4517c38b62c8e8a7bc1278ae1936e
Merge https://github.com/google/adk-python/pull/4802
**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
- Closes: #4623
**Problem:**
example_util.py was completely missing unit tests.
**Solution:**
I added unit tests for a variety of situations:
- Converting a text-only example to a string
- Converting a text-only example _with multiple Parts_ to a string
- Converting a text-only example to a string when the output contains a conversation between the user and model
- Converting another text-only example with a conversational output, but with clumped messages from each
- Converting an empty list to a string
- Converting an example including a function call to a string
- Converting an example including a function _response_ to a string
- Converting an example including both a function call _and_ a function response to a string
- Converting an example with text, a function call, and a function response to a string
- Building System Information from a list of examples
- Building System Information from an example provider
### Testing Plan
I ran the tests personally, and they successfully passed.
**Unit Tests:**
- [✓] I have added or updated unit tests for my change.
- [✓] All unit tests pass locally.
33 passed in 2.55s
**Manual End-to-End (E2E) Tests:**
To test my change, simply run the unit tests and they should pass. If you want to verify the effectiveness of my tests, try modifying the input given to my unit tests and see if they fail.
### 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
- I noticed build_example_si takes an argument for query even though it's not used if you pass in a list rather than a BaseExampleProvider. Is this expected behavior that is there for a reason, or should I open an issue for this?
- I also noticed that when model is None, it defaults to Gemini 2. This seems like it could cause issues on the user end. Is there a reason for this functionality?
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4802 from BowedMars374878:Issue-#4623 efa090e264b4cc155d4937ea2f2d8d90d7753ae6
PiperOrigin-RevId: 901025765
Change-Id: Ief9c2163e8d975f231a67a311967753a46c71d29
This will allow agent transfer to work smoothly in live workflow. See the comment added for details.
Closes issue #5238
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 900993889
Change-Id: I34c5f768482bc71351278dc0a2466885799dad1a
During agent transfer, the input transcription is represented as user input. Also, the previous implementation is incorrect in that the LlmResponse could never have content.role == 'user'. Modified the docstring to match the behavior.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 900980704
Change-Id: Ia48057c7f02b10be63f6d0e255c07fab177e759d
Merge https://github.com/google/adk-python/pull/4705
### Link to Issue or Description of Change
- Closes: #4666
**Problem:**
Gemini-2.0-flash model is still used in integration tests, but disabled for new users
**Solution:**
Replace all occurrences of Gemini-2.0-flash by Gemini-2.5-flash, in integration tests and docstrings.
Because gemini-2.0 is still enabled for some users, this PR doesn't clean the model from unit tests.
### Testing Plan
Run already existing unittests and integration 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.
- [x] Any dependent changes have been merged and published in downstream modules.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/4705 from morganroux:fix/issues/4666 3c390a2ed3abb7b2fc7bd99cfb801e8a2b1f5343
PiperOrigin-RevId: 900973552
Change-Id: I1d2dd4c749522b529537d5863e4a56865927da95
This change introduces `_add_events_to_memory_via_ingest` in `VertexAiMemoryBankService` to support adding events to memory using the `memories.ingest_events` API. This allows passing additional configurations such as `stream_id`, `force_flush`, and `generation_trigger_config`.
This path is triggered when `custom_metadata` contains `use_ingest` or `generation_trigger_config`.
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 900924805
Change-Id: Id1ae9f5050d38753c5d4791acc6f5ab3332a2f9f
This allows headers to refresh on each request. Also only add auth headers if no auth_scheme or auth_credential is specified
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 900900323
Change-Id: Idf2ec208616528612a428a5260ea0455dd986174
When from __future__ import annotations is used, type hints are stored as strings. This caused is_list_of_basemodel to fail in FunctionTool, preventing dictionaries from being automatically converted back to Pydantic models when passed to tools. Used get_type_hints to evaluate them.
Also updated 10_burgers.json test trace to reflect the successful execution after this fix.
Change-Id: I92a708dd17ef76fc222779cd28e4a2d551325ce8
The LoopAgent now only resets the state of its sub-agents and increments the loop count if the inner loop completes without being interrupted by an exit or pause signal. This ensures that when an invocation is paused, the sub-agent states are preserved for resumption.
Also cleanup dead code in base_agent.py.
Change-Id: Iab1285f44558d1334389920707b9a0c53d076428
- Automatically wrap `mode='task'` sub-agents as tools in `LlmAgent`.
- Exclude `task` mode agents from valid transfer targets in `agent_transfer.py`.
- Suppress transfer instructions entirely for agents in `task` or `single_turn` mode.
Change-Id: I59d84f75915eb4f6258896656c93d05b2a4519cb
Enables setting a default live model at the class level or overriding it, facilitating the use of custom or specialized models in live streaming scenarios.
Change-Id: I061556e1c0af95e25c307ab4ff63137939890406
Move node path and scheduler derivation logic into Context.__init__, removing duplicate path building logic in NodeRunner. This simplifies NodeRunner and ensures consistent path generation.
Also fixes a bug where root context paths were incorrectly prefixed with @1, causing test failures.
Change-Id: I55a2fa290221aa6fce87c8a2c476aa97788783a4
Filter events by invocation_id during rehydration in _reconstruct_node_states to avoid linear scans of unrelated invocations in long sessions. This improves performance from O(N) to O(K).
Change-Id: Ia5e03d6ce824905b61ec37753e52ff7e3917e48d
Moved the stateful aggregation logic from JoinNode to the Workflow orchestrator to simplify node implementation and prevent state leaks in loops. Removed in_nodes from Context as it is no longer needed.
Change-Id: If0677f65c735ee3bce985478f7990b4a3335b7df
Update unit tests to verify the presence and value of the client_info argument during client initialization.
PiperOrigin-RevId: 900448054
Change-Id: I9204681625f4a83b3fb8e9114fd4ba90fa9b2c68
This change introduces a `live_session_id` field to the `LlmResponse` dataclass and populates it in all responses generated by the `GeminiLlmConnection` when using a Live session. This allows tracking which Live session each response belongs to.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 900354397
Change-Id: I05be852aeba76ec62e70321ff8029654e5b22bdd
Renamed _node_runner_class to _node_runner to follow naming conventions and updated tests accordingly.
Change-Id: Ibc47255e6422a9bcb1368b79933d4499909534d7
Moved _NodePathBuilder from workflow to events because it is used by NodeInfo in event.py, which is in the core events package. This avoids events depending on workflow.
Change-Id: If37b994ad9e7012af2027c9d80a984cef65c5255
Enforced that BaseNode names must be valid Python identifiers, matching BaseAgent behavior.
Fixed tests that were using lambdas without explicit names.
Change-Id: I614d11c237d2b16c1fcd575606bbc95e11c42b17
Restored numbered comments in _scan_node_events and renamed it to _reconstruct_node_states to better reflect its purpose of reconstructing node states from events. Updated usages in _workflow.py and _dynamic_node_scheduler.py. Fixed imports and calls in test_rehydration_utils.py.
Change-Id: Ic693cbbce42fca80f82fe442503bbd9b3b15142f
The workflow-based LlmAgent was removed and replaced with the original LlmAgent, which supports the required streaming interfaces. The tests now pass successfully.
Change-Id: Iab47c3771eca70e2a7bcab4bebb128c480b14a61
Move the helper function _get_next_pending_nodes from _trigger_processor.py into WorkflowGraph class as an instance method. This improves cohesion and allows keeping _trigger.py as a pure data model file containing just the Trigger class, while deleting _trigger_processor.py.
Also formatted _workflow_graph.py to use 2-space indentation to follow ADK style guide, and added unit tests for the new method in test_workflow_graph.py. All tests passed.
Change-Id: Ie4a3059388a99bffc82db3299ad83af3976a442d
Implement AgentEngineSandboxComputer, a BaseComputer implementation that
uses Vertex AI Agent Engine Computer Use Sandbox as a remote browser
environment. This enables computer-use agents to operate in secure,
isolated cloud-based browser environments.
Key features:
- SandboxClient: Low-level CDP client using vertexai SDK send_command()
- AgentEngineSandboxComputer: BaseComputer implementation with session
state management for sandbox sharing across invocations
- Support for both auto-provisioning and bring-your-own-sandbox (BYOS) modes
- Automatic token refresh and retry logic for transient navigation errors
- Fix wait_5_seconds adapter to properly pass tool_context
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com>
PiperOrigin-RevId: 900292803
Change-Id: Ia1bdf22aa228b22367ece8ca9ba60ee96321ef99
Fixes#5073, #5310, and #5311 with three targeted updates to the `BigQueryAgentAnalyticsPlugin` (no changes to ADK core):
- Classifies `TransferToAgentTool` transfers to `RemoteA2aAgent` as `TRANSFER_A2A` instead of the generic `TRANSFER_AGENT` by resolving the target agent at the call level.
- Ensures a self-consistent BigQuery span tree by preferring the plugin's internal span stack over ambient OTel spans, resolving dangling `parent_span_id` references.
- Surfaces remote A2A interaction metadata (`a2a:request`, `a2a:response`, etc.) in BigQuery by detecting them in custom metadata and logging new `A2A_INTERACTION` events.
Co-authored-by: Haiyuan Cao <haiyuan@google.com>
PiperOrigin-RevId: 900224778
Change-Id: I1b28a2d5b77e4831d035b56448061db4988dcece
Previously, on_event_callback ran after append_event, so plugin
modifications (e.g. custom_metadata) were only visible in the
yielded stream but never persisted to the session store. This
moves the callback before persistence, matching the documented
contract in base_plugin.py.
Fixes#3990
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 899845848
Change-Id: I7243da8767d7c5a5a28d4a433db3c5b82c494281
The Gemini session now has a dedicated `send_tool_response` method, which is used instead of wrapping function responses in a `LiveClientToolResponse` and calling `send`.
`send` is deprecated.
Co-authored-by: Liang Wu <wuliang@google.com>
PiperOrigin-RevId: 899796634
Change-Id: I527909d64265628440098978583386a82e573fcb
Rename _schedule_dynamic_node_internal to _workflow_scheduler to clearly distinguish it from standalone execution paths. This prevents maintainers from misinterpreting valid fallback logic as dead legacy code. Also fix associated unit test mocks.
Change-Id: Ic76fd7348235321a460a0af31687f2e18b5524cc
Move _wrap_response, _unwrap_response, validate_resume_response, and _scan_node_events from monolithic utility files to dedicated _rehydration_utils.py, and split tests accordingly.
Change-Id: Icb99765668c576d459c564187ab4a073c66a2837
The connectivity check only verified that each node appeared as a to_node in some edge, which allowed disconnected routed subgraphs (e.g., B -> C (route='x'), C -> B (route='y')) to pass validation even though they were unreachable from START. Replace with a DFS traversal from START that computes true reachability.
Change-Id: I9f0457acbbbf9959d23792106cfa72a7c6e5b009