agentix
Multi-provider LLM client for Rust: streaming, non-streaming, tool calls, agent loops, MCP tools, structured output, multimodal input, and reasoning state round-trip.
DeepSeek, OpenAI, Anthropic, Gemini, Kimi, GLM, MiniMax, Mimo, Grok, and
OpenRouter all use the same Request API.
Quick Start
use ;
use StreamExt;
async
For one-shot requests:
let http = new;
let response = openai
.user
.complete
.await?;
println!;
Installation
[]
= "0.22.0"
Optional features:
# MCP client tools
= { = "0.22.0", = ["mcp"] }
# Expose local tools as an MCP server
= { = "0.22.0", = ["mcp-server"] }
# Use the local `claude -p` CLI as Provider::ClaudeCode
= { = "0.22.0", = ["claude-code"] }
# Compile-time gate for full request/response body logging
= { = "0.22.0", = ["sensitive-logs"] }
Design
Request is a value type. It contains provider, credentials, model, messages,
tools, and tuning knobs. Call stream() or complete() with a shared
reqwest::Client.
Agents are streams too. agent() emits token-level AgentEvents across a full
LLM/tool loop; agent_turns() emits one CompleteResponse per LLM turn.
use ;
let text = agent_turns
.last_content
.await;
Concurrency and pipelines are ordinary Rust:
use join_all;
let answers = join_all
.await;
Comparison
This is a positioning snapshot, not a benchmark. External frameworks move quickly; the agentix column tracks this repository's current behavior.
| agentix | rig | llm-chain | LangGraph | |
|---|---|---|---|---|
| Primary language | Rust | Rust | Rust | Python / JavaScript |
| Core abstraction | Request values and streams |
Agents, providers, embeddings, vector stores | Chains / prompts | Stateful graph runtime |
| Agent loop | Built in: agent() / agent_turns() |
Built in agent APIs | Manual / chain-oriented | Built in graph execution |
| Streaming text | Yes: LlmEvent::Token |
Yes | Limited / provider-dependent | Yes |
| Streaming tool calls | Yes: chunks + completed calls | Provider/API-dependent | Limited | Yes, through LangGraph stream modes |
| Streaming tool progress | Yes: ToolOutput::Progress -> AgentEvent::ToolProgress |
Custom app logic | Custom app logic | Yes, custom stream updates |
| Tool definition style | #[tool] on functions or impl blocks |
Tool traits / derive macros | Chain/tool abstractions | LangChain tools or custom node logic |
| Tool grouping | ToolBundle, +, +=, -, -= |
Agent/tool composition | Chain composition | Graph nodes / tool nodes |
| Multimodal input | Text, images, documents where provider supports them | Provider-dependent | Provider-dependent | Provider-dependent via model integrations |
| Structured output | JSON object + JSON Schema where provider supports it | Supported patterns vary by provider | Provider-dependent | Via model/tool integrations |
| Reasoning controls | Cross-provider ReasoningEffort |
Provider-specific | Provider-specific | Provider/model-specific |
| Provider support | 10 HTTP providers + optional Claude Code CLI | Multiple native provider integrations | Older/smaller provider surface | Broad via LangChain ecosystem |
| MCP client tools | Optional mcp feature |
Not core | Not core | Via integrations / custom nodes |
| MCP server | Optional mcp-server feature |
Not core | Not core | Via integrations / deployment stack |
Why this table matters: agentix is intentionally not a graph framework. It keeps
provider calls, tool execution, and agent turns as regular Rust values and
streams, so complex workflows can be built with ordinary async, Stream, and
Future composition.
Providers
Ten HTTP providers are built in. Provider::ClaudeCode is also available behind
the claude-code feature.
| Provider | Constructor | Default model | Default base URL | Wire format |
|---|---|---|---|---|
| DeepSeek | Request::deepseek(key) |
deepseek-chat |
https://api.deepseek.com |
Chat Completions-compatible |
| OpenAI | Request::openai(key) |
gpt-4o |
https://api.openai.com/v1 |
Responses API |
| Anthropic | Request::anthropic(key) |
claude-sonnet-4-20250514 |
https://api.anthropic.com |
Messages API |
| Gemini | Request::gemini(key) |
gemini-2.0-flash |
https://generativelanguage.googleapis.com/v1beta |
Gemini API |
| Kimi | Request::kimi(key) |
kimi-k2.5 |
https://api.moonshot.cn/v1 |
Chat Completions-compatible |
| GLM | Request::glm(key) |
glm-5 |
https://open.bigmodel.cn/api/paas/v4 |
Chat Completions-compatible |
| MiniMax | Request::minimax(key) |
MiniMax-M2.7 |
https://api.minimaxi.com/anthropic |
Anthropic-compatible |
| Mimo | Request::mimo(key) |
mimo-v2.5-pro |
https://api.xiaomimimo.com/anthropic |
Anthropic-compatible |
| Grok | Request::grok(key) |
grok-4 |
https://api.x.ai/v1 |
Chat Completions-compatible |
| OpenRouter | Request::openrouter(key) |
openrouter/auto |
https://openrouter.ai/api/v1 |
Chat Completions-compatible |
use ;
let req = new
.model
.user;
OpenAI is intentionally the official Responses API provider. For Azure, vLLM,
LocalAI, Ollama, llama.cpp server, or any endpoint that only speaks Chat
Completions, use Provider::OpenRouter with a custom base URL:
let req = openrouter
.base_url
.model;
Mimo uses the documented api-key: $MIMO_API_KEY authentication header.
Request API
use ;
let req = new
.model
.base_url
.system_prompt
.reminder
.max_tokens
.temperature
.reasoning_effort
.retries
.user
.tools;
Useful builder methods:
model,base_url,system_prompt,reminderuser,message,messagestoolsmax_tokens,temperature,reasoning_efforttext,json,json_schemaextra_bodyfor provider-specific top-level JSON fieldsretries(max, initial_delay_ms)
complete() returns CompleteResponse:
let response = req.complete.await?;
println!;
println!;
println!;
println!;
println!;
Streaming Events
LlmEvent is #[non_exhaustive]; include _ => {} in matches.
while let Some = stream.next.await
Provider-specific reasoning state is captured as AssistantState and attached
to Message::Assistant.provider_data by the agent loop. User code usually does
not need to inspect it.
Reasoning Control
ReasoningEffort is a single cross-provider knob:
use ;
let req = deepseek
.reasoning_effort
.user;
| Variant | DeepSeek | Anthropic-compatible | OpenAI Responses | Gemini 3+ | Gemini 2.5 | OpenRouter | Other chat providers |
|---|---|---|---|---|---|---|---|
None |
disable thinking | disable thinking | omit reasoning | minimal floor | budget 0 | none |
ignored |
Minimal |
high | low | minimal | minimal | 512 | minimal | ignored |
Low |
high | low | low | low | 1024 | low | ignored |
Medium |
high | medium | medium | medium | 4096 | medium | ignored |
High |
high | high | high | high | 8192 | high | ignored |
XHigh |
max | xhigh | xhigh | high | 16384 | xhigh | ignored |
Max |
max | max | high | high | 24576 | max | ignored |
| unset | provider default | provider default | omitted | omitted | omitted | omitted | omitted |
Notes:
ReasoningEffort::Noneis different from leaving the field unset.Noneexplicitly disables thinking where the provider supports that toggle.- DeepSeek drops sampling parameters such as
temperaturewhile thinking is enabled, because its API rejects that combination. - Thinking/tool-call state is automatically round-tripped for Anthropic-compatible providers, OpenAI Responses, Gemini, and OpenRouter.
Messages And Multimodal Input
User messages are Vec<Content>:
use ;
let req = anthropic.message;
Document support:
- Anthropic-compatible providers emit
documentblocks. - OpenAI Responses emits
input_file. - Gemini emits
inline_dataorfile_data. - OpenRouter emits file parts for providers/plugins that support them.
- DeepSeek, Grok, GLM, and Kimi silently drop document parts.
Images are supported by providers whose wire format accepts them. If a provider does not accept a content type, agentix drops or degrades the part rather than inventing an incompatible schema.
Tools
Use #[tool] on standalone functions or an impl agentix::Tool block.
Doc comments become tool and parameter descriptions.
use ;
/// Add two numbers.
/// a: first number
/// b: second number
async
;
let tools = default + add + Calculator;
Run a full agent loop:
use ;
use StreamExt;
let http = new;
let request = deepseek
.system_prompt;
let history = vec!;
let mut stream = agent;
while let Some = stream.next.await
Streaming tools can yield progress before their final result:
use ;
;
ToolBundle supports new, with, push, remove, +, +=, -, and -=.
MCP
MCP client tools require the mcp feature:
use ;
use Duration;
let playwright = stdio
.await?
.with_timeout
.with_output_limits;
let tools = default + playwright;
The mcp-server feature exposes local ToolBundles as MCP services. See
examples/06_mcp_server.rs.
Structured Output
For JSON object mode:
let response = openai
.system_prompt
.user
.json
.complete
.await?;
For JSON Schema mode:
use JsonSchema;
use Deserialize;
let schema = to_value?;
let response = openai
.system_prompt
.user
.json_schema
.complete
.await?;
let review: Review = response.json?;
Provider behavior:
- OpenAI Responses supports text, JSON object, and JSON Schema.
- Gemini supports JSON object and JSON Schema through generation config.
- DeepSeek degrades JSON Schema to JSON object with a warning.
- Grok, GLM, Kimi, and OpenRouter pass compatible
response_formatfields. - Anthropic-compatible providers ignore
response_format; use prompting or tools for strict structure.
See examples/08_structured_output.rs.
Claude Code
With the claude-code feature, Provider::ClaudeCode runs the local
claude -p CLI and lets agentix keep control of the LLM/tool loop. Auth comes
from the Claude CLI OAuth session.
= { = "0.22.0", = ["claude-code"] }
use ;
use StreamExt;
;
let http = new;
let request = claude_code
.model
.system_prompt;
let history = vec!;
let mut stream = agent;
while let Some = stream.next.await
See examples/10_claude_code.rs.
Sensitive Logging
Full request bodies, response bodies, streaming chunks, and MCP raw request bodies are sensitive and disabled by default. To enable them, opt in at compile time and runtime:
AGENTIX_LOG_BODIES=1
If either gate is missing, full bodies are not logged.
Examples
- 01_streaming.rs: streaming tokens
- 02_completion.rs: non-streaming completion
- 03_conversation.rs: conversation state
- 04_tools.rs: tool definitions
- 05_mcp_client.rs: MCP client tools
- 06_mcp_server.rs: MCP server
- 07_agent.rs: agent loop
- 08_structured_output.rs: JSON schema output
- 09_deep_research.rs: multi-step research flow
- 10_claude_code.rs: Claude Code provider
- 11_reasoning.rs: reasoning effort comparison
License
MIT OR Apache-2.0