Use the Pydantic AI Gateway's reported cost for `RequestUsage.cost`
Merged
AD
5d ago+402+402+012345678901234567890123456789-15-15-01234567890123456789
RequestUsage.costuses the cost the Pydantic AI Gateway reports in the response body (usage.logfire_ai_gateway.cost, falling back to the deprecatedusage.pydantic_ai_gateway.cost_estimate) instead of the genai-prices estimate, for OpenAI Chat/Responses, Groq and Anthropic, streamed and not. A reported0(response-cache hit) counts.- Google and Bedrock SDKs drop that body field, so on non-streamed requests they read the
logfire-ai-gateway-costheader instead. It holds the same unrounded cost as the body, so it also wins over the genai-prices estimate, and0USD(response-cache hit) counts. The deprecated, roundedpydantic-ai-gateway-price-estimateheader isn't read. Streamed Google and Bedrock responses carry no gateway cost and keep the estimate. InstrumentedEmbeddingModelreportsusage.costwhen set, matching model telemetry.cost()on responses and embedding results still returns the genai-prices estimate.- Docs: one "Request cost" section in
docs/gateway.md.
PR decisions
2026-10-24 · Reported cost telemetry precedence · iter -
- Decision: Preserve response usage cost precedence in model telemetry, including unknown models.
- Why: The resolved thread records the correction and proving test.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337#discussion_r4365616706
2026-10-24 · Adopted PR #7337 · iter -
- Decision: Bootstrapped branch context from PR discussion and existing implementation.
- Why: Existing brief and decisions were unfilled templates; no linked issue.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-24 · Preserve upstream Anthropic package split · iter -
- Decision: Port Gateway cost carry-through into models/anthropic/_response.py::map_usage and preserve upstream init.py unchanged.
- Why: Main moved usage mapping in the pure module split; keeping the old module would discard upstream structure.
- Source: https://github.com/pydantic/pydantic-ai/pull/11165
2026-10-24 · pre-push review 1 of 3 at 241bb3dc67f0ed87e464fbf6175c9e96bae96878 · iter -
- Decision: Reserved fresh reviewer dispatch; outcome pending.
- Why: Tree 478e309146ec35463941621651ad74ce52e58244; full branch scope ffbf82ef90975abb209014b6b2b4e4ac21b53ba6..241bb3dc67f0ed87e464fbf6175c9e96bae96878; first review in this task.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-24 · pre-push review 1 outcome at 241bb3dc67f0ed87e464fbf6175c9e96bae96878 · iter -
- Decision: Remediated: qualify Gateway request-cost docs for unpriced responses and state estimate-or-None fallback.
- Why: Reviewed tree 478e309146ec35463941621651ad74ce52e58244; full scope ffbf82ef90975abb209014b6b2b4e4ac21b53ba6..241bb3dc67f0ed87e464fbf6175c9e96bae96878. One actionable doc finding, no runtime change.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-24 · pre-push review 2 of 3 at 01c4cb85fc3ae0d1411ae25be3c73057664d1e99 · iter -
- Decision: Reserved fresh scoped follow-up review; outcome pending.
- Why: Tree 95648af40622023c612ec561faf74432dea2e2b2; scope 241bb3dc67f0ed87e464fbf6175c9e96bae96878..01c4cb85fc3ae0d1411ae25be3c73057664d1e99 is docs/gateway.md fallback wording. Prior reviewed tree 478e309146ec35463941621651ad74ce52e58244.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-24 · pre-push review 2 outcome at 01c4cb85fc3ae0d1411ae25be3c73057664d1e99 · iter -
- Decision: No findings; current at 01c4cb85fc3ae0d1411ae25be3c73057664d1e99.
- Why: Reviewed tree 95648af40622023c612ec561faf74432dea2e2b2; scoped delta 241bb3dc67f0ed87e464fbf6175c9e96bae96878..01c4cb85fc3ae0d1411ae25be3c73057664d1e99 plus full branch context. Prior documentation finding corrected.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-25 · Additional review selection · iter -
- Decision: David selected pydanty:review-branch for the finished PR diff.
- Why: The selected hosted review will assess provider cost behavior and may push remediation commits.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-25 · Preserve embedding pricing degradation · iter -
- Decision: Inline reported-cost precedence while preserving the existing non-Gateway estimation error behavior; do not replace it with best_effort_price in this PR.
- Why: Public target/candidate probes both warn on ValueError; the proposed shared-helper replacement suppresses that warning and changes users outside the Gateway fix.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337#issuecomment-6392299990
2026-10-26 · Ignore rounded deprecated cost headers · iter -
- Decision: David chose to ignore pydantic-ai-gateway-price-estimate; retain legacy body and canonical header support, with genai-prices fallback when available.
- Why: Recorded positive Bedrock cost rounds to zero in the deprecated header; treating that as authoritative can bypass a small client cost limit.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337#issuecomment-6392299990
2026-10-26 · pre-push review 3 of 3 at 12746fe4916560f6bb9cc6477aa3616d4116f063 · iter -
- Decision: Reserved final fresh scoped review; outcome pending.
- Why: Tree 96196acc7f5792bcd51bc5ef072fa9328066d456; delta since reviewed 01c4cb85fc3ae0d1411ae25be3c73057664d1e99 includes remediations and conflict-free current-main merge. Policy base 715651ef7fd3994395e85070ba3d6096c5b211c9.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · pre-push review 3 outcome at 12746fe4916560f6bb9cc6477aa3616d4116f063 · iter -
- Decision: No findings; current at 12746fe4916560f6bb9cc6477aa3616d4116f063. Pre-push review budget exhausted.
- Why: Reviewed tree 96196acc7f5792bcd51bc5ef072fa9328066d456; scoped follow-up since 01c4cb85 plus full branch context; authoritative target policy 715651ef. Clean unchanged candidate verified after review.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · Gateway header cost is a fallback only · iter -
- Decision: Exact body cost wins; the rounded header is used "only when the response can't be priced", and a zero "only on a response-cache hit".
- Why: The gateway writes both cost headers with toFixed(4), so small costs round to 0.0000USD; maintainer (Aditya) ruling, checked by an independent Opus review.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · pre-push review 1 of 3 at b6f888de0b448e770e7b1eeb561242f00c86ce0b · iter -
- Decision: Reserved fresh reviewer dispatch; outcome pending.
- Why: Tree 150fd4a241a37239434bf59f23736955d5a87d8f; full branch scope 2142330ea94e7858c6052365bc76e1d0906a3115..b6f888de0b448e770e7b1eeb561242f00c86ce0b; redesign of header handling plus test/docs consolidation.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · Deprecated cost header read as a fallback · iter -
- Decision: Read both header names; the header is used "only when the response can't be priced", and a zero "only on a response-cache hit".
- Why: Rounding only harms a header that overrides the estimate; as a fallback the deprecated header works on today's deployed gateway.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
- Supersedes: Ignore rounded deprecated cost headers
2026-10-26 · pre-push review 1 outcome at b6f888de0b448e770e7b1eeb561242f00c86ce0b · iter -
- Decision: remediated: limit docs fallback claim to non-streamed requests; module skipif instead of module-level skip; supersede stale header decision.
- Why: Reviewed tree 150fd4a241a37239434bf59f23736955d5a87d8f; full scope 2142330ea9..b6f888de0b. Three low findings, no runtime change.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · pre-push review 2 of 3 at 77471aac452099bd00b02f26604d0c030d3be3c0 · iter -
- Decision: Reserved fresh scoped follow-up review; outcome pending.
- Why: Tree c63f4830c73a92a0e18503ca1d38cb1c5efe7bcb; scope b6f888de0b..77471aac452099bd00b02f26604d0c030d3be3c0 (docs/gateway.md wording, test skip marker); prior reviewed tree 150fd4a241.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · pre-push review 2 outcome at 77471aac452099bd00b02f26604d0c030d3be3c0 · iter -
- Decision: remediated: gateway.md also names the Google/Bedrock cache-hit case.
- Why: Reviewed tree c63f4830c7; scope b6f888de0b..77471aac45. Prior findings fixed; one low docs finding.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · pre-push review 3 of 3 at ae7751f98540fa2655af911ea5a509aad81fb780 · iter -
- Decision: Reserved fresh scoped follow-up review; outcome pending.
- Why: Tree 59d99f6de454c268e9b4551e36cc5ca7c30da59c; scope 77471aac45..ae7751f98540fa2655af911ea5a509aad81fb780 (docs/gateway.md sentence); prior reviewed tree c63f4830c7.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · pre-push review 3 outcome at ae7751f98540fa2655af911ea5a509aad81fb780 · iter -
- Decision: no findings
- Why: Reviewed tree 59d99f6de454c268e9b4551e36cc5ca7c30da59c; scope 77471aac45..ae7751f985; prior docs finding fixed.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · post-budget lint fix at 2758aeb54316a7e7a8c42e954b34dd14a22c1d87 · iter -
- Decision: Pushed without a fourth review: review budget exhausted; delta is one line (if-statement to conditional expression) fixing ruff C901.
- Why: CI lint failed on ae7751f985 (_instrument complexity 16 > 15); ruff, pyright and embeddings instrumented tests pass locally.
- Source: https://github.com/pydantic/pydantic-ai/actions/runs/40357710901
2026-10-26 · post-budget review-thread fix at 08aed6ac38600e44cdb1170247a7a980335654ba · iter -
- Decision: Applied CI Review suggestion: read Anthropic gateway blocks from model_extra; no fourth pre-push review (budget exhausted).
- Why: One-line change; verified anthropic construct_type stores the blocks in model_extra; Anthropic recorded, stubbed and streamed tests pass.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
2026-10-26 · Gateway cost header wins over the estimate · iter -
- Decision:
logfire-ai-gateway-costsetsRequestUsage.costlike the body cost; nox-cache-status: HITcheck for a zero. Merge once the gateway sends the unrounded header in production. - Why: The gateway now sends the header unrounded, the same value as the body; it's set on non-streamed responses only.
- Source: https://github.com/pydantic/pydantic-ai/pull/7337
- Supersedes: Gateway header cost is a fallback only; Deprecated cost header read as a fallback