uarp-sdk
Async Rust client for the UARP — Universal Agent Runtime Platform API.
Full coverage of all 557 endpoints, built on reqwest, serde and tokio.
[]
= "0.3"
= { = "1", = ["macros", "rt-multi-thread"] }
= "0.3" # only if you use streams
Rust 1.88+. TLS is rustls by default; features = ["native-tls"] switches.
Quick start
use CreateAgentRequest;
async
Getting a key. Sign in at https://snaga.ai and create one in your tenant's
settings. A key looks like uarp_<prefix>_<secret>; the secret half is shown
once and never again. With a key that carries tenants:write you can mint more
through POST /api/v1/tenants/me/keys. Give each one the narrowest set of
scopes that does its job.
Client is cheap to clone — every clone shares one connection pool. Resource
groups are accessor methods: client.agents(), client.runs(),
client.sessions(), … 43 in all, each in uarp_sdk::api.
Streaming
SSE endpoints return an EventStream, a futures::Stream that reconnects with
Last-Event-ID:
use StreamExt;
let runs = client.runs;
let params = Defaultdefault;
let mut events = pin!;
while let Some = events.next.await
Pagination
use StreamExt;
let agents = client.agents;
let params = ListAgentsParams ;
let mut all = pin!;
while let Some = all.next.await
list_all follows the cursor until the server reports no further pages, and
stops if a server ever repeats a cursor.
An empty page does not end the walk. This API applies the page limit before filtering, so a page can come back with no items and more behind it — reading one as the end of the collection is what made 0.2.0 report empty lists. Three empty pages in a row do stop it.
Errors
use ;
match client.agents.get.await
ApiError carries the status, the parsed problem document, the response
headers, and correlation_id() for support tickets.
Configuration
let client = builder
.api_key
.base_url
.timeout
.max_retries
.user_agent
.default_header?
.http_client // proxies, tracing, custom TLS
.build?;
Per-call overrides
Rust has no default arguments, so rather than an options parameter on all 557 methods the overrides ride on a cheap clone of the client — the connection pool is shared:
client.with_idempotency_key.agents.create.await?;
client.with_timeout.agents.get.await?;
client.with_max_retries.agents.get.await?;
client.with_header.agents.list.await?;
// Reconnection behaviour for an event stream:
let quiet = client.with_stream_options;
let mut events = pin!;
with_options(RequestOptions { .. }) sets several at once.
Retries. 408, 409, 429, 500, 502, 503 and 504, plus connection errors, retry with
full-jitter backoff (500 ms → 8 s) and honour Retry-After. Reads always
retry; writes only when they carry an idempotency key, which every mutating
/api/v1/* call sends automatically.
Escape hatch
let value: Value = client
.raw
.await?;
Notes
- Fields the spec marks
requiredare plain values; everything else isOption<T>. Unknown response fields are ignored, except on models that declareadditionalProperties, which keep them inextra. - Enums are real enums with an
Other(String)catch-all, so a value the server adds later round-trips unchanged.as_str(),DisplayandFrom<&str>are provided. - The three
oneOfbodies in the spec are exposed asserde_json::Value. - Timestamps are
String(ISO-8601); the crate does not pull in a date library.
Development
Files under src/generated/ come from generator/ in the repository root;
edit the emitter, not the output.