creating-flow

Installation
SKILL.md

Robomotion Flow Builder

Robomotion is an RPA platform with a TypeScript SDK and a visual node editor. This skill is a thin index over the reference docs in ./docs/. Read the relevant doc when a topic comes up — don't try to memorize it from this file.

Hard Rules (SDK rejects violations at validate time)

The SDK enforces these. Violations throw at robomotion validate / build with descriptive messages, so the agent never silently produces broken flows:

  1. Node IDs MUST be 6-char lowercase hex — /^[0-9a-f]{6}$/. f.node(), .then(), f.edge() reject non-hex IDs ('begin', 'label', 'maps', uppercase) at registration. Generate each id at random (openssl rand -hex 3); never copy an example id from these docs and never write a pattern like a1b2c3 or aa11bb. See ./docs/reference/id-format.md.
  2. Subflow node ID = subflows/<id>.ts filename, exactly. Both must be 6-hex. The Designer's "enter subflow" UX depends on the match.
  3. f.addDependency(namespace, version) is validated against the live package index. version must be concrete ('latest' is rejected) and must exist in the package's published versions list. namespace must exist in https://packages.robomotion.io/stable/index.json. Run robomotion get packages <ns> or robomotion describe package <ns> to resolve real versions before calling addDependency. Never invent a version.
  4. Terminal nodes (Debug, Log, Stop, GoTo, End, WaitGroup.Done) have 0 outputs — wire TO them via f.edge(), never .then() from them.
  5. Every Core.Flow.GoTo references a Core.Flow.Label id that exists in the same flow file.
  6. A flow file is a declaration the Flow Designer can READ, not a program only Bun can run. The Designer parses main.ts and each subflows/*.ts statically, one file at a time, draws what it understood, and regenerates the whole file from the canvas on every save - whatever it could not read is gone from git after the person's first save. So: the ONE import is @robomotion/sdk; every node is a literal f.node() / .then() / f.edge() written inside the create callback (no helper functions, no loops, no .map()); every prop is a literal, an array/object of literals, a scope helper over one, or a string built from same-file consts with a template, + or [..].join('\n'); no spreads ({ ...SHARED }), no shorthand props, no imported helpers in a func. A shared helper string is declared again in each file that uses it. robomotion validate refuses the rest with "the Flow Designer cannot read it". Full table: ./docs/reference/project-format.md.
  7. The program is the flow; a Function node is glue code, written only where necessary, and written for a person to read. We do write code, but only where a step needs it: a Function shapes msg for the next node. The work goes into nodes: SQL lives in the SQL node with {{{field}}} placeholders, never string-built in JavaScript; a rule the person would name is its own Function with outputs: 2; formatting is the screen's job; there is no helper library, and never one pasted into every node. The code is formatted: one statement per line, blocks on their own lines, indented, blank lines between parts. No line limit - a long Function that does one thing and reads top to bottom is fine. robomotion validate refuses crammed code ("several statements on one line", "a whole block on one line") and the same block opening three or more Functions. Where each urge belongs: ./docs/reference/function-nodes.md.

Required First Line

Every flow file (main.ts and every subflows/*.ts) starts with this exact import — copy verbatim, including helpers you don't currently use (Bun won't flag dead imports, but missing ones become runtime ReferenceError):

Installs
120
GitHub Stars
4
First Seen
Apr 16, 2026