Flow
Design a workflow on a canvas a person and an agent share, then run that same graph in the browser, on Node, in PHP or in Python. One JSON document, one set of outputs, wherever it runs.
Pick an example and press Run. A User Input node opens a real form and waits for you; only the model and data calls are stubbed. Every canvas is documented with sticky notes.
Guarded. Same three workflows, same order. The only difference is that the guard, deals.has(41), is re-checked immediately before each one starts. Not at dispatch: the hazard is what changed in between.
- Enrich deal
Deal updated → Score & enrichwaitingNot run yet. - Archive deal
Deal updated → Archive + deletewaitingNot run yet. - Notify owner
Deal updated → Email the ownerwaitingNot run yet.
import { runCohort } from "@particle-academy/fancy-flow/engine";
await runCohort([enrich, archive, notify], executors, undefined, {
guard: () => deals.has(41), // re-checked before EACH workflow
reason: () => "deal #41 no longer exists", // recorded on the skipped result
});On a queue it is the same contract, made durable: FancyFlow::dispatchCohort() in fancy-flow-php enqueues only the head, hands the cohort on as each run settles, and records a skipped run's reason on the run itself. A run parked on a human approval holds the cohort until someone decides.
This is the real runCohort from @particle-academy/fancy-flow/engine, running in your browser over three real graphs. Fire it unguarded first: the interesting part is that nothing breaks.
One graph, run anywhere
The editor is where a graph is designed. Everything else is about where it runs, and who else can work on it.
A zero-React engine
@particle-academy/fancy-flow/engine runs a graph with no React, no DOM and no React Flow, on a server, a queue worker or a CLI. The editor is only for designing. The cohort demo above runs on it.
PHP and Python twins
fancy-flow-php and fancy-flow-py run the same WorkflowSchema v1 JSON with the same outputs, and refuse a document without version: 1 the same way. The PHP twin adds queued, durable runs that resume from a checkpoint.
A node marketplace, vendored
A marketplace node is source, not a package: npx fancy-cli@latest add node <kind> copies its editor kind and its JS and PHP backends into your project, so adding one adds no dependency.
A shuttle for AI, not an engine
Core declares a registerLlmClient contract and never imports a provider SDK. Opt-in adapters live on their own subpaths: ./llm/vercel-ai and ./llm/prism.
Cohorts and human pauses
runCohort re-checks a guard before each flow one trigger fires. A node waits for a person through the public pauseForHuman / decodePause contract, the same way the built-in approval and input nodes do.
Agents build on the same graph
The editor is controlled state, so registerFlowBridge lets an agent add, wire and run nodes on the canvas you see. On Laravel, fancy-flow-mcp builds workflows headlessly with deterministic, port-validated tools.
Read live from /r/nodes/index.json, the index the CLI installs from. The 31 core kinds ship inside fancy-flow 0.81.0 and are not listed: there is nothing to install.
In the editor
Notes on the canvas
A first-class note kind documents a flow in place. The engine skips notes, so their text never reaches a runner.
Swimlanes
Resizable lanes group the graph; drop a node in to file it. Lanes never execute, and edges cross them freely.
Undo, redo and staged deletes
Every committing edit is one reversible step (Ctrl+Z, Ctrl+Shift+Z). A confirmDelete hook lets a person approve what an agent removes.
Auto-layout
One click arranges the graph, or one lane's children, into a readable DAG with dagre, bundled and lazy-loaded.
Copy and paste subgraphs
Ctrl+C and Ctrl+V keep the wiring between the copied nodes intact; duplicate, align and distribute a selection.
Validated wiring
Drag an endpoint to rewire. A type-incompatible port pairing is refused by the same rule an agent's flow_connect obeys.
How it fits
The React package is the editor and the TypeScript engine; PHP and Python are runtime twins of that engine, and fancy-flow-mcp is a Laravel MCP server for building graphs without a canvas.
Human+ bridge
An agent drives this surface over MCP, through the same state a person sees, never the DOM.
import { registerFlowBridge } from "@particle-academy/agent-integrations/bridges/flow";tools: flow_*
Install
Install the runtime you need. Nodes from the marketplace are added with the CLI, never installed as a package.
npm install @particle-academy/fancy-flowcomposer require particle-academy/fancy-flow-phppip install fancy-flowcomposer require particle-academy/fancy-flow-mcp
The packages
Headless workflow engine + an optional React Flow editor — built-in trigger, logic, data, AI, human-in-the-loop and terminal nodes, a topological executor, and a FlowRunnerUx flow→UX bridge. The editor designs graphs; `/engine` runs them with zero React on a server, worker, or CLI (runtime twins: fancy-flow-php, fancy-flow-py).
PHP runtime for fancy-flow workflow graphs — the framework-free twin of @particle-academy/fancy-flow's engine. Same WorkflowSchema JSON in, same outputs out; author in <FlowEditor>, run on PHP. Adds a Laravel layer: queued durable runs with resume-from-checkpoint, human approval + user_input pauses, and an agent node. Headless; no UI.
Python runtime twin of the fancy-flow engine -- the same graph, the same node kinds, durable and queued runs. Pairs with fancy-flow (TS) and fancy-flow-php.
A Laravel MCP server that lets an agent build fancy-flow workflows HEADLESSLY -- list node kinds, add and connect nodes, configure them, validate and export a WorkflowSchema, without a canvas. Wraps fancy-flow-php, so the graph an agent composes here is the same document <FlowEditor> opens and the same one the PHP, TypeScript and Python runtimes execute.
Build your first flow
Start from the Workflow Studio starter kit, or read the fancy-flow docs for the editor, the engine and the node contract.
