Durable by default
Every step and decision is an immutable fact in an append-only log. State is fold(events) — never a mutable blob you hope stayed in sync.
Execution kernel for agentic applications
Loom treats an agentic workflow as a process that unfolds over time, not a request that returns once. Every decision is recorded as an immutable fact — so any execution can be paused for a human, resumed on another machine, replayed bit-for-bit for debugging, forked to explore alternatives, and evaluated against its own history.
Plain TypeScript. No DSL, no YAML, no state machines. Open source on GitHub; not on npm yet, so you build it from source.
No orchestration boilerplate. The gate is one await; its payload contract is
declared once and enforced before anything is written to the log.
import { flow$, step$, handler$ } from "@loom/core";
import { z } from "zod";
const assess = step$({
id: "assess",
inputSchema: z.object({ table: z.string() }),
outputSchema: z.object({ risk: z.enum(["low", "high"]) }),
handler: handler$(async (input) => rateMigration(input.table)),
});
const ApprovalDecision = z.object({ approved: z.boolean(), approvedBy: z.string() });
type ApprovalDecision = z.infer<typeof ApprovalDecision>;
const runner = async (ctx, input) => {
const { risk } = await ctx.run(assess, { table: input.table });
if (risk === "low") return apply(input.table);
// Durable checkpoint. The process can restart, redeploy, move machines —
// when the approval arrives, execution resumes from exactly here.
const decision = await ctx.suspend<ApprovalDecision>({
on: "ApprovalGranted",
correlationKey: input.table,
});
return decision.approved ? apply(input.table) : { applied: false };
};
export const migrationGuard = flow$({
id: "migration-guard",
version: "1.0.0",
steps: [assess],
// Parsed BEFORE the event is appended, so a malformed approval is refused
// rather than becoming a permanent part of the log.
resumeSchemas: { ApprovalGranted: ApprovalDecision },
}); Every step and decision is an immutable fact in an append-only log. State is fold(events) — never a mutable blob you hope stayed in sync.
One line parks an execution durably. It survives restarts, redeploys and machine moves, then resumes at exactly the same point — no state machine, no queue.
Re-fold any log and get identical state. Completed steps are served from the log, so effects never run twice. Debugging is time travel, not guesswork.
Branch an execution at a checkpoint, simulate several strategies in parallel, promote the winner. Git-style branching for running processes.
Flows read like async functions because they are. The intelligence is yours to write; Loom supplies the durable spine underneath it.
Storage, compute, LLM providers, protocols and renderers sit behind versioned SPIs with conformance kits. First- and third-party plugins wire identically.
Numbers are measured on committed benchmarks, not estimated — see the methodology and what they do not mean.
Scaffold an app, run it headless, suspend it for approval, resume it, then replay the log and watch it reproduce exactly.