Rust client for Driver.
cargo add crtrs-driveruse crtrs_driver::Driver;
let driver = Driver::from_env()?; // or Driver::new("dr_...")
let done = driver.run("what is https://creators.industries about?").await?;
println!("{}", done.and_then(|d| d.result).unwrap_or_default());Events: plan, plan_item_start, action, done, fatal. Nothing else is
surfaced — internal kinds, raw tool ids and raw error messages stay server-side.
Stream them as they land instead of waiting for the run to finish:
use futures_util::StreamExt;
let events = driver.stream("summarize https://example.com").await?;
futures_util::pin_mut!(events);
while let Some(ev) = events.next().await {
let ev = ev?;
println!("{} {:?}", ev.kind, ev.tool);
}run_with(prompt, opts, |ev| …) is the middle ground: a callback per event, the
final done event as the return.
Register local tools the agent can call. The agent runs in the cloud, but the tool runs on your machine — when the agent needs it, the client runs your function locally and sends the result back, then the run continues.
use crtrs_driver::{arg_str, define_tool, Driver, Param, ParamType};
use serde_json::json;
let weather = define_tool("get_weather")
.describe("Get the current weather for a city.")
.param(Param::new("city", ParamType::String).with_description("city name, e.g. 'Barcelona'"))
.param(Param::new("units", ParamType::String).optional())
.call(|args| {
let city = arg_str(&args, "city").unwrap_or_default();
Ok(json!({ "city": city, "temp": 24 }))
});
let driver = Driver::builder().tool(weather).build()?;
let done = driver.run("what should I wear in Barcelona today?").await?;Args arrive named, keyed by the param names you declared — read them with
arg_str / arg_u64 / arg_bool / arg_f64, or index args directly. call
is blocking and runs on a blocking thread, so it can do real work (disk,
network, a DB) without stalling the event stream. Implement the Tool trait
directly instead of define_tool for full control. See
examples/tool.rs.
let driver = Driver::builder()
.api_key("dr_...") // or DRIVER_API_KEY
.base_url("https://driver.tors.app") // or DRIVER_BASE_URL
.engine("claude") // openai | mistral | claude | openrouter
.model("claude-opus-5")
.engine_key("sk-...") // the engine's key, NOT the dr_ credential
.zdr(true) // zero data retention for every run
.build()?;Per-run overrides go through RunOptions: RunOptions::new().zdr(false) forces
a retained run on a zdr-by-default client, .tools([...]) swaps the tool list
for that call. run_zdr(prompt) is sugar for a single zero-retention run — the
cloud stores nothing the execution sees, so events stream here and die here. It
needs the account entitlement; without it the run fails with 403.
Requires an async runtime (the examples and tests use tokio).
MIT