Repository navigation
Python: [Bug]: BedrockChatClient reports the client's default model on non-streaming responses, not the model it sent the request to #9398
Description
Observed Behavior
When I pass a model per call with options={"model": ...}, BedrockChatClient sends the request to that model, but the non-streaming ChatResponse.model is the model the client was created with. If the client has no default model, response.model is None.
This also lands in telemetry, since gen_ai.response.model is read from response.model.
Streaming is fine. It reports the model the request went to.
Expected Behavior
response.model is the model the request was sent to, same as the streaming path.
Steps to Reproduce
- Create
BedrockChatClient(model="model-a", ...). - Call
get_response(..., options={"model": "model-b"})without streaming. - The Converse request uses
modelId="model-b", butresponse.modelis"model-a".
Minimal Reproduction
import asyncio
from typing import Any
from agent_framework import Message
from agent_framework_bedrock import BedrockChatClient
class ConverseStub:
"""Returns the real Converse response shape. Converse does not echo the model id."""
def __init__(self) -> None:
self.calls: list[dict[str, Any]] = []
def converse(self, **kwargs: Any) -> dict[str, Any]:
self.calls.append(kwargs)
return {
"output": {"message": {"role": "assistant", "content": [{"text": "hi"}]}},
"stopReason": "end_turn",
"usage": {"inputTokens": 3, "outputTokens": 1, "totalTokens": 4},
"metrics": {"latencyMs": 10},
}
async def main() -> None:
stub = ConverseStub()
client = BedrockChatClient(model="model-a", region="us-east-1", client=stub)
response = await client.get_response(
[Message(role="user", contents=["hello"])],
options={"model": "model-b"},
)
print("sent modelId: ", stub.calls[-1]["modelId"])
print("response.model: ", response.model)
no_default = BedrockChatClient(region="us-east-1", client=stub)
response = await no_default.get_response(
[Message(role="user", contents=["hello"])],
options={"model": "model-b"},
)
print("no client default:", response.model)
asyncio.run(main())Output on main (95511ff):
sent modelId: model-b
response.model: model-a
no client default: None
Error Messages and Stack Traces
None. The value is just wrong.
Root cause
_process_converse_response sets model = response.get("modelId") or output.get("modelId") or self.model (python/packages/bedrock/agent_framework_bedrock/_chat_client.py:769). The Converse response has no modelId field (botocore ConverseResponse members: output, stopReason, usage, metrics, additionalModelResponseFields, trace, performanceConfig, serviceTier), so it always falls back to self.model. The streaming path already passes request["modelId"] (line 408).
Package Versions
agent-framework-bedrock: 1.0.0b261008, agent-framework-core: 1.21.0 (main at 95511ff)
Python Version
Python 3.12
Operating System
macOS
Regression
Unknown
Additional Context
Same kind of issue as #9138 for Gemini streaming. The review on #9139 asked to label responses with the resolved request model rather than the client default, which is what I'd do here: pass request["modelId"] into _process_converse_response. It's a few lines plus a test, so I can open a PR.
Acknowledgements
- I searched existing issues and did not find a duplicate.
- I personally verified this behavior and the reproduction details are authentic.
- I will wait for explicit maintainer agreement before starting implementation of a non-trivial change.
Metadata
Metadata
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
github-actions commentedon Oct 14, 2026
🤖 Automated triage reproduction notes (agent-authored — trust but verify)
Agent analysis
The defect reproduces in python/packages/bedrock/agent_framework_bedrock/_chat_client.py::_inner_get_response and _process_converse_response at lines 423 and 769 when a non-streaming call overrides the client model and Converse omits modelId. Minimal repro: use a stub returning a normal Converse response without modelId, call get_response with options={"model": "model-b"} on clients configured with model-a or no default, and assert response.model equals model-b.
python/packages/bedrock/tests/test_bedrock_client.py1.0.0b2610081.0.0b261008