Skip to content

fix: OpenAI API compliance for tool response format#2450

Open
drewd789 wants to merge 2 commits intoQwenLM:mainfrom
drewd789:fix/tool-response-format
Open

fix: OpenAI API compliance for tool response format#2450
drewd789 wants to merge 2 commits intoQwenLM:mainfrom
drewd789:fix/tool-response-format

Conversation

@drewd789
Copy link
Copy Markdown
Contributor

Description

Fixes OpenAI API compliance bug in tool response storage and conversion format.

Problem

When using tools with OpenAI-compatible APIs (e.g., hunter-alpha via OpenRouter), conversation history containing tool calls would fail with 400 errors. The root cause was non-compliance with the OpenAI API standard for tool response messages (ChatCompletionToolMessageParam).

Issues:

  1. Tool responses were stored with role: user instead of role: tool
  2. Storage included Gemini-format functionResponse parts in a message field
  3. The converter duplicated the functionResponse in the messages array

Solution

Storage Layer (chatRecordingService.ts)

  • Stop storing tool results message field with Gemini-style functionResponse parts
  • The tool_result stream now stores only the tool output data

Conversion Layer (sessionService.ts)

  • buildApiHistoryFromConversation now reconstructs tool messages from toolCallResult records
  • Outputs proper OpenAI format: {role: tool, tool_call_id, content}

Testing

Two-part commit strategy:

  1. test commit (57787a2): Adds failing tests that verify the bug exists

    • chatRecordingService.test.ts: Verifies tool_result records lack message field
    • sessionService.test.ts: Verifies buildApiHistoryFromConversation builds proper tool messages
  2. fix commit (8226024): Implements the fix that makes tests pass

Related Issues

Fixes issues with OpenAI-compatible API providers when tools are used in conversation.

Checklist

  • Tests added (failing tests first, then fix)
  • Code follows project conventions
  • Commit messages follow conventional commits

@Mingholy Mingholy added the scope/content-generation AI content generation label Mar 18, 2026
@drewd789 drewd789 force-pushed the fix/tool-response-format branch 5 times, most recently from f6b1f8a to ca6e72d Compare March 18, 2026 02:45
@tanzhenxin
Copy link
Copy Markdown
Collaborator

tanzhenxin commented Mar 18, 2026

@drewd789 Thanks for your contribution, but can you help link any existing issue to this PR or file a new one if necessary? We would like to reproduce issue first before merging any PR targeting core module.

@tanzhenxin tanzhenxin self-assigned this Mar 18, 2026
Add tests that demonstrate the OpenAI API compliance issue with tool
response storage format (https://go.openai.com/chat-api-ref).
See ChatCompletionToolMessageParam.

The current implementation stores tool results with a message field
containing Gemini-format functionResponse parts. This causes 400 errors
when sending conversation history to at least one OpenAI-compatible API
(hunter-alpha via OpenRouter) because:
- Tool responses are stored as role: "user" instead of role: "tool"
- The parts array with functionResponse is Gemini format, not OpenAI
- The converter duplicates the functionResponse in the messages array

Tests added:
- chatRecordingService.test.ts: Verify tool_result records do NOT have
  a message field (will fail until fix is applied)
- sessionService.test.ts: Verify buildApiHistoryFromConversation
  reconstructs tool messages from toolCallResult (will fail until
  fix is applied)

These tests will pass after the fix that:
1. Removes message field from tool_result records in storage
2. Reconstructs tool messages from toolCallResult at API time
3. Ensures proper OpenAI format: {role: "tool", tool_call_id, content}
Fix storage and conversion of tool results to comply with OpenAI API
standard (https://go.openai.com/chat-api-ref), specifically the
ChatCompletionToolMessageParam requirements.

The previous implementation stored tool results with a message field
containing Gemini-format functionResponse parts. This caused 400 errors
when sending conversation history to OpenAI-compatible APIs because:
- Tool results were stored with role: "user" instead of role: "tool"
- The parts array used Gemini functionResponse format, not OpenAI
- The converter duplicated functionResponse in the messages array

Changes made:
- chatRecordingService: stop storing tool results message field with
  Gemini-style functionResponse parts; tool_result stream now stores
  only tool output data
- sessionService: buildApiHistoryFromConversation now reconstructs tool
  messages from toolCallResult records in proper OpenAI format:
  {role: tool, tool_call_id, content}

This resolves 400 errors with OpenAI-compatible APIs (e.g., hunter-alpha
via OpenRouter).

Fixes the failing tests added in commit 68e30077c.
@drewd789 drewd789 force-pushed the fix/tool-response-format branch from ca6e72d to 9d671c1 Compare March 18, 2026 03:47
@tanzhenxin tanzhenxin added the status/need-information More information is needed to resolve this issue. label Mar 18, 2026
@drewd789
Copy link
Copy Markdown
Contributor Author

@tanzhenxin yes, will post for this and the other PR later today, swamped at the moment.

@drewd789
Copy link
Copy Markdown
Contributor Author

drewd789 commented Mar 18, 2026

@tanzhenxin https://youtu.be/xwd5oZxwyes

Video of both bugs repro'd. This PR fixes the 400 error at the end. Repro is very easy, just use openrouter/hunter-alpha and get it to make a tool call like list_directory that produces the malformed ChatCompletionToolMessageParam. Will post an official issue a bit later today.

@tanzhenxin
Copy link
Copy Markdown
Collaborator

@drewd789 Thanks again for the posted video. I tried to reproduce the two issues you mentioned, the first issue has already been resolved in another PR #2403 , and the other issue is still not fixed on this branch.

(The hunter-alpha is offline now, the new model id is "xiaomi/mimo-v2-pro)
image

@tanzhenxin
Copy link
Copy Markdown
Collaborator

But it seemed that only this model has this problem, tried another model on OpenRouter, it was perfectly fine.

image

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

Labels

scope/content-generation AI content generation status/need-information More information is needed to resolve this issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants