googleapis / googleapis/python-genai
Gemini 2.5 Pro intermittently emits reasoning-like content as normal text with include_thoughts=False
- Dominant language
- Python
- Stars
- 4k
- Forks
- 1k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 40
Description
## Summary
When using `gemini-2.5-pro` through the Gemini Developer API with the Python GenAI SDK, reasoning-like content is intermittently emitted through the ordinary text path even though `ThinkingConfig(include_thoughts=False)` is set.
The response may begin with a preamble shaped like this synthetic, sanitized example:
```text
thought. Here's a thinking process for how to respond...
[intended final response]
```
The application separates every response part for which `bool(part.thought)` is true before exposing normal text. The preamble nevertheless reaches the ordinary text path, so it is not structurally identifiable as a thought part at the point where the SDK response is consumed.
This appears related to #2121, but the observed environment uses Gemini 2.5 Pro, the Gemini Developer API, a newer SDK version, and explicitly sets `include_thoughts=False`.
## Environment details
- Programming language: Python
- OS: Linux
- Language runtime version: 3.14.3
- Package version: `google-genai==2.18.0`
- Model: `gemini-2.5-pro`
- Backend: Gemini Developer API
- Mode: async `generate_content_stream()`
## Sanitized request shape
```python
from google import genai
from google.genai import types
client = genai.Client(api_key=API_KEY)
stream = await client.aio.models.generate_content_stream(
model="gemini-2.5-pro",
contents="Respond with only the final answer.",
config=types.GenerateContentConfig(
thinking_config=types.ThinkingConfig(
thinking_budget=128,
include_thoughts=False,
),
),
)
async for chunk in stream:
for part in chunk.candidates[0].content.parts:
if getattr(part, "thought", False):
continue
if part.text:
print(part.text)
```
The behavior is intermittent, so this simplified prompt does not reproduce it deterministically. It shows the request and response-consumption shape without including any private prompt or application data.
## Expected behavior
With `include_thoughts=False`, reasoning summaries should not appear in the ordinary visible text stream. If reasoning content is returned, applications should have a reliable structured field such as `part.thought=True` with which to separate it from the final response.
## Actual behavior
Reasoning-like prose can appear before the intended final response through the same ordinary text path as the answer. Filtering all parts marked with `part.thought=True` therefore does not prevent the preamble from being exposed.
For affected responses, application-level usage metadata does not report thought tokens. Raw pre-SDK SSE payload capture is not currently available, so it is not yet clear whether the marker is absent in the API response or lost during SDK transformation.
## Questions
1. Is reasoning content ever expected to appear in ordinary `part.text` with `part.thought` unset when `include_thoughts=False`?
2. Is this a known issue for `gemini-2.5-pro` on the Gemini Developer API?
3. Is there a reliable structured signal clients can use to distinguish this content from the final answer?
4. Is additional raw-response instrumentation recommended to determine whether this originates in the backend or the SDK transformation layer?
## Related issues
- #2121
- #2239
Contributor guide
Assessment
This issue has not been assessed yet.