Skip to content

Sayiir — Fast, Simple Durable Workflow Engine

The fast, simple durable workflow engine. Graph-based, continuation-driven execution — just write normal Python, TypeScript, or Rust, with native WASM support for Cloudflare Workers and the edge. Native performance, automatic checkpointing, no infrastructure to deploy.

Zero Learning Curve

Clean, typed, idiomatic APIs in Python, TypeScript, and Rust. No DSL, no YAML — just familiar patterns.

Library Not Platform

pip install sayiir, pnpm add sayiir, or add a Cargo dep. No orchestrator to deploy.

Native Rust Performance

Rust core, no replay overhead. JSON by default, swap to zero-copy rkyv or any binary codec.

Built for the Edge

First-class Cloudflare Workers runtime. Checkpoint-and-exit across requests, D1 persistence, cron-driven resume — durable orchestration that fits short-lived runtimes.

Durable AI Agents

Long-running, retry-heavy, human-in-the-loop. Run RAG pipelines and agent loops that survive evictions, park on signals, and resume on cron.

Pluggable & Lightweight

Swap backends, codecs, runners. InMemory for tests, Postgres for production, D1 on the edge.

See it in action
from sayiir import task, Flow, run_workflow
@task
def fetch_user(user_id: int) -> dict:
return {"id": user_id, "name": "Alice"}
@task
def send_email(user: dict) -> str:
return f"Sent welcome to {user['name']}"
workflow = Flow("welcome").then(fetch_user).then(send_email).build()
result = run_workflow(workflow, 42)
import { task, flow, runWorkflow } from "sayiir";
const fetchUser = task("fetch-user", (userId: number) => {
return { id: userId, name: "Alice" };
});
const sendEmail = task("send-email", (user: { id: number; name: string }) => {
return `Sent welcome to ${user.name}`;
});
const workflow = flow<number>("welcome")
.then(fetchUser)
.then(sendEmail)
.build();
const result = await runWorkflow(workflow, 42);
use sayiir_runtime::prelude::*;
#[task(timeout = "30s", retries = 3)]
async fn fetch_user(id: u64) -> Result<User, BoxError> {
db.get_user(id).await
}
#[task]
async fn send_email(user: User) -> Result<(), BoxError> {
email_service.send_welcome(&user).await
}
let workflow = workflow! {
name: "welcome",
steps: [fetch_user, send_email]
}.unwrap();
import { task, flow, Engine } from "@sayiir/cloudflare";
const fetchUser = task("fetch-user", async (id: number) => {
const res = await fetch(`https://api.example.com/users/${id}`);
return res.json() as Promise<{ id: number; name: string }>;
});
const sendEmail = task("send-email", async (user: { id: number; name: string }) =>
`Sent welcome to ${user.name}`);
const onboarding = flow<number>("onboarding").then(fetchUser).then(sendEmail).build();
export default {
async fetch(request: Request, env: { DB: D1Database }): Promise<Response> {
const engine = await Engine.create(env.DB);
const instanceId = `onboard-${crypto.randomUUID()}`;
return Response.json(await engine.run(onboarding, instanceId, 42));
},
// Cron resume sweeps parked + evicted instances back to life
async scheduled(_e: ScheduledEvent, env: { DB: D1Database }): Promise<void> {
const engine = await Engine.create(env.DB);
await engine.resumeAll(onboarding);
},
};

Rust/WASM core, D1 persistence, signal/delay parking, cron-driven resume. No external orchestrator, no separate database.


Sayiir Server — Coming Soon

Same workflows, same code — plus a managed platform with a web dashboard, multi-tenancy, scheduled triggers, observability, and Kubernetes-native deployment. Learn more →