Skip to content

The agent guide

SHEET
A5
REV
flowfig 0.8.4
DATE
2026-10-05

This page is the output of npx flowfig docs in flowfig 0.8.4. Your agent reads the same text.

flowfig draws animated flow figures. A figure has boxes, the edges between the boxes, and steps. In each step, a packet moves along the edges. The output is one animated SVG of 5 to 50 kB, with no script. The SVG plays in a GitHub README, in PR and issue comments, and in blog posts.

You write a JSON spec. You never write SVG by hand. npx flowfig checks the spec, renders it and prints the figure back.

flowfig draws how something works: parts, the messages between them, and the order of the messages.

  • An architecture, a data flow or a pipeline: the map of boxes and edges. Group parts by service, network or trust boundary.
  • A flowchart with branches: shape: "decision" for each branch, one step per path.

flowfig does not draw class or ER diagrams (fields, types, cardinality), charts of numbers or mind maps. If the user asks for one of these, say so and suggest Mermaid (classDiagram, erDiagram). Draw nothing with flowfig.

A topic gives the detail for one kind of figure. Before you write that kind of spec, print its topic with npx flowfig docs <topic>.

  • rail: a request lifecycle, a call chain or a Mermaid sequenceDiagram.
  • marks: a state lifecycle, a state machine or a Mermaid stateDiagram.
  • timeline: a roadmap, a plan with dates or a Mermaid gantt.
  • lanes: a process that several roles do (a ticket, an order, a refund), or an SOP.
  • verify: a verify finding in the render output, or a check in CI.

If the code has more than one flow, name each flow in the reply. Draw one flow or one structure view. For the whole system, draw one top view with groups, or a set of figures that covers every part. Keep each figure to 12 boxes or fewer.

Before the spec, list the facts that the figure must show. Use the code and its wiring (config, compose, route and queue files) or the pasted Mermaid. Give each fact its file:line:

  • every part (service, function, store, queue, external system);
  • every call, in order, as caller → callee: payload (file:line of the call);
  • every call that does not wait for an answer, and every consumer of each queue or topic;
  • every branch, every error path and every end state;
  • for an SOP, the facts in the lanes topic.

If the code does not show a fact, leave it out. Do not guess a part, a name or an order.

Each fact becomes a box, an edge, a beat, a data card or a show row. Write each text in plain words (see “Plain text”). Use real example data from the code or its tests.

Give each box and edge that draws code a source from the fact list: "src/auth/login.ts#verifyPassword". The code name goes in source, and the reader sees it on hover. A method uses Owner.name: "src/auth/session.ts#Session.refresh". An edge source names the function that makes the call. An edge needs no source when the code of its from box makes the call.

An edge across a process gets via: the name that both sides use in the code. The via is the queue or topic ("order-paid"), the HTTP path ("/internal/users"), or the store name of the caller ("sales_facts"). A store box (a table, a file, a cache key) may have no source. An edge to a store box still needs via. A route handler with no name keeps a file source. An edge into it uses via with the route path. An edge out of it in the same process uses no via.

Mark a hop that does not wait for an answer with "async": true. This rule covers every send to a queue or topic, every emitted event, and every call without await. A pasted Mermaid design wins over this rule: keep each arrow as the Mermaid draws it.

Run the render from the repo root.

npx flowfig - out.svg <<'SPEC'
{ "props": { "layout": ..., "edges": [...], "steps": [...] } }
SPEC

If the check finds an error, the render writes no SVG. The render prints the check lines. Next come one line per edge (from -> to: label) and one line per step (step "<label>": N hops). Last come the verify findings and counts. This output is the read-back: you need no other command.

Fix the figure and render again:

  • Compare the edge lines with the fact list. Each edge goes from the caller to the callee that its fact names.
  • Fix each verify finding. The verify topic explains each one.
  • Fix a layout fault in the layout first: rows, columns, around or a gap. Never remove a fact to pass the check.
  • small-text: the figure is too wide. Use two rows, more steps, or two figures. Do not change --width.
  • text-overflow: give the box a larger width, or move a detail to sub or say. Never cut a fact, a number or a unit: “within 30 days of delivery” does not become “within 30 days”.
  • plain-text: write the text again in plain words. The message names the reason. Keep a product name.
  • Fix every other warning, or tell the user why it stays. Never use --no-check to hide a fault.

If you can open a browser, take two screenshots of the SVG a few seconds apart. If the browser blocks file:// URLs, run python3 -m http.server. If you cannot open a browser, write “not looked at” in the reply. Never report a look that you did not do.

The reply has these parts, in this order:

  1. the path of each SVG;
  2. what each figure shows, with the counts and names copied from the figure:, edge and step lines;
  3. the flow you drew, why, and the other flows that exist;
  4. each fact that the figure leaves out, and why;
  5. the lines 0 errors, 0 warnings and figure: ..., copied as printed, and whether you looked at the SVG;
  6. the verify count line, copied as printed;
  7. at the end, one line npx flowfig open <path> for each SVG. Do not run it yourself.

To change an SVG later, print its spec with npx flowfig --spec out.svg.

props has layout (required), edges (required), steps, speed and theme. speed is the ms for a packet to cross one edge (default 900). theme sets accent, fg, muted, bg, surface, border and font. The topics give rail, lanes, timeline and today.

A layout group has children, and optional id (an edge target), label (a framed title), direction, gap (px), align. direction is "row" or "column". align is "start", "center" or "end". Every other layout item is a box.

A box has a unique id and a label (both required). Its optional fields are sub (a smaller line), shape, width (px), source, lines and tone. shape is "box", "decision" or "store". source is path#Owner.name, from the repo root. lines is the least lines of a content card. tone is blue, purple, green, orange, red or gray. The topics give at, from, to and mark.

An edge has from and to (a box or group id), and optional id (default from->to), label, source and via. around: "above" or "below" routes it over or under the boxes between. quiet: true draws it only while a step uses it.

A step has label and flow, and optional caption and nodes (boxes to highlight). flow is a list of beats. A beat is an edge id or an array of edge ids that run at the same time. A beat can also be { edges?, say?, show?, light?, ms? }.

  • edges: an edge id, a hop, or an array of these. A hop is { edge, back?, data?, tone?, async?, source?, via? }. back: true runs the packet from to to from. data is a card that moves with the packet. tone is green (success), orange (a retry), red (an error), gray (idle) or purple (async).
  • say: the caption for the beat. light: boxes to highlight. ms: the beat length.
  • show: { boxId: [{ tag?, tone?, text, meta?, mark?, mono? }] }. The rows fill the content card of each box until the step ends.
  • Use shape: "store" for data at rest and shape: "decision" for a branch.
  • Keep one main path, left to right. Put side parts in a column group.
  • A quiet: true edge needs a beat that uses it.
  • Keep an SVG to one or two steps: it loops with no controls. For tabs or pause, use the React player <Flow {...props} />.

The reader does not know the code.

  • A box label names the role in 1 to 4 plain words. Bad: "authRateLimiter". Good: "Rate limiter".
  • A sub line holds a short plain detail. Bad: "redis.incr()". Good: "5 tries a minute".
  • An edge label names the action or the data. Bad: "validateCredentials()". Good: "check password".
  • No code names in labels or sentences. The code name goes in source and shows on hover. Bad: “loginHandler calls findUserByEmail”. Good: “The API finds the user by email”.
  • A say line or a caption has 15 words or fewer, with the actor first. The check warns above 20 words. Bad: “A session is made after the password check”. Good: “The API makes a session”.
  • A step label has 1 to 4 words. The check skips this rule. Bad: “How a user logs in”. Good: “Log in”.
  • No filler words: seamless, robust, powerful, leverage, effortless. Bad: “seamless lookups”. Good: “cached lookups”.
  • Data shows real values from the code. The check skips this rule. Bad: "an error response". Good: "401 bad_credentials".
{
"props": {
"layout": {
"children": [
{ "id": "client", "label": "Browser" },
{ "id": "api", "label": "API Server" },
{ "id": "db", "label": "Database", "shape": "store" }
]
},
"edges": [
{ "id": "req", "from": "client", "to": "api", "label": "GET /users/42" },
{ "id": "q", "from": "api", "to": "db", "label": "read user" }
],
"steps": [
{
"label": "Read a user",
"flow": [
{ "edges": { "edge": "req", "data": "GET /users/42" }, "say": "The browser asks for user 42." },
{ "edges": "q", "show": { "db": [{ "tag": "row", "tone": "gray", "text": "Ada Lovelace" }] }, "say": "The API server reads the row." },
{ "edges": { "edge": "req", "back": true, "data": "200 OK" }, "say": "The API server sends the user." }
]
}
]
}
}
npx flowfig spec.json out.svg # render a spec file, or a .ts module whose default export is a spec
npx flowfig check <input> [--json] # list the faults of a spec or an SVG
npx flowfig --spec out.svg # print the spec that an SVG carries
npx flowfig gif out.svg [out.gif] # write an animated GIF (needs Chrome, Edge, Chromium or Brave)
npx flowfig docs [topic] # print this guide, or one topic

--strict makes warnings errors. --width sets the page width. --no-check skips the check.