Skip to content

fix(formatter): ensure assistant messages with tool_calls always include content field#1283

Open
uuuyuqi wants to merge 2 commits intoagentscope-ai:mainfrom
uuuyuqi:fix/assistant-null-content
Open

fix(formatter): ensure assistant messages with tool_calls always include content field#1283
uuuyuqi wants to merge 2 commits intoagentscope-ai:mainfrom
uuuyuqi:fix/assistant-null-content

Conversation

@uuuyuqi
Copy link
Copy Markdown
Contributor

@uuuyuqi uuuyuqi commented Apr 25, 2026

Description

When Qwen3 and similar models operate in thinking mode, assistant messages may contain reasoning_content + tool_calls but null content. Due to @JsonInclude(NON_NULL) on OpenAIMessage and DashScopeMessage, the null content field was entirely omitted from the JSON request body, causing strict OpenAI-compatible APIs (e.g. vLLM) to reject the request with:

Input error. Field required: input.messages.N.content

Root Cause

In both OpenAIMessageConverter and DashScopeMessageConverter, when an assistant message has tool_calls but no TextBlock, the content field was left as null on the DTO. Jackson's @JsonInclude(NON_NULL) then omitted the field entirely during serialization.

Fix

Explicitly set content to an empty string "" (instead of leaving it null) when an assistant message has tool_calls but no text content. This ensures the content field is always present in the serialized JSON.

Changed files:

  • OpenAIMessageConverter.convertAssistantMessage() — set content="" when hasTextContent is false and tool calls exist
  • DashScopeMessageConverter.convertToSimpleContent() — replace null content with "" for assistant messages with tool calls

Close #1268

Checklist

  • Code has been formatted with mvn spotless:apply
  • All tests are passing (mvn test)
  • Javadoc comments are complete and follow project conventions
  • Related documentation has been updated (e.g. links, examples, etc.)
  • Code is ready for review

Made with Cursor

…ude content field

When Qwen3 and similar models operate in thinking mode, assistant messages
may contain reasoning_content + tool_calls but null content. Due to
@JsonInclude(NON_NULL), the null content field was omitted from the JSON
request, causing strict OpenAI-compatible APIs (e.g. vLLM) to reject the
request with "Field required: input.messages.N.content".

Fix by explicitly setting content to empty string ("") when an assistant
message has tool_calls but no text content, in both OpenAIMessageConverter
and DashScopeMessageConverter.

Close agentscope-ai#1268

Change-Id: I2ac07a81e8681a049c253501ab93856b94836a8e
Co-developed-by: Cursor <noreply@cursor.com>
@uuuyuqi uuuyuqi requested a review from a team April 25, 2026 07:13
… and fix missed locations

- Move content="" fallback to the top of convertAssistantMessage() so it
  applies to all assistant messages (not just those with tool_calls)
- Fix the same null-content issue in DashScopeMultiAgentFormatter.formatAssistantToolCall()
- Update DashScopeTextOnlyGroundTruthTest expected values accordingly

Change-Id: Idd54f515a99fe046230bfab4c3c218bce264c255
Co-developed-by: Cursor <noreply@cursor.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

[Bug]:OpenAIMessageConverter produces assistant messages with null content when using vLLM + Qwen3 thinking mode

1 participant