diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock
index 446e7cac..9e32abfd 100644
--- a/.speakeasy/gen.lock
+++ b/.speakeasy/gen.lock
@@ -1,19 +1,19 @@
lockVersion: 2.0.0
id: c48cf606-fb42-4a45-9c23-8f0555307828
management:
- docChecksum: 38b116dcd76ec799eea497e956a66f42
+ docChecksum: a4b4ee77d44e7138e1f47168f14951c4
docVersion: 1.0.0
speakeasyVersion: 1.803.2
generationVersion: 2.950.13
- releaseVersion: 1.3.134
- configChecksum: 0e56e7298a9f49166f549c467785dc2a
+ releaseVersion: 1.3.135
+ configChecksum: b8528f4962f0149fe2fc73ca88dc8641
repoURL: https://github.com/OpenRouterTeam/python-sdk.git
installationURL: https://github.com/OpenRouterTeam/python-sdk.git
published: true
persistentEdits:
- generation_id: 3b40450a-e752-4c54-a7ea-fa2b2379e8a5
- pristine_commit_hash: fa88f444fcfab969f83fa311fdbc0b6f854d4732
- pristine_tree_hash: 808ca2b64e771b552d2ab1dbd7e4be848b3b22d0
+ generation_id: 8c9796fc-3794-4282-a931-32d6f2368721
+ pristine_commit_hash: 4e55cd60625d98bb755e362a88d4b881ef0c3868
+ pristine_tree_hash: 91a6498ea72ed956778bbbbc3c542be3bf47d3c9
features:
python:
acceptHeaders: 3.0.0
@@ -3152,8 +3152,12 @@ trackedFiles:
pristine_git_object: a226240fb3b94358d33acc91761a8bba03309b63
docs/components/deferredtoolscontrol.mdx:
id: 13db9fb1f102
- last_write_checksum: sha1:92e20daf24c49c040d40dcba0d6b5f4ec46900f6
- pristine_git_object: c226e1a86b4a6b12668e11e4033c0568a8d4c52d
+ last_write_checksum: sha1:af549b4b689285860c5b3acd7db1dbbced30b911
+ pristine_git_object: 70fe8e10bfd7967e0c379fe93a52a3f4d474ada8
+ docs/components/deferredtoolscontrolscope.mdx:
+ id: 61fade4412af
+ last_write_checksum: sha1:9d82e5340c3123b7c48033b16798b0142a8461c8
+ pristine_git_object: e29edbc3c509f99ebf885f54b4ad3a5fe1a839f7
docs/components/deferredtoolsdetails.mdx:
id: 18832b6c60aa
last_write_checksum: sha1:15b5cc53097084283f00f04ce8b0f4016a0abb5c
@@ -4706,6 +4710,10 @@ trackedFiles:
id: 4e1ceba5a654
last_write_checksum: sha1:2efe0463c8d0ed63159bbcc8cb8c21743800b88e
pristine_git_object: e3e71d16be9294f68ca671f76dbcc8b6d8ecc749
+ docs/components/interface.mdx:
+ id: 6e52661d8f9f
+ last_write_checksum: sha1:696e93ea18a796a28e3db3e405abaae4da1894bd
+ pristine_git_object: d309553a56067f9815f11e40dceb63cfd9f1a426
docs/components/internalserverresponseerrordata.mdx:
id: 9a443dea63c5
last_write_checksum: sha1:5ebe83b940cb6501be7ffc5d87524957ed7a2823
@@ -11560,8 +11568,8 @@ trackedFiles:
pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544
pyproject.toml:
id: 5d07e7d72637
- last_write_checksum: sha1:6e48b629c4bfafa5dcf8bc93147c57eb8f96cdb5
- pristine_git_object: 5b4e440a737ba8ed964a5cc9b6851bd47c51c849
+ last_write_checksum: sha1:64580e8affa06e934741726c9dc8ec5f0702c85e
+ pristine_git_object: 5af69cb461a7323d556b64b92575c08bf6d28e91
scripts/prepare_readme.py:
id: e0c5957a6035
last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54
@@ -11588,8 +11596,8 @@ trackedFiles:
pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137
src/openrouter/_version.py:
id: d8d15ad6c586
- last_write_checksum: sha1:3b5e6293f12225b7d6c19926d454cf4c103c69dd
- pristine_git_object: bff9ce30b9bc2b3728d6aa1754711f0e1b5de43f
+ last_write_checksum: sha1:95c492e5022d06d245533d9c330753e7a439afdc
+ pristine_git_object: e048fa8bceac02ec4890c13596bd528c06a32ea9
src/openrouter/alpha.py:
id: 306c4d93308d
last_write_checksum: sha1:80cc0f39649445431cc2247ed0e0765438467766
@@ -11636,8 +11644,8 @@ trackedFiles:
pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1
src/openrouter/components/__init__.py:
id: 81754e97b3f4
- last_write_checksum: sha1:41368ba38a9a07f48992136b74214ae7fe2949bc
- pristine_git_object: e02bf331a2bd0026ae9cfe4dce27099db6eda3bf
+ last_write_checksum: sha1:75101b722e8c5947eef015cf67a618d459c03b21
+ pristine_git_object: c8f0c0d7c5db5d5f1d97b0f65845425d68237186
src/openrouter/components/aabenchmarkentry.py:
id: e2e0f0b48c82
last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c
@@ -12980,8 +12988,8 @@ trackedFiles:
pristine_git_object: 8a4e94425724c374a040ea028d0933db39ec1451
src/openrouter/components/deferredtoolscontrol.py:
id: b8b6ceef6f86
- last_write_checksum: sha1:5e39422e677b596848df4fadf4b32f80d554cab7
- pristine_git_object: cef37bad7a45c3731eeca91832fa4f867c885825
+ last_write_checksum: sha1:40f64cc19ddc3e79e3eaf6af3ee2bc17bd13cf40
+ pristine_git_object: 04a1a09bf46c0839ebc9a3634fddd7aa36e61a12
src/openrouter/components/deferredtoolsdetails.py:
id: 044f0e33803d
last_write_checksum: sha1:2f8fcc43fc779a0cb9621149875a5e7bbfa5e6dc
@@ -21493,3 +21501,8 @@ examples:
"500":
application/json: {"error": {"code": 500, "message": "Internal Server Error"}}
examplesVersion: 1.0.2
+releaseNotes: |
+ ## Python SDK Changes:
+ * `open_router.presets.create_presets_chat_completions()`: `request.deferred_tools` **Changed**
+ * `open_router.presets.create_presets_messages()`: `request.deferred_tools` **Changed**
+ * `open_router.presets.create_presets_responses()`: `request.deferred_tools` **Changed**
diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml
index 1355eb65..4756df05 100644
--- a/.speakeasy/gen.yaml
+++ b/.speakeasy/gen.yaml
@@ -37,7 +37,7 @@ generation:
documentation: mintlify
preApplyUnionDiscriminators: true
python:
- version: 1.3.134
+ version: 1.3.135
additionalDependencies:
dev:
pytest: '>=8.3'
diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml
index 0592be98..1474c29c 100644
--- a/.speakeasy/out.openapi.yaml
+++ b/.speakeasy/out.openapi.yaml
@@ -12163,6 +12163,13 @@ components:
type: 'bm25'
validation: 'runtime'
properties:
+ interface:
+ description: 'How the universal profile exposes the hidden catalog to the provider. Absent or `wrappers`: the `tool_search` and `tool_exec` tools. `code_mode`: one `tool_code` tool that runs a short JavaScript program in which `search()` and `call()` reach the catalog, so several searches and calls complete in one tool result. Experimental.'
+ enum:
+ - 'wrappers'
+ - 'code_mode'
+ type: 'string'
+ x-speakeasy-unknown-values: allow
profile:
description: 'Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation.'
enum:
@@ -12174,6 +12181,13 @@ components:
enum:
- 'v1'
type: 'string'
+ scope:
+ description: 'Which tools the universal profile defers. Absent or `all`: every wrappable tool outside the coding-harness core set. `mcp`: only MCP server tools (`mcp__*` names and Responses namespaces outside `functions`); the harness keeps its own built-in tools direct. Experimental.'
+ enum:
+ - 'all'
+ - 'mcp'
+ type: 'string'
+ x-speakeasy-unknown-values: allow
search:
$ref: '#/components/schemas/DeferredToolsSearchStrategy'
validation:
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index 9d7d95cf..0e7675e2 100644
--- a/.speakeasy/workflow.lock
+++ b/.speakeasy/workflow.lock
@@ -2,8 +2,8 @@ speakeasyVersion: 1.803.2
sources:
OpenRouter API:
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:00c04687d464fa96db56087dbd329415297b5bf20d6a937926c2866e51c7c264
- sourceBlobDigest: sha256:84763d7d924a44236c865d42fbe309c658fe5c4fda8a54065640c6d5b52a436d
+ sourceRevisionDigest: sha256:17d431cc2b441bd24a7e6da415e0803a785bf77a04af3fd1495d1690e277c8b8
+ sourceBlobDigest: sha256:d4d80c90a12f9704a8cc4c2d4fe2000627cf68e83a7904f94d8046df35dec466
tags:
- latest
- 1.0.0
@@ -11,10 +11,10 @@ targets:
open-router:
source: OpenRouter API
sourceNamespace: open-router-chat-completions-api
- sourceRevisionDigest: sha256:00c04687d464fa96db56087dbd329415297b5bf20d6a937926c2866e51c7c264
- sourceBlobDigest: sha256:84763d7d924a44236c865d42fbe309c658fe5c4fda8a54065640c6d5b52a436d
+ sourceRevisionDigest: sha256:17d431cc2b441bd24a7e6da415e0803a785bf77a04af3fd1495d1690e277c8b8
+ sourceBlobDigest: sha256:d4d80c90a12f9704a8cc4c2d4fe2000627cf68e83a7904f94d8046df35dec466
codeSamplesNamespace: open-router-python-code-samples
- codeSamplesRevisionDigest: sha256:74e65c8c21babdd13dd933553f2d35e3c2b3e070ea3b6cc2fb6f578072947372
+ codeSamplesRevisionDigest: sha256:a63434ddbe1e3bbac8b718e0db88c44b2bae6c29c2e5f2e97704c21f4e032811
workflow:
workflowVersion: 1.0.0
speakeasyVersion: 1.803.2
diff --git a/RELEASES.md b/RELEASES.md
index 2baa1fdc..dbce763b 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -4109,4 +4109,14 @@ Based on:
### Generated
- [python v1.3.134] .
### Releases
-- [PyPI v1.3.134] https://pypi.org/project/openrouter/1.3.134 - .
\ No newline at end of file
+- [PyPI v1.3.134] https://pypi.org/project/openrouter/1.3.134 - .
+
+## 2026-11-06 18:33:24
+### Changes
+Based on:
+- OpenAPI Doc
+- Speakeasy CLI 1.803.2 (2.950.13) https://github.com/speakeasy-api/speakeasy
+### Generated
+- [python v1.3.135] .
+### Releases
+- [PyPI v1.3.135] https://pypi.org/project/openrouter/1.3.135 - .
\ No newline at end of file
diff --git a/docs/components/deferredtoolscontrol.mdx b/docs/components/deferredtoolscontrol.mdx
index c226e1a8..70fe8e10 100644
--- a/docs/components/deferredtoolscontrol.mdx
+++ b/docs/components/deferredtoolscontrol.mdx
@@ -9,7 +9,9 @@ Opt-in versioned router-level deferred-tool protocol. Replay assistant reasoning
| Field | Type | Required | Description | Example |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `interface` | [Optional[components.Interface]](../components/interface.mdx) | ➖ | How the universal profile exposes the hidden catalog to the provider. Absent or `wrappers`: the `tool_search` and `tool_exec` tools. `code_mode`: one `tool_code` tool that runs a short JavaScript program in which `search()` and `call()` reach the catalog, so several searches and calls complete in one tool result. Experimental. | |
| `profile` | [components.Profile](../components/profile.mdx) | ✔️ | Loading profile. `portable` serves the `defer_loading` tools with router-built search and call wrappers on any model and keeps the catalog fixed. `universal` defers every wrappable tool behind the same wrappers so the provider-facing tool list never changes, and rebuilds the catalog from each request so tools can be added or removed mid-conversation. | |
| `protocol` | [components.Protocol](../components/protocol.mdx) | ✔️ | N/A | |
+| `scope` | [Optional[components.DeferredToolsControlScope]](../components/deferredtoolscontrolscope.mdx) | ➖ | Which tools the universal profile defers. Absent or `all`: every wrappable tool outside the coding-harness core set. `mcp`: only MCP server tools (`mcp__*` names and Responses namespaces outside `functions`); the harness keeps its own built-in tools direct. Experimental. | |
| `search` | [components.DeferredToolsSearchStrategy](../components/deferredtoolssearchstrategy.mdx) | ✔️ | Router-local regex/BM25 or caller-owned custom search. | \{
"max_results": 5,
"type": "bm25"
} |
| `validation` | [components.Validation](../components/validation.mdx) | ✔️ | Where tool-call arguments are checked against the original schema. Only `runtime` (in OpenRouter) is available in this release. | |
\ No newline at end of file
diff --git a/docs/components/deferredtoolscontrolscope.mdx b/docs/components/deferredtoolscontrolscope.mdx
new file mode 100644
index 00000000..e29edbc3
--- /dev/null
+++ b/docs/components/deferredtoolscontrolscope.mdx
@@ -0,0 +1,22 @@
+---
+title: "DeferredToolsControlScope"
+---
+
+Which tools the universal profile defers. Absent or `all`: every wrappable tool outside the coding-harness core set. `mcp`: only MCP server tools (`mcp__*` names and Responses namespaces outside `functions`); the harness keeps its own built-in tools direct. Experimental.
+
+## Example Usage
+
+```python
+from openrouter.components import DeferredToolsControlScope
+
+# Open enum: unrecognized values are captured as UnrecognizedStr
+value: DeferredToolsControlScope = "all"
+```
+
+
+## Values
+
+This is an open enum. Unrecognized values will not fail type checks.
+
+- `"all"`
+- `"mcp"`
diff --git a/docs/components/interface.mdx b/docs/components/interface.mdx
new file mode 100644
index 00000000..d309553a
--- /dev/null
+++ b/docs/components/interface.mdx
@@ -0,0 +1,22 @@
+---
+title: "Interface"
+---
+
+How the universal profile exposes the hidden catalog to the provider. Absent or `wrappers`: the `tool_search` and `tool_exec` tools. `code_mode`: one `tool_code` tool that runs a short JavaScript program in which `search()` and `call()` reach the catalog, so several searches and calls complete in one tool result. Experimental.
+
+## Example Usage
+
+```python
+from openrouter.components import Interface
+
+# Open enum: unrecognized values are captured as UnrecognizedStr
+value: Interface = "wrappers"
+```
+
+
+## Values
+
+This is an open enum. Unrecognized values will not fail type checks.
+
+- `"wrappers"`
+- `"code_mode"`
diff --git a/pyproject.toml b/pyproject.toml
index 5b4e440a..5af69cb4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "openrouter"
-version = "1.3.134"
+version = "1.3.135"
description = "Official Python Client SDK for OpenRouter."
authors = [{ name = "OpenRouter" },]
readme = "README-PYPI.md"
diff --git a/src/openrouter/_version.py b/src/openrouter/_version.py
index bff9ce30..e048fa8b 100644
--- a/src/openrouter/_version.py
+++ b/src/openrouter/_version.py
@@ -3,10 +3,10 @@
import importlib.metadata
__title__: str = "openrouter"
-__version__: str = "1.3.134"
+__version__: str = "1.3.135"
__openapi_doc_version__: str = "1.0.0"
__gen_version__: str = "2.950.13"
-__user_agent__: str = "speakeasy-sdk/python 1.3.134 2.950.13 1.0.0 openrouter"
+__user_agent__: str = "speakeasy-sdk/python 1.3.135 2.950.13 1.0.0 openrouter"
try:
if __package__ is not None:
diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py
index e02bf331..c8f0c0d7 100644
--- a/src/openrouter/components/__init__.py
+++ b/src/openrouter/components/__init__.py
@@ -1823,7 +1823,9 @@
)
from .deferredtoolscontrol import (
DeferredToolsControl,
+ DeferredToolsControlScope,
DeferredToolsControlTypedDict,
+ Interface,
Profile,
Protocol,
Validation,
@@ -6293,6 +6295,7 @@
"DeferredRegexSearchType",
"DeferredRegexSearchTypedDict",
"DeferredToolsControl",
+ "DeferredToolsControlScope",
"DeferredToolsControlTypedDict",
"DeferredToolsDetails",
"DeferredToolsDetailsTypedDict",
@@ -6918,6 +6921,7 @@
"Installation",
"InstallationTypedDict",
"InstructType",
+ "Interface",
"InternalServerResponseErrorData",
"InternalServerResponseErrorDataTypedDict",
"Interval",
@@ -10061,7 +10065,9 @@
"DeferredRegexSearchType": ".deferredregexsearch",
"DeferredRegexSearchTypedDict": ".deferredregexsearch",
"DeferredToolsControl": ".deferredtoolscontrol",
+ "DeferredToolsControlScope": ".deferredtoolscontrol",
"DeferredToolsControlTypedDict": ".deferredtoolscontrol",
+ "Interface": ".deferredtoolscontrol",
"Profile": ".deferredtoolscontrol",
"Protocol": ".deferredtoolscontrol",
"Validation": ".deferredtoolscontrol",
diff --git a/src/openrouter/components/deferredtoolscontrol.py b/src/openrouter/components/deferredtoolscontrol.py
index cef37bad..04a1a09b 100644
--- a/src/openrouter/components/deferredtoolscontrol.py
+++ b/src/openrouter/components/deferredtoolscontrol.py
@@ -5,9 +5,20 @@
DeferredToolsSearchStrategy,
DeferredToolsSearchStrategyTypedDict,
)
-from openrouter.types import BaseModel, UnrecognizedStr
-from typing import Literal, Union
-from typing_extensions import TypedDict
+from openrouter.types import BaseModel, UNSET_SENTINEL, UnrecognizedStr
+from pydantic import model_serializer
+from typing import Literal, Optional, Union
+from typing_extensions import NotRequired, TypedDict
+
+
+Interface = Union[
+ Literal[
+ "wrappers",
+ "code_mode",
+ ],
+ UnrecognizedStr,
+]
+r"""How the universal profile exposes the hidden catalog to the provider. Absent or `wrappers`: the `tool_search` and `tool_exec` tools. `code_mode`: one `tool_code` tool that runs a short JavaScript program in which `search()` and `call()` reach the catalog, so several searches and calls complete in one tool result. Experimental."""
Profile = Union[
@@ -23,6 +34,16 @@
Protocol = Literal["v1",]
+DeferredToolsControlScope = Union[
+ Literal[
+ "all",
+ "mcp",
+ ],
+ UnrecognizedStr,
+]
+r"""Which tools the universal profile defers. Absent or `all`: every wrappable tool outside the coding-harness core set. `mcp`: only MCP server tools (`mcp__*` names and Responses namespaces outside `functions`); the harness keeps its own built-in tools direct. Experimental."""
+
+
Validation = Literal["runtime",]
r"""Where tool-call arguments are checked against the original schema. Only `runtime` (in OpenRouter) is available in this release."""
@@ -37,6 +58,10 @@ class DeferredToolsControlTypedDict(TypedDict):
r"""Router-local regex/BM25 or caller-owned custom search."""
validation: Validation
r"""Where tool-call arguments are checked against the original schema. Only `runtime` (in OpenRouter) is available in this release."""
+ interface: NotRequired[Interface]
+ r"""How the universal profile exposes the hidden catalog to the provider. Absent or `wrappers`: the `tool_search` and `tool_exec` tools. `code_mode`: one `tool_code` tool that runs a short JavaScript program in which `search()` and `call()` reach the catalog, so several searches and calls complete in one tool result. Experimental."""
+ scope: NotRequired[DeferredToolsControlScope]
+ r"""Which tools the universal profile defers. Absent or `all`: every wrappable tool outside the coding-harness core set. `mcp`: only MCP server tools (`mcp__*` names and Responses namespaces outside `functions`); the harness keeps its own built-in tools direct. Experimental."""
class DeferredToolsControl(BaseModel):
@@ -52,3 +77,25 @@ class DeferredToolsControl(BaseModel):
validation: Validation
r"""Where tool-call arguments are checked against the original schema. Only `runtime` (in OpenRouter) is available in this release."""
+
+ interface: Optional[Interface] = None
+ r"""How the universal profile exposes the hidden catalog to the provider. Absent or `wrappers`: the `tool_search` and `tool_exec` tools. `code_mode`: one `tool_code` tool that runs a short JavaScript program in which `search()` and `call()` reach the catalog, so several searches and calls complete in one tool result. Experimental."""
+
+ scope: Optional[DeferredToolsControlScope] = None
+ r"""Which tools the universal profile defers. Absent or `all`: every wrappable tool outside the coding-harness core set. `mcp`: only MCP server tools (`mcp__*` names and Responses namespaces outside `functions`); the harness keeps its own built-in tools direct. Experimental."""
+
+ @model_serializer(mode="wrap")
+ def serialize_model(self, handler):
+ optional_fields = set(["interface", "scope"])
+ serialized = handler(self)
+ m = {}
+
+ for n, f in type(self).model_fields.items():
+ k = f.alias or n
+ val = serialized.get(k, serialized.get(n))
+
+ if val != UNSET_SENTINEL:
+ if val is not None or k not in optional_fields:
+ m[k] = val
+
+ return m
diff --git a/uv.lock b/uv.lock
index a87b0277..72974935 100644
--- a/uv.lock
+++ b/uv.lock
@@ -231,7 +231,7 @@ wheels = [
[[package]]
name = "openrouter"
-version = "1.3.134"
+version = "1.3.135"
source = { editable = "." }
dependencies = [
{ name = "httpcore" },