Skip to content

feat(ai-chat): forward custom body fields to onChatMessage options#886

Merged
threepointone merged 4 commits into
mainfrom
feat/forward-body-to-onChatMessage
Feb 11, 2026
Merged

feat(ai-chat): forward custom body fields to onChatMessage options#886
threepointone merged 4 commits into
mainfrom
feat/forward-body-to-onChatMessage

Conversation

@whoiskatrin

Copy link
Copy Markdown
Contributor

Summary

  • Forward custom body fields from client sendMessage / prepareSendMessagesRequest to the server-side onChatMessage handler via options.body
  • Previously, any extra fields in the request body (beyond messages and clientTools) were silently dropped during parsing
  • Add body?: Record<string, unknown> to OnChatMessageOptions type and extract custom fields using rest destructuring

Motivation

Users sending custom data alongside chat messages (e.g. model selection, temperature, metadata) had no way to access it server-side. The data was parsed but only messages and clientTools were extracted — everything else was discarded.

Ref: https://discord.com/channels/595317990191398933/1344688586146189475/1470897271649341491

Usage

// Client
await sendMessage(
  { role: "user", parts: [{ type: "text", text }] },
  { body: { model: "gpt-4", temperature: 0.7 } }
);

// Server
async onChatMessage(onFinish, options) {
  const model = options?.body?.model ?? "default-model";
}

Changes

  • packages/ai-chat/src/index.ts — Add body to OnChatMessageOptions; extract custom fields via rest destructuring and pass to onChatMessage
  • packages/ai-chat/src/tests/worker.ts — Capture options.body in test agent for verification
  • packages/ai-chat/src/tests/custom-body.test.ts — Tests for body forwarding, exclusion of internal fields, and undefined when empty

Custom data sent via prepareSendMessagesRequest or the AI SDK body
option in sendMessage was being silently dropped on the server side.

Extract all non-internal fields (everything except messages and
clientTools) from the parsed request body and pass them through as
options.body in onChatMessage, so users can send dynamic context
like model selection or metadata from client to server.
@changeset-bot

changeset-bot Bot commented Feb 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3e0eb90

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

This PR includes changesets to release 2 packages
Name Type
@cloudflare/ai-chat Patch
agents 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

pkg-pr-new Bot commented Feb 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/agents@886

commit: 3e0eb90

@whoiskatrin

Copy link
Copy Markdown
Contributor Author

/bonk review this PR

Co-authored-by: whoiskatrin <whoiskatrin@users.noreply.github.com>
@ask-bonk

ask-bonk Bot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Here's my review of this PR:


PR Review: feat(ai-chat): forward custom body fields to onChatMessage options

Verdict: Looks good overall. One issue with the changeset needs fixing before merge.

What it does

The PR adds a body field to OnChatMessageOptions so that custom fields sent by the client alongside chat messages (e.g., model name, temperature, metadata) are forwarded to the server-side onChatMessage handler. Previously, only messages and clientTools were extracted from the parsed request body; everything else was silently discarded.

Code changes review

packages/ai-chat/src/index.ts — Core implementation is clean and minimal:

  • Uses rest destructuring (...customBody) at index.ts:339 to capture extra fields after extracting messages and clientTools. This is the right approach.
  • The index signature [key: string]: unknown on the type assertion is correct for allowing rest properties.
  • body is set to undefined when customBody is empty (index.ts:397-399), which is good API design — avoids passing an empty {} that would be truthy.
  • The body?: Record<string, unknown> type on OnChatMessageOptions (index.ts:75) is well-documented.

packages/ai-chat/src/tests/worker.ts — Test agent modifications are appropriate:

  • Captures options.body into _capturedBody for test verification.
  • Adds @callable() method getCapturedBody() and clears it in clearCapturedContext().
  • Properly typed onChatMessage signature with StreamTextOnFinishCallback<ToolSet> and OnChatMessageOptions.

packages/ai-chat/src/tests/custom-body.test.ts — Tests cover the three key cases well:

  1. Custom fields are forwarded correctly
  2. messages and clientTools are excluded from body
  3. body is undefined when no custom fields are present

Issue: Changeset bump level

The changeset at .changeset/forward-body-to-onchatmessage.md correctly marks this as minor (adding a new optional field to an existing type is additive/backward-compatible). However, the changeset bot comment shows this PR is releasing as Major for all 4 packages. This looks like it's picking up a pre-existing major changeset file already in the .changeset/ directory — worth verifying that's intentional and not caused by this PR. The changeset file itself in this PR is correctly minor.

Nit (non-blocking)

The body field is only forwarded for the initial CF_AGENT_USE_CHAT_REQUEST path. The tool continuation path (CF_AGENT_TOOL_RESULT at index.ts:524-526) does not forward body. This is probably fine since tool continuations don't have a new request body, but it's worth documenting that options.body will be undefined during auto-continue after client tool results — users who rely on body data (like model selection) for every onChatMessage call would need to store it themselves on the first call.

Tests

All 40 Workers tests pass (7 test files), including the 3 new custom-body.test.ts tests. Build succeeds. Oxlint reports no warnings or errors on the changed files.

github run

@threepointone

Copy link
Copy Markdown
Contributor

bonk is right, let's make this a patch, and then ship it

@threepointone

Copy link
Copy Markdown
Contributor

wait why is it showing as major

@threepointone

Copy link
Copy Markdown
Contributor

sigh I'll fix it. but also let's make this a patch?

@threepointone threepointone left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pending making changeset a patch

@whoiskatrin

Copy link
Copy Markdown
Contributor Author

/bonk can you make a changeset a patch please?

Co-authored-by: whoiskatrin <whoiskatrin@users.noreply.github.com>
@ask-bonk

ask-bonk Bot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Done — changed the changeset from minor to patch for @cloudflare/ai-chat.

github run

@threepointone

Copy link
Copy Markdown
Contributor

/bonk can you file an issue to followup on the nit

@ask-bonk

ask-bonk Bot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Filed: #887

The issue tracks the nit from the review — options.body is only populated on the initial CF_AGENT_USE_CHAT_REQUEST path and will be undefined during tool continuation (CF_AGENT_TOOL_RESULT). The issue proposes either persisting and re-forwarding the body automatically, or documenting the current behavior so users know to store it themselves on the first call.

github run

@threepointone
threepointone merged commit 4292f6b into main Feb 11, 2026
4 checks passed
@threepointone
threepointone deleted the feat/forward-body-to-onChatMessage branch February 11, 2026 10:55
@github-actions github-actions Bot mentioned this pull request Feb 11, 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