When switching an LLM search pipeline to Anthropic's server-side web_search tool ({'type': 'web_search_20250305', 'name': 'web_search'}), the common assumption is that litellm's OpenAI-shape normalization drops the citation blocks, forcing a raw httpx call to /v1/messages (and losing any litellm-based cost telemetry). Verified false on litellm 1.93 + claude-opus-4-8 (2026-08-10):
response.choices[0].message.content= concatenated text blocks.message.provider_specific_fields['citations']= list-of-lists (one inner list per text block), each citation carryingurl,title,cited_text(verbatim page snippet) ANDsupported_text— the exact generated span the citation vouches for. Locatingsupported_textin the concatenated content gives byte-exact citation spans without server-supplied offsets.message.provider_specific_fields['web_search_results']= the web_search_tool_result blocks.- The search queries are NOT in provider_specific_fields — they land in
message.tool_calls[*].function.argumentsas JSON{"query": ...}(tool nameweb_search). Parse those for query auditing (e.g. detecting a model searching for its own invented figure).
Gotchas: opus-4-8 rejects temperature (reasoning model — only default/1 supported; litellm raises UnsupportedParamsError on 0.0), and cited_text comes from the search index so it may not appear verbatim in the live page you fetch yourself.
This keeps PostHog/litellm $ai_generation cost tracking intact for server-tool calls — no manual telemetry emission needed.