Use popular coding agents from your Rust code.
Claude Code, OpenAI Codex, OpenCode, and any OpenAI-compatible model — Ollama, OpenRouter, vLLM, LM Studio, llama-server. Call them from your program instead of opening a terminal. You do not shell out, and you do not parse each agent's own output format. Every agent returns the same event stream.
cargo add agent-harness- No terminal. Run an agent from your code and read its output as typed events, not scraped text.
- Every agent looks the same. Text, reasoning, tool calls, plans, token
usage, and lifecycle all arrive as
RunEvent. - Swap agents without rewriting. Change the constructor. Your loop stays.
- A built-in agent for open models. The
openai-compatiblefeature is not a wrapper. It speaks the chat API and runs the tool loop in Rust. - Hand the agent your functions. A
ToolServerofHostTools lives in your process and is offered to the agent as an MCP server — no server binary, no port. Claude Code reaches it over its control protocol; the built-in agent dispatches to it directly. - Add your own agent. Implement
Harnessin your own crate and register it. No fork. - Discovery, not installation.
readiness()reports what is on the machine.install_hintsays where to get what is missing. This crate installs nothing.
Build an agent. Call run. Read events until the run exits.
(run hands back a receiver to loop over. start takes a callback instead —
reach for it when you are forwarding events straight onto a socket and an
intermediate hop would be waste. An adapter implements only start; every
harness gets run for free.)
use harness::{Claude, Harness, RunEvent, RunRequest};
let (_handle, events) = Claude::new().run(RunRequest {
run_id: "demo".into(),
prompt: "In one sentence, what is a Markdown heading?".into(),
..Default::default()
})?;
for event in events {
match event {
RunEvent::Text { delta, .. } => print!("{delta}"),
RunEvent::Exited { .. } => break,
_ => {}
}
}Name what you mean; the rest defaults — no working directory, RunMode::Ask
(answer only; Edit lets it write files), no resumed session, no attachments.
To use Codex, an ACP agent, or a local model, change the constructor. The loop does not change. There is a runnable example for each:
cargo run --example claude # Claude Code
cargo run --example codex # OpenAI Codex
cargo run --example acp --features acp # OpenCode
cargo run --example gemini --features acp # Gemini CLI
cargo run --example ollama --features openai-compatible # a local model
cargo run --example llama_cpp --features openai-compatible # llama-server
cargo run --example tool_call --features openai-compatible # tools, end to endFull documentation, features, and provider setup:
crates/agent-harness ·
docs.rs
| crate | what it is |
|---|---|
agent-harness |
the framework. Imported as harness. |
cli-stream |
a standalone subprocess engine. Spawns a CLI, streams stdout and stderr line by line, and cancels it. It knows nothing about agents. |
In active development. The API can still change. See CHANGELOG.md for breaking changes and how to migrate.
MIT or Apache-2.0, at your option.