Skip to content

Commit 8f85260

Browse files
allen-stephencopybara-github
authored andcommitted
fix(live): history_config rejection on Vertex/Enterprise Live sessions
Merge google#6035 **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 **Problem:** On the Vertex AI / Gemini Enterprise Agent Platform backend, ADK auto-injects `history_config` into the Live setup message when seeding conversation history. That backend has no `history_config` field and rejects it with `ValueError: history_config parameter is only supported in Gemini Developer API mode, not in Gemini Enterprise Agent Platform mode` **Solution:** Gate the history_config auto-injection to the Gemini Developer API backend only (`isinstance(llm, Gemini)` and `llm._api_backend == GoogleLLMVariant.GEMINI_API`). On Vertex, history is already seeded via the sanctioned `send_history` (`send_client_content`) path. ### Testing Plan **Unit Tests:** - [X] I have added or updated unit tests for my change. - [X] All unit tests pass locally. $ pytest tests/unittests/flows/llm_flows/test_base_llm_flow.py -k history_config 2 passed, 35 deselected, 4 warnings in 0.78s **Manual End-to-End (E2E) Tests:** Verified intended functionality in ADK web. ### 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 N/A COPYBARA_INTEGRATE_REVIEW=google#6035 from allen-stephen:fix/live-history-config-bug cf8e1fc PiperOrigin-RevId: 933402607
1 parent 780b0ab commit 8f85260

2 files changed

Lines changed: 81 additions & 10 deletions

File tree

src/google/adk/flows/llm_flows/base_llm_flow.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,18 @@ async def run_live(
555555
# initial_history_in_client_content to True. This tells the Live server
556556
# that the provided history already includes the model's past responses,
557557
# preventing the server from generating duplicate responses for those replayed turns.
558+
#
559+
# ``history_config`` is only supported by the Gemini Developer API
560+
# backend; the Vertex AI / Gemini Enterprise Agent Platform backend has
561+
# no such field on its live setup message and rejects it. On Vertex,
562+
# history is instead seeded by ``send_history`` below
563+
# (``send_client_content`` with prior turns), so we skip
564+
# ``history_config`` for that backend.
558565
if (
559566
llm_request.contents
560567
and not invocation_context.live_session_resumption_handle
568+
and isinstance(llm, Gemini)
569+
and llm._api_backend == GoogleLLMVariant.GEMINI_API # pylint: disable=protected-access
561570
):
562571
if not llm_request.live_connect_config:
563572
llm_request.live_connect_config = types.LiveConnectConfig()

tests/unittests/flows/llm_flows/test_base_llm_flow.py

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,15 +1402,8 @@ async def mock_receive_2():
14021402

14031403

14041404
@pytest.mark.asyncio
1405-
@pytest.mark.parametrize(
1406-
'api_backend',
1407-
[
1408-
GoogleLLMVariant.GEMINI_API,
1409-
GoogleLLMVariant.VERTEX_AI,
1410-
],
1411-
)
1412-
async def test_run_live_history_config_set_for_all_backends(api_backend):
1413-
"""Test that run_live sets history_config for all backends."""
1405+
async def test_run_live_history_config_set_for_gemini_api_backend():
1406+
"""history_config is auto-set when seeding history on the Gemini API backend."""
14141407

14151408
real_model = Gemini(model='gemini-3.1-flash-live-preview')
14161409
mock_connection = mock.AsyncMock()
@@ -1457,7 +1450,7 @@ async def mock_receive():
14571450
Gemini,
14581451
'_api_backend',
14591452
new_callable=mock.PropertyMock,
1460-
return_value=api_backend,
1453+
return_value=GoogleLLMVariant.GEMINI_API,
14611454
):
14621455
try:
14631456
async for _ in flow.run_live(invocation_context):
@@ -1475,6 +1468,75 @@ async def mock_receive():
14751468
)
14761469

14771470

1471+
@pytest.mark.asyncio
1472+
async def test_run_live_history_config_not_set_for_vertex_backend():
1473+
"""history_config is NOT auto-set on the Vertex backend (it rejects it).
1474+
1475+
The Vertex AI / Gemini Enterprise Agent Platform live setup message has no
1476+
``history``/``history_config`` field. ADK seeds Vertex history via
1477+
``send_history`` (``send_client_content``) instead, so the auto-injection of
1478+
``history_config`` must be skipped for this backend.
1479+
"""
1480+
1481+
real_model = Gemini(model='gemini-3.1-flash-live-preview')
1482+
mock_connection = mock.AsyncMock()
1483+
1484+
class StopTestError(Exception):
1485+
pass
1486+
1487+
async def mock_receive():
1488+
yield LlmResponse(
1489+
content=types.Content(parts=[types.Part.from_text(text='hi')])
1490+
)
1491+
raise StopTestError('stop')
1492+
1493+
mock_connection.receive = mock.Mock(side_effect=mock_receive)
1494+
1495+
agent = Agent(name='test_agent', model=real_model)
1496+
invocation_context = await testing_utils.create_invocation_context(
1497+
agent=agent
1498+
)
1499+
invocation_context.live_request_queue = LiveRequestQueue()
1500+
1501+
flow = BaseLlmFlowForTesting()
1502+
1503+
with mock.patch.object(flow, '_send_to_model', new_callable=AsyncMock):
1504+
1505+
async def mock_preprocess(ctx, req):
1506+
req.contents = [
1507+
types.Content(parts=[types.Part.from_text(text='history')])
1508+
]
1509+
yield Event(id=Event.new_id(), author='test')
1510+
1511+
with mock.patch.object(
1512+
flow, '_preprocess_async', side_effect=mock_preprocess
1513+
):
1514+
with mock.patch.object(
1515+
Gemini, '_api_backend', new_callable=mock.PropertyMock
1516+
) as mock_backend:
1517+
mock_backend.return_value = GoogleLLMVariant.VERTEX_AI
1518+
with mock.patch(
1519+
'google.adk.models.google_llm.Gemini.connect'
1520+
) as mock_connect:
1521+
mock_connect.return_value.__aenter__.return_value = mock_connection
1522+
1523+
try:
1524+
async for _ in flow.run_live(invocation_context):
1525+
pass
1526+
except StopTestError:
1527+
pass
1528+
1529+
assert mock_connect.call_count == 1
1530+
called_req = mock_connect.call_args[0][0]
1531+
# history_config must NOT be auto-injected on Vertex.
1532+
assert (
1533+
called_req.live_connect_config is None
1534+
or called_req.live_connect_config.history_config is None
1535+
)
1536+
# History is still seeded via send_history (send_client_content).
1537+
mock_connection.send_history.assert_awaited_once()
1538+
1539+
14781540
@pytest.mark.asyncio
14791541
async def test_run_live_respects_explicit_initial_history_in_client_content_false():
14801542
"""Test that run_live respects explicit initial_history_in_client_content=False in RunConfig."""

0 commit comments

Comments
 (0)