Skip to content

feat(ai): add preparedTools/preparedToolChoice to experimental_streamModelCall#13823

Draft
gr2m wants to merge 1 commit intomainfrom
gr2m/stream-model-call-serializable-tools
Draft

feat(ai): add preparedTools/preparedToolChoice to experimental_streamModelCall#13823
gr2m wants to merge 1 commit intomainfrom
gr2m/stream-model-call-serializable-tools

Conversation

@gr2m
Copy link
Copy Markdown
Collaborator

@gr2m gr2m commented Mar 25, 2026

Summary

Add support for pre-prepared serializable tool descriptors in experimental_streamModelCall. When preparedTools is provided, the function skips prepareToolsAndToolChoice and uses the descriptors directly. This is needed to unblock #13820.

Alternative approach: #13824

Problem

experimental_streamModelCall requires ToolSet for its tools parameter. ToolSet contains Zod schemas and execute functions — neither of which are serializable. When streamModelCall is called inside a Workflow 'use step' function, the ToolSet crosses the step serialization boundary and fails:

[Workflow] Serialization failed {
  context: 'step arguments',
  problematicValue: ZodObject { ... }
}

Solution

Allow callers to pre-prepare tools outside the serialization boundary and pass the serializable result through:

// Outside the step boundary:
const { tools: preparedTools, toolChoice: preparedToolChoice } =
  await experimental_prepareToolsAndToolChoice({ tools, toolChoice });

// Inside the step (serialization boundary):
const { stream } = await experimental_streamModelCall({
  model,
  messages,
  preparedTools,      // JSON schemas, no Zod
  preparedToolChoice, // plain object
});

New types

Intentionally alias internal LanguageModelV4* types to shield consumers from provider spec version changes:

  • FunctionToolDescriptor — serializable function tool descriptor (JSON schema, name, description)
  • ProviderToolDescriptor — serializable provider tool descriptor
  • ToolDescriptor — union of the above
  • ToolChoiceDescriptor — serializable tool choice (auto | none | required | { tool: name })

New exports from ai

  • FunctionToolDescriptor, ProviderToolDescriptor, ToolDescriptor, ToolChoiceDescriptor (types)
  • experimental_prepareToolsAndToolChoice (function — extracts serializable descriptors from ToolSet)

Test plan

  • pnpm build in packages/ai — passes
  • pnpm test:node in packages/ai — 2266 tests pass
  • Existing tests unaffected (preparedTools is optional, no behavior change when not provided)

Add support for pre-prepared serializable tool descriptors in
experimental_streamModelCall. When preparedTools is provided, the
function skips prepareToolsAndToolChoice and uses the descriptors
directly.

This enables callers that operate across serialization boundaries
(e.g., Workflow step functions) to prepare tools once outside the
boundary and pass the serializable result through.

New types:
- FunctionToolDescriptor: serializable function tool (JSON schema)
- ProviderToolDescriptor: serializable provider tool
- ToolDescriptor: union of the above
- ToolChoiceDescriptor: serializable tool choice

These types intentionally alias the internal LanguageModelV4* types
to shield consumers from provider spec version changes.

Also exports experimental_prepareToolsAndToolChoice for callers that
need to pre-prepare tools explicitly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tigent tigent bot added ai/core core functions like generateText, streamText, etc. Provider utils, and provider spec. feature New feature or request labels Mar 25, 2026
gr2m added a commit that referenced this pull request Mar 25, 2026
Move prepareToolsAndToolChoice out of streamModelCall so it only
accepts serializable ToolDescriptor[] and ToolChoiceDescriptor
instead of the full ToolSet (which contains non-serializable Zod
schemas and execute functions).

Callers must now call experimental_prepareToolsAndToolChoice before
streamModelCall to convert ToolSet → ToolDescriptor[].

This is the alternative to #13823 (which adds preparedTools alongside
tools). This approach is cleaner — streamModelCall only deals with
serializable types — but requires updating stream-text.ts to prepare
tools before the call.

New types and exports: same as #13823.

TODO: Update stream-text.test.ts and other tests that pass ToolSet
directly to streamModelCall.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gr2m
Copy link
Copy Markdown
Collaborator Author

gr2m commented Mar 25, 2026

Alternative approach: #13824 removes tools: ToolSet from streamModelCall entirely, accepting only ToolDescriptor[]. Cleaner API but breaking change — all callers must call prepareToolsAndToolChoice first.

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

Labels

ai/core core functions like generateText, streamText, etc. Provider utils, and provider spec. feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant