Repository navigation
AnthropicLlm never populates LlmResponse.model_version #6847
Description
🔴 Required Information
Describe the Bug:
AnthropicLlm (google/adk/models/anthropic_llm.py) never sets LlmResponse.model_version,
on either the streaming or non-streaming path. Every other first-party model wrapper populates
it from the underlying API response:
google_llm.pysetsmodel_version=modelfrom the Gemini response.lite_llm.pysetsmodel_version=response.model/model_version=part.model(this covers
Claude-via-LiteLLM too, so that path does not have this bug).apigee_llm.pysetsmodel_version=response.get('model').
AnthropicLlm has the same data available and does not read it:
- Non-streaming:
message_to_generate_content_response()(anthropic_llm.py:672) takes
message: anthropic_types.Messageand builds theLlmResponseat line 686 without ever
touchingmessage.model— the Anthropic SDK'sMessageobject exposes the actual resolved
model id there. - Streaming: the
message_startevent handler (anthropic_llm.py:998) reads
event.message.usagefor token accounting (lines 999-1002) but never reads
event.message.model, so the aggregatedLlmResponseyielded at the end of the stream
(anthropic_llm.py:1112) also has nomodel_version.
This matters because Anthropic model aliases (e.g. claude-sonnet-5) resolve to a dated
snapshot server-side, and model_version is the mechanism ADK already uses elsewhere (event
telemetry, DatabaseSessionService-persisted Event rows, the gen_ai.response.model span
attribute in telemetry/tracing.py) to record which snapshot actually served a given response.
For the Anthropic direct-API path, all of that ends up null.
Steps to Reproduce:
- Install
google-adk(reproduced on 2.7.0, but present since the module's introduction). - Configure an
LlmAgentwithmodel=AnthropicLlm(model="claude-sonnet-5")(ANTHROPIC_API_KEYset). - Run any turn, streaming or non-streaming, and inspect the yielded
LlmResponse(s) — or, if
usingDatabaseSessionService/any other persistedSessionService, inspect the stored
Eventrow for that turn. - Compare
LlmResponse.model_versionagainst the same check withGeminiorLiteLlm(model="claude-...").
Expected Behavior:
LlmResponse.model_version is populated with the model id/snapshot Anthropic actually served
(message.model non-streaming, event.message.model streaming), matching the behavior of
google_llm.py, lite_llm.py, and apigee_llm.py.
Observed Behavior:
LlmResponse.model_version is always None for every response AnthropicLlm produces, on
both the streaming and non-streaming paths.
Environment Details:
- ADK Library Version (pip show google-adk): 2.7.0
- Desktop OS: macOS
- Python Version (python -V): 3.13.7
Model Information:
- Are you using LiteLLM: No — using
AnthropicLlmdirectly (AsyncAnthropic, keyed byANTHROPIC_API_KEY), not the LiteLLM path. - Which model is being used: claude-sonnet-5 (also reproduces on other Claude ids)
🟡 Optional Information
Regression:
Not a regression — model_version appears to have never been wired into AnthropicLlm since
the class was introduced.
Additional Context:
This looks like the same class of gap as #5394 ("AnthropicLlm never populates
LlmResponse.finish_reason"), which was part of a batch of AnthropicLlm parity issues
(#5392–#5397) filed against this file. That issue's linked PR (#5512) showed the finish_reason
line had originally been commented out with # TODO: Deal with these later, and although both
community PRs for it (#5441, #5512) were closed unmerged, the fix did land internally by 2.7.0
(anthropic_llm.py:1121 now sets finish_reason=to_google_genai_finish_reason(stop_reason)).
model_version doesn't appear to be tracked anywhere in that batch or elsewhere in the tracker —
filing this separately so it doesn't fall through the same gap.
Minimal Reproduction Code:
from google.adk.models.anthropic_llm import AnthropicLlm
from google.adk.models.llm_request import LlmRequest
from google.genai import types
llm = AnthropicLlm(model="claude-sonnet-5")
request = LlmRequest(
contents=[types.Content(role="user", parts=[types.Part.from_text(text="hi")])],
)
async def main():
async for response in llm.generate_content_async(request):
print("model_version:", response.model_version) # always None
import asyncio
asyncio.run(main())How often has this issue occurred?:
- Always (100%)
Activity
fix(models): populate model_version on AnthropicLlm responses
aaravxsingh15 commentedon Aug 22, 2026
Hi, I’d like to work on this issue. I plan to populate LlmResponse.model_version for both streaming and non-streaming Anthropic responses and add focused unit tests. Please let me know if this approach is acceptable.
omar-infinitusai commentedon Aug 22, 2026
Hey @feiiiiii5 and @aaravxsingh15 ! Thanks for opening the PRs 🙏 . I was hoping to also capture the model_version for partial responses during reasoning. This proposed solution accounts for that: #6850
sanketpatil06 commentedon Aug 25, 2026
Hi @omar-infinitusai, thanks for reporting this issue and submitting the fix. We observed the same behavior on our end.
Your PR #6850 is currently under review by our team, and we will let you know if anything further is needed.
fix: populate model_version on AnthropicLlm responses