Stuart LabsOpen sourceSpring 2026
AgenticNodes
A local graph editor and runtime for agent workflows. You wire model, tool and data nodes on a canvas, run the graph, and inspect every node and edge event in per-agent swimlanes.
- Role
- Sole developer
- Status
- Public repo, development paused
- Stack
- Python, FastAPI, React 19, TypeScript, Vite, React Flow, Server-Sent Events, MCP, Supabase, Cloudflare Tunnel
- Links
- Source on GitHub ↗

The one-line description I gave the repo is "Scratch but for AI Agents. Developer focused n8n with full end-to-end control." AgenticNodes (the studio inside is called Graph Agent Studio) is a local app where an agent is a graph. Nodes are model calls, tools, data steps and control flow, and edges decide what runs next. You build the graph on a canvas, press run, and watch each step happen live.
I built it alone. It started in March as a prototype inside my agent-spec repo, moved into its own repository on March 29, and took 61 commits there through May 14.
Where it came from
I design every agent against the same six-part spec: model, tool registry, control loop, state, memory and logging. I first wrote that spec as templates in a separate agent-spec repo in February, and AgenticNodes grew out of a graph-agent prototype there. The spec still shapes this repo, since each part has its own design doc in docs/.
In AgenticNodes the graph is the agent. The first graph completed an agentic task end to end on March 30. The example bundled with the runtime since its first commit is a tool-schema repair loop. A model proposes a tool payload, the tool validates it, and if validation fails a conditional edge routes the error back to a repair step, capped by a configurable repair limit. A failed validation becomes a result the graph can branch on, and the run keeps going.
How it is put together
The backend is a Python runtime behind a FastAPI API. The studio is React 19 with Vite and React Flow.
The runtime validates connections by node category (start, api, provider, tool, control flow, data, end) and never by vendor. A model node binds to a provider such as a mock, OpenAI, the Anthropic API, or a local Claude Code install that the runtime calls through the claude CLI. Swapping providers is a binding change, and the canvas doesn't move. A new node type is added only when execution semantics differ.
The control loop is plain on purpose. It starts at the declared start node, executes, records output and timing, then picks the next edge: a matching conditional edge first, otherwise a standard one. It stops when an output node finishes, a loop guard trips (visits per node, repair attempts, or an optional step cap), or an unrecoverable error occurs. Guards end the run with a structured terminal event, so a looping graph shows up in the log as a reason, not a stack trace.
Events as the source of truth
Every run emits a versioned event stream, and that one stream drives live streaming over Server-Sent Events, replay of past runs and the UI. Nodes never mutate shared state directly. They return results, and a reducer folds events into run state. That keeps the frontend and backend views of a run in sync, and a stored manifest plus its event log is enough to rebuild a past run.
The swimlane view is built directly on those events. A test_environment document groups several isolated agent graphs under one run, and each agent gets its own lane of event cards with inputs, payloads and errors.

From canvas to something that runs on its own
By late April I wanted graphs that fire without me pressing run, so start nodes now declare a trigger mode. Manual runs are immediate. Discord messages, cron schedules, inbound webhooks and Supabase row events are listeners kept alive by background services. Inbound webhooks need a public URL, so the studio manages a cloudflared tunnel that boots with the first active listener and stops with the last. Each fire becomes a child run, and child events are mirrored onto the listener session so they appear as their own lanes.
Around that core sit the pieces a real workflow needed. There is MCP server management (boot, stop, capability discovery, per-tool toggles). Graphs can iterate spreadsheet rows, branch on conditions and split work in parallel. A Python script node runs uploaded scripts in a subprocess with a 30-second default timeout and typed error codes. Run storage defaults to the local filesystem and can mirror to Supabase asynchronously in batches. An agents CLI launches and tails graphs headlessly, and a Mock Run swaps API-backed model providers for mocks so a graph can be tested without live model calls.
Building it with coding agents
I built AgenticNodes with Claude Code and Cursor in the loop, and I set the repo up for that. Most design docs have a paired Claude Code skill, and a written rule says a doc and its skill change in the same commit, so the guidance an agent loads stays in step with the spec. The backend has 34 test files covering execution, the event contract, MCP, triggers and storage.
Where it stands
Feature work paused in May. In October I removed personal example data and screenshots before leaving the repository public. Durable memory is still a placeholder interface behind a stable contract. That was a deliberate scoping call while I proved the execution model, and the contract means memory can be added later without changing the control loop.
Next
Build the Environment, Then Optimize the Harness →