Google Team Member and Copybara-Service
42eeaef2b3
refactor: Extract reusable private methods
...
PiperOrigin-RevId: 871151624
2026-02-17 00:05:25 -08:00
Xiang (Sean) Zhou and Copybara-Service
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
Liang Wu and Copybara-Service
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
George Weale and Copybara-Service
663cb75b32
fix: Conditionally preserve function call IDs in LLM requests
...
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
2026-02-09 10:46:55 -08:00
Xuan Yang and Copybara-Service
2220d885cd
fix: Check will_continue for streaming function calls
...
Related: https://github.com/google/adk-python/issues/4311
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 865074872
2026-02-03 15:33:44 -08:00
Google Team Member and Copybara-Service
00aba2d884
feat: Improve asyncio loop handling and test cleanup
...
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
2026-01-30 10:47:09 -08:00
Xuan Yang and Copybara-Service
853a3b0e14
fix: Do not treat FCs and FRs as invisible when marked as thoughts
...
Related: https://github.com/google/adk-python/issues/4159
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 860254198
2026-01-23 14:25:42 -08:00
Xiang (Sean) Zhou and Copybara-Service
714c3ad047
feat: Support run tools in separate thread for live mode
...
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com >
PiperOrigin-RevId: 860242861
2026-01-23 13:55:31 -08:00
Xuan Yang and Copybara-Service
d62f9c896c
chore: Always skip executing partial function calls
...
Related: https://github.com/google/adk-python/issues/4159
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 859184844
2026-01-21 11:20:16 -08:00
George Weale and Copybara-Service
2367901ec5
chore: Upgrade to headers to 2026
...
Co-authored-by: George Weale <gweale@google.com >
PiperOrigin-RevId: 858763407
2026-01-20 14:50:09 -08:00
Xiang (Sean) Zhou and Copybara-Service
ab62b1bffd
fix: Use the agent name as the author of the audio event
...
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com >
PiperOrigin-RevId: 855789317
2026-01-13 10:38:53 -08:00
George Weale and Copybara-Service
b28721508a
feat: make LlmAgent.model optional with a default fallback
...
LlmAgent now resolves model from ancestors or a system default (gemini-2.5-flash) when unset. Added LlmAgent.set_default_model() to override the default globally
Co-authored-by: George Weale <gweale@google.com >
PiperOrigin-RevId: 853006116
2026-01-06 17:56:14 -08:00
George Weale and Copybara-Service
688f48fffb
fix: Update empty event check to include executable code and execution results
...
Close #3859
Close #3921
Co-authored-by: George Weale <gweale@google.com >
PiperOrigin-RevId: 852375447
2026-01-05 11:04:34 -08:00
Xuan Yang and Copybara-Service
0b1cff2976
feat: Enable PROGRESSIVE_SSE_STREAMING feature by default
...
Related: https://github.com/google/adk-python/issues/3705
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 846793027
2025-12-19 10:50:49 -08:00
Google Team Member and Copybara-Service
f35d129b4c
feat(fix): Check all content parts for emptiness in _contains_empty_content
...
PiperOrigin-RevId: 845954226
2025-12-17 16:03:12 -08:00
Xiang (Sean) Zhou and Copybara-Service
c6320caaa5
feat: Support interactions API for calling models
...
Co-authored-by: Xiang (Sean) Zhou <seanzhougoogle@google.com >
PiperOrigin-RevId: 843032402
2025-12-10 21:21:14 -08:00
Xuan Yang and Copybara-Service
786aaed335
feat: Support streaming function call arguments in progressive SSE streaming feature
...
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 837172244
2025-11-26 10:15:31 -08:00
qieqieplus and Copybara-Service
4a42d0d9d8
feat: Add enum constraint to agent_name for transfer_to_agent
...
Merge https://github.com/google/adk-python/pull/2437
Current implementation of `transfer_to_agent` doesn't enforce strict constraints on agent names, we could use JSON Schema's enum definition to implement stricter constraints.
Co-authored-by: Xuan Yang <xygoogle@google.com >
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2437 from qieqieplus:main 052e8e73b9d61c0998573a2077f15864873d0dd7
PiperOrigin-RevId: 836410397
2025-11-24 16:51:36 -08:00
Google Team Member and Copybara-Service
631b58336d
fix: Content is marked non empty if its first part contains text or inline_data or file_data or func call/response
...
PiperOrigin-RevId: 835063599
2025-11-20 22:19:28 -08:00
Xuan Yang and Copybara-Service
a5ac1d5e14
feat: Add progressive SSE streaming feature
...
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 833483804
2025-11-17 13:55:38 -08:00
Henrique Cadioli and Copybara-Service
8f3c3bfda5
fix: cache canonical tools to avoid multiple calls when streaming
...
Merge https://github.com/google/adk-python/pull/3299
Fixes https://github.com/google/adk-python/issues/3237
Co-authored-by: Xuan Yang <xygoogle@google.com >
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3299 from hcadioli:fix/cache-tools de02bd3e4533c3741edf05788a5e8b2d3d38bae4
PiperOrigin-RevId: 829499299
2025-11-07 10:51:32 -08:00
ananyablonko and Copybara-Service
0fccc7933a
fix(core): ParallelAgent's branching with include_contents='none' may cause index out of range error
...
Merge https://github.com/google/adk-python/pull/2961
Fixes #2404
Consider code where a sub_agent somewhere under a ParallelAgent has include_contents='none'.
```python
import asyncio
import os
from typing import TypedDict
from dotenv import load_dotenv
from google.adk.agents import LlmAgent, ParallelAgent, SequentialAgent
from google.adk.runners import Runner
from google.adk.sessions import DatabaseSessionService, InMemorySessionService
from google.genai import types
import logging
USE_DB=False
load_dotenv()
logging.basicConfig(
filename='log.log',
level=logging.DEBUG
)
for logger_name in ["httpcore"]:
logging.getLogger(logger_name).setLevel(logging.ERROR)
class AgentArgs(TypedDict):
model: str
instruction: str
class SessionArgs(TypedDict):
user_id: str
session_id: str
agent_args = AgentArgs(
model="gemini-2.0-flash",
instruction="Answer 'Ack' and nothing else."
)
session_args = SessionArgs(
user_id="0",
session_id="0"
)
app_name = "Test"
def create_agent_in_branch(i: int):
agent_1 = LlmAgent(
name=f"subagent_{i}_1",
**agent_args
)
agent_2 = LlmAgent(
name=f"subagent_{i}_2",
include_contents='none',
**agent_args
)
return SequentialAgent(
name=f"agent_{i}",
sub_agents=[agent_1, agent_2]
)
root = ParallelAgent(
name="root",
sub_agents=[create_agent_in_branch(i) for i in range(1, 5)]
)
runner = Runner(
agent=root,
app_name=app_name,
session_service=DatabaseSessionService(db_url=os.getenv("DB_URL", "")) if USE_DB else InMemorySessionService(),
)
async def main() -> None:
try:
await runner.session_service.delete_session(app_name=app_name, **session_args)
except:
pass
await runner.session_service.create_session(app_name=app_name, **session_args)
message = types.Content(role="user", parts=[types.Part(text=" ")])
async for event in runner.run_async(**session_args, new_message=message):
if event.is_final_response():
print(((event.content or types.Content()).parts or [types.Part()])[0].text or "")
if __name__ == '__main__':
asyncio.run(main())
```
The log here will often have one or more ```subagent_{i}_2``` not receive their prompts from ```subagent_{i}_1```.
This inconsistency is caused by the way ```include_contents='none'``` is implemented in flows/llm_flows/contents.py:328-356:
```python
for i in range(len(events) - 1, -1, -1):
event = events[i]
if event.author == 'user' or _is_other_agent_reply(agent_name, event):
return _get_contents(current_branch, events[i:], agent_name)
return []
```
That is, we first find the most recent (other-agent / user) event, **even if it's not on our branch**, and then filter the remainder. Thus in the above example, we may sometimes filter out all events, when we expect to have the event of a previous agent in a ```SequentialAgent```.
The solution is to first filter events by branch, and only then search for the latest.
### TEST SUMMARY:
```
=================================================== short test summary info ===================================================
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-LoopAgent-LoopAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-google.adk.agents.LoopAgent-LoopAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-google.adk.agents.loop_agent.LoopAgent-LoopAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-ParallelAgent-ParallelAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-google.adk.agents.ParallelAgent-ParallelAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-google.adk.agents.parallel_agent.ParallelAgent-ParallelAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-SequentialAgent-SequentialAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-google.adk.agents.SequentialAgent-SequentialAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[GOOGLE_AI-google.adk.agents.sequential_agent.SequentialAgent-SequentialAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-LoopAgent-LoopAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-google.adk.agents.LoopAgent-LoopAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-google.adk.agents.loop_agent.LoopAgent-LoopAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-ParallelAgent-ParallelAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-google.adk.agents.ParallelAgent-ParallelAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-google.adk.agents.parallel_agent.ParallelAgent-ParallelAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-SequentialAgent-SequentialAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-google.adk.agents.SequentialAgent-SequentialAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_with_sub_agents[VERTEX-google.adk.agents.sequential_agent.SequentialAgent-SequentialAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_llm_agent_with_sub_agents[GOOGLE_AI-LlmAgent-LlmAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_llm_agent_with_sub_agents[GOOGLE_AI-google.adk.agents.LlmAgent-LlmAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_llm_agent_with_sub_agents[GOOGLE_AI-google.adk.agents.llm_agent.LlmAgent-LlmAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_llm_agent_with_sub_agents[VERTEX-LlmAgent-LlmAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_llm_agent_with_sub_agents[VERTEX-google.adk.agents.LlmAgent-LlmAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/agents/test_agent_config.py::test_agent_config_discriminator_llm_agent_with_sub_agents[VERTEX-google.adk.agents.llm_agent.LlmAgent-LlmAgent] - FileNotFoundError: Config file not found: C:\Users\AnanYablonko\AppData\Local\Temp\pytest-of-AnanYablonko\pytest-1\test_age...
FAILED tests/unittests/cli/utils/test_cli_tools_click.py::test_cli_run_invokes_run_cli[GOOGLE_AI] - AssertionError: assert 1 == 0
FAILED tests/unittests/cli/utils/test_cli_tools_click.py::test_cli_run_invokes_run_cli[VERTEX] - AssertionError: assert 1 == 0
FAILED tests/unittests/cli/utils/test_cli_tools_click.py::test_cli_eval_with_eval_set_file_path[GOOGLE_AI] - assert 0 == 1
FAILED tests/unittests/cli/utils/test_cli_tools_click.py::test_cli_eval_with_eval_set_file_path[VERTEX] - assert 0 == 1
FAILED tests/unittests/evaluation/test_local_eval_sets_manager.py::TestLocalEvalSetsManager::test_local_eval_sets_manager_update_eval_case_eval_set_not_found[GOOGLE_AI] - OSError: [Errno 22] Invalid argument: '<tests.unittests.evaluation.test_local_eval_sets_manager.TestLocalEvalSetsManager ob...
FAILED tests/unittests/evaluation/test_local_eval_sets_manager.py::TestLocalEvalSetsManager::test_local_eval_sets_manager_update_eval_case_eval_set_not_found[VERTEX] - OSError: [Errno 22] Invalid argument: '<tests.unittests.evaluation.test_local_eval_sets_manager.TestLocalEvalSetsManager ob...
FAILED tests/unittests/evaluation/test_local_eval_sets_manager.py::TestLocalEvalSetsManager::test_local_eval_sets_manager_delete_eval_case_eval_set_not_found[GOOGLE_AI] - OSError: [Errno 22] Invalid argument: '<tests.unittests.evaluation.test_local_eval_sets_manager.TestLocalEvalSetsManager ob...
FAILED tests/unittests/evaluation/test_local_eval_sets_manager.py::TestLocalEvalSetsManager::test_local_eval_sets_manager_delete_eval_case_eval_set_not_found[VERTEX] - OSError: [Errno 22] Invalid argument: '<tests.unittests.evaluation.test_local_eval_sets_manager.TestLocalEvalSetsManager ob...
FAILED tests/unittests/sessions/test_session_service.py::test_get_session_with_config[GOOGLE_AI-SessionServiceType.DATABASE] - OSError: [Errno 22] Invalid argument
FAILED tests/unittests/sessions/test_session_service.py::test_get_session_with_config[VERTEX-SessionServiceType.DATABASE] - OSError: [Errno 22] Invalid argument
================================= 34 failed, 4540 passed, 3044 warnings in 187.68s (0:03:07) ==================================
```
Co-authored-by: Wei Sun (Jack) <weisun@google.com >
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2961 from ananyablonko:main b4a21adcd4231efeffd552a96734b2161b317e0a
PiperOrigin-RevId: 828700099
2025-11-05 17:41:35 -08:00
Xuan Yang and Copybara-Service
9ec38c0d89
feat: Add on_model_error_callback in LlmAgent
...
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 828560608
2025-11-05 11:37:08 -08:00
Xuan Yang and Copybara-Service
6a94af24bf
chore: Disable SetModelResponseTool workaround for Vertex AI Gemini 2+ models
...
Gemini models now [support Function calling being used together with structured output on Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#structured-output-bp ).
Co-authored-by: Xuan Yang <xygoogle@google.com >
PiperOrigin-RevId: 827709903
2025-11-03 17:12:01 -08:00
Josh Soref and Copybara-Service
aa1233608a
chore: Fix spelling
...
Merge https://github.com/google/adk-python/pull/2447
This PR corrects misspellings identified by the [check-spelling action](https://github.com/marketplace/actions/check-spelling )
The misspellings have been reported at https://github.com/jsoref/adk-python/actions/runs/16840838898/attempts/1#summary-47711379253
The action reports that the changes in this PR would make it happy: https://github.com/jsoref/adk-python/actions/runs/16840839269/attempts/1#summary-47711380479
Note: while I use tooling to identify errors, the tooling doesn't _actually_ provide the corrections, I'm picking them on my own. I'm a human, and I may make mistakes.
I've included a couple of changes to make CI happy. Personally, I object to CI being in a state of "random drive by person who adds a blank line in the middle of a file must fix all the preexisting bugs in the file", but that appears to be the state for this repository.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2447 from jsoref:spelling d85398e7fd154d124d477c6af6181481a01f34e0
PiperOrigin-RevId: 827629615
2025-11-03 13:33:53 -08:00