llmoxide
Rust SDK for OpenAI, Anthropic, Gemini, and Ollama with a small, shared surface:
non-streaming and streaming calls, plus normalized SSE Events.
Lower-level types (Client, ResponseRequest, chat sessions, and the like) are documented in
Rustdoc (cargo doc --open in this repo); this page only shows the shortest path.
Dependencies
[]
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
Usage
Crate-root helpers return a Prompt handle. .send, .stream, and .list_models
work on every provider the same way.
Anthropic
send:
async
stream:
async
Tools (crate llmoxide-tools) work the same on every provider; register schemas, then
run_with_tools_text on a Prompt. Use run_with_tools_stream_text when you want
llmoxide::Event::TextDelta / ToolCall callbacks during the loop (example:
crates/llmoxide-tools/examples/add_tool_stream.rs).
Debugging:
- Set
LLMOXIDE_DEBUG_TOOLS_STREAM=1for stderr logs from the tools runner (rounds, tool-call counts, response summaries). - Set
LLMOXIDE_DEBUG_ANTHROPIC_STREAM=1(or reuseLLMOXIDE_DEBUG_TOOLS_STREAM=1) for stderr logs from the Anthropic SSE parser (tool JSON assembly, parse failures, fallthrough).
[]
= "0.1"
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
= { = "1", = ["derive"] }
= { = "0.8", = false, = ["derive"] }
use ;
use JsonSchema;
use ;
async
OpenAI
send:
async
Gemini
async
Ollama (default http://localhost:11434)
async
Ollama (custom base URL)
async
List models
async
Chain .model("model-id") or .max_output_tokens(n) before .send / .stream when you need
them. With the default new_auto() behavior, the first model from the provider list is used when
you do not set .model; if that does not match your account (for example some Anthropic setups),
set .model("…") explicitly or pick an id from .list_models().await.
Multimodal messages and extensions
Message content is a list of ContentPart
values. Besides plain Text and tool parts, the enum includes images (ImageUrl,
ImageBase64), reasoning text (Thinking, mapped to native formats where the provider supports
it), and an opaque Citation payload for references. Provider adapters decide what can be sent
on each turn (for example Ollama attaches base64 images on user messages only; ImageUrl may be
unsupported on some backends).
For response-time fields that do not fit a stable shape yet (citations, safety metadata, usage
details), check Response::metadata (and optionally the raw-json feature for the full provider
payload). The API stays #[non_exhaustive] so new variants and metadata keys can appear without
forcing a major bump for every provider addition.
Stability / compatibility
This repo is still early-stage. Until 1.0:
- Public API may change between minor versions (
0.x). - Provider streaming details are best-effort; the crate aims to keep the high-level contract
stable (e.g.
Response::text(), tool calling loop behavior), while adapters may need updates as providers evolve.
Tool-calling + streaming invariants (llmoxide-tools):
run_with_tools_stream_textemits exactly one finalEvent::Completed(for the last assistant message).- Tool-calling rounds may have empty assistant text (e.g. a turn that only emits a
tool_useblock).
CLI
Binary name: llmoxide (package llmoxide-cli).
Examples (-a Anthropic, -o OpenAI, -g Gemini, -l Ollama):
ANTHROPIC_API_KEY=...
ANTHROPIC_API_KEY=...
OPENAI_API_KEY=...
OPENAI_API_KEY=...
GEMINI_API_KEY=...
See llmoxide --help for stream, chat, models, and flags like --model and --ollama-host.
Live integration tests (local keys)
Opt-in network tests (#[ignore]). Use a local .env (see .env.example), then:
The second command exercises tool calling (add) against OpenAI, Anthropic, Gemini, and Ollama (set LLMOXIDE_TEST_OLLAMA=1 or OLLAMA_HOST for local Ollama; use a model that supports tools). It also runs live_openai_add_tool_stream and live_anthropic_add_tool_stream (run_with_tools_stream_text).