Skip to main content

Getting Started

import 'package:stem/stem.dart';

final workflow = HostedWorkflow<String, String>(
name: 'welcome',
run: (context, name) async {
final cleaned = await context.step('normalize', () => name.trim());
return 'Welcome, $cleaned!';
},
);

Future<void> main() async {
final host = await WorkflowHost.inMemory(workflows: [workflow]);
try {
final run = await host.submit(workflow, 'Ada');
print(await run.result);
} finally {
await host.close();
}
}

inMemory creates, starts, and owns the app. submit persists and enqueues one run; result observes it. Closing neither deletes nor cancels a run.

For production, use WorkflowHost.create with a persistent app factory. After a restart, re-register compatible definitions and reattach with host.observe(workflow, savedRunId); this does not submit another execution. recover(limit: 100) re-enqueues a bounded batch of runnable runs, and duplicate delivery remains possible.

context.sleep(name, duration) creates a durable timer checkpoint. context.awaitEvent(name, event) waits for a topic event emitted with host.emitEvent(...). Events are not run-addressed or buffered before a watcher exists. Task delivery, replay, and external effects are at least once; use idempotency keys.