This change replaces the use of `ChatCompletionDeveloperMessage` with `ChatCompletionSystemMessage` and sets the role to "system" for providing system instructions to LiteLLM models
Close#3657
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 835388738
Merge https://github.com/google/adk-python/pull/3576
**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: #3557
- Related: #_issue_number_
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
When creating a BaseAgent with multiple sub-agents, there was no validation to ensure that all sub-agents have unique names. This could lead to confusion when trying to find or reference specific sub-agents by name, as duplicate names would make it ambiguous which agent is being referenced.
**Solution:**
Added a @field_validator for the sub_agents field in BaseAgent that validates all sub-agents have unique names. The validator:
Checks for duplicate names in the sub-agents list
Raises a ValueError with a clear error message listing all duplicate names found
Returns the validated list if all names are unique
Handles edge cases like empty lists gracefully
### Testing Plan
_Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes._
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
Added 4 new test cases in tests/unittests/agents/test_base_agent.py:
test_validate_sub_agents_unique_names_single_duplicate: Verifies that a single duplicate name raises ValueError
test_validate_sub_agents_unique_names_multiple_duplicates: Verifies that multiple duplicate names are all reported in the error message
test_validate_sub_agents_unique_names_no_duplicates: Verifies that unique names pass validation successfully
test_validate_sub_agents_unique_names_empty_list: Verifies that empty sub-agents list passes validation
All tests pass locally. You can run with:
pytest tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_single_duplicate tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_multiple_duplicates tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_no_duplicates tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_empty_list -v
**Manual End-to-End (E2E) Tests:**
_Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix._
Test Case 1: Duplicate names should raise error
from google.adk.agents import Agent
agent1 = Agent(name="sub_agent", model="gemini-2.5-flash")
agent2 = Agent(name="sub_agent", model="gemini-2.5-flash") # Same name
# This should raise ValueError
try:
parent = Agent(
name="parent",
model="gemini-2.5-flash",
sub_agents=[agent1, agent2]
)
except ValueError as e:
print(f"Expected error: {e}")
# Output: Found duplicate sub-agent names: `sub_agent`. All sub-agents must have unique names.
Test Case 2: Unique names should work
from google.adk.agents import Agent
agent1 = Agent(name="agent1", model="gemini-2.5-flash")
agent2 = Agent(name="agent2", model="gemini-2.5-flash")
# This should work without error
parent = Agent(
name="parent",
model="gemini-2.5-flash",
sub_agents=[agent1, agent2]
)
print("Success: Unique names validated correctly")
### 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.
### Additional context
This change adds validation at the BaseAgent level, so it automatically applies to all agent types that inherit from BaseAgent (e.g., LlmAgent, LoopAgent, etc.). The validation uses Pydantic's field validator system, which runs during object initialization, ensuring the constraint is enforced early and consistently.
The error message clearly identifies which names are duplicated, making it easy for developers to fix the issue:
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3576 from sarojrout:feat/validate-unique-sub-agent-names 07adf1f9a5fc935389eb9dfa3cbc1311f551ebe3
PiperOrigin-RevId: 835358118
The `database_session_service` now updates the `update_time` of a session to the event's timestamp when an event is appended
Close#2721
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834994070
LlmResponse/Event now keep both provider reasoning output and the raw vendor payload so callbacks and loggers can inspect hidden “thoughts” or trace bugs without rewriting adapters.
LiteLLM’s adapter and streaming loop emit reasoning chunks alongside text and aggregate them into final events -> all responses now carry a JSON-safe copy of the source payload for debug. UnsafeLocalCodeExecutor uses the documented exec(code, globals, globals) form, letting helper functions defined inside snippets call each other.
Close#1749
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834956847
Merge https://github.com/google/adk-python/pull/3430
**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: #3429
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
The existing `/list-apps` endpoint only returns the name of the folder that each agent is in
**Solution:**
This adds a new endpoint `/list-apps-detailed` which will load each agent using the existing `AgentLoader.load_agent` method, and then return the folder name, display name (with underscores replaced with spaces for a more readable version), description, and the agent type.
This does introduce overhead if you had multiple agents since they all need to be loaded, but by maintaining the existing `/list-apps` endpoint, users can choose which one to hit if they don't want to load all agents. Since the existing `load_agents` method will cache results, there's only a penalty on the first hit.
### Testing Plan
Created a unit test for this, similar to the `/list-apps`. Also tested this with my own ADK instance to verify it loaded correctly.
```
curl --location "localhost:8000/list-apps-detailed"
```
```json
{
"apps": [
{
"name": "agent_1",
"displayName": "Agent 1",
"description": "A test description for a test agent",
"agentType": "package"
},
{
"name": "agent_2",
"displayName": "Agent 2",
"description": "A test description for a test agent ",
"agentType": "package"
},
{
"name": "agent_3",
"displayName": "Agent 3",
"description": "A test description for a test agent",
"agentType": "package"
}
]
}
```
**Unit Tests:**
- [X] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
3054 passed, 2383 warnings in 46.96s
### 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/3430 from dylan-apex:more-detailed-list-apps e6864fd61a673da5fd2fb28d2d7d72cb90f5af0a
PiperOrigin-RevId: 834907771
The `Parameter` class now provides default Python names based on the parameter location when the original name is empty. This prevents parameters from having an empty string as their Python name, especially for request bodies defined without a top-level name.
Close#2213
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834850255
Retrying only on closed_resource error is not enough to be reliable for production environments due to the other network errors that may occur -- remote protocol error, read timeout, etc. We will update this to retry on all errors. Since it is only a one-time retry, it should not affect latency significantly. Fixes https://github.com/google/adk-python/issues/2561.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 834514264
This change will help the tools user identify per agent job usage in BQ console and INFORMATION_SCHEMA views. This change fulfills the feature request #3582. Here is a demo after change: screen/C6YB4ge2FM2ZREi.
PiperOrigin-RevId: 834480140
This change introduces `input_transcription` and `output_transcription` fields to session events, enabling the storage and retrieval of transcription data in both the database and Vertex AI session services.
Closes#3172
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 834366848
This change loads the agent or app from the specified directory before creating the session. This allows using the correct application name (from the `App` object if applicable) when initializing the session, rather than always defaulting to the folder name. The variable `root_agent` is also renamed to `agent_or_app` to better reflect that it can be either an Agent or an App
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 833839070
Currently logic to check for a disconnected session only checks for certain headers but doesn't detect all cases, leading to situations where it tries to connect to a session that is down. This adds logic so that we ping the server to check if it is disconnected. Fixes https://github.com/google/adk-python/issues/3321.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 833487825