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:
- 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 likea1b2c3oraa11bb. See./docs/reference/id-format.md. - Subflow node ID =
subflows/<id>.tsfilename, exactly. Both must be 6-hex. The Designer's "enter subflow" UX depends on the match. f.addDependency(namespace, version)is validated against the live package index.versionmust be concrete ('latest'is rejected) and must exist in the package's publishedversionslist.namespacemust exist inhttps://packages.robomotion.io/stable/index.json. Runrobomotion get packages <ns>orrobomotion describe package <ns>to resolve real versions before callingaddDependency. Never invent a version.- Terminal nodes (
Debug,Log,Stop,GoTo,End,WaitGroup.Done) have 0 outputs — wire TO them viaf.edge(), never.then()from them. - Every
Core.Flow.GoToreferences aCore.Flow.Labelid that exists in the same flow file. - A flow file is a declaration the Flow Designer can READ, not a program only Bun can run. The Designer parses
main.tsand eachsubflows/*.tsstatically, 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 literalf.node()/.then()/f.edge()written inside thecreatecallback (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-fileconsts with a template,+or[..].join('\n'); no spreads ({ ...SHARED }), no shorthand props, no imported helpers in afunc. A shared helper string is declared again in each file that uses it.robomotion validaterefuses the rest with "the Flow Designer cannot read it". Full table:./docs/reference/project-format.md. - 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
msgfor 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 withoutputs: 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 validaterefuses 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):