pub struct Workflow {Show 17 fields
pub name: String,
pub version: u32,
pub priority: Priority,
pub unload: Unload,
pub durable: Option<bool>,
pub state: BTreeMap<String, StateDecl>,
pub description: Option<String>,
pub armed: bool,
pub inputs_schema: Option<Value>,
pub concurrency: Concurrency,
pub key: Option<String>,
pub tool: Option<WorkflowTool>,
pub limits: WorkflowLimits,
pub outputs_schema: Option<Value>,
pub steps: BTreeMap<String, Step>,
pub hash: String,
pub definition: Value,
}Expand description
A parsed, validated workflow.
Fields§
§name: String§version: u32§priority: PriorityScheduling weight under contention. low admissions shed one pressure
level EARLIER (at warn, not just shed),
and ready steps of higher-priority runs are scheduled first each tick.
It is a tiebreak under scarcity, not a reservation.
unload: UnloadRetirement policy for live runs (unload: {policy, timeout}).
durable: Option<bool>Durability class: Some(false) ⇒ runs of this workflow are memory-only
(no checkpoints, gone after a restart — the fast path for recomputable
work); Some(true) ⇒ durable even under store.durability.work: ephemeral. None in a freshly parsed document; the loader resolves it
against the store’s default before the definition is armed.
state: BTreeMap<String, StateDecl>Declared run variables: {key: {type, reducer}}.
Optional, and the point is to make concurrent writes a DECLARED policy instead of a heuristic. Without it the parser can only guess from the modes two racing writers happen to use; with it, the workflow states what a key is and how writes to it combine, and disagreement is a config error rather than a value that depends on completion order.
description: Option<String>§armed: bool§inputs_schema: Option<Value>§concurrency: Concurrency§key: Option<String>The logical thing a run is ABOUT, rendered from the trigger payload
("{{payload.account_id}}").
Everything else in the runtime is keyed — breakers, rate buckets, start
state, webhook dedup, step idempotency — but the run itself had no
logical name, only an id. That is why per-entity serialization was not
expressible: max_runs could count runs but not runs about the same
account.
tool: Option<WorkflowTool>Register this workflow in the tool registry as a first-class contract.
The shapes already match: a workflow carries a description, an input
schema, an output schema and a definition hash, which is exactly a tool
contract. What it adds over an MCP tool is everything the engine
already has — a “tool call” that takes thirty minutes, survives a
restart, and has retry, breaker, idempotency and a human gate INSIDE
it. And it is strictly better for the trifecta fold: a subagent handed
billing.refund spends its legs on one reviewed procedure instead of a
whole server’s tool surface.
limits: WorkflowLimits§outputs_schema: Option<Value>§steps: BTreeMap<String, Step>§hash: StringSHA-256 of the canonical definition. A run pins the hash it started
against, so a redefinition never changes the shape of work already in
flight, and workflow.list can show whether two instances agree.
definition: ValueThe definition as given (canonical JSON), for workflow.list/hash.
Implementations§
Source§impl Workflow
impl Workflow
pub fn start_steps(&self) -> Vec<&Step>
pub fn step(&self, id: &str) -> Option<&Step>
Sourcepub fn dependents(&self, id: &str) -> Vec<&Step>
pub fn dependents(&self, id: &str) -> Vec<&Step>
The steps that depend on id.
Sourcepub fn is_long_lived(&self) -> bool
pub fn is_long_lived(&self) -> bool
Whether any start node makes this workflow long-lived: one that keeps firing — a timer, a schedule, a subscription, an inbound signal, event, A2A message or stream — rather than running once and finishing.
This decides daemon shape. An instance holding a long-lived workflow must not idle-exit, because the workflow’s whole purpose is to still be there when its trigger arrives.
Sourcepub fn topo_order(&self) -> Vec<String>
pub fn topo_order(&self) -> Vec<String>
The step ids in a deterministic topological order (deps first).