Skip to content

Agents SDK crash with LiteLLM Proxy server and Gemini Models #2190

@aliasgher-sketric

Description

@aliasgher-sketric
  • Have you read the custom model provider docs, including the 'Common issues' section? Yes, Model provider docs
  • Have you searched for related issues? Yes, no existing issue found.

The Usage.add() method in agents/usage.py fails with TypeError: unsupported operand type(s) for +: 'int' and 'NoneType' when aggregating usage from LLM providers that return None for cached_tokens or reasoning_tokens.

The issue is that lines 31-34 guard against None values:

self.requests += other.requests if other.requests else 0
self.input_tokens += other.input_tokens if other.input_tokens else 0
self.output_tokens += other.output_tokens if other.output_tokens else 0
self.total_tokens += other.total_tokens if other.total_tokens else 0

But lines 35-43 do not have the same guards:

self.input_tokens_details = InputTokensDetails(
    cached_tokens=self.input_tokens_details.cached_tokens
    + other.input_tokens_details.cached_tokens  # ← No null check!
)

self.output_tokens_details = OutputTokensDetails(
    reasoning_tokens=self.output_tokens_details.reasoning_tokens
    + other.output_tokens_details.reasoning_tokens  # ← No null check!
)

Additionally, when output_tokens_details or input_tokens_details is explicitly passed as None during Usage instantiation (from LLM response parsing), Pydantic validation fails because the field types don't accept None.

Debug information

  • Agents SDK version: v0.6.2 (also affects latest)
  • Python version: 3.13
  • LLM Provider: Google Gemini via LiteLLM Proxy server

Repro steps

from agents import Agent, Runner
from agents import OpenAIResponsesModel, AsyncOpenAI

client = AsyncOpenAI(
        base_url="http://localhost:4000",
        api_key=os.environ.get("GEMINI_API_KEY"),
    )

model = OpenAIResponsesModel(
        model="gemini/gemini-2.5-flash",
        openai_client=client,
    )

# Use any non-OpenAI model provider that may return None for token details
agent = Agent(
    name="test",
    model=model, 
    instructions="You are a helpful assistant."
)

# Run a conversation that triggers usage aggregation
result = await Runner.run(agent, "Hello!")

When the LLM response has input_tokens_details.cached_tokens = None or output_tokens_details.reasoning_tokens = None, the Usage.add() method crashes.

Expected behavior

The SDK should handle None values gracefully by defaulting to 0, consistent with how requests, input_tokens, output_tokens, and total_tokens are handled.

Proposed fix

def add(self, other: "Usage") -> None:
    self.requests += other.requests if other.requests else 0
    self.input_tokens += other.input_tokens if other.input_tokens else 0
    self.output_tokens += other.output_tokens if other.output_tokens else 0
    self.total_tokens += other.total_tokens if other.total_tokens else 0
    
    # Add null guards for nested token details
    other_cached = (other.input_tokens_details.cached_tokens 
                    if other.input_tokens_details and other.input_tokens_details.cached_tokens 
                    else 0)
    other_reasoning = (other.output_tokens_details.reasoning_tokens 
                       if other.output_tokens_details and other.output_tokens_details.reasoning_tokens 
                       else 0)
    
    self.input_tokens_details = InputTokensDetails(
        cached_tokens=(self.input_tokens_details.cached_tokens 
                       if self.input_tokens_details and self.input_tokens_details.cached_tokens 
                       else 0) + other_cached
    )

    self.output_tokens_details = OutputTokensDetails(
        reasoning_tokens=(self.output_tokens_details.reasoning_tokens 
                          if self.output_tokens_details and self.output_tokens_details.reasoning_tokens 
                          else 0) + other_reasoning
    )

I'm happy to submit a PR for this fix.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions