FlowAgent-Studio
A low-code studio for composing AI workflows: drag nodes onto a canvas, wire them into an agent pipeline, and run it with streaming output and inspectable state.
The problem#
Wiring an LLM pipeline in code is fine until someone non-technical wants to change it. FlowAgent-Studio is a visual environment where a workflow is a graph: prompt nodes, tool calls, retrieval steps, condition branches and loops — connected on a canvas, executed by an engine, with every intermediate value inspectable.
The architecture in one paragraph#
The canvas produces a declarative graph (nodes + typed edges). A separate execution engine topologically sorts the graph, runs each node with a resumable executor, and streams events (node started, token, node finished, error) over SSE to the UI. Because the graph is pure data, the same workflow can run headless from a CLI — the canvas is just one client.
type WorkflowNode = {
id: string;
kind: "prompt" | "retrieval" | "tool" | "branch" | "loop";
config: Record<string, unknown>;
inputs: EdgeRef[];
};
// The engine never touches React. Events flow out; UI is a subscriber.
engine.run(workflow).on("node:finished", (event) => {
timeline.record(event.nodeId, event.output);
});Decisions worth writing down#
- Graph-as-data, engine-as-library. UI state and workflow state are fully separate, which made testing the engine trivial and kept the canvas swappable.
- Every node is inspectable. Clicking a node mid-run shows its exact input, raw output and timing — the difference between "it works" and "I can debug it".
- Typed edges. A retrieval node exposes ranked documents; a prompt node accepts them; the editor refuses to connect incompatible ports. Types catch most user error before execution does.
- Streaming everything. Users watch tokens arrive node by node. Latency feels halved even though it isn't.
Hard parts#
Partial failure. A tool node timing out mid-graph shouldn't nuke a 20-step run. Each node returns a result-or-error value, and branch nodes can route on failure — so retries and fallbacks are visible in the graph instead of buried in code.
Loops with state. Iterative agents need accumulators. I modelled loop state as an explicit edge input, which forced the semantics to stay simple: what flows in, flows back.
What I learned#
Visual programming lives or dies on error affordances. A stack trace is useless to a canvas user; highlighting the exact node and surfacing its message next to it is the whole game.