chat-openrouter 0.1.2

OpenRouter provider for chat-rs (OpenAI-compatible Responses API).
Documentation

chat-openrouter

OpenRouter provider for chat-rs. OpenRouter exposes two OpenAI-compatible wires; the builder picks one and hands off to the matching wire crate:

  • Responses API (Beta) (default) → chat-responses, build() returns a ResponsesClient.
  • Chat Completions (opt in via .with_completions()) → chat-completions, build() returns a ChatCompletionsClient.

OpenRouter is a unified gateway in front of hundreds of models from many vendors. The model slug selects which one, and is vendor-prefixed (e.g. anthropic/claude-sonnet-4, openai/gpt-4o, google/gemini-2.5-pro).

Install

[dependencies]
chat-core = "0.4.0"
chat-openrouter = "0.1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Or via the umbrella crate: chat-rs = { version = "0.5.0", features = ["openrouter"] }.

Usage

use chat_openrouter::OpenRouterBuilder;
use chat_core::{builder::ChatBuilder, types::messages};

// Default: Responses API.
let client = OpenRouterBuilder::new()
    .with_model("anthropic/claude-sonnet-4")
    .build();

// Opt in to Chat Completions instead.
let client = OpenRouterBuilder::new()
    .with_completions()
    .with_model("openai/gpt-4o")
    .build();

let mut chat = ChatBuilder::new().with_model(client).build();

let mut msgs = messages::from_user(vec!["Hello!"]);
let response = chat.complete(&mut msgs).await?;

Set OPENROUTER_API_KEY in your environment or call .with_api_key() on the builder.

Capabilities

  • Completions — text generation with tool calling and structured output, on either wire
  • Streaming — token-by-token output over SSE (requires the stream feature); both wire clients implement it
  • Reasoning.with_reasoning_effort("high") for reasoning-capable models (Responses wire only)

Notes

  • Two wires. OpenRouter speaks both the OpenAI Responses API (Beta) and Chat Completions. The builder picks one upstream — .with_completions() switches from the default Responses wire — and returns the underlying wire client directly (ResponsesClient or ChatCompletionsClient); there is no wrapper type. Both already implement the chat-rs provider traits.
  • Stateless. The OpenRouter Responses API persists no server-side state and has no previous_response_id round-trip. The builder always disables response-id reuse and sends the full conversation each turn.
  • No WebSocket. OpenRouter has no WebSocket/realtime endpoint; streaming is SSE over HTTP. The builder is still generic over Transport, so a custom transport can be supplied via .with_transport(...).

Custom Endpoint / Transport

Override the base URL with .with_base_url(...) or supply a custom transport with .with_transport(...).

Feature Flags

Streaming is gated on the stream feature:

chat-openrouter = { version = "0.1.0", features = ["stream"] }