neutron product · PD003 · stage: implemented · 2026-08-05

Governed Workflows: visual automation where every node answers to the gate

A React-Flow canvas in the Neutron UI over the assay durable engine already shipping in every instance. The node palette is the capability registry — not a hand-built connector library — and every mutating step runs through the same approval gate as an agent turn.

stage implemented ux feedback addendum actioning → engine assay (bundled sidecar) editor React Flow, apps/ui home neutron core estimate ~20–30 agent sessions, 3 phases SaaS-safe owned IP, no license exposure
01 · Why, and why not n8n

The connector treadmill is already solved

02 · Placement

Core, not orbit

Workflows are durable server-side state — triggers, runs, approvals, audit — so they live in core, next to the gate and the registry. Orbit is a device client: it reaches the same workflows through the core API under the same RBAC, and a workflow step that must execute on a machine goes through orbit's existing exec-gate as a capability call. Where the canvas is shown is a UI/RBAC decision, never a second implementation.

03 · The surface

What a user sees

One new tab in the workspace: Workflows. Left rail lists the agent's granted capabilities — the palette is read straight from the registry, so anything an admin registers appears here with its gate policy already attached. The canvas shows the graph with live run state. The inspector is where governance becomes visible: selecting a gated node shows the policy chain and the approval that is blocking it.

step done waiting on approval not yet run
weekly-outreach-digest waiting on approval Runs Pause Run now

Palette · granted capabilities

mcp__gitlabmcp
mcp__stripegated
web_searchtool
search_docsrag
outreach.sendhard-gate
channels.posttool
agent turncore
approvalgate

Palette = capability registry. No workflow-specific connectors exist anywhere — register an MCP server, it becomes a node.

trigger · cron
Mon 09:00 Europe/Londonassay schedule
capability · mcp
mcp__gitlab__list_issueslabel = customer-signal auto · floor read
agent turn
Scout drafts the digestpersona: growth · effort: low headless turn
approval gate
Owner reviewrequester ≠ approver approver_roles: owner
capability · connector
outreach.sendallowlisted contacts only hard gate · config cannot waive
notify
post to #marketingthread: weekly digest

Inspector · approval gate

blockingoutreach.send
requesteragent: scout
approverrole: owner
waiting2h 14m
Approve Deny
policy chain
tool_policy— unset
approval_requiredoutreach ⇒ gate
mode defaultapproval-gated
auditop-hash recorded

Same durable approval row as a chat turn — the card also lands in the owner's inbox and on WhatsApp / Slack. Approving from any surface resumes the run.

04 · The fit

How it plugs into the existing core

Three flows, almost entirely through machinery that already ships. The build is the canvas, one route module, and a step executor — everything below the executor line is untouched.

ships today (repo path) new build approval semantics
Authoring & viewing
Workflows canvasapps/ui · React Flow
graph JSON
Workflow routesroutes/workflows.ts
CRUD
Postgresdelta migration NNNN
also authored by
Agentsgated workflow_upsert — models write the graph
Execution
Triggersassay cron · webhooks · channel events
fires
Step executorapps/api/src/workflows/
every step
Gateguardrails.ts · floor + tool_policy
allowed
Capability registrycapabilities/ · mcp | tool | skill
reaches
MCP ecosystemthe connector catalog — not ours to build
Governance & evidence
Durable approvalsauthz/approval-wait.ts
card lands in
Inbox + channelsconnectors/inbox.ts · Slack · WhatsApp
resolved by
Separation of dutiesneutron-authz · requester ≠ approver
recorded in
Audit + costauthz/audit.ts · providers/cost.ts

Agent-turn nodes reuse the engine seam (engine/index.ts) — a workflow step can be a headless Claude, Codex, or OpenCode turn with the same event stream and account-pool rotation as chat. Retries, resume, and schedule durability come from the assay sidecar the image already bundles: no second engine, no second credential store, no second cron. The non-escalation invariant holds for graphs — a workflow step has exactly the authority of the seat that owns it, same as a turn.

05 · A run, end to end

The governed path of one execution

Trigger fires. Assay cron (or webhook / channel event) wakes the run with a durable row — restart-safe from the first instant.assay sidecar · schedules/
Executor loads the graph and walks it step by step, persisting state per node.workflows/ · NEW
Gate check per step. Floor allowlist, tool_policy chain, hard gates — identical code path to an agent chat turn.guardrails.ts
Approval card lands in the owner's inbox, Slack, WhatsApp. Run parks durably; pods can restart while it waits.approval-wait.ts · inbox
Human resolves. Requester can't self-approve; owner-tier actions demand owner, not admin.neutron-authz
Step executes. Audit row with op-hash, cost attributed to the workflow's agent, canvas updates live.audit.ts · cost.ts
06 · Node types

Six node kinds, five of them existing machinery

NodeWhat it doesRuns on
TriggerCron, inbound webhook, channel event (message, reaction, intake label)assay cron + existing webhook routesexists
CapabilityOne gated call: MCP tool, CLI tool, or skill from the registrycapabilities/ + guardrails gateexists
Agent turnHeadless prompt to a named agent; output feeds the next nodeengine seam (claude / codex / opencode)exists
ApprovalExplicit human checkpoint with role-routed approverdurable approvals + inboxexists
NotifyPost to channel / thread / inbox cardchannels + realtime busexists
BranchCondition on a prior node's output (expression, no LLM)executor — plain codenew
07 · Data & API

Three tables, one route module

AdditionShapeNotes
workflowsid, name, graph JSONB, owner seat, enabled, versiondelta migration — self-applies at boot
workflow_runsid, workflow_id, trigger, status, started/endedparked | running | waiting_approval | done | failed
workflow_step_runsrun_id, node_id, status, input/output refs, approval_idjoins to the existing approvals + audit rows
routes/workflows.tsCRUD + run + runs list + SSE run eventsguarded by the standard fail-closed API guard
authoring toolworkflow_upsert exposed to agentshard-gated like agent-admin — humans approve the graph an agent proposes
08 · Vertical composition

The loop that makes verticals configuration, not code

Workflows are the last piece of a loop whose other three pieces exist. Developer, marketing, and ops verticals become pack + capability-set + workflow templates.

Admin agentagent-admin tier · opt-in
seats + personas
Packsinstallable org units
hands
Registry + vettingPD004 capability supply
process
Workflow graphworkflow_upsert · this PD
every step
Owner approvesone inbox

Depends on PD004 capability supply for curated tool sets and PD005 model routing for headless model/effort choice.

09 · Phases

Shippable slices

1 · Viewer

~3–5 sessions
  • Read-only canvas of existing assay workflows + schedules
  • Live run state overlay, run history list
  • Zero new execution surface — pure UI over what runs today
ship: workflows become visible

2 · Executor

~8–12 sessions
  • Graph-JSON definition + step executor, every node gated
  • Trigger wiring: cron, webhook, channel events
  • Durable runs: park on approval, resume across restarts
ship: workflows become a product

3 · Editor

~8–12 sessions
  • Drag-and-drop palette from the capability registry
  • Node config panels, validation, versioning
  • Agent authoring tool + “paste an n8n workflow” translation flow
ship: full visual autonomy, governed
10 · Non-goals

What this deliberately is not

No n8n runtime compatibility. Importing n8n JSON faithfully means reimplementing every node forever. Instead: the agent translates a pasted n8n workflow into native nodes from the user's granted capabilities — a one-time authoring task, and a SaaS onboarding weapon.
No hand-built connector library. The MCP ecosystem is the catalog; the registry, OAuth 2.1 stack, and vetting pipeline already exist to consume it.
No second execution engine. Embedding n8n is barred by license under SaaS; embedding Activepieces (MIT) stays the break-glass hedge only if customers demand a no-code catalog MCP can't cover.
No ungoverned lane. A workflow step has exactly the authority of the seat that owns it — the non-escalation invariant applies to graphs the same as turns.
11 · Acceptance

What proves it