OpenRouterProvider#
Connect a provider and configure retries, credentials, and transport. See the guide.
- class zett_agent.providers.openrouter.OpenRouterProvider(model, api_key, transport=None, *, base_url=None, temperature=None, retry=RetryOptions(base_delay=0.25, max_delay=8.0, max_retries=3), timeout=TimeoutOptions(connect=5.0, first_byte=60.0, idle=600.0), site_url=None, app_name=None, send_prompt_cache_key=True, extra_headers=None, extra_query=None, extra_body=None)[source]#
Stream any model OpenRouter serves.
- Parameters:
model (str) – OpenRouter model slug, such as
anthropic/claude-sonnet-4.5.api_key (str) – OpenRouter API key.
transport (httpx.AsyncBaseTransport | None) – Optional HTTPX transport for custom routing or tests.
base_url (str | None) – API root; None uses
https://openrouter.ai/api/v1.temperature (float | None) – Optional sampling temperature.
retry (RetryOptions) – Model-owned retry/backoff policy; never restarts an emitted stream.
timeout (TimeoutOptions) – How long the provider may stay silent before the request is given up on. See
TimeoutOptions.site_url (str | None) – Your app’s URL, sent as
HTTP-Refererso OpenRouter can attribute traffic.app_name (str | None) – Your app’s name, sent as
X-OpenRouter-Title.send_prompt_cache_key (bool) – Declare the run’s prompt cache key on every request. OpenRouter uses it to keep a conversation on one upstream provider.
extra_headers (Mapping[str, str] | None) – HTTP headers sent on every request after the adapter’s own.
extra_query (Mapping[str, str] | None) – URL query parameters sent on every request.
extra_body (Mapping[str, JsonValue] | None) – JSON fields merged into every request body last. OpenRouter-only fields such as
provider(routing preferences) orreasoningoptions go here; areasoninggiven here replaces the one built from the request’s effort.
Note
A reasoning level is always sent as
reasoning.effort; OpenRouter passes it on in the form the upstream model takes and ignores it for a model that cannot reason. Reasoning that cannot be shown as text (encrypted or summarized) is kept on the message and sent back unchanged.Examples
Route one request through OpenRouter:
model = OpenRouterProvider( model="anthropic/claude-sonnet-4.5", api_key=os.environ["OPENROUTER_API_KEY"], site_url="https://example.com", app_name="My agent", ) try: client = await create_agent(model) print((await client.run("Explain this function")).content) finally: await model.aclose()
- provider_name = 'openrouter'#
Name stored on messages this provider produced and compared before reasoning is replayed.
- reasoning_keys: ClassVar[tuple[str, ...]] = ('reasoning', 'reasoning_content')#
Fields of a streamed delta that carry reasoning text, in order of preference. Services differ on the name (
reasoning_contentandreasoningare the two in use), and reading both is harmless because only the first one that has text is used.
- request_fields(request)[source]#
Send the reasoning level as a
reasoningobject, and the parallel-tools preference.- Parameters:
request (ModelRequest)
- Return type:
dict[str, JsonValue]
- replay_reasoning(message, payload)[source]#
Send back
reasoning_detailsunchanged, or the plain reasoning text if there are none.- Parameters:
message (AssistantMessage)
payload (dict[str, JsonValue])
- Return type:
None
- read_delta(delta)[source]#
Read the
reasoningtext, and keep everyreasoning_detailsentry for replay.
- merge_replay(blocks, fragment)[source]#
Join the pieces of one reasoning detail into one entry.
A detail can arrive in several chunks that share a
typeand an integerindex. Theirtextandsummaryare concatenated; any other field takes the latest value that is not null, which is how a signature that closes a text detail is kept. A detail without anindexcannot be told apart from its neighbour, so it is never merged.
- async aclose()#
Close the SDK’s owned HTTP connection pool.
- Return type:
None
- chat_stop(finish_reason, *, has_tool_calls, refusal_text, stream_error, native_finish_reason)#
Say why the response ended. Override it for a service with finish reasons of its own.
- native_deferred_tools = False#
See
zett_agent.model.NativeDeferredToolsModel.native_deferred_tools. A provider opts in by overriding this on its class; the default keeps Responses, Chat Completions, Google, and Ollama on the withhold-and-search path.
- read_usage(usage)#
Read the
usageobject of a chunk.The default accepts every spelling of the cache and reasoning counters that the compatible services use.
- Parameters:
usage (Mapping[str, JsonValue])
- Return type:
- response = False#
Whether this adapter uses a Responses-style endpoint instead of its provider’s traditional message or chat-completions endpoint. Only the providers read it; the runtime does not.
- status_error(error)#
Turn an HTTP failure into the typed error the runtime reports.
The default reports a refusal the service sent as an HTTP error, a rejected credential, and everything else as
ProviderHTTPError. A service that explains failures in a body of its own overrides this and falls back tosuper().- Parameters:
error (APIStatusError)
- Return type:
- sync(*, runtime=None)#
Return a context-managed synchronous view; optionally share a runtime.
Omitting runtime creates a new background thread for this view. Passing an existing runtime reuses its loop and leaves its shutdown to the caller. This API is for service entry points, not Extension lifecycle hooks.
Examples
Use a model or tool from a plain function:
with read_file.sync() as read: result = read({"path": "README.md"})
- Parameters:
runtime (SyncRuntime | None)
- Return type:
SyncObject[Self]