Skip to content

Python: [Bug]: Gemini streaming drops the model when a chunk has no model_version #9138

Description

@Ayoubhm07

Description

GeminiChatClient._process_chunk passes chunk.model_version straight into ChatResponseUpdate.model, with no fallback. _process_generate_response, 33 lines above in the same file, falls back to self.model for the same field:

model=response.model_version or self.model,

Both methods take the same type, types.GenerateContentResponse (:1034-1036 and :1066), and model_version is Optional[str] there. The SDK documents per-chunk absence for the very next field of that class, prompt_feedback: "Sent only in the first stream chunk."

What happens: ChatResponse.model is built only from the updates _types.py:2229-2230 keeps the last non-None value, and the Gemini client has no catch-up afterwards so when no chunk carries model_version, a streamed response ends up with model=None.

What I expected: the configured model, which is what the non-streaming path reports for the same input.

Why it matters: observability.py:3551-3552 sets gen_ai.response.model from that field. RESPONSE_MODEL is part of GEN_AI_METRIC_ATTRIBUTES (:3558), and _filter_metric_attributes drops absent keys before _capture_response records token_usage_histogram and operation_duration_histogram (:3604-3610). So on Gemini streams the token and duration histograms lose their per-model dimension, and _backfill_request_model (:1905) cannot recover the span name either.

Steps to reproduce: drive get_response(..., stream=True) over a single chunk whose model_version is unset, then read updates[0].model. No API key and no network are needed.

Code Sample

from unittest.mock import MagicMock

chunk = MagicMock()
chunk.model_version = None


Feed that chunk through `GeminiChatClient.get_response(..., stream=True)` and read `updates[0].model`.

Expected: the configured model.
Actual: `None`.

Error Messages / Stack Traces

No exception is raised. The failure is silent: the field is simply absent
from the span attributes and from the metric dimensions

Package Versions

agent-framework-core: 1.20.0, agent-framework-gemini: 1.0.0b261002, google-genai: 2.27.0

Python Version

Python 3.11.4

Additional Context

MistralChatClient has the same asymmetry at _chat_client.py:800 / :830, but its SDK types CompletionChunk.model as required, so the gap is not reachable there. OllamaChatClient has no fallback on either path, so it is self-consistent. A PR for the Gemini case follows.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 7, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 7, 2026
  3. github-actions commented on Oct 7, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    Repro: python/packages/gemini/agent_framework_gemini/_chat_client.py::GeminiChatClient._process_chunk emits model=None when a streaming GenerateContentResponse.model_version is unset. Construct a client with model gemini-2.5-flash, mock one model-less chunk through get_response(..., stream=True), and assert the first update reports the configured model.

    • Failing test: python/packages/gemini/tests/test_gemini_client.py::test_get_response_streaming_falls_back_to_configured_model
    • Files examined: python/packages/gemini/agent_framework_gemini/_chat_client.py, python/packages/gemini/tests/test_gemini_client.py, python/packages/core/agent_framework/_types.py, python/packages/core/agent_framework/observability.py, python/packages/gemini/pyproject.toml
    • Tests run: python/packages/gemini/tests/test_gemini_client.py::test_get_response_streaming_falls_back_to_configured_model
    • Reported version: 1.0.0b261002
    • Current version: 1.0.0b261002
  4. added
    agentsUsage: [Issues, PRs], Target: Single agent
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agentsUsage: [Issues, PRs], Target: Single agentpythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions