Skip to content

Commit 79ac418

Browse files
committed
fix: reject json response mime with function calling
1 parent 3329ced commit 79ac418

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

src/google/adk/agents/llm_agent.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,24 @@ def __maybe_save_output_to_state(self, event: Event):
943943

944944
@model_validator(mode='after')
945945
def __model_validator_after(self) -> LlmAgent:
946+
generate_content_config = self.generate_content_config
947+
if (
948+
self.tools
949+
and generate_content_config
950+
and generate_content_config.response_mime_type == 'application/json'
951+
):
952+
tool_config = generate_content_config.tool_config
953+
function_calling_config = (
954+
tool_config.function_calling_config if tool_config else None
955+
)
956+
mode = function_calling_config.mode if function_calling_config else None
957+
mode_value = getattr(mode, 'value', mode)
958+
if mode_value is None or str(mode_value).upper() != 'NONE':
959+
raise ValueError(
960+
'`response_mime_type="application/json"` is incompatible with '
961+
'function calling. Set `function_calling_config.mode` to "NONE" '
962+
'or remove tools from the agent.'
963+
)
946964
return self
947965

948966
@field_validator('generate_content_config', mode='after')

tests/unittests/agents/test_llm_agent_fields.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,51 @@ def _a_tool():
250250
)
251251

252252

253+
@pytest.mark.parametrize('mode', ['AUTO', 'ANY', None])
254+
def test_generate_content_config_json_response_with_function_calling_throws(
255+
mode,
256+
):
257+
def _a_tool():
258+
pass
259+
260+
function_calling_config = (
261+
types.FunctionCallingConfig(mode=mode) if mode else None
262+
)
263+
tool_config = (
264+
types.ToolConfig(function_calling_config=function_calling_config)
265+
if function_calling_config
266+
else None
267+
)
268+
269+
with pytest.raises(ValueError, match='response_mime_type="application/json"'):
270+
LlmAgent(
271+
name='test_agent',
272+
tools=[_a_tool],
273+
generate_content_config=types.GenerateContentConfig(
274+
response_mime_type='application/json',
275+
tool_config=tool_config,
276+
),
277+
)
278+
279+
280+
def test_generate_content_config_json_response_with_function_calling_none():
281+
def _a_tool():
282+
pass
283+
284+
agent = LlmAgent(
285+
name='test_agent',
286+
tools=[_a_tool],
287+
generate_content_config=types.GenerateContentConfig(
288+
response_mime_type='application/json',
289+
tool_config=types.ToolConfig(
290+
function_calling_config=types.FunctionCallingConfig(mode='NONE')
291+
),
292+
),
293+
)
294+
295+
assert agent.generate_content_config.response_mime_type == 'application/json'
296+
297+
253298
def test_before_model_callback():
254299
def _before_model_callback(
255300
callback_context: CallbackContext,

0 commit comments

Comments
 (0)