Skip to content

fix: send reasoning content as reasoning field in assistant message history#451

Merged
threepointone merged 3 commits intocloudflare:mainfrom
mchenco:mchen/reasoning-content-fix
Mar 21, 2026
Merged

fix: send reasoning content as reasoning field in assistant message history#451
threepointone merged 3 commits intocloudflare:mainfrom
mchenco:mchen/reasoning-content-fix

Conversation

@mchenco
Copy link
Contributor

@mchenco mchenco commented Mar 21, 2026

Summary

  • Fixes a bug in convert-to-workersai-chat-messages.ts where reasoning parts in assistant messages were concatenated into the content string instead of being sent as a separate field
  • When reasoning is smeared into content, models like @cf/moonshotai/kimi-k2.5 and @cf/zai-org/glm-4.7-flash receive their own internal reasoning as if it were spoken text, corrupting the conversation history and causing empty text responses or leaked special tokens on subsequent turns
  • Reasoning parts are now accumulated separately and sent as the reasoning field on the assistant message object — the field name Chat Completions spec expects on input for reasoning models

Root cause

In multi-turn agentic conversations (e.g. using generateText with tools), the ai-sdk stores reasoning content as reasoning parts on assistant messages. When building the message history for the next turn, the provider was doing:

case "reasoning": {
  // Reasoning is passed through to text for the message conversion,
  // since Workers AI doesn't have a separate reasoning field in messages
  text += part.text;  // BUG: smears reasoning into content string
}

This sends hundreds of tokens of internal model reasoning back to the model as if it were the assistant's spoken reply, which confuses the chat template and causes the model to send back content in reasoning.

Fix

case "reasoning": {
  reasoning += part.text;  // accumulate separately
}

// then when building the message:
messages.push({
  content: text,
  role: "assistant",
  ...(reasoning ? { reasoning } : {}),  // sidecar field Chat Completions spec expects
  tool_calls: ...,
});

The reasoning field name is what Chat Completions spec CustomChatCompletionMessageParam defines for input — reasoning_content exists on ConversationMessage but is deprecated in favour of reasoning.

Testing

Updated existing unit tests and added 4 new cases in convert-to-workersai-chat-messages.test.ts covering:

  • reasoning sent as reasoning field, not concatenated into content
  • reasoning field omitted when absent
  • multiple reasoning parts accumulated into one field
  • tool calls preserved alongside reasoning in multi-turn conversations

Full suite: 213 tests passing.

@changeset-bot
Copy link

changeset-bot bot commented Mar 21, 2026

🦋 Changeset detected

Latest commit: b12704b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
workers-ai-provider Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 21, 2026

Open in StackBlitz

npx https://pkg.pr.new/cloudflare/ai/ai-gateway-provider@451
npx https://pkg.pr.new/cloudflare/ai/@cloudflare/tanstack-ai@451
npx https://pkg.pr.new/cloudflare/ai/workers-ai-provider@451

commit: b12704b

mchenco and others added 2 commits March 21, 2026 09:21
Apply formatting and minor code style changes across the repo: reindent demos.json, rewrap README examples, normalize imports/whitespace in TS source and tests, and tidy up changelog formatting. These are non-functional readability changes (no behavioural logic changes), including small console.log and array formatting adjustments, type assertion wrapping, and consistent ternary formatting.
@threepointone threepointone force-pushed the mchen/reasoning-content-fix branch from d84e5c1 to f0ebbfc Compare March 21, 2026 09:22
Refresh demos' package-lock.json files and update demos.json package_json_hash entries. Bump multiple dependencies and metadata across demo locks (notable bumps: @ai-sdk/gateway 3.0.66→3.0.77, @ai-sdk/provider-utils 4.0.19→4.0.21, @cloudflare/unenv-preset 2.15.0→2.16.0, @cloudflare/vite-plugin 1.29.1→1.30.0, rollup platform packages 4.59.0→4.59.1, ai 6.0.116→6.0.134, @emnapi/runtime 1.9.0→1.9.1) and small lockfile metadata tweaks. These updates ensure demo dependencies and recorded hashes are in sync with the updated locks.
@threepointone threepointone merged commit a2c3bd3 into cloudflare:main Mar 21, 2026
3 checks passed
@github-actions github-actions bot mentioned this pull request Mar 21, 2026
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.

2 participants