rtb-ai v0.1¶
A single chat client across providers. genai
covers the mainstream (OpenAI, Gemini, Ollama, OpenAI-compatible);
the Claude backend additionally drops down to direct reqwest
calls against the Anthropic Messages API for features genai does
not surface — prompt caching, extended thinking, citations.
Public API¶
use rtb_ai::{AiClient, ChatRequest, Config, Message, Provider};
# async fn run() -> Result<(), rtb_ai::AiError> {
let client = AiClient::new(Config {
provider: Provider::Claude,
model: "claude-opus-4-7".into(),
..Config::default()
})?;
let reply = client.chat(ChatRequest {
messages: vec![Message::user("Summarise this changelog in one line.")],
cache_control: true,
..ChatRequest::default()
}).await?;
# Ok(())
# }
Config and ChatRequest are plain structs with public fields and a
Default impl — set what you need, spread the rest. Provider is
#[non_exhaustive].
| Item | Purpose |
|---|---|
[AiClient] |
new / chat / chat_stream / chat_structured. |
[Config], [Provider] |
Provider selection, model, endpoint, auth. |
[Message], [Role], [ContentBlock], [Citation], [Usage] |
Request/response message model. |
[ChatRequest], [ChatResponse], [ChatStream], [ChatStreamEvent] |
Call shapes — one-shot, streaming, and structured. |
[ThinkingMode] |
Extended-thinking control on the Claude backend. |
[AiError] |
thiserror + miette::Diagnostic error enum. |
[validate_base_url] |
Endpoint allowlist guard (see below). |
Structured output¶
chat_structured::<T>() takes any T: serde::Deserialize +
schemars::JsonSchema. The generated JSON Schema is sent with the
request and the response is validated with jsonschema before
deserialising — a malformed model response surfaces as an
AiError, never a partial T.
Endpoint safety¶
Every Config::base_url passes [validate_base_url]: non-HTTPS
schemes, URLs carrying userinfo (user:pass@host), and placeholder
hosts (example.com and subdomains) are rejected. Tests against a
wiremock/httpmock server set Config::allow_insecure_base_url,
which is #[serde(skip)] so config files can't downgrade HTTPS
enforcement. Each successful AiClient::new logs the endpoint
hostname at INFO — never the path or query.
Model defaults¶
New AI code defaults to Claude 4.7 models with prompt caching at every stable point (system prompt, tools, static context). Migration mapping: Opus 4.6 → Opus 4.7, Sonnet 4.5 → Sonnet 4.6, Haiku 4.5 (current).
Secrets¶
API keys cross the boundary as secrecy::SecretString and are
resolved through the precedence chain documented in
configure credentials. Never
log the exposed form.
Spec¶
Authoritative contract:
docs/development/specs/2026-05-01-rtb-ai-v0.1.md.