01 — Your First Workflow
Build and run a single-task workflow embedded in your own process. The engine is identical in both languages; pick your tab.
A workflow named greeting with one task that writes a message into the
Context, executed by a
Runner against SQLite.
[dependencies]
cloacina = "0.7"
tokio = { version = "1", features = ["full"] }
serde_json = "1"
The backend is chosen at runtime from the database URL — no feature flags.
pip install cloaca # SQLite + PostgreSQL
Pre-built wheels for Linux and macOS on Python 3.9–3.12.
A Task is an async function with an id;
a Workflow names a set of tasks.
The #[workflow] module attribute names the workflow; #[task] functions inside
it are its tasks:
use cloacina::{task, workflow, Context, TaskError};
#[workflow(name = "greeting", description = "Say hello")]
pub mod greeting {
use super::*;
#[task]
pub async fn hello(ctx: &mut Context<serde_json::Value>) -> Result<(), TaskError> {
ctx.insert("message", serde_json::json!("Hello World!"))?;
Ok(())
}
}
The WorkflowBuilder context manager assembles @cloaca.task functions declared
inside it (registered automatically on exit):
import cloaca
with cloaca.WorkflowBuilder("greeting") as builder:
builder.description("Say hello")
@cloaca.task()
def hello(context):
context.set("message", "Hello World!")
return context
Create a Runner against SQLite and execute the workflow by name.
use cloacina::runner::{DefaultRunner, DefaultRunnerConfig};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let runner = DefaultRunner::with_config(
"sqlite://app.db?mode=rwc",
DefaultRunnerConfig::default(),
).await?;
let result = runner.execute("greeting", Context::new()).await?;
println!("status: {:?}", result.status);
println!("context: {:?}", result.final_context);
runner.shutdown().await?;
Ok(())
}
runner = cloaca.DefaultRunner("sqlite:///app.db")
result = runner.execute("greeting", cloaca.Context())
print("status:", result.status)
print("context:", result.final_context)
runner.shutdown()
You’ll see a completed status and the message value in the final context.
- A task is an async function with an
id; a workflow names a set of tasks. - A runner executes a workflow against a database (SQLite here) and persists state — so execution survives restarts.
- 02 — Passing data with Context
- Reference: Workflow · Task · Context · Runner