Skip to content

[openai] Responses API drops function_call and function_call_output from gen_ai.input.messages #651

Description

@sfc-gh-zeningchen

Describe your environment

OS: Linux
Python version: Python 3.14.7
Package version: opentelemetry-instrumentation-genai-openai 1.2b0.dev
GenAI library and version: openai 2.47.0

What happened?

On the Responses API path, get_input_messages skips any input item without a string role. Responses input arrives as a flat item list, so function_call and function_call_output items carry no role and never reach gen_ai.input.messages.

A model call that follows a tool call therefore records only the original user message, and no tool_call_response part is emitted anywhere. The recorded conversation is not just incomplete, it misleads: the span shows the model answering with no visible tool result, and the recorded input token count contradicts the recorded message list.

Steps to Reproduce

Run a two-turn tool loop with the plain openai SDK, no agent framework, with content capture enabled:

first = client.responses.create(
model="gpt-4o-mini",
input=[{"role": "user", "content": "What's the weather in Seattle?"}],
tools=[weather_tool],
)

history = [{"role": "user", "content": "What's the weather in Seattle?"}]
history.extend(first.output) # the function_call item
history.append({
"type": "function_call_output",
"call_id": first.output[0].call_id,
"output": "Sunny, 18C",
})

client.responses.create(model="gpt-4o-mini", input=history, tools=[weather_tool])

Then compare the second request body against the second span's gen_ai.input.messages.

Expected Result

Three messages, matching the three items sent on the wire: the user turn, an assistant message holding a tool_call part, and a tool message holding a tool_call_response part whose id matches the tool_call.

This is the shape the semantic conventions show for a tool loop, and opentelemetry-instrumentation-genai-anthropic already records it that way given an equivalent history.

Actual Result

One message. Both tool items are dropped:

wire request #2: input items=3 types=['user', 'function_call', 'function_call_output']
span : gen_ai.input.messages = 1 msg
[{"role":"user","parts":[{"content":"What's the weather in Seattle?","type":"text"}]}]
gen_ai.usage.input_tokens = 129

129 input tokens against a single short user message.

Additional context

No response

Would you like to implement a fix?

Yes

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions