chat-rs
Providers

Providers

The backends chat-rs can talk to, and the helpers that compose them.

A provider is an implementation of model capabilities. You build one, hand it to ChatBuilder::with_model, and everything else, the loop, tools, streaming, retries, and middleware, works the same way regardless of which provider you chose.

Helpers

Three providers are not tied to a single vendor. They get the most attention because you can build a lot on top of them.

  • The Router composes several providers behind a single one, with a routing strategy, fallback, and a circuit breaker.
  • Completions is the OpenAI Chat Completions wire. Point it at any OpenAI-compatible server, or use it to build your own provider.
  • Responses is the OpenAI Responses API wire, with input streaming and reasoning effort.

Vendors

Each vendor provider presets the URL, auth, and any vendor-specific niceties.

ProviderBuilderFeatureWraps
ClaudeClaudeBuilderclaudenative
GeminiGeminiBuildergemininative
OpenAIOpenAIBuilderopenairesponses
OllamaOllamaBuilderollamacompletions
Apple Foundation ModelsAppleFMBuilderapplefmon-device
DeepSeekDeepSeekBuilderdeepseekcompletions
CerebrasCerebrasBuildercerebrascompletions
HuggingFaceHuggingFaceBuilderhuggingfacecompletions
mistral.rsMistralRsBuildermistralrslocal
OpenRouterOpenRouterBuilderopenrouterresponses / completions

Capabilities at a glance

ProviderStreamEmbeddingsStructuredNative tools
Claudeyesnoyesthinking
Geminiyesyesyescode exec, search, maps
OpenAIyesyesyesweb search, image gen
Ollamayesyesyesno
Apple Foundation Modelsyesnonono
DeepSeekyesnoyesno
Cerebrasyesnoyesno
HuggingFaceyesnoyesno
mistral.rsyesyesyesno
OpenRouteryesnoyesno

Enable a provider with its cargo feature:

Cargo.toml
chat-rs = { version = "0.5.3", features = ["claude", "gemini", "openai"] }

Bring your own provider

A provider is just one trait. Implement CompletionProvider and your backend plugs into the same loop as everything else. It does not need to speak Chat Completions or the Responses API.

use async_trait::async_trait;
use chat_rs::{
    ChatFailure, ChatResponse, CompletionProvider, Messages,
    types::{options::ChatOptions, tools::ToolDeclarations},
};

struct MyProvider;

#[async_trait]
impl CompletionProvider for MyProvider {
    async fn complete(
        &mut self,
        messages: &mut Messages,
        tools: Option<&dyn ToolDeclarations>,
        options: Option<&ChatOptions>,
        schema: Option<&schemars::Schema>,
    ) -> Result<ChatResponse, ChatFailure> {
        // Call your model, then hand back a ChatResponse.
        todo!()
    }
}

If you target an OpenAI-compatible endpoint, you usually do not need to write this by hand: build on Completions instead.

On this page