Skip to content

@ai-sdk/open-responses: allow explicit codecs for documented bare extension types #19933

Description

@me2seeks

Description

@ai-sdk/open-responses@2.0.35 added the experimental extension codec registry from #18899 / #18900. The registry safely solves request encoding, response and event decoding, and history replay for normative namespaced Open Responses extensions.

Some public Responses-compatible implementations expose documented implementation extensions using legacy OpenAI-style bare discriminators instead of <implementor>:<type>. Examples include hosted-search and custom-tool families such as:

  • request tools: web_search, custom
  • output/input items: web_search_call, custom_tool_call, custom_tool_call_output
  • streaming events: response.web_search_call.*, response.custom_tool_call_input.*

These types are not Open Responses core types and should not become portable defaults. However, an application also cannot explicitly register their wire semantics today: OpenResponsesNamespacedType requires ${string}:${string}, and registry validation requires the wire namespace to match the extension ID namespace.

As a result, the safe codec seam exists, but documented Responses-compatible extensions using bare discriminators still require a provider fork or a request/response-mutating fetch wrapper.

Expected behavior

Would you be open to an explicit opt-in mechanism for codecs to register exact bare tool, item, and event discriminators?

The API shape is open, but it should preserve the current safety properties:

  1. Registration remains explicit and package-local.
  2. Every accepted bare discriminator is exactly allowlisted by a codec.
  3. Unknown tool, item, and event types remain unsupported; there is no arbitrary JSON passthrough.
  4. Duplicate registrations and ambiguous ownership are rejected.
  5. The same codec continues to own request encoding, non-streaming decoding, streaming decoding, and lossless history replay.
  6. Namespaced extensions remain the default and retain their current namespace validation.

Possible shapes include an explicit allowBareTypes capability on an extension, separate bareToolType / bareItemTypes / bareEventTypes fields, or another API that makes the non-portable opt-in visible.

Why this is distinct from existing requests

Reproduction

A codec whose provider-tool ID is acme.web_search cannot register the implementation wire type web_search:

const extension: Experimental_OpenResponsesExtension = {
  id: "acme.web_search",
  toolType: "web_search", // rejected by the public type
  itemTypes: ["web_search_call"], // rejected by the public type
  eventTypes: ["response.web_search_call.completed"], // rejected by the public type
  encodeTool: () => ({}),
  decodeItem: () => [],
  decodeEvent: () => [],
};

Casting around the TypeScript constraint still fails registry validation at runtime because each wire type lacks the required acme: namespace.

Non-goals

  • Do not classify bare web_search, custom, or related item names as Open Responses core types.
  • Do not add vendor/model capability detection to @ai-sdk/open-responses.
  • Do not pass through arbitrary unknown JSON.
  • Do not weaken validation for existing namespaced registrations.

AI SDK Version

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions