-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
When using adk run --save_session, session files are serialized with snake_case field names (app_name, user_id, usage_metadata). However, adk web serializes the same session files with camelCase field names (appName, userId, usageMetadata). This inconsistency breaks compatibility between session files generated by different ADK CLI commands, despite both using the same Pydantic models with alias_generator=alias_generators.to_camel configuration.
To Reproduce
Minimal reproduction:
- Create a simple agent in
src/my_agent/agent.py:
from google.adk import Agent
root_agent = Agent(
name="test_agent",
model="gemini-2.5-flash",
instruction="You are a test agent. Say hello.",
)- Create input file
input.json:
{
"state": {},
"queries": ["Hello!"]
}- Run agent with session saving:
adk run src/my_agent --save_session --session_id test --replay input.json- Inspect the saved session file:
cat src/my_agent/test.session.json | jq 'keys'Observed output (snake_case):
["app_name", "events", "id", "last_update_time", "state", "user_id"]- Compare with a session file from
adk web(runadk web src/my_agentand check saved session)
Expected output from adk web (camelCase):
["appName", "events", "id", "lastUpdateTime", "state", "userId"]Field comparison:
adk run output (incorrect):
{
"app_name": "test_agent",
"user_id": "user",
"events": [{
"model_version": "gemini-2.5-flash",
"usage_metadata": {
"prompt_token_count": 123,
"candidates_token_count": 456
}
}]
}adk web output (correct):
{
"appName": "test_agent",
"userId": "user",
"events": [{
"modelVersion": "gemini-2.5-flash",
"usageMetadata": {
"promptTokenCount": 123,
"candidatesTokenCount": 456
}
}]
}Expected behavior
Both adk run and adk web should serialize session files with camelCase field names, consistent with the Pydantic model configuration in Session and Event classes:
model_config = ConfigDict(
alias_generator=alias_generators.to_camel,
populate_by_name=True,
)All session files should use: appName, userId, modelVersion, usageMetadata, promptTokenCount, candidatesTokenCount, etc.
Desktop
- OS: macOS (darwin 24.6.0)
- Python version: 3.12.11 (
python -V) - ADK version: 1.18.0+ (
pip show google-adk)
Model Information
- Are you using LiteLLM: No
- Which model is being used: gemini-2.5-flash
Additional context
Root cause identified:
In google/adk/cli/cli.py at line 218, the session serialization is missing by_alias=True:
217: with open(session_path, 'w', encoding='utf-8') as f:
218: f.write(session.model_dump_json(indent=2, exclude_none=True))For comparison, adk_web_server.py correctly includes by_alias=True at lines 1424 and 1523:
1423: sse_event = event.model_dump_json(
1424- exclude_none=True, by_alias=True
1425- )Proposed fix:
Change line 218 in google/adk/cli/cli.py to:
f.write(session.model_dump_json(indent=2, exclude_none=True, by_alias=True))Affected fields:
All Pydantic model fields in Session, Event, and nested objects:
- Session:
app_name→appName,user_id→userId,last_update_time→lastUpdateTime - Event:
model_version→modelVersion,usage_metadata→usageMetadata,invocation_id→invocationId - UsageMetadata:
prompt_token_count→promptTokenCount,candidates_token_count→candidatesTokenCount
Impact:
Session files from adk run cannot be easily consumed by tools expecting the documented camelCase format. This requires workarounds in consuming code to parse both formats, and breaks consistency expectations for the same data structure.