A3S Flow
A3S Flow is an AI Native Workflow Engine and Rust SDK for work that must survive process restarts, delayed retries, timers, asynchronous messages, callbacks, and worker replacement. Every meaningful transition is appended to history. The engine projects state from that history and rejects replay drift instead of silently accepting a different decision. The same repository also maintains the reusable authoring package, React and Vue hooks, CLI, and coding-agent Skill that operate on Flow's versioned workflow document contract.
| When this happens | Flow keeps this durable |
|---|---|
| A process dies after a step completes | The committed output is replayed; completed work is not invoked again |
| A retry, timer, signal, or callback is not ready | The run suspends without retaining an in-memory stack or worker |
| A parent starts one or many child workflows | Child identities, policies, and terminal outcomes survive either cross-stream crash window |
| New workflow code rolls out | Runtime build IDs and immutable patch markers keep histories on compatible replay paths |
| Multiple workers append concurrently | Expected-sequence writes select one durable winner and reject stale decisions |
[!IMPORTANT] Flow owns workflow graph validation, append-only history, durable replay, and lifecycle state. The host owns node implementations, authorization, tenant policy, credentials, tool access, and logical idempotency for external side effects. A3S Cloud binds those product capabilities; it does not duplicate Flow's compiler or runtime.
Authoring components, hooks, CLI, and Skill
@a3s-lab/flow-ui is the reusable authoring package for Flow workflows. It
keeps the node catalog, editor components, framework hooks, command-line tools,
and agent instructions on the same manifest and graph contracts.
| Surface | Current contract |
|---|---|
| Playground | Integrated visual authoring route with a 35-node cross-border order fulfillment sample covering all 20 registry manifests, drag and drop, typed connections, A3S UI configuration forms, DAG compilation, and DSL inspection |
| Node catalog | 18 public manifests in six authoring groups, with fields, defaults, ports, runtime bindings, and durable node identity |
| React | Node preview and configuration components plus useA3SFlowNode for controlled-ready node state |
| Vue | A useA3SFlowNode composable over the same node object, defaults, and manifest registry |
| Custom nodes | Immutable host catalogs with A3S UI form rendering, exact executor capabilities, and a publication gate |
| CLI | a3s-flow nodes, node, new, sample, validate, compile, and digest, all with JSON output |
| Skill | An installable a3s-flow Skill that queries the CLI before creating, connecting, validating, or reviewing a workflow |
The Workflow Playground, React guide, Vue guide, custom node guide, CLI reference, and Skill guide document each surface. The complete node catalog and configuration reference live under Workflow nodes.
Quick start
Add Flow and an async runtime:
[]
= "=1.1.0"
= "0.1"
= "1"
= { = "1", = ["macros", "rt"] }
Keep deterministic workflow decisions separate from side-effecting steps:
use ;
use async_trait;
use json;
use Arc;
;
async
start_with_id() makes creation safe to retry when the run ID, workflow spec,
and input match. Authority drift returns a conflict. For a complete typed
example with two durable steps, run:
Execution model
One replay cycle has four explicit phases:
- Project the current
WorkflowRunSnapshotfrom immutable history. - Ask
FlowRuntimefor one deterministicRuntimeCommand. - Validate the command and append its events at an expected sequence.
- Replay, suspend on durable external state, or reach one terminal outcome.
That boundary produces concrete guarantees:
- A successful step becomes visible to workflow code only after
StepCompletedis durable. - Reusing an ID with different input, retry policy, deadline, signal name, callback token, or metadata fails as non-deterministic replay.
- Timers, delayed retries, signals, and hooks release compute while the run is suspended.
- Crash recovery reconstructs state from typed events rather than an in-memory stack.
The physical side-effect boundary is intentionally at least once. If a process dies after an external effect succeeds but before its output commits, the attempt is delivered again. Step implementations must use a stable idempotency key derived from workflow and step identity.
Capability map
The following contracts are implemented on the current main branch and backed
by runnable examples or integration tests.
| Area | Current contract | Evidence |
|---|---|---|
| Durable steps | Sequential steps, concurrent step batches, typed input/output helpers, stable IDs, progress, and child-operation references | sequential_steps, batch_steps |
| Retry policy | Immediate retry, fixed delay, and capped exponential backoff with deterministic full jitter; exhaustion can fail or return to workflow fallback logic | retry_backoff, recoverable_step_failure |
| Suspension | Durable timers, declared named signals, and token-routed hooks/callbacks resume without holding a worker | scheduler_worker, workflow_signals, hook_approval |
| Cancellation | Cleanup-aware cancellation enters Cancelling, replays stable cleanup steps, and records one typed terminal outcome; force cancellation remains explicit |
cancellation |
| Child workflows | First-class single children and bounded concurrent batches persist every child identity before execution and recover partial cross-stream progress | child_workflow, child_workflow_batch |
| Long histories | continue_as_new closes one stream and resumes from a fresh linked stream with the exact inherited workflow authority |
continue_as_new |
| Safe rollout | Exact runtime-build routing rejects incompatible workers before mutation; immutable patch markers preserve old and new replay branches | replay_safe_patch, rollout recipe |
| Persistence | In-memory and JSONL stores are built in; SQLite and PostgreSQL share the FlowEventStore contract and canonical A3S ORM migrations |
local_file_durability, sqlite_durability, postgres_durability |
| Dispatch | A3S Boot task management is recommended; embedded compatibility queues and FlowWorker remain available |
boot_task_policy, task_queue_durability |
| Observability | Post-commit observers, fan-out, an A3S Event bridge, and a repair-aware local JSONL audit sink mirror committed events without becoming state authority | observer_fanout, local_audit_log |
| Native TypeScript | Optional source compilation, artifact identity, dependency-manifest verification, and a versioned JSON invocation protocol; Rust remains the durable authority | native_ts_preflight, protocol guide |
Bounded retries
Retry policy is part of the replayed command. Exponential policies derive full jitter from immutable run, step, and attempt identity, so a restart cannot change the selected durable deadline:
use RetryPolicy;
use Duration;
let retry = exponential;
Ok
Bounded child fan-out
start_child_workflows() validates the entire batch, persists every generated
child run ID, then advances siblings concurrently. A batch contains at most
MAX_CHILD_WORKFLOW_BATCH_SIZE children (currently 64), and parent outcomes are
recorded in durable request order rather than completion order.
let children = items
.into_iter
.enumerate
.map
.collect;
Ok
Split larger fan-outs into stable windows and emit the next window only after
the current outcomes are durable. Single and batched children share the same
RequestCancellation and Abandon policies.
Workflow DAG
WorkflowDsl is the versioned portable document contract. Its executable
payload is a directed graph of nodes and edges. Flow validates structure and
derives a deterministic plan; the host binds each node's data.type to an
authorized executor.
Compile the same wire shape into a stable plan and semantic identity:
use WorkflowDag;
The compiler rejects duplicate IDs, missing endpoints, self-edges, cycles,
invalid cross-scope edges, and malformed iteration or loop containers. Unknown
fields round-trip, while layout, selection, and viewport do not affect the
execution digest. An empty canvas remains importable as a draft but cannot
produce an execution plan. See the runnable
workflow_dsl_import example.
Production operations
Persistence
All stores preserve the same event envelope and replay contract.
| Store | Best fit | Feature |
|---|---|---|
InMemoryEventStore |
Tests and ephemeral embedded work | Built in |
LocalFileEventStore |
Single-process JSONL durability | Built in |
SqliteEventStore |
Single-node durable applications | sqlite |
PostgresEventStore |
Multi-process workers sharing authoritative history | postgres |
SQLite and PostgreSQL use a3s-orm for typed access, checksummed migrations,
transactional appends, active-hook routing, scheduled-wakeup indexes, and
whole-history retention. Production PostgreSQL deployments run migration
authority separately, then admit serving workers only after verifying the
canonical migration ledger. See Upgrading to Flow 1.0.
Retention removes only complete eligible continuation/child components and
leaves checksum tombstones. Flow never compacts part of an event stream;
workflows use continue_as_new to bound replay history without rewriting the
source of truth.
Dispatch and optional features
| Feature | Adds |
|---|---|
native-ts (default) |
Native TypeScript compile and invocation adapter |
sqlite |
SQLite event history and retention |
postgres |
PostgreSQL history and compatibility task queue |
boot |
Recommended A3S Boot task-manager integration |
a3s-event |
Post-commit A3S Event sink |
BootFlowTaskManager owns processor registration, job state, retry/timeout
policy, stalled-job handling, logical deduplication, startup, and shutdown.
FlowWorker plus the in-memory, local-file, or PostgreSQL compatibility queues
remain available to embedded hosts.
Native TypeScript
NativeTsRuntime compiles TypeScript workflow and step source into a native
artifact and invokes it through a versioned JSON protocol. Artifact identity
binds source, compiler backend, working directory, protocol, OS, and
architecture. In strict compiler-manifest mode, Flow verifies the complete
dependency graph before and after atomic publication.
Install the compiler and provide Bun on PATH (or set A3S_FLOW_BUN):
TypeScript is an adapter, not a second SDK, event store, scheduler, or workflow lifecycle. Read the compiler and protocol contract.
Ownership boundary
| Flow owns | The host owns |
|---|---|
| Workflow document/graph parsing, structural invariants, deterministic plans, and semantic digests | Node semantics, capability bindings, credentials, and authoring policy |
| Reusable node manifests, configuration components, React and Vue hooks, CLI commands, and the workflow-authoring Skill | Product-specific node availability, identity, authorization, publication, and hosted editor behavior |
| Append-only run history and expected-sequence writes | Product authorization, tenancy, and publication lifecycle |
| Replay validation and terminal state | Logical idempotency for physical side effects |
| Step, retry, wait, signal, hook, child-workflow, cancellation, and continuation lifecycles | Which tools and external systems a step may call |
| Runtime-build admission, patch markers, scheduling, stores, workers, and observer contracts | Deployment policy, compatible-build declarations, and telemetry destinations |
This split keeps Flow reusable as the sole durable orchestration authority without turning the SDK into a hosted product control plane.
Examples and guides
Start with one executable path, then move to the concern you need.
| Goal | Example or guide |
|---|---|
| First durable workflow | sequential_steps |
| Concurrent durable steps | batch_steps |
| Fixed/exponential retry and fallback | retry_backoff, recoverable_step_failure |
| Compensation | compensation |
| Timers, signals, and approval callbacks | scheduler_worker, workflow_signals, hook_approval |
| Cleanup-aware cancellation | cancellation |
| Single and batched child workflows | child_workflow, child_workflow_batch |
| Replay-safe code changes | replay_safe_patch |
| Local and shared durability | local_file_durability, sqlite_durability, postgres_durability |
| Native TypeScript | native_ts_preflight, native_ts_greeting |
| Workflow definition import | workflow_dsl_import |
| Reference | What it owns |
|---|---|
| Documentation website | Guided setup, execution concepts, production operations, runtimes, examples, and API map |
| Architecture | Event sourcing, replay, store, scheduler, and native-runtime boundaries |
| Cookbook | Stable IDs, retries, batches, timers, hooks, signals, cancellation, and compensation |
| Functional plan | Capability-level evidence, completion gates, maintenance work, and non-goals |
| API stability | SemVer, durable compatibility, MSRV, and the 1.0.0 release contract |
| Upgrading to Flow 1.0 | Supported pre-v1 histories/schemas, rollout, verification, and rollback |
| API docs | Public Rust types and methods |
| Security policy | Supported releases, trust boundaries, and private reporting |
Development
Run checks from this crate, not from the A3S monorepo root:
RUSTDOCFLAGS="-D warnings"
Rust 1.88 is the minimum supported Rust version. Repository recipes provide the deeper matrices:
A3S_FLOW_POSTGRES_URL=postgres://user:pass@localhost:5432/a3s_flow \
A3S_FLOW_NATIVE_TS_COMPILER=/path/to/a3s-flow-native-compiler \
CI also checks public API compatibility, the feature matrix, a real PostgreSQL gate, package contents, and an end-to-end Bun workflow on Linux and Windows.
Release status
The crate currently declares version 1.1.0. This compatible minor release
adds bounded concurrent child-workflow batches, bounded exponential retries,
and hardened custom workflow-node authoring while preserving the Flow 1.x
runtime, replay, and persistence contracts.
Reusable workflow-authoring components, React and Vue hooks, the CLI, and the Skill are maintained in this repository. Hosted tenancy, authorization, product-specific capability binding, deployment policy, and the multi-tenant control plane remain outside the Rust crate; A3S Cloud owns those product surfaces.
Maintenance is contract-led: preserve SemVer and replay compatibility, keep SQLite/PostgreSQL parity gates aligned, track the native compiler protocol and supported targets, and add adapters only for concrete deployments. The functional plan is the source of truth for capability evidence and release gates.
License
MIT © A3S Lab