llm-universal
One async Rust client for OpenAI-compatible Chat Completions and the Anthropic Messages API. Write your chat and tool-calling code once and switch providers by switching the constructor.
AnthropicProvider—POST /v1/messagesOpenAiProvider—POST /chat/completions; also works with any OpenAI-compatible server (Ollama, vLLM, LM Studio, OpenRouter, Groq) viawith_base_url- Tool calling with one normalized format for both providers
- Errors modeled on the official SDKs (
BadRequest,Authentication,RateLimit, …, request IDs, retry rules) - Client-side validation before any network call
- Safe defaults: connect/request timeouts, no redirects (the key never goes to another host),
API keys redacted from
Debug
Install
[]
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
Quick start
use ;
async
Local OpenAI-compatible server:
# use OpenAiProvider;
let ollama = new.with_base_url;
Tool calling
# use *;
# use json;
# async
A complete loop is in examples/tools.rs: cargo run --example tools.
Errors
LlmError variant |
When | SDK equivalent |
|---|---|---|
Api(Box<ApiError>) |
non-2xx response | APIStatusError and subclasses |
Connection |
DNS, TLS, dropped connection | APIConnectionError |
Timeout |
request timed out | APIConnectionTimeoutError |
Deserialize |
body is not JSON | JSONDeserialize (async-openai) |
InvalidResponse |
JSON is missing expected fields | — |
InvalidArgument |
client-side validation failed | InvalidArgument (async-openai) |
ApiError carries status, kind (ApiErrorKind::RateLimit, …), message, error_type,
code, param, request_id and the JSON body. Its message format matches the SDKs:
401 invalid x-api-key
429 Rate limit reached for requests
invalid args: model must not be empty
# use *;
# async
is_retryable() follows the SDK retry rules: 408, 409, 429, >= 500, connection errors and timeouts.
Notes
- Anthropic newer models accept only
temperature = 1.0; leavetemperatureunset unless you need it. - Extended-thinking blocks are not part of the normalized message; if you enable thinking, keep the raw response to send signed thinking blocks back unchanged.
- Streaming is not supported yet.
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.