Chat Completions replay emits an invalid sequence for two messages in one tool-call turn
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- Half a day
- Newbie friendliness
- 70/100
Research direction
The merge logic lives in Converter.items_to_messages in agents/models/chatcmpl_converter.py, and the SDK comment the report quotes about the rejected sequence sits near it. Start by running the repro snippet from the issue to see the current [assistant(tool_calls), assistant, tool] output. Done means that consecutive same-turn messages fold into the tool-call assistant, the tool result follows immediately, and a later assistant turn stays separate. The existing single-message case should still convert as it does now.
Written by the indexing model from the issue text.
Description
Please read this first
- Have you read the docs? Yes.
- Have you searched for related issues? Yes. #4727 was fixed for a single message following a streamed tool call by #4728; this reports the remaining multi-message case.
Describe the bug
When replaying a Responses-format history ordered as [function_call, message, message, function_call_output], Converter.items_to_messages merges only the first message into the assistant with tool_calls. The second message becomes a separate assistant message before the tool result. The Chat Completions request therefore contains [assistant(tool_calls), assistant, tool]. The SDK's own comment says this sequence is rejected by the API. A message after a refusal in the same tool turn has the same problem.
The malformed payload was observed in a direct converter probe and in the payload passed by Runner.run to a local mocked chat.completions.create. A live HTTP 400 was not measured; the rejection is inferred from the documented Chat Completions tool-call ordering contract and the error shown in #4727.
Debug information
- Agents SDK version: 0.23.1 (also reproduced on
mainat125efa029b4bfd84238bd2c4fd69c3406f802663). - Related library versions: none required for the direct probe.
- Python version: 3.12.
- Operating system: Windows.
- Model and model provider: Chat Completions adapter; local mock client, no paid API call.
- Does the issue reproduce with the latest Agents SDK release? Yes, v0.23.1.
- Does the issue occur consistently or intermittently? Consistently for this input order.
Relevant observed roles:
user
assistant(content='Let me check the weather.', tool_calls=[call_1])
assistant(content='One moment.')
tool(tool_call_id='call_1', content='sunny')
Repro steps
from agents.models.chatcmpl_converter import Converter
items = [
{"role": "user", "content": "What is the weather?"},
{"id": "fc_1", "call_id": "call_1", "name": "get_weather", "arguments": "{}", "type": "function_call"},
{"id": "msg_1", "type": "message", "role": "assistant", "status": "completed", "content": [{"type": "output_text", "text": "Let me check the weather.", "annotations": []}]},
{"id": "msg_2", "type": "message", "role": "assistant", "status": "completed", "content": [{"type": "output_text", "text": "One moment.", "annotations": []}]},
{"type": "function_call_output", "call_id": "call_1", "output": "sunny"},
]
for message in Converter.items_to_messages(items):
print(message)
On v0.23.1, the second assistant message separates the tool-call assistant from its tool result. A control history with just one assistant message between function_call and function_call_output converts correctly.
Expected behavior
The two same-turn text messages should be merged into a single assistant message with the declared tool_calls, immediately followed by the tool result. A later assistant turn after the tool result should stay separate.
- Dominant language
- Python
- Stars
- 29.9k
- Forks
- 4.8k
- Avg merge
- 22h 17m
- Merged PRs (30d)
- 208
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openai/openai-agents-python
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
openai/openai-agents-python#5348 · 2 comments ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
openai/openai-agents-python#5353 · 1 comment ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 3/5 1-2 days Newbie friendliness 65/100
openai/openai-agents-python#5336 · 1 comment ·
Maintainers usually reply within 1 day
-
Finished tool call is dropped when a parallel tool's guardrail tripsPossibly taken @jbeckwith-oai claimed this 6 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 35/100
openai/openai-agents-python#5327 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
openai/openai-agents-python#5322 · 2 comments ·
Maintainers usually reply within 1 day
All issues in openai/openai-agents-python
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
task
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
danparshall/claude_researcher#87 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
datajoint/datajoint-python#1586 ·
Maintainers usually reply within 1 day
-
1D intercept of length 1 is accepted as `fix_params` in population GLM with more than 1 unitPossibly taken @dhvani7014 claimed this today. Openbug good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
flatironinstitute/nemos#642 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
uniswap-python/uniswap-python#487 ·