Blitflow
TypeScript SDK

Building workflows

Author workflow definitions dynamically — the draft builder and graph conversion.

Beyond referencing workflows published from the Studio editor, you can build definitions dynamically in code and run them inline. Two tools help, both producing a plain Workflow object.

The draft builder

createWorkflow() gives you an imperative builder with connection-type checking and validation:

import { BlitClient, createWorkflow, getNode, run } from "@blitflow/sdk";

const client = new BlitClient({ apiKey: process.env.BLITFLOW_TOKEN });
const draft = createWorkflow(client);

// declare workflow inputs (returns a ref string like "${prompt.value}")
const promptRef = draft.addInput("prompt", "TEXT");

// add nodes by spec id, wiring inputs to refs or literals
const gen = draft.addNode("rd-fast", {
  prompt: promptRef,
  removeBg: true,
  seed: 7,
});

// or connect ports explicitly — returns { ok, reason? } on type mismatch
// draft.connect(gen.id, "image", upscale.id, "init");

// expose outputs
draft.addOutput("sprite", `\${${gen.id}.image}`);

// validate before running
const problems = draft.validate();
if (problems.length > 0)
  throw new Error(problems.map((p) => p.message).join("\n"));

const workflow = draft.toWorkflow();
const outputs = await run(client, workflow, {
  prompt: { kind: "text", value: "a brass key" },
});
MethodPurpose
addInput(name, connector)Add an input node; returns its ${name.value} ref
addNode(specId, inputs?)Add a node from the palette
connect(fromId, fromPort, toId, toPort)Wire an edge with connector-type checking
addOutput(name, ref)Add an output node exposing a result
validate()Returns a list of validation errors (empty = OK)
toWorkflow()Produce the final Workflow JSON

Fetch node specs first (getNode / searchNodes) so you wire real port names and valid enum values — see Nodes & specs.

graphToWorkflow() — convert a visual graph

If your application maintains its own node-and-edge graph model (like the Studio editor does), graphToWorkflow() converts it into a definition. It is spec-aware: it resolves port types, turns exposed ports into input nodes, and materializes primitives as input or const nodes.

import { graphToWorkflow } from "@blitflow/sdk";

const workflow = graphToWorkflow({
  nodes: [
    {
      id: "n1",
      specId: "rd-fast",
      values: { seed: 7 },
      exposed: ["prompt"],
    },
  ],
  edges: [
    // { source: "n1", sourceHandle: "image", target: "n2", targetHandle: "init" }
  ],
  specsById, // Record<string, NodeSpec> — from searchNodes()/getNode()
  outputNodes: [{ id: "out1", label: "sprite" }],
  primitives: [],
});
ArgumentDescription
nodesGraph nodes: specId, inline socket values, and exposed input ports (become workflow inputs)
edgesConnections: source/sourceHandletarget/targetHandle
specsByIdNode specs used to resolve port types
outputNodesOutput sinks — each label becomes a workflow output name
primitivesConstants and workflow-input placeholders feeding the graph

Publishing

Programmatically built workflows are best run inline — pass the object straight to run() / POST /v1/runs. Publishing versioned workflows (and rolling back @latest) happens in the Studio; publish there when you want a stable <id>@<version> ref for other systems to consume.

On this page