googleapis / googleapis/python-genai

tool_config mode="ANY" with automatic function calling exhausts maximum_remote_calls and returns empty text, with no warning

Open
#2,839 1 comment 0 reactions 1 assignee Assigned to @kkorpal View on GitHub
priority: p2 type: bug
Dominant language
Python
Stars
4k
Forks
1k
Avg merge
2d 11h
Merged PRs (30d)
40

Description

### Summary

`FunctionCallingConfig(mode="ANY")` combined with automatic function
calling produces a request that consumes the whole remote-call budget and
returns **empty text**, with no error and no warning. `mode="ANY"`
obliges the model to emit a function call on every turn; AFC dutifully
executes each one and asks again; the loop only ends when
`maximum_remote_calls` runs out, at which point there is no natural
language answer to return because the model was never permitted to give
one.

The combination is detectable at config time, and the library already
warns about two neighbouring misconfigurations — just not this one.

### Where

`google/genai/_extra_utils.py`, at `ccbc6c5`. Both existing guards live
in the same function:

```python
if (... maximum_remote_calls is not None
and int(...maximum_remote_calls) <= 0):
logger.warning(
'max_remote_calls in automatic_function_calling_config'
f' {...} is less than or equal to 0. Disabling automatic function'
' calling. Please set max_remote_calls to a positive integer.'
)
return True

if (config_model.automatic_function_calling.disable
and ...maximum_remote_calls is not None
and 'maximum_remote_calls' in ...model_fields_set
and int(...maximum_remote_calls) > 0):
logger.warning(
'`automatic_function_calling.disable` is set to `True`. And'
' `automatic_function_calling.maximum_remote_calls` is a positive'
' number ...'
)
```

There is no equivalent check for `tool_config.function_calling_config.mode
== ANY` while AFC is enabled.

### Why it matters

Every symptom points away from the cause. You get a successful response
object, `finish_reason` looks ordinary, and the text is empty — so the
natural conclusion is that the model failed to answer, or the prompt is
bad, or the tools are wrong. The actual cause is two settings that are
each individually reasonable and only interact badly together. The
`logger.info('Reached max remote calls...')` that does fire reads as
routine, because it is the same message a legitimately long tool chain
produces.

### Reproduce

```python
from google import genai
from google.genai import types

def get_weather(city: str) -> str:
return f"sunny in {city}"

client = genai.Client()
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents="What is the weather in Paris?",
config=types.GenerateContentConfig(
tools=[get_weather],
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode="ANY")
),
),
)
print(repr(resp.text)) # empty
```

### Suggested fix

A warning at config time, in the same place as the two existing ones —
something to the effect that `mode="ANY"` with automatic function calling
enabled will consume `maximum_remote_calls` and return no text, and that
`mode="AUTO"` is wanted if the model should be allowed to answer.

I am raising this as an issue rather than sending the patch because
whether you want a warning here is your call: `mode="ANY"` is a
legitimate setting, and someone driving the loop manually with AFC
disabled has a perfectly good reason to use it. If you would like the
warning, I am happy to send a PR.

### Environment

- google-genai: read from source at `ccbc6c5` (current `main`); latest
release at time of writing is v2.17.0
- Python: 3.13

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.