# Durable Workflow Rust SDK
`durable-workflow` is the first-party Rust SDK for Durable Workflow workers
and clients. It can register workflow and activity handlers, long-poll the
worker protocol, start, signal, and query workflow executions, expose named
read-only query handlers, heartbeat workers and activities, and exchange
JSON-native payloads through the platform's generic Avro wrapper.
## Install
Add the exact crates.io release with Cargo:
```sh
cargo add durable-workflow@0.1.0 --exact
```
Or add the same exact requirement directly to `Cargo.toml`:
```toml
[dependencies]
durable-workflow = "=0.1.0"
```
Version `0.1.0` requires Rust `1.86` or newer. Query APIs described below are
available from the direct-successor `0.1.1` release.
## Compatibility
| `0.1.0` | `>=0.2,<0.3` | `1.2` | `2` |
| `0.1.1+` | `>=0.2,<0.3` | `1.2` (queries require `1.8`) | `2` |
The machine-readable values live in `[package.metadata.durable-workflow]` in
`Cargo.toml` as `supported-server-versions`, `worker-protocol-version`, and
`control-plane-version`. Query-capable releases also publish `query-tasks`,
`query-task-minimum-worker-protocol-version`, and `payload-codecs`. Existing
worker operations retain the `1.2` baseline; only query-task poll, complete,
and fail requests use the additive `1.8` feature floor. The server's advertised
protocol manifests remain authoritative when checking compatibility during
deployment.
## Worker
```rust
use durable_workflow::{json, Client, Result, Worker};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::builder("http://127.0.0.1:8080")
.token(std::env::var("DURABLE_WORKFLOW_TOKEN").ok())
.namespace("default")
.build()?;
let mut worker = Worker::new(client.clone(), "rust-workers");
worker.register_activity("hello.activity", |ctx, args| async move {
ctx.heartbeat(json!({"stage": "started"})).await?;
let name = args.first().and_then(|value| value.as_str()).unwrap_or("world");
Ok(json!(format!("hello, {name}")))
});
worker.register_workflow("hello.workflow", |ctx, _input| async move {
let signal = ctx.wait_signal("start").await?;
let name = signal.first().and_then(|value| value.as_str()).unwrap_or("world");
let greeting = ctx.activity("hello.activity", json!([name])).await?;
Ok(json!({"greeting": greeting}))
});
worker.register_query("hello.workflow", "started-by", |ctx, _args| async move {
let name = ctx
.signals("start")
.last()
.and_then(|args| args.first())
.cloned()
.unwrap_or(json!(null));
Ok(name)
});
worker.run().await
}
```
## Client
```rust
# use durable_workflow::{json, Client, Result};
# async fn example(client: Client) -> Result<()> {
let handle = client
.start_workflow("hello.workflow", "rust-workers", "hello-rust-1", json!([]))
.await?;
client
.signal_workflow(&handle.workflow_id, "start", json!(["Rust"]))
.await?;
let started_by = handle.query("started-by", json!([])).await?;
assert_eq!(started_by, json!("Rust"));
let output = handle.result(Default::default()).await?;
# println!("{output}");
# Ok(())
# }
```
## Queries
`Worker::register_query` associates a public query name with a workflow type.
The handler receives an immutable `QueryContext` containing the normalized
workflow input, committed history, and decoded signals in workflow order. It
has no command-emission API, and completing or failing a query task does not
append history or advance workflow execution.
Query handlers must remain read-only: do not mutate captured application state
or perform side effects. Rebuild the answer from the supplied snapshot. The
same handler serves running workflows and successfully completed workflows:
```rust
# use durable_workflow::{json, Client, Worker};
# fn configure(client: Client) {
let mut worker = Worker::new(client, "counter-workers");
`Client::heartbeat_activity_task` directly.
## Example
`examples/hello_world.rs` contains a complete round trip: it registers a Rust
worker, starts a workflow, sends a signal, runs an activity, heartbeats that
activity, exposes a named query, and waits for the completed result.
With a Durable Workflow server running locally:
```sh
DURABLE_WORKFLOW_SERVER_URL=http://127.0.0.1:8080 \
DURABLE_WORKFLOW_TOKEN=your-token \
cargo run --example hello_world
```
`TASK_QUEUE` optionally overrides the default `rust-workers` task queue.
## API documentation
The complete API reference is published at
[rust.durable-workflow.com](https://rust.durable-workflow.com/). Documentation
for `main` is rebuilt and deployed automatically.
## Ownership and versioning
The Durable Workflow project owns and maintains the crate. This repository is
the authoritative source for the `durable-workflow` crate and its Rust API
documentation.
Crate releases follow semantic versioning and are tagged with the exact crate
version, such as `0.1.1`. Rust SDK versions are independent from Durable
Workflow server image versions. A compatible server range is declared in
package metadata instead of coupling crate publication to a server release.