pulse-client — Rust SDK for StreamFlow Pulse
Official Rust client for Pulse — the AI Agent Platform. Async-first, reqwest + serde stack, MSRV 1.82.
use PulseClient;
async
Install
[]
= "2.6.0"
= { = "1", = ["macros", "rt-multi-thread"] }
Requires Rust 1.82+ as a best-effort MSRV (declared in Cargo.toml). CI tests against stable only — the transitive dep graph (reqwest → hyper-util → tokio-rustls → base64ct → …) shifts its own floor frequently, so chasing an MSRV in CI produces flaky red builds for reasons unrelated to this code. If you hit a build error on a Rust older than stable, bump your toolchain.
Why pulse-client (Rust)
- Async-first — every method returns
Future. Drops naturally into tokio + axum + actix. - Three external deps —
reqwest(HTTP, the de facto standard) +serde+serde_json. No Hyper-direct fiddling, no custom transports. rustlsby default — no system OpenSSL dance. Cross-compile works out of the box.- Sibling parity — same surface + naming as the Python (
pulse-py), JavaScript (@olsisoft/pulse-client), Java (com.streamflow:pulse-client), and Go (github.com/olsisoft/pulse-go) SDKs. - Cheap to clone —
PulseClient: Clone, the underlyingreqwest::Clientpools connections, the token sits behindArc<RwLock>. Share a single instance across tasks. - Spec-aligned — every method corresponds 1:1 to an endpoint in the Pulse OpenAPI 3.1 spec. Drift caught at PR time by the in-tree spec invariant tests (B-103).
Quick start
use Duration;
use ;
async
Supported surfaces (v2.6.0)
| Resource | Methods | Notes |
|---|---|---|
client.auth() |
login(user, pass), refresh(refresh_token), organizations(), switch_org(org_id) |
Auto-caches JWT after login / refresh / switch_org. |
client.pipelines() |
list(), get(id), create(definition), delete(id) |
definition follows the CreatePipelineRequest schema. |
client.agents() |
list(), get(id) |
Read-only — agents are owned by pipelines. |
client.templates() |
list() |
The 223+ first-party templates. |
client.users() |
list() |
Requires USERS_LIST permission (Owner / Platform Admin personas). |
client.version() |
top-level | Public — no JWT required. |
Every method returns impl Future<Output = Result<Value, PulseError>>. Value is the re-exported serde_json::Value — full document, no schema-bound DTOs (yet). Schema-bound types land in v3.0.
Full ~112-endpoint surface documented in Swagger UI at <pulse-server>/api-docs. Less-used methods land opportunistically as user-facing demand surfaces.
Authentication
Three patterns:
// 1. Username + password (interactive / CLI tools)
let client = builder
.base_url
.build?;
client.auth.login.await?;
// 2. Pre-minted JWT (CI / service accounts)
let client = builder
.base_url
.token
.build?;
// 3. Hot token rotation (long-running daemons)
client.set_token;
client.clear_token; // log out
For long-running processes, persist refreshToken from login() and call client.auth().refresh(&refresh_token) before the JWT expires (default 1 h TTL).
Error handling
use PulseError;
match client.pipelines.get.await
Convenience predicates: err.is_auth_error(), is_not_found(), is_validation_error(), is_rate_limited(). Every error carries status_code(), path(), body().
Custom reqwest::Client (proxies, mTLS, shared pools, tracing)
let shared = builder
.timeout
.proxy
// .add_root_certificate(...) // for mTLS / internal CAs
.build?;
let client = builder
.base_url
.http_client
.build?;
Development
CI runs the same on every push touching pulse-rs/ — see .github/workflows/pulse-rs.yaml.
Roadmap
- v2.5.x — current async API, 5 core resources,
version(). - v2.6.x — expanded resource coverage: backups, schedules, credentials, settings, approvals, chat.
- v3.0 — schema-bound DTOs (typed structs instead of
serde_json::Value); event-stream consumer as aStream<Item = Event>consuming/api/pulse/events/stream(SSE). - B-098 satellite — once
olsisoft/pulse-rsexists, this in-tree code lifts out and publishes to crates.io.cargo add pulse-clientwill switch to the satellite; in-tree continues to mirror for one release cycle.
Track progress in docs/STREAMFLOW-BACKLOG.md under item B-098.
License
Apache 2.0 — same as the parent Pulse repository.