DocsSDK clients
SDK clients
Markdown ↗

Rust

On this pageAsyncBlockingTimeouts and private CAsInteractive approvalsFunctions in your applicationConversation sessionsProvider settings component

Typed clients for an authenticated AgenticDriver host: discovery, buffered runs, event streaming, scoped retrieval, ingestion and vector indexing/deletion. Requires Rust 1.89+ and, for the async interface, a Tokio runtime with I/O and time enabled. Canonical data, authorization and acceptance of draft artifacts stay with the application.

Optional detached jobs expose submit_job, read_job, cancel_job and job_events in both blocking and async clients, with public JobSubmit, JobInfo, JobState, JobIdentity, JobEventsRequest and JobEventPage types. Dropping an HTTP future does not cancel accepted background work; use cancel_job explicitly. Reconnect using next_cursor; event pages never execute application tools.

Install the published crate from crates.io. For the async client:

toml
[dependencies]
agenticdriver = { version = "=0.2.0-rc.2", default-features = false, features = ["async"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
FeaturesInterface
Default: async, blockingBoth client styles
async onlyAsyncAgenticClient, EventStream
blocking onlyAgenticClient (also blocking::AgenticClient)
No default featuresShared request, response, event and error types; no client constructors

Both transports use Rustls with certificate and hostname verification. Remote hosts require HTTPS; HTTP is allowed only for loopback. Redirects and automatic transport retries are disabled. A bearer token and an explicit provider/model selection are required. No provider fallback is performed.

Async

rust
#[cfg(feature = "async")]
async fn example() -> Result<(), Box<dyn std::error::Error>> {
use agenticdriver::{AsyncAgenticClient, EventPayload, RunRequest};

let client = AsyncAgenticClient::new(
    "https://driver.example", std::env::var("DRIVER_TOKEN")?,
)?;
let request = RunRequest::new("my-provider-instance", "my-model", "Summarize this context");
let mut stream = client.stream(&request).await?;
while let Some(event) = stream.next().await {
    let event = event?;
    match event.payload()? {
        EventPayload::TextDelta { text } => print!("{text}"),
        EventPayload::RunCompleted { result } => println!("\nRun: {}", result.run_id),
        EventPayload::RunFailed { error } | EventPayload::RunCancelled { error } => {
            return Err(agenticdriver::Error::Driver(error.clone()).into());
        }
        _ => {}
    }
}
Ok(())
}

run, protocol, providers, refresh_providers, ingest_context, index_context, search_context, and delete_context are async methods. run returns RunResult or an Error, including Error::Driver(DriverError) with an open-ended code, message, retryable flag and optional uncertain outcome.

stream().await returns an owned stream with next().await -> Option<Result<Event>>. Event::payload() provides a typed EventPayload enum for exhaustive handling with a wildcard for future additions. Envelope fields and the existing extra map remain available. A run.failed or run.cancelled event is returned once; the caller handles its typed error. Wire/transport errors return Err once. After any terminal event or error, next() returns None and the response is closed.

Dropping the stream or calling close() closes the HTTP response, which signals cancellation to the host. Dropping an in-flight run, stream, ingestion or retrieval future also closes that request. A polled next() future owns its response: cancelling it (for example, the losing branch in tokio::select!) closes the entire stream. Subsequent reads return None; this is not a resumable read timeout. An unpolled future has no effect. There is no background reader or per-stream worker thread. Reads apply backpressure, and independent streams may share a cloned client. Dropping a client does not close streams that have already been returned; the stream owns that responsibility.

Blocking

rust
#[cfg(feature = "blocking")]
fn example() -> Result<(), Box<dyn std::error::Error>> {
use agenticdriver::{AgenticClient, RunRequest};
let client = AgenticClient::new("http://127.0.0.1:7433", std::env::var("DRIVER_TOKEN")?)?;
let request = RunRequest::new("my-provider-instance", "my-model", "Hello");
let result = client.run(&request)?;
client.stream(&request, |event| {
    if let Some(text) = event.text { print!("{text}"); }
    true // Returning false cancels and closes the unfinished response.
})?;
Ok(())
}

Create, use and drop the blocking client outside an async runtime, or entirely inside tokio::task::spawn_blocking. The existing callback API is preserved: it visits failure/cancellation terminal events and then returns Error::Driver unless the callback returns false. A callback cannot interrupt a pending blocking network read; use the async interface for prompt external cancellation.

Timeouts and private CAs

Runs and context operations have no default total or read timeout. Optional RunRequest::idle_timeout_ms / IngestRequest::idle_timeout_ms is measured by the host against actual model/tool/context progress; protocol pings do not reset it. Omitting it adds no inactivity policy. The transport bounds connection setup to 10 seconds and discovery requests to 10 seconds; these are separate from run time.

For a private CA, call either client's with_ca_pem(url, token, Some(&pem_bytes)). This adds a trusted CA and preserves certificate and hostname checks. Never send provider API keys as driver bearer tokens. Keep the driver token in server-side configuration or the application's credential store.

npm run test:clients builds and installs the actual language packages, compiles examples and runs pure contracts. It does not simulate connections or model answers. Use real connection checks for provider execution.

Interactive approvals

Set request.approvals = Some(ApprovalPolicy::interactive(ApprovalIdlePolicy::Pause)) and consume a stream. Match EventPayload::ApprovalRequested { approval }, review its call, then use client.decide_approval(&approval.decision(ApprovalAction::Approve)) (await on the async client). Deny and Cancel are also explicit actions. Match ApprovalResolved for the outcome; keep consuming to the terminal run event.

The host must enable this feature and grant approveTools. run rejects interactive mode because it cannot deliver review requests. There is no default approval expiry; choose expiresAfterMs / the typed equivalent when needed. Decisions are single-use and are never retried automatically. A receipt does not confirm a tool effect. See the approval contract.

Functions in your application

Set RunRequest.application_tools to Vec<ApplicationToolDefinition> and select the same names in tools. Match EventPayload::ToolExecutionRequested { execution } to invoke your application's function. Use client.report_tool_progress(&execution.identity()) after real work and client.complete_tool(&execution.success(output)) to return a serde_json::Value once. Await both on the async client. execution.failure() sends the fixed public failure code without leaking private exception details.

Host opt-in and named token grants are required; review defaults to required. Dropping/cancelling the stream invalidates tickets. The application must also cancel its own work cooperatively; effects cannot be undone by a disconnect. There is no default inactivity deadline or automatic retry. See the full contract.

Conversation sessions

Create/read/delete methods and typed session models support explicit conversation continuation. Pass only the returned session ID and revision on each run, then use the next revision from the successful result. Provider/account/model changes require an explicitly created conversation with exported visible history. Host opt-in, account binding and per-operation token grants are required. Idle retention pauses during active work; no default execution deadline is introduced. See the session contract and binding examples.

Provider settings component

The provider and connection panel supplies provider/model settings, remote management and local/remote setup through the existing SDK client. TypeScript, Python, Go and Rust packages share the same embeddable browser component and provide native backend bindings. These additions are available on sdk-roadmap and are not in the published 0.1.0 packages.

Maintained with the AgenticDriver SDKSource snapshot ↗