Choose a provider¶
Talk to Anthropic Cloud¶
The default. Config::default() already selects it:
use rtb_chat::{AiClient, Config, Provider};
use secrecy::SecretString;
let client = AiClient::new(Config {
provider: Provider::Anthropic,
model: "claude-opus-4-7".into(),
api_key: SecretString::from(std::env::var("ANTHROPIC_API_KEY")?),
..Config::default()
})?;
This is the backend that supports prompt caching, extended thinking, citations,
temperature, max_tokens, timeout and typed auth and rate-limit errors.
Prefer it when you have the choice.
Talk to an Anthropic-compatible gateway¶
Use Provider::AnthropicLocal and set base_url. Without the override it
sends to api.anthropic.com, exactly like Provider::Anthropic:
use url::Url;
let client = AiClient::new(Config {
provider: Provider::AnthropicLocal,
model: "claude-opus-4-7".into(),
base_url: Some(Url::parse("https://gateway.internal/anthropic")?),
api_key: SecretString::from(std::env::var("GATEWAY_TOKEN")?),
..Config::default()
})?;
/v1/messages is appended to whatever you supply, with any trailing slash
trimmed first.
This is also the only way to reach a self-hosted endpoint at all — see Point at an OpenAI-compatible endpoint.
Talk to OpenAI or Gemini¶
let client = AiClient::new(Config {
provider: Provider::OpenAi,
model: "gpt-4.1".into(),
api_key: SecretString::from(std::env::var("OPENAI_API_KEY")?),
..Config::default()
})?;
Two things to know before you ship this:
AiClient::newwrites the key into the process environment asOPENAI_API_KEY(orGEMINI_API_KEYfor Gemini). Build one client per process; a second client for the same provider overwrites the first one's key.temperature,max_tokens,timeoutandbase_urlare all ignored on this path. Whatever you set, the provider's defaults apply.
Both are covered in What rtb-chat does not do.
Talk to a local Ollama¶
let client = AiClient::new(Config {
provider: Provider::Ollama,
model: "llama3".into(),
// Required to be non-empty, never sent anywhere.
api_key: SecretString::from("unused".to_string()),
..Config::default()
})?;
The endpoint is genai's default, http://localhost:11434/. base_url will not
move it.
Point at an OpenAI-compatible endpoint¶
You cannot, in v0.7.2. Provider::OpenAiCompatible validates base_url and then
ignores it, so the request goes wherever genai routes it from the model name —
and an unrecognised name routes to Ollama on localhost. The full explanation is in
A custom base_url is ignored on every genai-backed provider.
Your options today:
- If the endpoint speaks the Anthropic Messages format, use
Provider::AnthropicLocalwithbase_url. That path honours the override. - If it speaks the OpenAI format, use the vendor's own genai adapter by
namespacing the model name —
together::meta-llama/Llama-3-70b,groq::llama-3.1-70b.Config::api_keywill not reach it:Provider::OpenAiCompatiblewrites the key toOPENAI_API_KEY, and those adapters readTOGETHER_API_KEYandGROQ_API_KEY, so you have to export the vendor's variable yourself. That reaches the vendor's public endpoint, not a private one. - If it is a private OpenAI-format host,
rtb-chatcannot reach it yet.
Check the request went where you meant¶
The routing surprise on the genai path is quiet: no error, just an answer from somewhere else, or a connection refused on localhost.
Two ways to confirm:
Read the INFO log. AiClient::new emits one line with the provider and the
host it will use:
The literal openai-compatible is the tell that there is no real endpoint behind
this client.
Read the error. genai names the adapter it chose when a call fails:
provider error: Web call failed for model 'llama-3.1-70b-instruct (adapter: Ollama)'.
Cause: Reqwest error: error sending request for url (http://localhost:11434/api/chat)
adapter: Ollama on a provider you did not set to Ollama means the model name
matched nothing and fell through to the default.