[ Skip to content ](https://ai.pydantic.dev/api/usage/#pydantic_aiusage)
**Join us at the inaugural PyAI Conf in San Francisco on March 10th![Learn More](https://pyai.events/?utm_source=pydantic-ai) **
[ ![logo](https://ai.pydantic.dev/img/logo-white.svg) ](https://ai.pydantic.dev/ "Pydantic AI")
Pydantic AI
pydantic_ai.usage
Type to start searching
[ pydantic/pydantic-ai
  * v1.63.0
  * 15.1k
  * 1.7k

](https://github.com/pydantic/pydantic-ai "Go to repository")
[ ![logo](https://ai.pydantic.dev/img/logo-white.svg) ](https://ai.pydantic.dev/ "Pydantic AI") Pydantic AI
[ pydantic/pydantic-ai
  * v1.63.0
  * 15.1k
  * 1.7k

](https://github.com/pydantic/pydantic-ai "Go to repository")
  * [ Pydantic AI  ](https://ai.pydantic.dev/)
  * [ Installation  ](https://ai.pydantic.dev/install/)
  * [ Getting Help  ](https://ai.pydantic.dev/help/)
  * [ Troubleshooting  ](https://ai.pydantic.dev/troubleshooting/)
  * [ Pydantic AI Gateway  ](https://ai.pydantic.dev/gateway/)
  * Documentation
    * Core Concepts
      * [ Agents  ](https://ai.pydantic.dev/agent/)
      * [ Dependencies  ](https://ai.pydantic.dev/dependencies/)
      * [ Function Tools  ](https://ai.pydantic.dev/tools/)
      * [ Output  ](https://ai.pydantic.dev/output/)
      * [ Messages and chat history  ](https://ai.pydantic.dev/message-history/)
      * [ Direct Model Requests  ](https://ai.pydantic.dev/direct/)
    * Models & Providers
      * [ Overview  ](https://ai.pydantic.dev/models/overview/)
      * [ OpenAI  ](https://ai.pydantic.dev/models/openai/)
      * [ Anthropic  ](https://ai.pydantic.dev/models/anthropic/)
      * [ Google  ](https://ai.pydantic.dev/models/google/)
      * [ xAI  ](https://ai.pydantic.dev/models/xai/)
      * [ Bedrock  ](https://ai.pydantic.dev/models/bedrock/)
      * [ Cerebras  ](https://ai.pydantic.dev/models/cerebras/)
      * [ Cohere  ](https://ai.pydantic.dev/models/cohere/)
      * [ Groq  ](https://ai.pydantic.dev/models/groq/)
      * [ Hugging Face  ](https://ai.pydantic.dev/models/huggingface/)
      * [ Mistral  ](https://ai.pydantic.dev/models/mistral/)
      * [ OpenRouter  ](https://ai.pydantic.dev/models/openrouter/)
      * [ Outlines  ](https://ai.pydantic.dev/models/outlines/)
    * Tools & Toolsets
      * [ Function Tools  ](https://ai.pydantic.dev/tools/)
      * [ Advanced Tool Features  ](https://ai.pydantic.dev/tools-advanced/)
      * [ Toolsets  ](https://ai.pydantic.dev/toolsets/)
      * [ Deferred Tools  ](https://ai.pydantic.dev/deferred-tools/)
      * [ Built-in Tools  ](https://ai.pydantic.dev/builtin-tools/)
      * [ Common Tools  ](https://ai.pydantic.dev/common-tools/)
      * [ Third-Party Tools  ](https://ai.pydantic.dev/third-party-tools/)
    * Advanced Features
      * [ Image, Audio, Video & Document Input  ](https://ai.pydantic.dev/input/)
      * [ Thinking  ](https://ai.pydantic.dev/thinking/)
      * [ HTTP Request Retries  ](https://ai.pydantic.dev/retries/)
    * MCP
      * [ Overview  ](https://ai.pydantic.dev/mcp/overview/)
      * [ Client  ](https://ai.pydantic.dev/mcp/client/)
      * [ FastMCP Client  ](https://ai.pydantic.dev/mcp/fastmcp-client/)
      * [ Server  ](https://ai.pydantic.dev/mcp/server/)
    * [ Multi-Agent Patterns  ](https://ai.pydantic.dev/multi-agent-applications/)
    * [ Web Chat UI  ](https://ai.pydantic.dev/web/)
    * [ Embeddings  ](https://ai.pydantic.dev/embeddings/)
    * [ Testing  ](https://ai.pydantic.dev/testing/)
  * Pydantic Evals
    * [ Overview  ](https://ai.pydantic.dev/evals/)
    * Getting Started
      * [ Quick Start  ](https://ai.pydantic.dev/evals/quick-start/)
      * [ Core Concepts  ](https://ai.pydantic.dev/evals/core-concepts/)
    * Evaluators
      * [ Overview  ](https://ai.pydantic.dev/evals/evaluators/overview/)
      * [ Built-in Evaluators  ](https://ai.pydantic.dev/evals/evaluators/built-in/)
      * [ LLM Judge  ](https://ai.pydantic.dev/evals/evaluators/llm-judge/)
      * [ Custom Evaluators  ](https://ai.pydantic.dev/evals/evaluators/custom/)
      * [ Report Evaluators  ](https://ai.pydantic.dev/evals/evaluators/report-evaluators/)
      * [ Span-Based  ](https://ai.pydantic.dev/evals/evaluators/span-based/)
    * How-To Guides
      * [ Logfire Integration  ](https://ai.pydantic.dev/evals/how-to/logfire-integration/)
      * [ Dataset Management  ](https://ai.pydantic.dev/evals/how-to/dataset-management/)
      * [ Dataset Serialization  ](https://ai.pydantic.dev/evals/how-to/dataset-serialization/)
      * [ Concurrency & Performance  ](https://ai.pydantic.dev/evals/how-to/concurrency/)
      * [ Multi-Run Evaluation  ](https://ai.pydantic.dev/evals/how-to/multi-run/)
      * [ Retry Strategies  ](https://ai.pydantic.dev/evals/how-to/retry-strategies/)
      * [ Metrics & Attributes  ](https://ai.pydantic.dev/evals/how-to/metrics-attributes/)
    * Examples
      * [ Simple Validation  ](https://ai.pydantic.dev/evals/examples/simple-validation/)
  * Pydantic Graph
    * [ Overview  ](https://ai.pydantic.dev/graph/)
    * [ Beta API  ](https://ai.pydantic.dev/graph/beta/)
      * [ Steps  ](https://ai.pydantic.dev/graph/beta/steps/)
      * [ Joins & Reducers  ](https://ai.pydantic.dev/graph/beta/joins/)
      * [ Decisions  ](https://ai.pydantic.dev/graph/beta/decisions/)
      * [ Parallel Execution  ](https://ai.pydantic.dev/graph/beta/parallel/)
  * Integrations
    * [ Debugging & Monitoring with Pydantic Logfire  ](https://ai.pydantic.dev/logfire/)
    * Durable Execution
      * [ Overview  ](https://ai.pydantic.dev/durable_execution/overview/)
      * [ Temporal  ](https://ai.pydantic.dev/durable_execution/temporal/)
      * [ DBOS  ](https://ai.pydantic.dev/durable_execution/dbos/)
      * [ Prefect  ](https://ai.pydantic.dev/durable_execution/prefect/)
    * UI Event Streams
      * [ Overview  ](https://ai.pydantic.dev/ui/overview/)
      * [ AG-UI  ](https://ai.pydantic.dev/ui/ag-ui/)
      * [ Vercel AI  ](https://ai.pydantic.dev/ui/vercel-ai/)
    * [ Agent2Agent (A2A)  ](https://ai.pydantic.dev/a2a/)
  * Related Packages
    * [ clai  ](https://ai.pydantic.dev/cli/)
  * Examples
    * [ Setup  ](https://ai.pydantic.dev/examples/setup/)
    * Getting Started
      * [ Pydantic Model  ](https://ai.pydantic.dev/examples/pydantic-model/)
      * [ Weather agent  ](https://ai.pydantic.dev/examples/weather-agent/)
    * Conversational Agents
      * [ Chat App with FastAPI  ](https://ai.pydantic.dev/examples/chat-app/)
      * [ Bank support  ](https://ai.pydantic.dev/examples/bank-support/)
    * Data & Analytics
      * [ SQL Generation  ](https://ai.pydantic.dev/examples/sql-gen/)
      * [ Data Analyst  ](https://ai.pydantic.dev/examples/data-analyst/)
      * [ RAG  ](https://ai.pydantic.dev/examples/rag/)
    * Streaming
      * [ Stream markdown  ](https://ai.pydantic.dev/examples/stream-markdown/)
      * [ Stream whales  ](https://ai.pydantic.dev/examples/stream-whales/)
    * Complex Workflows
      * [ Flight booking  ](https://ai.pydantic.dev/examples/flight-booking/)
      * [ Question Graph  ](https://ai.pydantic.dev/examples/question-graph/)
    * Business Applications
      * [ Slack Lead Qualifier with Modal  ](https://ai.pydantic.dev/examples/slack-lead-qualifier/)
    * UI Examples
      * [ Agent User Interaction (AG-UI)  ](https://ai.pydantic.dev/examples/ag-ui/)
  * API Reference
    * pydantic_ai
      * [ pydantic_ai.ag_ui  ](https://ai.pydantic.dev/api/ag_ui/)
      * [ pydantic_ai.agent  ](https://ai.pydantic.dev/api/agent/)
      * [ pydantic_ai.builtin_tools  ](https://ai.pydantic.dev/api/builtin_tools/)
      * [ pydantic_ai.common_tools  ](https://ai.pydantic.dev/api/common_tools/)
      * [ pydantic_ai — Concurrency  ](https://ai.pydantic.dev/api/concurrency/)
      * [ pydantic_ai.direct  ](https://ai.pydantic.dev/api/direct/)
      * [ pydantic_ai.durable_exec  ](https://ai.pydantic.dev/api/durable_exec/)
      * [ pydantic_ai.embeddings  ](https://ai.pydantic.dev/api/embeddings/)
      * [ pydantic_ai.exceptions  ](https://ai.pydantic.dev/api/exceptions/)
      * [ pydantic_ai.ext  ](https://ai.pydantic.dev/api/ext/)
      * [ pydantic_ai.format_prompt  ](https://ai.pydantic.dev/api/format_prompt/)
      * [ pydantic_ai.mcp  ](https://ai.pydantic.dev/api/mcp/)
      * [ pydantic_ai.messages  ](https://ai.pydantic.dev/api/messages/)
      * [ pydantic_ai.models.anthropic  ](https://ai.pydantic.dev/api/models/anthropic/)
      * [ pydantic_ai.models  ](https://ai.pydantic.dev/api/models/base/)
      * [ pydantic_ai.models.bedrock  ](https://ai.pydantic.dev/api/models/bedrock/)
      * [ pydantic_ai.models.cerebras  ](https://ai.pydantic.dev/api/models/cerebras/)
      * [ pydantic_ai.models.cohere  ](https://ai.pydantic.dev/api/models/cohere/)
      * [ pydantic_ai.models.fallback  ](https://ai.pydantic.dev/api/models/fallback/)
      * [ pydantic_ai.models.function  ](https://ai.pydantic.dev/api/models/function/)
      * [ pydantic_ai.models.google  ](https://ai.pydantic.dev/api/models/google/)
      * [ pydantic_ai.models.xai  ](https://ai.pydantic.dev/api/models/xai/)
      * [ pydantic_ai.models.groq  ](https://ai.pydantic.dev/api/models/groq/)
      * [ pydantic_ai.models.huggingface  ](https://ai.pydantic.dev/api/models/huggingface/)
      * [ pydantic_ai.models.instrumented  ](https://ai.pydantic.dev/api/models/instrumented/)
      * [ pydantic_ai.models.mcp_sampling  ](https://ai.pydantic.dev/api/models/mcp-sampling/)
      * [ pydantic_ai.models.mistral  ](https://ai.pydantic.dev/api/models/mistral/)
      * [ pydantic_ai.models.openai  ](https://ai.pydantic.dev/api/models/openai/)
      * [ pydantic_ai.models.openrouter  ](https://ai.pydantic.dev/api/models/openrouter/)
      * [ pydantic_ai.models.outlines  ](https://ai.pydantic.dev/api/models/outlines/)
      * [ pydantic_ai.models.test  ](https://ai.pydantic.dev/api/models/test/)
      * [ pydantic_ai.models.wrapper  ](https://ai.pydantic.dev/api/models/wrapper/)
      * [ pydantic_ai.output  ](https://ai.pydantic.dev/api/output/)
      * [ pydantic_ai.profiles  ](https://ai.pydantic.dev/api/profiles/)
      * [ pydantic_ai.providers  ](https://ai.pydantic.dev/api/providers/)
      * [ pydantic_ai.result  ](https://ai.pydantic.dev/api/result/)
      * [ pydantic_ai.retries  ](https://ai.pydantic.dev/api/retries/)
      * [ pydantic_ai.run  ](https://ai.pydantic.dev/api/run/)
      * [ pydantic_ai.settings  ](https://ai.pydantic.dev/api/settings/)
      * [ pydantic_ai.tools  ](https://ai.pydantic.dev/api/tools/)
      * [ pydantic_ai.toolsets  ](https://ai.pydantic.dev/api/toolsets/)
      * [ pydantic_ai.ui.ag_ui  ](https://ai.pydantic.dev/api/ui/ag_ui/)
      * [ pydantic_ai.ui  ](https://ai.pydantic.dev/api/ui/base/)
      * [ pydantic_ai.ui.vercel_ai  ](https://ai.pydantic.dev/api/ui/vercel_ai/)
      * pydantic_ai.usage  [ pydantic_ai.usage  ](https://ai.pydantic.dev/api/usage/)
        * [ usage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage)
        * [ UsageBase  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase)
          * [ input_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.input_tokens)
          * [ cache_write_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.cache_write_tokens)
          * [ cache_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.cache_read_tokens)
          * [ output_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.output_tokens)
          * [ input_audio_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.input_audio_tokens)
          * [ cache_audio_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.cache_audio_read_tokens)
          * [ output_audio_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.output_audio_tokens)
          * [ details  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.details)
          * [ total_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.total_tokens)
          * [ opentelemetry_attributes  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.opentelemetry_attributes)
          * [ has_values  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.has_values)
        * [ RequestUsage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage)
          * [ incr  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage.incr)
          * [ __add__  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage.__add__)
          * [ extract  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage.extract)
        * [ RunUsage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage)
          * [ requests  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.requests)
          * [ tool_calls  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.tool_calls)
          * [ input_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.input_tokens)
          * [ cache_write_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.cache_write_tokens)
          * [ cache_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.cache_read_tokens)
          * [ input_audio_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.input_audio_tokens)
          * [ cache_audio_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.cache_audio_read_tokens)
          * [ output_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.output_tokens)
          * [ details  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.details)
          * [ incr  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.incr)
          * [ __add__  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.__add__)
        * [ Usage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.Usage)
        * [ UsageLimits  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits)
          * [ request_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.request_limit)
          * [ tool_calls_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.tool_calls_limit)
          * [ input_tokens_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.input_tokens_limit)
          * [ output_tokens_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.output_tokens_limit)
          * [ total_tokens_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.total_tokens_limit)
          * [ count_tokens_before_request  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.count_tokens_before_request)
          * [ has_token_limits  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.has_token_limits)
          * [ check_before_request  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.check_before_request)
          * [ check_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.check_tokens)
          * [ check_before_tool_call  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.check_before_tool_call)
    * pydantic_evals
      * [ pydantic_evals.dataset  ](https://ai.pydantic.dev/api/pydantic_evals/dataset/)
      * [ pydantic_evals.evaluators  ](https://ai.pydantic.dev/api/pydantic_evals/evaluators/)
      * [ pydantic_evals.reporting  ](https://ai.pydantic.dev/api/pydantic_evals/reporting/)
      * [ pydantic_evals.otel  ](https://ai.pydantic.dev/api/pydantic_evals/otel/)
      * [ pydantic_evals.generation  ](https://ai.pydantic.dev/api/pydantic_evals/generation/)
    * pydantic_graph
      * [ pydantic_graph  ](https://ai.pydantic.dev/api/pydantic_graph/graph/)
      * [ pydantic_graph.nodes  ](https://ai.pydantic.dev/api/pydantic_graph/nodes/)
      * [ pydantic_graph.persistence  ](https://ai.pydantic.dev/api/pydantic_graph/persistence/)
      * [ pydantic_graph.mermaid  ](https://ai.pydantic.dev/api/pydantic_graph/mermaid/)
      * [ pydantic_graph.exceptions  ](https://ai.pydantic.dev/api/pydantic_graph/exceptions/)
      * Beta API
        * [ pydantic_graph.beta  ](https://ai.pydantic.dev/api/pydantic_graph/beta/)
        * [ pydantic_graph.beta.graph  ](https://ai.pydantic.dev/api/pydantic_graph/beta_graph/)
        * [ pydantic_graph.beta.graph_builder  ](https://ai.pydantic.dev/api/pydantic_graph/beta_graph_builder/)
        * [ pydantic_graph.beta.step  ](https://ai.pydantic.dev/api/pydantic_graph/beta_step/)
        * [ pydantic_graph.beta.join  ](https://ai.pydantic.dev/api/pydantic_graph/beta_join/)
        * [ pydantic_graph.beta.decision  ](https://ai.pydantic.dev/api/pydantic_graph/beta_decision/)
        * [ pydantic_graph.beta.node  ](https://ai.pydantic.dev/api/pydantic_graph/beta_node/)
    * fasta2a
      * [ fasta2a  ](https://ai.pydantic.dev/api/fasta2a/)
  * Project
    * [ Contributing  ](https://ai.pydantic.dev/contributing/)
    * [ Upgrade Guide  ](https://ai.pydantic.dev/changelog/)
    * [ Version policy  ](https://ai.pydantic.dev/version-policy/)


  * [ usage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage)
  * [ UsageBase  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase)
    * [ input_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.input_tokens)
    * [ cache_write_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.cache_write_tokens)
    * [ cache_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.cache_read_tokens)
    * [ output_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.output_tokens)
    * [ input_audio_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.input_audio_tokens)
    * [ cache_audio_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.cache_audio_read_tokens)
    * [ output_audio_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.output_audio_tokens)
    * [ details  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.details)
    * [ total_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.total_tokens)
    * [ opentelemetry_attributes  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.opentelemetry_attributes)
    * [ has_values  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.has_values)
  * [ RequestUsage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage)
    * [ incr  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage.incr)
    * [ __add__  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage.__add__)
    * [ extract  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage.extract)
  * [ RunUsage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage)
    * [ requests  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.requests)
    * [ tool_calls  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.tool_calls)
    * [ input_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.input_tokens)
    * [ cache_write_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.cache_write_tokens)
    * [ cache_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.cache_read_tokens)
    * [ input_audio_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.input_audio_tokens)
    * [ cache_audio_read_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.cache_audio_read_tokens)
    * [ output_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.output_tokens)
    * [ details  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.details)
    * [ incr  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.incr)
    * [ __add__  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage.__add__)
  * [ Usage  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.Usage)
  * [ UsageLimits  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits)
    * [ request_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.request_limit)
    * [ tool_calls_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.tool_calls_limit)
    * [ input_tokens_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.input_tokens_limit)
    * [ output_tokens_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.output_tokens_limit)
    * [ total_tokens_limit  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.total_tokens_limit)
    * [ count_tokens_before_request  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.count_tokens_before_request)
    * [ has_token_limits  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.has_token_limits)
    * [ check_before_request  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.check_before_request)
    * [ check_tokens  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.check_tokens)
    * [ check_before_tool_call  ](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageLimits.check_before_tool_call)


  1. [ Pydantic AI  ](https://ai.pydantic.dev/)
  2. [ API Reference  ](https://ai.pydantic.dev/api/ag_ui/)
  3. [ pydantic_ai  ](https://ai.pydantic.dev/api/ag_ui/)


# `pydantic_ai.usage`
###  UsageBase `dataclass`
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
```
| ```
@dataclass(repr=False, kw_only=True)
class UsageBase:
    input_tokens: Annotated[
        int,
        # `request_tokens` is deprecated, but we still want to support deserializing model responses stored in a DB before the name was changed
        Field(validation_alias=AliasChoices('input_tokens', 'request_tokens')),
    ] = 0
    """Number of input/prompt tokens."""

    cache_write_tokens: int = 0
    """Number of tokens written to the cache."""
    cache_read_tokens: int = 0
    """Number of tokens read from the cache."""

    output_tokens: Annotated[
        int,
        # `response_tokens` is deprecated, but we still want to support deserializing model responses stored in a DB before the name was changed
        Field(validation_alias=AliasChoices('output_tokens', 'response_tokens')),
    ] = 0
    """Number of output/completion tokens."""

    input_audio_tokens: int = 0
    """Number of audio input tokens."""
    cache_audio_read_tokens: int = 0
    """Number of audio tokens read from the cache."""
    output_audio_tokens: int = 0
    """Number of audio output tokens."""

    details: Annotated[
        dict[str, int],
        # `details` can not be `None` any longer, but we still want to support deserializing model responses stored in a DB before this was changed
        BeforeValidator(lambda d: d or {}),
    ] = dataclasses.field(default_factory=dict[str, int])
    """Any extra details returned by the model."""

    @property
    @deprecated('`request_tokens` is deprecated, use `input_tokens` instead')
    def request_tokens(self) -> int:
        return self.input_tokens

    @property
    @deprecated('`response_tokens` is deprecated, use `output_tokens` instead')
    def response_tokens(self) -> int:
        return self.output_tokens

    @property
    def total_tokens(self) -> int:
        """Sum of `input_tokens + output_tokens`."""
        return self.input_tokens + self.output_tokens

    def opentelemetry_attributes(self) -> dict[str, int]:
        """Get the token usage values as OpenTelemetry attributes."""
        result: dict[str, int] = {}
        if self.input_tokens:
            result['gen_ai.usage.input_tokens'] = self.input_tokens
        if self.output_tokens:
            result['gen_ai.usage.output_tokens'] = self.output_tokens

        details = self.details.copy()
        if self.cache_write_tokens:
            details['cache_write_tokens'] = self.cache_write_tokens
        if self.cache_read_tokens:
            details['cache_read_tokens'] = self.cache_read_tokens
        if self.input_audio_tokens:
            details['input_audio_tokens'] = self.input_audio_tokens
        if self.cache_audio_read_tokens:
            details['cache_audio_read_tokens'] = self.cache_audio_read_tokens
        if self.output_audio_tokens:
            details['output_audio_tokens'] = self.output_audio_tokens
        if details:
            prefix = 'gen_ai.usage.details.'
            for key, value in details.items():
                # Skipping check for value since spec implies all detail values are relevant
                if value:
                    result[prefix + key] = value
        return result

    def __repr__(self):
        kv_pairs = (f'{f.name}={value!r}' for f in fields(self) if (value := getattr(self, f.name)))
        return f'{self.__class__.__qualname__}({", ".join(kv_pairs)})'

    def has_values(self) -> bool:
        """Whether any values are set and non-zero."""
        return any(dataclasses.asdict(self).values())

```

---|---
####  input_tokens `class-attribute` `instance-attribute`
```
input_tokens: Annotated[](https://docs.python.org/3/library/typing.html#typing.Annotated "typing.Annotated")[
    int[](https://docs.python.org/3/library/functions.html#int),
    Field[](https://docs.pydantic.dev/latest/api/fields/#pydantic.fields.Field "pydantic.Field")(
        validation_alias=AliasChoices[](https://docs.pydantic.dev/latest/api/aliases/#pydantic.aliases.AliasChoices "pydantic.AliasChoices")(
            input_tokens[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.input_tokens "input_tokens



      class-attribute
      instance-attribute
   \(pydantic_ai.usage.UsageBase.input_tokens\)"), request_tokens
        )
    ),
] = 0

```

Number of input/prompt tokens.
####  cache_write_tokens `class-attribute` `instance-attribute`
```
cache_write_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of tokens written to the cache.
####  cache_read_tokens `class-attribute` `instance-attribute`
```
cache_read_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of tokens read from the cache.
####  output_tokens `class-attribute` `instance-attribute`
```
output_tokens: Annotated[](https://docs.python.org/3/library/typing.html#typing.Annotated "typing.Annotated")[
    int[](https://docs.python.org/3/library/functions.html#int),
    Field[](https://docs.pydantic.dev/latest/api/fields/#pydantic.fields.Field "pydantic.Field")(
        validation_alias=AliasChoices[](https://docs.pydantic.dev/latest/api/aliases/#pydantic.aliases.AliasChoices "pydantic.AliasChoices")(
            output_tokens[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase.output_tokens "output_tokens



      class-attribute
      instance-attribute
   \(pydantic_ai.usage.UsageBase.output_tokens\)"), response_tokens
        )
    ),
] = 0

```

Number of output/completion tokens.
####  input_audio_tokens `class-attribute` `instance-attribute`
```
input_audio_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of audio input tokens.
####  cache_audio_read_tokens `class-attribute` `instance-attribute`
```
cache_audio_read_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of audio tokens read from the cache.
####  output_audio_tokens `class-attribute` `instance-attribute`
```
output_audio_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of audio output tokens.
####  details `class-attribute` `instance-attribute`
```
details: Annotated[](https://docs.python.org/3/library/typing.html#typing.Annotated "typing.Annotated")[
    dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), int[](https://docs.python.org/3/library/functions.html#int)], BeforeValidator[](https://docs.pydantic.dev/latest/api/functional_validators/#pydantic.functional_validators.BeforeValidator "pydantic.BeforeValidator")(lambda d: d or {})
] = field[](https://docs.python.org/3/library/dataclasses.html#dataclasses.field "dataclasses.field")(default_factory=dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), int[](https://docs.python.org/3/library/functions.html#int)])

```

Any extra details returned by the model.
####  total_tokens `property`
```
total_tokens: int[](https://docs.python.org/3/library/functions.html#int)

```

Sum of `input_tokens + output_tokens`.
####  opentelemetry_attributes
```
opentelemetry_attributes() -> dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), int[](https://docs.python.org/3/library/functions.html#int)]

```

Get the token usage values as OpenTelemetry attributes.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
```
| ```
def opentelemetry_attributes(self) -> dict[str, int]:
    """Get the token usage values as OpenTelemetry attributes."""
    result: dict[str, int] = {}
    if self.input_tokens:
        result['gen_ai.usage.input_tokens'] = self.input_tokens
    if self.output_tokens:
        result['gen_ai.usage.output_tokens'] = self.output_tokens

    details = self.details.copy()
    if self.cache_write_tokens:
        details['cache_write_tokens'] = self.cache_write_tokens
    if self.cache_read_tokens:
        details['cache_read_tokens'] = self.cache_read_tokens
    if self.input_audio_tokens:
        details['input_audio_tokens'] = self.input_audio_tokens
    if self.cache_audio_read_tokens:
        details['cache_audio_read_tokens'] = self.cache_audio_read_tokens
    if self.output_audio_tokens:
        details['output_audio_tokens'] = self.output_audio_tokens
    if details:
        prefix = 'gen_ai.usage.details.'
        for key, value in details.items():
            # Skipping check for value since spec implies all detail values are relevant
            if value:
                result[prefix + key] = value
    return result

```

---|---
####  has_values
```
has_values() -> bool[](https://docs.python.org/3/library/functions.html#bool)

```

Whether any values are set and non-zero.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
 99
100
101
```
| ```
def has_values(self) -> bool:
    """Whether any values are set and non-zero."""
    return any(dataclasses.asdict(self).values())

```

---|---
###  RequestUsage `dataclass`
Bases: `UsageBase[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase "UsageBase



      dataclass
   \(pydantic_ai.usage.UsageBase\)")`
LLM usage associated with a single request.
This is an implementation of `genai_prices.types.AbstractUsage` so it can be used to calculate the price of the request using [genai-prices](https://github.com/pydantic/genai-prices).
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
```
| ```
@dataclass(repr=False, kw_only=True)
class RequestUsage(UsageBase):
    """LLM usage associated with a single request.

    This is an implementation of `genai_prices.types.AbstractUsage` so it can be used to calculate the price of the
    request using [genai-prices](https://github.com/pydantic/genai-prices).
    """

    @property
    def requests(self):
        return 1

    def incr(self, incr_usage: RequestUsage) -> None:
        """Increment the usage in place.

        Args:
            incr_usage: The usage to increment by.
        """
        return _incr_usage_tokens(self, incr_usage)

    def __add__(self, other: RequestUsage) -> RequestUsage:
        """Add two RequestUsages together.

        This is provided so it's trivial to sum usage information from multiple parts of a response.

        **WARNING:** this CANNOT be used to sum multiple requests without breaking some pricing calculations.
        """
        new_usage = copy(self)
        new_usage.incr(other)
        return new_usage

    @classmethod
    def extract(
        cls,
        data: Any,
        *,
        provider: str,
        provider_url: str,
        provider_fallback: str,
        api_flavor: str = 'default',
        details: dict[str, Any] | None = None,
    ) -> RequestUsage:
        """Extract usage information from the response data using genai-prices.

        Args:
            data: The response data from the model API.
            provider: The actual provider ID
            provider_url: The provider base_url
            provider_fallback: The fallback provider ID to use if the actual provider is not found in genai-prices.
                For example, an OpenAI model should set this to "openai" in case it has an obscure provider ID.
            api_flavor: The API flavor to use when extracting usage information,
                e.g. 'chat' or 'responses' for OpenAI.
            details: Becomes the `details` field on the returned `RequestUsage` for convenience.
        """
        details = details or {}
        for provider_id, provider_api_url in [(None, provider_url), (provider, None), (provider_fallback, None)]:
            try:
                provider_obj = get_snapshot().find_provider(None, provider_id, provider_api_url)
                _model_ref, extracted_usage = provider_obj.extract_usage(data, api_flavor=api_flavor)
                return cls(**{k: v for k, v in extracted_usage.__dict__.items() if v is not None}, details=details)
            except Exception:
                pass
        return cls(details=details)

```

---|---
####  incr
```
incr(incr_usage: RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")) -> None

```

Increment the usage in place.
Parameters:
Name | Type | Description | Default
---|---|---|---
`incr_usage` |  `RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")` |  The usage to increment by. |  _required_
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
116
117
118
119
120
121
122
```
| ```
def incr(self, incr_usage: RequestUsage) -> None:
    """Increment the usage in place.

    Args:
        incr_usage: The usage to increment by.
    """
    return _incr_usage_tokens(self, incr_usage)

```

---|---
####  __add__
```
__add__(other: RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")) -> RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")

```

Add two RequestUsages together.
This is provided so it's trivial to sum usage information from multiple parts of a response.
**WARNING:** this CANNOT be used to sum multiple requests without breaking some pricing calculations.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
124
125
126
127
128
129
130
131
132
133
```
| ```
def __add__(self, other: RequestUsage) -> RequestUsage:
    """Add two RequestUsages together.

    This is provided so it's trivial to sum usage information from multiple parts of a response.

    **WARNING:** this CANNOT be used to sum multiple requests without breaking some pricing calculations.
    """
    new_usage = copy(self)
    new_usage.incr(other)
    return new_usage

```

---|---
####  extract `classmethod`
```
extract(
    data: Any[](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any"),
    *,
    provider: str[](https://docs.python.org/3/library/stdtypes.html#str),
    provider_url: str[](https://docs.python.org/3/library/stdtypes.html#str),
    provider_fallback: str[](https://docs.python.org/3/library/stdtypes.html#str),
    api_flavor: str[](https://docs.python.org/3/library/stdtypes.html#str) = "default",
    details: dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), Any[](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")] | None = None
) -> RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")

```

Extract usage information from the response data using genai-prices.
Parameters:
Name | Type | Description | Default
---|---|---|---
`data` |  `Any[](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")` |  The response data from the model API. |  _required_
`provider` |  `str[](https://docs.python.org/3/library/stdtypes.html#str)` |  The actual provider ID |  _required_
`provider_url` |  `str[](https://docs.python.org/3/library/stdtypes.html#str)` |  The provider base_url |  _required_
`provider_fallback` |  `str[](https://docs.python.org/3/library/stdtypes.html#str)` |  The fallback provider ID to use if the actual provider is not found in genai-prices. For example, an OpenAI model should set this to "openai" in case it has an obscure provider ID. |  _required_
`api_flavor` |  `str[](https://docs.python.org/3/library/stdtypes.html#str)` |  The API flavor to use when extracting usage information, e.g. 'chat' or 'responses' for OpenAI. |  `'default'`
`details` |  `dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), Any[](https://docs.python.org/3/library/typing.html#typing.Any "typing.Any")] | None` |  Becomes the `details` field on the returned `RequestUsage` for convenience. |  `None`
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
```
| ```
@classmethod
def extract(
    cls,
    data: Any,
    *,
    provider: str,
    provider_url: str,
    provider_fallback: str,
    api_flavor: str = 'default',
    details: dict[str, Any] | None = None,
) -> RequestUsage:
    """Extract usage information from the response data using genai-prices.

    Args:
        data: The response data from the model API.
        provider: The actual provider ID
        provider_url: The provider base_url
        provider_fallback: The fallback provider ID to use if the actual provider is not found in genai-prices.
            For example, an OpenAI model should set this to "openai" in case it has an obscure provider ID.
        api_flavor: The API flavor to use when extracting usage information,
            e.g. 'chat' or 'responses' for OpenAI.
        details: Becomes the `details` field on the returned `RequestUsage` for convenience.
    """
    details = details or {}
    for provider_id, provider_api_url in [(None, provider_url), (provider, None), (provider_fallback, None)]:
        try:
            provider_obj = get_snapshot().find_provider(None, provider_id, provider_api_url)
            _model_ref, extracted_usage = provider_obj.extract_usage(data, api_flavor=api_flavor)
            return cls(**{k: v for k, v in extracted_usage.__dict__.items() if v is not None}, details=details)
        except Exception:
            pass
    return cls(details=details)

```

---|---
###  RunUsage `dataclass`
Bases: `UsageBase[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.UsageBase "UsageBase



      dataclass
   \(pydantic_ai.usage.UsageBase\)")`
LLM usage associated with an agent run.
Responsibility for calculating request usage is on the model; Pydantic AI simply sums the usage information across requests.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
```
| ```
@dataclass(repr=False, kw_only=True)
class RunUsage(UsageBase):
    """LLM usage associated with an agent run.

    Responsibility for calculating request usage is on the model; Pydantic AI simply sums the usage information across requests.
    """

    requests: int = 0
    """Number of requests made to the LLM API."""

    tool_calls: int = 0
    """Number of successful tool calls executed during the run."""

    input_tokens: int = 0
    """Total number of input/prompt tokens."""

    cache_write_tokens: int = 0
    """Total number of tokens written to the cache."""

    cache_read_tokens: int = 0
    """Total number of tokens read from the cache."""

    input_audio_tokens: int = 0
    """Total number of audio input tokens."""

    cache_audio_read_tokens: int = 0
    """Total number of audio tokens read from the cache."""

    output_tokens: int = 0
    """Total number of output/completion tokens."""

    details: dict[str, int] = dataclasses.field(default_factory=dict[str, int])
    """Any extra details returned by the model."""

    def incr(self, incr_usage: RunUsage | RequestUsage) -> None:
        """Increment the usage in place.

        Args:
            incr_usage: The usage to increment by.
        """
        if isinstance(incr_usage, RunUsage):
            self.requests += incr_usage.requests
            self.tool_calls += incr_usage.tool_calls
        return _incr_usage_tokens(self, incr_usage)

    def __add__(self, other: RunUsage | RequestUsage) -> RunUsage:
        """Add two RunUsages together.

        This is provided so it's trivial to sum usage information from multiple runs.
        """
        new_usage = copy(self)
        new_usage.incr(other)
        return new_usage

```

---|---
####  requests `class-attribute` `instance-attribute`
```
requests: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of requests made to the LLM API.
####  tool_calls `class-attribute` `instance-attribute`
```
tool_calls: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Number of successful tool calls executed during the run.
####  input_tokens `class-attribute` `instance-attribute`
```
input_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Total number of input/prompt tokens.
####  cache_write_tokens `class-attribute` `instance-attribute`
```
cache_write_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Total number of tokens written to the cache.
####  cache_read_tokens `class-attribute` `instance-attribute`
```
cache_read_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Total number of tokens read from the cache.
####  input_audio_tokens `class-attribute` `instance-attribute`
```
input_audio_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Total number of audio input tokens.
####  cache_audio_read_tokens `class-attribute` `instance-attribute`
```
cache_audio_read_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Total number of audio tokens read from the cache.
####  output_tokens `class-attribute` `instance-attribute`
```
output_tokens: int[](https://docs.python.org/3/library/functions.html#int) = 0

```

Total number of output/completion tokens.
####  details `class-attribute` `instance-attribute`
```
details: dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), int[](https://docs.python.org/3/library/functions.html#int)] = field[](https://docs.python.org/3/library/dataclasses.html#dataclasses.field "dataclasses.field")(
    default_factory=dict[](https://docs.python.org/3/library/stdtypes.html#dict)[str[](https://docs.python.org/3/library/stdtypes.html#str), int[](https://docs.python.org/3/library/functions.html#int)]
)

```

Any extra details returned by the model.
####  incr
```
incr(incr_usage: RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)") | RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")) -> None

```

Increment the usage in place.
Parameters:
Name | Type | Description | Default
---|---|---|---
`incr_usage` |  `RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)") | RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")` |  The usage to increment by. |  _required_
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
203
204
205
206
207
208
209
210
211
212
```
| ```
def incr(self, incr_usage: RunUsage | RequestUsage) -> None:
    """Increment the usage in place.

    Args:
        incr_usage: The usage to increment by.
    """
    if isinstance(incr_usage, RunUsage):
        self.requests += incr_usage.requests
        self.tool_calls += incr_usage.tool_calls
    return _incr_usage_tokens(self, incr_usage)

```

---|---
####  __add__
```
__add__(other: RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)") | RequestUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RequestUsage "RequestUsage



      dataclass
   \(pydantic_ai.usage.RequestUsage\)")) -> RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)")

```

Add two RunUsages together.
This is provided so it's trivial to sum usage information from multiple runs.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
214
215
216
217
218
219
220
221
```
| ```
def __add__(self, other: RunUsage | RequestUsage) -> RunUsage:
    """Add two RunUsages together.

    This is provided so it's trivial to sum usage information from multiple runs.
    """
    new_usage = copy(self)
    new_usage.incr(other)
    return new_usage

```

---|---
###  Usage `dataclass` `deprecated`
Bases: `RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)")`
Deprecated
`Usage` is deprecated, use `RunUsage` instead
Deprecated alias for `RunUsage`.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
244
245
246
247
```
| ```
@dataclass(repr=False, kw_only=True)
@deprecated('`Usage` is deprecated, use `RunUsage` instead')
class Usage(RunUsage):
    """Deprecated alias for `RunUsage`."""

```

---|---
###  UsageLimits `dataclass`
Limits on model usage.
The request count is tracked by pydantic_ai, and the request limit is checked before each request to the model. Token counts are provided in responses from the model, and the token limits are checked after each response.
Each of the limits can be set to `None` to disable that limit.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
```
| ```
@dataclass(repr=False, kw_only=True)
class UsageLimits:
    """Limits on model usage.

    The request count is tracked by pydantic_ai, and the request limit is checked before each request to the model.
    Token counts are provided in responses from the model, and the token limits are checked after each response.

    Each of the limits can be set to `None` to disable that limit.
    """

    request_limit: int | None = 50
    """The maximum number of requests allowed to the model."""
    tool_calls_limit: int | None = None
    """The maximum number of successful tool calls allowed to be executed."""
    input_tokens_limit: int | None = None
    """The maximum number of input/prompt tokens allowed."""
    output_tokens_limit: int | None = None
    """The maximum number of output/response tokens allowed."""
    total_tokens_limit: int | None = None
    """The maximum number of tokens allowed in requests and responses combined."""
    count_tokens_before_request: bool = False
    """If True, perform a token counting pass before sending the request to the model,
    to enforce `request_tokens_limit` ahead of time.

    This may incur additional overhead (from calling the model's `count_tokens` API before making the actual request) and is disabled by default.

    Supported by:

    - Anthropic
    - Google
    - Bedrock Converse

    Support for OpenAI is in development: https://github.com/pydantic/pydantic-ai/issues/3430
    """

    @property
    @deprecated('`request_tokens_limit` is deprecated, use `input_tokens_limit` instead')
    def request_tokens_limit(self) -> int | None:
        return self.input_tokens_limit

    @property
    @deprecated('`response_tokens_limit` is deprecated, use `output_tokens_limit` instead')
    def response_tokens_limit(self) -> int | None:
        return self.output_tokens_limit

    @overload
    def __init__(
        self,
        *,
        request_limit: int | None = 50,
        tool_calls_limit: int | None = None,
        input_tokens_limit: int | None = None,
        output_tokens_limit: int | None = None,
        total_tokens_limit: int | None = None,
        count_tokens_before_request: bool = False,
    ) -> None:
        self.request_limit = request_limit
        self.tool_calls_limit = tool_calls_limit
        self.input_tokens_limit = input_tokens_limit
        self.output_tokens_limit = output_tokens_limit
        self.total_tokens_limit = total_tokens_limit
        self.count_tokens_before_request = count_tokens_before_request

    @overload
    @deprecated(
        'Use `input_tokens_limit` instead of `request_tokens_limit` and `output_tokens_limit` and `total_tokens_limit`'
    )
    def __init__(
        self,
        *,
        request_limit: int | None = 50,
        tool_calls_limit: int | None = None,
        request_tokens_limit: int | None = None,
        response_tokens_limit: int | None = None,
        total_tokens_limit: int | None = None,
        count_tokens_before_request: bool = False,
    ) -> None:
        self.request_limit = request_limit
        self.tool_calls_limit = tool_calls_limit
        self.input_tokens_limit = request_tokens_limit
        self.output_tokens_limit = response_tokens_limit
        self.total_tokens_limit = total_tokens_limit
        self.count_tokens_before_request = count_tokens_before_request

    def __init__(
        self,
        *,
        request_limit: int | None = 50,
        tool_calls_limit: int | None = None,
        input_tokens_limit: int | None = None,
        output_tokens_limit: int | None = None,
        total_tokens_limit: int | None = None,
        count_tokens_before_request: bool = False,
        # deprecated:
        request_tokens_limit: int | None = None,
        response_tokens_limit: int | None = None,
    ):
        self.request_limit = request_limit
        self.tool_calls_limit = tool_calls_limit
        self.input_tokens_limit = input_tokens_limit if input_tokens_limit is not None else request_tokens_limit
        self.output_tokens_limit = output_tokens_limit if output_tokens_limit is not None else response_tokens_limit
        self.total_tokens_limit = total_tokens_limit
        self.count_tokens_before_request = count_tokens_before_request

    def has_token_limits(self) -> bool:
        """Returns `True` if this instance places any limits on token counts.

        If this returns `False`, the `check_tokens` method will never raise an error.

        This is useful because if we have token limits, we need to check them after receiving each streamed message.
        If there are no limits, we can skip that processing in the streaming response iterator.
        """
        return any(
            limit is not None for limit in (self.input_tokens_limit, self.output_tokens_limit, self.total_tokens_limit)
        )

    def check_before_request(self, usage: RunUsage) -> None:
        """Raises a `UsageLimitExceeded` exception if the next request would exceed any of the limits."""
        request_limit = self.request_limit
        if request_limit is not None and usage.requests >= request_limit:
            raise UsageLimitExceeded(f'The next request would exceed the request_limit of {request_limit}')

        input_tokens = usage.input_tokens
        if self.input_tokens_limit is not None and input_tokens > self.input_tokens_limit:
            raise UsageLimitExceeded(
                f'The next request would exceed the input_tokens_limit of {self.input_tokens_limit} ({input_tokens=})'
            )

        total_tokens = usage.total_tokens
        if self.total_tokens_limit is not None and total_tokens > self.total_tokens_limit:
            raise UsageLimitExceeded(  # pragma: lax no cover
                f'The next request would exceed the total_tokens_limit of {self.total_tokens_limit} ({total_tokens=})'
            )

    def check_tokens(self, usage: RunUsage) -> None:
        """Raises a `UsageLimitExceeded` exception if the usage exceeds any of the token limits."""
        input_tokens = usage.input_tokens
        if self.input_tokens_limit is not None and input_tokens > self.input_tokens_limit:
            raise UsageLimitExceeded(f'Exceeded the input_tokens_limit of {self.input_tokens_limit} ({input_tokens=})')

        output_tokens = usage.output_tokens
        if self.output_tokens_limit is not None and output_tokens > self.output_tokens_limit:
            raise UsageLimitExceeded(
                f'Exceeded the output_tokens_limit of {self.output_tokens_limit} ({output_tokens=})'
            )

        total_tokens = usage.total_tokens
        if self.total_tokens_limit is not None and total_tokens > self.total_tokens_limit:
            raise UsageLimitExceeded(f'Exceeded the total_tokens_limit of {self.total_tokens_limit} ({total_tokens=})')

    def check_before_tool_call(self, projected_usage: RunUsage) -> None:
        """Raises a `UsageLimitExceeded` exception if the next tool call(s) would exceed the tool call limit."""
        tool_calls_limit = self.tool_calls_limit
        tool_calls = projected_usage.tool_calls
        if tool_calls_limit is not None and tool_calls > tool_calls_limit:
            raise UsageLimitExceeded(
                f'The next tool call(s) would exceed the tool_calls_limit of {tool_calls_limit} ({tool_calls=}).'
            )

    __repr__ = _utils.dataclasses_no_defaults_repr

```

---|---
####  request_limit `class-attribute` `instance-attribute`
```
request_limit: int[](https://docs.python.org/3/library/functions.html#int) | None = request_limit

```

The maximum number of requests allowed to the model.
####  tool_calls_limit `class-attribute` `instance-attribute`
```
tool_calls_limit: int[](https://docs.python.org/3/library/functions.html#int) | None = tool_calls_limit

```

The maximum number of successful tool calls allowed to be executed.
####  input_tokens_limit `class-attribute` `instance-attribute`
```
input_tokens_limit: int[](https://docs.python.org/3/library/functions.html#int) | None = (
    input_tokens_limit
    if input_tokens_limit is not None
    else request_tokens_limit
)

```

The maximum number of input/prompt tokens allowed.
####  output_tokens_limit `class-attribute` `instance-attribute`
```
output_tokens_limit: int[](https://docs.python.org/3/library/functions.html#int) | None = (
    output_tokens_limit
    if output_tokens_limit is not None
    else response_tokens_limit
)

```

The maximum number of output/response tokens allowed.
####  total_tokens_limit `class-attribute` `instance-attribute`
```
total_tokens_limit: int[](https://docs.python.org/3/library/functions.html#int) | None = total_tokens_limit

```

The maximum number of tokens allowed in requests and responses combined.
####  count_tokens_before_request `class-attribute` `instance-attribute`
```
count_tokens_before_request: bool[](https://docs.python.org/3/library/functions.html#bool) = (
    count_tokens_before_request
)

```

If True, perform a token counting pass before sending the request to the model, to enforce `request_tokens_limit` ahead of time.
This may incur additional overhead (from calling the model's `count_tokens` API before making the actual request) and is disabled by default.
Supported by:
  * Anthropic
  * Google
  * Bedrock Converse


Support for OpenAI is in development: https://github.com/pydantic/pydantic-ai/issues/3430
####  has_token_limits
```
has_token_limits() -> bool[](https://docs.python.org/3/library/functions.html#bool)

```

Returns `True` if this instance places any limits on token counts.
If this returns `False`, the `check_tokens` method will never raise an error.
This is useful because if we have token limits, we need to check them after receiving each streamed message. If there are no limits, we can skip that processing in the streaming response iterator.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
354
355
356
357
358
359
360
361
362
363
364
```
| ```
def has_token_limits(self) -> bool:
    """Returns `True` if this instance places any limits on token counts.

    If this returns `False`, the `check_tokens` method will never raise an error.

    This is useful because if we have token limits, we need to check them after receiving each streamed message.
    If there are no limits, we can skip that processing in the streaming response iterator.
    """
    return any(
        limit is not None for limit in (self.input_tokens_limit, self.output_tokens_limit, self.total_tokens_limit)
    )

```

---|---
####  check_before_request
```
check_before_request(usage: RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)")) -> None

```

Raises a `UsageLimitExceeded` exception if the next request would exceed any of the limits.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
```
| ```
def check_before_request(self, usage: RunUsage) -> None:
    """Raises a `UsageLimitExceeded` exception if the next request would exceed any of the limits."""
    request_limit = self.request_limit
    if request_limit is not None and usage.requests >= request_limit:
        raise UsageLimitExceeded(f'The next request would exceed the request_limit of {request_limit}')

    input_tokens = usage.input_tokens
    if self.input_tokens_limit is not None and input_tokens > self.input_tokens_limit:
        raise UsageLimitExceeded(
            f'The next request would exceed the input_tokens_limit of {self.input_tokens_limit} ({input_tokens=})'
        )

    total_tokens = usage.total_tokens
    if self.total_tokens_limit is not None and total_tokens > self.total_tokens_limit:
        raise UsageLimitExceeded(  # pragma: lax no cover
            f'The next request would exceed the total_tokens_limit of {self.total_tokens_limit} ({total_tokens=})'
        )

```

---|---
####  check_tokens
```
check_tokens(usage: RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)")) -> None

```

Raises a `UsageLimitExceeded` exception if the usage exceeds any of the token limits.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
```
| ```
def check_tokens(self, usage: RunUsage) -> None:
    """Raises a `UsageLimitExceeded` exception if the usage exceeds any of the token limits."""
    input_tokens = usage.input_tokens
    if self.input_tokens_limit is not None and input_tokens > self.input_tokens_limit:
        raise UsageLimitExceeded(f'Exceeded the input_tokens_limit of {self.input_tokens_limit} ({input_tokens=})')

    output_tokens = usage.output_tokens
    if self.output_tokens_limit is not None and output_tokens > self.output_tokens_limit:
        raise UsageLimitExceeded(
            f'Exceeded the output_tokens_limit of {self.output_tokens_limit} ({output_tokens=})'
        )

    total_tokens = usage.total_tokens
    if self.total_tokens_limit is not None and total_tokens > self.total_tokens_limit:
        raise UsageLimitExceeded(f'Exceeded the total_tokens_limit of {self.total_tokens_limit} ({total_tokens=})')

```

---|---
####  check_before_tool_call
```
check_before_tool_call(projected_usage: RunUsage[](https://ai.pydantic.dev/api/usage/#pydantic_ai.usage.RunUsage "RunUsage



      dataclass
   \(pydantic_ai.usage.RunUsage\)")) -> None

```

Raises a `UsageLimitExceeded` exception if the next tool call(s) would exceed the tool call limit.
Source code in `pydantic_ai_slim/pydantic_ai/usage.py`
```
400
401
402
403
404
405
406
407
```
| ```
def check_before_tool_call(self, projected_usage: RunUsage) -> None:
    """Raises a `UsageLimitExceeded` exception if the next tool call(s) would exceed the tool call limit."""
    tool_calls_limit = self.tool_calls_limit
    tool_calls = projected_usage.tool_calls
    if tool_calls_limit is not None and tool_calls > tool_calls_limit:
        raise UsageLimitExceeded(
            f'The next tool call(s) would exceed the tool_calls_limit of {tool_calls_limit} ({tool_calls=}).'
        )

```

---|---
© Pydantic Services Inc. 2024 to present
