Skip to content

Conversation

@codefromthecrypt
Copy link
Contributor

@codefromthecrypt codefromthecrypt commented Nov 3, 2025

Some openai API clones (such as ollama) don't populate new token detail fields, resulting in None values that bypass Pydantic validation. This results in agent crashes like this:

    ^
  File "/Users/codefromthecrypt/.cache/uv/environments-v2/agent-ce802ac7ec8719af/lib/python3.14/site-packages/agents/run.py", line 1740, in _get_new_response
    context_wrapper.usage.add(new_response.usage)
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "/Users/codefromthecrypt/.cache/uv/environments-v2/agent-ce802ac7ec8719af/lib/python3.14/site-packages/agents/usage.py", line 76, in add
    cached_tokens=self.input_tokens_details.cached_tokens
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + other.input_tokens_details.cached_tokens
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

This fix adds a __post_init__ method to normalize None to 0 for "cached_tokens" and "reasoning_tokens" on any Usage object creation. This defensive approach handles the issue at the boundary we control (just after the stainless generated code), allowing absence of these newer fields to not break agents.

@codefromthecrypt codefromthecrypt force-pushed the fix-usage-none-handling branch 2 times, most recently from ef862d7 to c1a9802 Compare November 4, 2025 01:48
@codefromthecrypt codefromthecrypt changed the title fix(usage): Handle None values in token details when adding usage fix(usage): Normalize None token details on Usage initialization Nov 4, 2025
@codefromthecrypt
Copy link
Contributor Author

FYI I'm aware it could be a bikeshed discussion if these fields are really optional or not. for example, they are more or less implied or explicitly required in the latest openai openapi yaml. However, there is defensive code around other token fields, that coerce to zero. Plus the impact is tricky to workaround otherwise even if PRs are raised everywhere. So, hoping we can add similar defense here

Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'e fine to deal with this reality, but can you update the code comment a bit more for future maintainers?

Some providers don't populate optional token detail fields, resulting
in None values that bypass Pydantic validation. This fix adds a
__post_init__ method to normalize None to 0 for cached_tokens and
reasoning_tokens on any Usage object creation.

This defensive approach handles the issue at the boundary we control,
regardless of how providers construct their response objects.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Copy link
Member

@seratch seratch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@seratch seratch merged commit 15ad038 into openai:main Nov 5, 2025
9 checks passed
@codefromthecrypt codefromthecrypt deleted the fix-usage-none-handling branch November 5, 2025 02:48
@seratch seratch added this to the 0.5.x milestone Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants