Skip to content

fix: preserve tool_search output item IDs after provider metadata round trips - #17678

Merged
lgrammel merged 3 commits into
mainfrom
bugfix/17666-1
Jul 22, 2026
Merged

fix: preserve tool_search output item IDs after provider metadata round trips#17678
lgrammel merged 3 commits into
mainfrom
bugfix/17666-1

Conversation

@lgrammel

@lgrammel lgrammel commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Background

Stored OpenAI Responses continuations could duplicate a hosted tool_search call item ID, causing OpenAI to reject the request.

Root Cause

The response parser stores the tool-search output item ID in providerMetadata, but the result serializer previously read only providerOptions and therefore fell back to toolCallId. The reproduction showed this emitted the call ID twice instead of preserving distinct call and output IDs.

Summary

Updated tool-search result serialization to prefer providerOptions, then providerMetadata, then toolCallId; added focused regression coverage using the package-level provider-utils type import; and added a patch changeset.

Testing

Regression coverage asserts distinct stored call and output references after a providerMetadata round trip. The OpenAI Node and Edge suites each passed 791 tests, and workspace type checking plus lint and formatting checks passed.

End-to-end Validation

  • pnpm -C examples/ai-functions exec tsx src/generate-text/openai/responses-tool-search.ts — live OpenAI run completed successfully with distinct tsc_... and tso_... IDs and no duplicate-item rejection.

Related Issues

Fixes #17666

Closes #17674

Co-authored-by: seandearnaley 5084762+seandearnaley@users.noreply.github.com
Co-authored-by: lgrammel 205036+lgrammel@users.noreply.github.com

@lgrammel

Copy link
Copy Markdown
Collaborator Author

Bugfix review

Outcome: approved

Reproduction replay

Status: no-longer-reproduces

The exact original reproduction completed successfully and the original bug signal did not appear.

Fixes issue

Status: fully-addresses

The tool-search result branch now follows the required precedence of providerOptions, providerMetadata, then toolCallId, preserving the distinct output item ID.

Side effects

Risk: low

Existing providerOptions behavior and fallback behavior remain intact; only tool-search results carrying providerMetadata gain the previously omitted ID handling.

Performance

Risk: low

The change adds one constant-time optional metadata lookup per relevant tool-search result and introduces no allocations or retained state of consequence.

Backwards compatibility

Risk: low

Stored data is not mutated, providerOptions retains precedence, and histories containing response-produced providerMetadata now serialize correctly rather than duplicating the call ID.

Architecture

Risk: low

The fix is localized to the OpenAI Responses prompt converter, mirrors its existing tool-call compatibility logic, and adds no dependencies, exports, or cross-package abstractions.

Change scope

Status: minimal

The diff contains only the targeted serializer change, a focused regression test preserving both metadata paths, and the required patch changeset.

Security

Risk: low

The change only selects an existing provider item identifier and introduces no new parsing, network access, credential handling, or executable input path.

Testing

Status: appropriate

The regression test reproduces the realistic providerMetadata round trip and asserts distinct call and output references; existing providerOptions coverage remains in place.

Verification

Inspected the complete merge-base diff and adjacent parser/converter paths. The focused converter suites passed in both Node and Edge environments with 119 tests each, and workspace type checking plus lint and formatting checks passed.

@@ -0,0 +1,64 @@
import type { ToolNameMapping } from '../../../provider-utils/src/create-tool-name-mapping';

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

import needs to be @provider-utils/create-tool-name-mapping

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Updated the test to import ToolNameMapping from the resolvable @ai-sdk/provider-utils package entrypoint instead of reaching into provider-utils through a deep relative source path.

@lgrammel

Copy link
Copy Markdown
Collaborator Author

Addressed PR comment 5043162580.

Bugfix review

Outcome: approved

Reproduction replay

Status: no-longer-reproduces

... 53 more line(s) omitted

No behavioral change was needed from the approval; the serializer precedence, regression coverage, and changeset remain intact. Verification was rerun after the subsequent import correction.

@lgrammel

Copy link
Copy Markdown
Collaborator Author

Bugfix review

Outcome: approved

Reproduction replay

Status: no-longer-reproduces

The exact original reproduction completed successfully and the original bug signal did not appear.

Fixes issue

Status: fully-addresses

The tool-search result serializer now reads itemId from providerOptions first, providerMetadata second, and toolCallId last, preserving distinct call and output references.

Side effects

Risk: low

Existing providerOptions precedence and toolCallId fallback remain unchanged; only histories carrying the previously ignored providerMetadata item ID serialize differently.

Performance

Risk: low

The change adds one constant-time optional metadata lookup per hosted tool-search result and introduces no material allocations or retained state.

Backwards compatibility

Risk: low

No stored data is mutated or migrated; existing histories now use their preserved output item ID when serialized, while older histories without metadata retain the toolCallId fallback.

Architecture

Risk: low

The behavior remains localized to the OpenAI Responses converter, mirrors the adjacent tool-call compatibility logic, and adds no dependencies, exports, or cross-package abstractions.

Change scope

Status: minimal

The diff contains only the targeted converter change, focused regression coverage retaining both metadata paths, and the required patch changeset.

Security

Risk: low

The change only selects an existing provider item identifier and adds no parsing, network, credential, URL-handling, or executable-input behavior.

Testing

Status: appropriate

The regression test covers the realistic providerMetadata round trip and distinct stored references, while existing tests continue covering providerOptions behavior and fallback-related converter behavior.

Verification

Inspected the complete merge-base diff and adjacent OpenAI response parser and converter paths. The OpenAI Node and Edge suites each passed 791 tests, package type checking passed, and focused lint, formatting, and diff checks reported no issues.

@lgrammel
lgrammel merged commit bc43dc2 into main Jul 22, 2026
54 of 55 checks passed
@lgrammel
lgrammel deleted the bugfix/17666-1 branch July 22, 2026 08:24
lgrammel added a commit that referenced this pull request Jul 22, 2026
…ata round trips (#17690)

## Background

Stored OpenAI Responses continuations could duplicate a hosted
tool_search call item ID, causing OpenAI to reject the request.

## Root Cause

The response parser stores the tool-search output item ID in
providerMetadata, but the result serializer previously read only
providerOptions and therefore fell back to toolCallId. The reproduction
showed this emitted the call ID twice instead of preserving distinct
call and output IDs.

## Summary

Updated tool-search result serialization to prefer providerOptions, then
providerMetadata, then toolCallId; added focused regression coverage
using the package-level provider-utils type import; and added a patch
changeset.

## Testing

Regression coverage asserts distinct stored call and output references
after a providerMetadata round trip. The OpenAI Node and Edge suites
each passed 791 tests, and workspace type checking plus lint and
formatting checks passed.

## End-to-end Validation

- `pnpm -C examples/ai-functions exec tsx
src/generate-text/openai/responses-tool-search.ts` — live OpenAI run
completed successfully with distinct `tsc_...` and `tso_...` IDs and no
duplicate-item rejection.

## Related Issues

Fixes #17666

Closes #17674

Backport of #17678

Co-authored-by: seandearnaley
<5084762+seandearnaley@users.noreply.github.com>
Co-authored-by: lgrammel <205036+lgrammel@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Published in:

Package Version
ai 7.0.35 github npm
@ai-sdk/amazon-bedrock 5.0.28 github npm
@ai-sdk/angular 3.0.35 github npm
@ai-sdk/azure 4.0.19 github npm
@ai-sdk/devtools 1.0.7 github npm
@ai-sdk/gateway 4.0.27 github npm
@ai-sdk/google 4.0.22 github npm
@ai-sdk/google-vertex 5.0.26 github npm
@ai-sdk/harness 1.0.40 github npm
@ai-sdk/harness-claude-code 1.0.41 github npm
@ai-sdk/harness-codex 1.0.42 github npm
@ai-sdk/harness-deepagents 1.0.39 github npm
@ai-sdk/harness-opencode 1.0.41 github npm
@ai-sdk/harness-pi 1.0.40 github npm
@ai-sdk/langchain 3.0.35 github npm
@ai-sdk/llamaindex 3.0.35 github npm
@ai-sdk/openai 4.0.18 github npm
@ai-sdk/otel 1.0.35 github npm
@ai-sdk/policy-opa 1.0.35 github npm
@ai-sdk/react 4.0.38 github npm
@ai-sdk/rsc 3.0.35 github npm
@ai-sdk/sandbox-just-bash 1.0.40 github npm
@ai-sdk/sandbox-vercel 1.0.40 github npm
@ai-sdk/svelte 5.0.35 github npm
@ai-sdk/tui 1.0.36 github npm
@ai-sdk/vue 4.0.35 github npm
@ai-sdk/workflow 1.0.35 github npm
@ai-sdk/workflow-harness 1.0.40 github npm

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@ai-sdk/openai: preserve tool_search output item id after metadata round trip

1 participant