The API is workflows

Flowdrome’s AI integration isn’t a sidecar service bolted onto the product — it is built out of the product. The MCP endpoint and the Authoring REST API are implemented as two workflows you can open in the Studio and read, node by node:

AI client ──HTTP──▶ /mcp (transport only) ──▶ "MCP Server" workflow
AI client ──stdio─▶ relay (transport only) ──┘        │  svc:authoring-api/…
                                             "Authoring API" workflow
                                                      │  platform SDK

                                                  the Nucleus

MCP Server implements the Model Context Protocol as a graph: a routed HTTP trigger takes the JSON-RPC POST, a parse node validates the envelope (notifications → 202, garbage → 400), a Switch fans out on the method (initialize / tools/list / ping / tools/call), a second Switch routes tools/call to one node per tool, and a shared finalize node shapes and truncates every reply. The tool catalog an AI sees when it calls tools/list is served by a node in that graph.

Authoring API implements the tools’ behavior: one routed trigger serving ten endpoints with bearer auth on the trigger, one script branch per route speaking the platform SDK, and a graph path for every status — bad token exits the unauthorized port into a 401 response node, an invalid graph exits into a 422 with coded issues, a stale baseVersion into a 409.

The layers outside the canvas contain no protocol knowledge: /mcp forwards each message verbatim to the MCP Server workflow, and the stdio relay pipes lines to /mcp. Both workflows are seeded automatically on a fresh Nucleus, so all of this works out of the box.

The svc: URL scheme

The MCP Server’s tool nodes call the Authoring API the way any workflow calls another first-class service workflow — with a svc: URL:

svc:authoring-api/catalog
svc:authoring-api/workflows/wf_123

svc:name/path routes to /api/svc/{slug} on the Nucleus, where slug is the target workflow’s name lowercased and dashed (Authoring APIauthoring-api). It is the production-grade sibling of the mock: scheme: same mechanics — a workflow answers the HTTP request — but named for what it is. Anything a node can do with a URL (HTTP Request, integrations, script fetch) understands both.

Same trust model as mocks: the engine’s own workers reach /api/svc freely on loopback; remote callers need a Nucleus token with Run capability.

Locked workflows

Both service workflows ship with "locked": true in their document — a flag any workflow can carry:

  • View-only everywhere. The Studio opens a locked workflow read-only: the canvas is inspectable but inert (no dragging, wiring, deleting, or config edits), with a Locked — view only badge. The server backstops the UI: any document write or delete answers 423 Locked — that covers REST, the SDK, and AI agents alike.
  • Unlocking is a deliberate act. The only mutation a locked workflow accepts is PUT /api/workflows/{id}/locked with { "locked": false }, and it requires Manage capability — editing stays a separate, lesser permission.
  • It travels with the document. locked is a top-level field of flowdrome.workflow.v1, so it survives export/import and ships inside the auto-seeded system workflows.

Lock your own workflows the same way — a production flow nobody should touch, a template you hand to a team, or anything an agent builds that you want frozen after review.

Why build it this way?

Three reasons, in increasing order of importance:

  1. Transparency. There is no hidden middleware to trust — the entire API surface is readable on a canvas, and its error paths are wires you can follow.
  2. One engine. The API benefits from everything workflows get for free: run history with full data capture, the debugger, versioning, the fleet. When an AI calls create_workflow, that call is itself a run you can open and single-step.
  3. Proof. If the platform’s own AI protocol server can be a workflow — JSON-RPC parsing, method dispatch, per-tool fan-out, response shaping — then the primitives (routed triggers, switches, script nodes, response nodes) are strong enough for whatever API you need to build on it.