Skip to content
All projects
AgentsCore Developer2025

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.

TypeScriptLLMOrchestrationReactStreaming

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.