Skip to content

fix(telemetry): report OpenAI tool arguments as an object, not a JSON string - #68

Open
apucacao wants to merge 1 commit into
mainfrom
alexis/openai-tool-args-object
Open

apucacao wants to merge 1 commit into
mainfrom
alexis/openai-tool-args-object

Conversation

@apucacao

@apucacao apucacao commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Warning

This content was written by AI.

Summary

The Responses API and the Agents SDK carry function_call.arguments as an opaque JSON string. Anthropic and LangChain hand over an object, and every other handler puts an object on a tool_call part. Passing the string through meant the content carriers encoded it a second time, so an OpenAI span and an Anthropic span described the same kind of tool call differently.

Both handlers already parse that string to call the tool. Only the span disagreed with the code two lines below it.

A string that is not JSON comes back verbatim rather than raising. A truncated stream is worth reporting as it arrived, and raising inside the telemetry path would take down a run the provider has already billed. The helper runs before the tool call rather than reusing the parsed arguments, so a malformed string still reaches the span that records the failure.

The shared content layer is untouched. How a provider spells its arguments is the call site's business, the same rule the cache folding follows.

This re-lands #23, which was merged into the branch of #22 instead of into main and so never shipped. Rebased onto main, with the overlap against #18's inputContentParts resolved by keeping both helpers.


Note

Overview
OpenAI’s Responses API and Agents SDK expose function_call.arguments as a JSON string, while other providers record tool_call parts with parsed objects. Passing the raw string into span content caused double JSON encoding, so OpenAI traces disagreed with Anthropic-style spans for the same kind of call.

Both openai-messages and openai-agents now use a shared toolArguments() helper: parse valid JSON strings before writing chat output, input replay, and execute_tool attributes; invalid or truncated strings stay verbatim so telemetry never throws and failed calls still show what the model sent.

New span tests lock in parsed objects on gen_ai.output.messages and malformed-argument behavior on tool spans.

Reviewed by Cursor Bugbot for commit 45e335d. Bugbot is set up for automated code reviews on this repo. Configure here.

… string

The Responses API and the Agents SDK both carry function_call.arguments as an opaque
JSON string. Every other handler puts a parsed object on a tool_call part, because
Anthropic and LangChain hand over an object.

Passing the string through left the content carriers encoding it a second time, so a
reader saw "arguments": "{\"q\":1}" on an OpenAI span and "arguments": {"q": 1} on an
Anthropic span describing the same kind of call.

Both handlers already parse this string to call the tool. Only the span disagreed with
the code two lines below it.

A string that is not JSON comes back verbatim rather than raising. A truncated stream
is worth reporting as it arrived, and raising inside the telemetry path would take down
a run the provider has already billed. The helper runs before the tool call rather than
reusing the parsed arguments, so a malformed string still reaches the span that records
the failure.

Applied at the seven sites that build a tool_call part or write tool-call content,
across both OpenAI packages. The shared content layer is untouched: how a provider
spells its arguments is the call site's business, the same rule the cache folding
follows.

Re-landing the content of #23, which was merged into the branch of #22 rather than into
main and so never shipped. Rebased onto main and the conflict with #18's
inputContentParts resolved by keeping both helpers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant