Module 3: Exporting, Normalizing, and Structuring the Repository

6. Documenting a workflow for handoff

Description

By the end of this lesson you will be able to document an n8n workflow at the level a professional handoff demands: a per-workflow README with its purpose, its trigger, its dependencies, the credentials it requires, the variables it uses, and a diagram of its nodes. You'll know how to use sticky notes inside the canvas —the notes that travel within the workflow's own JSON— to leave explanations right where things happen, and you'll have a clear picture of the concrete standard job postings are chasing when they ask for "documentation good enough for another developer to pick up."

This matters because documentation is what turns your work into something transferable, and transferable is what the market pays for. A workflow only you understand is a risk for the company: if you leave, the knowledge leaves with you. A documented workflow is an asset: anyone on the team can pick it up, understand it, and maintain it. The "documented JSON" phrase in job postings points exactly at this, and of the two words, "documented" is the one most people neglect —the JSON comes out of the export, but the documentation is written by a person who decided it was worth the effort.

Connection to the module: lesson 5 built the repo's skeleton and reserved the docs/ folder. This lesson fills it. It's the second step of "organizing": lesson 5 said where each thing goes, this one says what each thing does. With the documentation in place, the cumbre-automations repository finally delivers on its full promise —versioned, secret-free, with clean diffs, structured, and documented— and it's ready for lesson 7 to automate its maintenance and lesson 8 to deliver it. After this lesson, order-triage isn't just a file: it's a file someone else can pick up.

Documenting means answering the questions of whoever arrives

Before writing a line of documentation, it's worth understanding what documenting well actually is, because it's easy to confuse it with "writing a lot." It isn't. Documenting well is anticipating the questions whoever picks up the workflow is going to ask, and answering them before they're asked.

Imagine a new teammate inherits order-triage tomorrow, with you unavailable. What are they going to wonder, and in what order?

  1. What does this exist for? Before looking at a single node, they need to know the purpose. Without that, everything else is noise with no frame.
  2. How does it turn on? Does it run on its own every hour, or when an order arrives, or when someone presses a button? The trigger defines when and why it runs.
  3. What does it need to work? What credentials, external services, and variables does it depend on? Without this, they import it and it doesn't start.
  4. What does it do, in order? The path through the nodes: what happens first, what next, where decisions get made.
  5. What can go wrong? The fragile points, the assumptions, what needs watching.

Documenting means answering these five questions in writing, so whoever arrives finds them already resolved. Not in the order they occur to you, but in the order someone else needs them: first the purpose, which gives the frame; then the trigger and dependencies, which place the workflow in its environment; then the flow; and finally the assumptions, which is the fine detail that only makes sense once you already understand the rest. That order isn't arbitrary: it's the path along which a person builds understanding, from general to specific. Notice that none of these get answered by looking at the JSON: the JSON says how the workflow is built, but not what for, nor what it assumes, nor what to watch. That layer of "why" is the one only a person can write, and it's what makes the difference between a file and a deliverable.

Think of it as the difference between an appliance with a manual and one without. Both work the same. But the one with a manual, anyone can use; the one without, only whoever built it, and only as long as they remember. Documentation is your workflow's manual.

And there's a reason this documentation lives in the same repository as the workflow, not in a loose document on some drive: documentation gets versioned with the logic. When you change order-triage and update its README in the same commit, Git's history keeps the two together, synchronized forever. Whoever looks at an old version of the workflow sees that version's documentation, not today's. A manual living outside the repo goes out of sync on day one; one living inside travels tied to the logic it describes. That's the whole point of "documented JSON": it isn't JSON and separately documentation, it's a repository where the two are one single versioned thing.

The per-workflow README

The concrete form of that documentation, in cumbre-automations, is a Markdown file per workflow inside docs/: docs/order-triage.md, docs/inventory-sync.md, and so on. Each one answers the five questions with a fixed structure, so they all read the same way and whoever knows one can navigate the rest.

These are the sections of a per-workflow README:

Purpose. One or two sentences: what business problem it solves. "Receives orders coming in through the store, classifies them by priority with an AI model, and enriches each one with the customer's CRM data, so the sales team handles urgent ones first." No technical detail yet; the what and the what for.

Trigger. What turns the workflow on. A Webhook (an external request arrives), a Schedule (every X time), a Manual Trigger (by hand). Include the detail someone else needs: if it's a Webhook, which path it listens on; if it's a Schedule, how often.

Dependencies. What it depends on to work: external services (the CRM, the AI model), other workflows if it calls them, special nodes. It's the map of "what else has to be alive for this to run."

Required credentials. The list of credentials, with their type and purpose —never their values, as lessons 3 and 5 hammered home. "Header Auth Cumbre CRM key to read the CRM; language-model credential Cumbre LLM key for the AI Agent." This tells whoever imports the workflow exactly which credentials to create on their instance.

Variables. The configuration values the workflow uses that can change between environments: thresholds, base URLs, queue names. It's the preview of Module 4, which formalizes how those variables differ between dev, staging, and prod.

Node diagram. A visual representation of the flow: which node goes to which. We'll look at it in detail in a moment, because there's a way to do it that looks good directly on GitHub.

Notes and assumptions. The fifth question —"what can go wrong?"—: the fragile points, what's assumed, what needs watching. "Assumes the order always brings customer_id; if it's missing, the CRM node fails." This is the section whoever inherits the workflow appreciates the most, because it's the knowledge that normally only lives in the author's head.

The node diagram: Mermaid and the ASCII fallback

A diagram is worth a thousand words when it comes to understanding a flow. There are two practical ways to include one in a Markdown file, and it's worth knowing both.

Mermaid is a language for describing diagrams with text, which GitHub (and many Markdown viewers) renders as a drawing automatically. The nice part is that the diagram is text —so it gets versioned, diffed, and edited like any other part of the repo— but it looks like a diagram when someone opens the file on GitHub. It's written inside a code block marked as mermaid:

```mermaid
flowchart LR
    A[Webhook: new order] --> B[AI Agent: classifies]
    B --> C[HTTP Request: queries CRM]
    C --> D[Set: builds response]
```

Let's break it down: flowchart LR says "a flowchart, left to right"; each line A[text] --> B[text] draws a box with that text and an arrow to the next one. The letters A, B, C are just internal names for connecting the boxes. When someone opens docs/order-triage.md on GitHub, they're going to see four boxes connected by arrows, not the code.

The ASCII fallback. Not every viewer renders Mermaid, so it's worth having a version that reads fine even if nothing renders: a diagram made of characters. It's more rustic but works anywhere:

Webhook ──► AI Agent ──► HTTP Request ──► Set
(new       (classifies)  (queries CRM)   (builds
 order)                                   response)

Which one should you use? For a repo on GitHub, Mermaid looks professional and stays easy to maintain. If you don't know where the documentation is going to be read, ASCII is bulletproof. Many teams put both: the Mermaid for whoever sees it rendered, and an ASCII line as a quick summary. Don't obsess over this; a simple, correct diagram beats an elaborate, outdated one.

Worked example: docs/order-triage.md

Let's put it all together in order-triage's real README. This is the complete file as it would live at docs/order-triage.md:

# order-triage

## Purpose
Receives orders coming in through the online store, classifies them by
priority with an AI model (urgent / normal / needs human review), and
enriches each one with the customer's data pulled from the CRM. The goal
is for the sales team to handle urgent ones first without manual review.

## Trigger
- **Type:** Webhook (POST)
- **Path:** `/new-order`
- **Fires:** every time the store triggers a new order.

## Dependencies
- **Cumbre CRM** (external service, via HTTP Request) — has to be
  reachable for the enrichment to work.
- **Language model** (via AI Agent node) — classifies the order.

## Required credentials
| Credential | Type | What for |
|---|---|---|
| Cumbre CRM key | Header Auth | Reading customer data in the CRM |
| Cumbre LLM key | (language model) | Classifying the order with the AI Agent |

> Real values are NOT in this repo. Create them on your instance; see
> `credentials/README.md`.

## Variables
| Variable | Example | What for |
|---|---|---|
| `CRM_BASE_URL` | `https://crm.cumbre.example` | CRM's base URL (changes per environment) |
| `PRIORITY_THRESHOLD` | `2000` | Amount above which an order is flagged urgent |

## Node diagram
```mermaid
flowchart LR
    A[Webhook: new order] --> B[AI Agent: classifies priority]
    B --> C[HTTP Request: queries CRM]
    C --> D[Set: builds enriched response]
```

## Notes and assumptions
- Assumes every order brings `customer_id`. If it's missing, the CRM node
  responds 404 and the workflow stops there. (Pending: handle that case.)
- The AI Agent's classification is a suggestion, not a final decision:
  the team can reassign priority by hand.
- The CRM has a request-per-minute limit; with very high order spikes,
  consider a wait node. Not yet a problem in production.

Look at what this document achieves. On one screen, someone who never saw order-triage before knows what it exists for, how it turns on, what it depends on, which credentials to create, which variables to adjust per environment, how it flows, and —most valuable— what it assumes and what to watch. They could pick up the workflow tomorrow. That's a handoff.

And notice what it doesn't have: it doesn't explain what a Webhook is or how an HTTP Request node works. Any n8n developer already knows that; documenting it would be noise. Good documentation assumes the trade's general knowledge and focuses on what's specific to this workflow. Over-documenting buries what matters under what's obvious.

Sticky notes: documentation that travels in the JSON

There's a second layer of documentation, complementary to the README, that lives inside the workflow itself: sticky notes.

A sticky note in n8n is a special node that does nothing during execution —it doesn't process data, it doesn't connect to the flow— and whose only job is showing text stuck to the canvas, like a post-it on a board. You add it from the node panel just like any other, write text (it supports Markdown), and place it next to the node or group of nodes you want to explain. You can change its color and size to group things visually.

Here's what makes them relevant to this module: a sticky note is a node, and nodes travel in the exported JSON. When you export order-triage, the note goes with it, as a node of type n8n-nodes-base.stickyNote with your text inside. That means it gets versioned on its own, with nothing extra from you, and it travels to any instance where you import the workflow. Whoever opens order-triage in the editor —not in the repo, in n8n itself— sees your explanations stuck right where they matter.

This solves a problem the README doesn't solve as well: proximity documentation. The README is great for the big picture, but when someone is looking at a specific node in the editor and wonders "why does this node have this odd configuration?", they're not going to go to the repo to look up the README. A sticky note next to the node answers right there, at the exact moment of doubt.

The rule for when to use which:

  • README (in docs/): the big picture, the purpose, the dependencies, the diagram. What someone reads before opening the workflow.
  • Sticky note (on the canvas): the pinpoint explanation of an odd node or group. What someone needs while looking at the workflow.

A good example of a sticky note in order-triage, stuck next to the HTTP Request node:

📌 This node queries the CRM with the order's customer_id.
If the order doesn't bring customer_id, the CRM responds 404 and the
workflow stops. Handling that case is pending.
Credential: Cumbre CRM key (Header Auth).

Notice this note repeats something that's also in the README —the customer_id assumption— and it's fine that it repeats it: the README says it for whoever reads the big picture, the note says it for whoever's standing in front of the node. The same information in both places someone might need it.

A pattern worth adopting is the header note: a large sticky note at the top left of the canvas, the first thing whoever opens the workflow sees, with the purpose in one sentence and a pointer to the full README. Something like:

📋 order-triage — classifies incoming orders and enriches them with CRM data.
Full documentation: docs/order-triage.md in the repo.

It's the editor's equivalent of the repo's cover: it orients in two seconds and points to the detailed documentation for whoever wants more. With that note, someone who opens the workflow in n8n without having seen the repo still knows what they're looking at and where to read more.

A security warning, because sticky notes travel in the JSON: never write a secret in a sticky note. Since it gets exported with the workflow, an API key written in a note would end up in the repo just as if you'd put it in a node. The note documents which credential is used and of what type, never its value. Lesson 3's rule never rests.

Two things almost everyone forgets to document

There are two pieces of documentation most people overlook, and in a workflow like order-triage, they're among the most important. It's worth treating them separately.

The input and output contract

A workflow with a Webhook receives data from outside. The question whoever inherits it is going to ask —and that neither the JSON nor the diagram answers— is: what exact shape does that data have to have? If the order has to bring customer_id and line_items, and someone sends one without customer_id, the workflow fails. Documenting the input contract means writing an example of the data the workflow expects:

## Input contract
The Webhook expects a POST shaped like this:

    {
      "order_id": "ORD-2041",
      "customer_id": "CUST-118",     // required; without this, the CRM fails
      "channel": "web",
      "line_items": [ ... ]
    }

With that, whoever connects a new source to the Webhook knows what to send without guessing or reading the workflow node by node. And along the way, you document the critical assumption —customer_id is required— right where it's understood why. The same applies to the output: if the workflow returns an enriched order with a priority field, show it, so whoever consumes that output knows what to expect.

What's specific to a workflow with AI

order-triage uses an AI Agent node, and AI nodes have their own documentation needs a regular workflow doesn't. Three things worth writing down:

  • Which model it uses and why. "Classifies with a language model via the Cumbre LLM key credential." If the model can change per environment —a cheaper one in dev, a better one in prod— say so; it's exactly the kind of thing Module 4 and Module 5 cover.
  • What it's asked to do (the instruction). The prompt or system instruction is workflow logic just as much as any node's configuration. Document what you're asking the model: "Classify the order as urgent, normal, or needs_review based on the amount and the customer's history." Without this, nobody understands why the model decides what it decides.
  • That the output isn't deterministic. This is the key warning, and the one that surprises people coming from regular workflows the most: an AI model can give different answers to the same input. An If node always decides the same way; an AI Agent doesn't necessarily. Documenting this stops someone from reporting as a "bug" something that's the component's nature, and it sets the stage for Module 5, which teaches how to test AI workflows despite that variability.

These two sections —data contract and AI notes— are what separate documentation that's "correct" from documentation that truly lets someone else pick up a modern AI workflow without suffering.

The standard job postings mean: "so someone else can pick it up"

It's worth naming the standard we're chasing, because it isn't "document a lot" or "document nicely." It's a concrete criterion, and handoff job postings express it in almost these words: documentation good enough for another developer to pick up the workflow and maintain it without the author's help.

"Good enough" is the key word, and it cuts both ways:

  • Good enough on the low end: it has to be sufficient. If a competent developer opens your repo and can't start the workflow, or doesn't understand what it's for, or doesn't know which credentials to create, the documentation isn't good enough, no matter how many pages it has.
  • Good enough on the high end: it doesn't have to overflow. Documenting every obvious node, explaining what a Webhook is, repeating what the JSON already says clearly —that isn't more documentation, it's more noise, and it buries what actually matters.

The practical test, one you can apply yourself, is the stranger test: give your repo to someone who knows n8n but doesn't know this workflow, and ask them to get it running and explain what it does. Wherever they get stuck, documentation is missing. Wherever they get bored reading the obvious, there's excess. The sweet spot is where that person moves forward on their own, without getting stuck and without yawning.

That standard —"someone else can, without me"— is the same one running through the whole module, now applied to documentation. A repo that meets it is, literally, what the best job postings ask for in writing. It isn't an extra: it's the deliverable.

Common mistakes

Documenting the how and forgetting the why (conceptual). What happens: someone writes documentation that describes node by node what each does —"the Set node adds a priority field"— but never says what the workflow exists for or what it assumes. Why it happens: the how reads straight off the canvas, so it's the easy part to write; the why takes thinking. How to spot it: if your documentation can be reconstructed just by looking at the workflow, it's not adding anything; the value is in what the workflow doesn't say about itself. How to fix it: focus on purpose, assumptions, and "what to watch" —the three things only you know and that the JSON doesn't reveal. Leave the how for the diagram and pinpoint sticky notes.

Writing a secret in a sticky note or in the README (practical and dangerous). What happens: someone, to "get it documented," pastes the CRM key into a sticky note or into the workflow's README. Since the note travels in the JSON and the README is in the repo, the secret ends up versioned. Why it happens: in the moment, it feels useful to have the key "handy" next to the explanation. How to spot it: search your notes and READMEs for anything shaped like a key (sk-..., Bearer ..., passwords). How to fix it: documentation says which credential is used and of what type, never its value. If you find a documented secret, besides deleting it, rotate the credential (lesson 3): it was in plain text, so you have to assume it's compromised.

Documenting once and never touching it again (conceptual). What happens: someone writes excellent documentation on day one, changes the workflow three times over the following months, and never updates the document. Now the documentation lies: it describes a workflow that no longer exists, and that's worse than no documentation, because it misleads. Why it happens: updating the doc is an extra step easy to skip when there's a rush. How to spot it: every time you change a workflow, ask yourself whether its README is still true; if you don't know, open it and compare. How to fix it: treat documentation as part of the change, not a later step —if you changed the trigger, update the Trigger section in the same commit. Outdated documentation is debt that charges interest.

Confusing quantity with quality (conceptual). What happens: someone writes ten pages of documentation believing more is better, and buries the three things that matter under filler paragraphs explaining the obvious. Why it happens: "documenting well" gets confused with "documenting a lot," and volume gives a false sense of rigor. How to spot it: apply the stranger test; if that person gets bored or lost in the volume, there's excess text. How to fix it: aim for "good enough," not "exhaustive." One well-thought-out screen beats ten pages nobody finishes. Documentation is meant to be read, and what's too long doesn't get read.

Exercises

Exercise 1 — Classify README or sticky note. For each piece of documentation, say whether it belongs in the per-workflow README (docs/) or in a sticky note on the canvas, and why: (a) the workflow's general purpose; (b) a warning about why a specific HTTP Request node has a retry configured; (c) the diagram of the whole flow; (d) the list of required credentials; (e) a note next to a Code node explaining a non-obvious calculation.

See solution

(a) README. It's the big picture; read before opening the workflow. (b) Sticky note. It's a pinpoint explanation of a specific node; needed while looking at that node in the editor. (c) README. The diagram of the whole flow is panorama, not proximity. (d) README. The dependency list is aggregate information, and it's worth having it in the repo for whoever doesn't open the editor. (e) Sticky note. A non-obvious calculation in a Code node is best explained stuck to the node, where the doubt arises.

Why it works: there's one rule —README for what's read before (panorama), sticky note for what's needed while (proximity). If you're clear on that distinction, you know where to put any piece of documentation without hesitating. And notice some things, like the customer_id assumption, live well in both places: that's not a mistake, it's covering both moments.

Exercise 2 — Write the Mermaid diagram. The inventory-sync workflow has this flow: a Schedule Trigger that runs every hour, then an HTTP Request that reads the store's stock, then a Code node that compares it against internal inventory, and finally a node that updates whichever ones differ. Write the Mermaid block for its node diagram.

See solution
```mermaid
flowchart LR
    A[Schedule: every hour] --> B[HTTP Request: reads store stock]
    B --> C[Code: compares against internal inventory]
    C --> D[Update: syncs the ones that differ]
```

The pieces: flowchart LR for a left-to-right flow; each node with an internal letter (A, B, C, D) and its text in brackets; the --> arrows connecting them in flow order. If you wrote flowchart TD (top-down) that's valid too; it's a matter of what reads better. What matters is that the four boxes are in the right order and connected.

Why it works: writing a Mermaid diagram by hand shows you how simple it is —plain text GitHub turns into a drawing— and why it beats pasting a screenshot: the text gets versioned, diffed, and edited when the workflow changes; an image doesn't. A diagram that stays in sync with the rest of the repo on its own is a diagram that doesn't go stale.

Exercise 3 — Apply the stranger test. Take one of your own workflows (or order-triage with this lesson's README) and pretend you're seeing it for the first time. Without opening the editor, just with the README: could you say what it exists for, how it turns on, which credentials to create, and what to watch? Note every question the README doesn't answer for you.

See solution

There's no single answer; the result is your list of gaps. What most people discover doing this honestly is that their documentation answers the how well but falls short in two places: the assumptions (what the workflow assumes about its input data) and the per-environment variables (what changes between dev and prod). Those are exactly the two things only the author knows, and the ones that slow down whoever inherits the work the most.

If your README answered all four questions without you having to open the editor, it meets the handoff standard. If you got stuck on one, that's exactly what's missing —no more, no less.

Why it works: the stranger test is the only honest way to measure whether your documentation is "good enough," because it forces you to read it without the knowledge you have in your head. It's uncomfortable on purpose: the goal is to find the gaps yourself, before the person inheriting the workflow finds them —with frustration.

Summary and next step

In this lesson you learned that documenting means anticipating and answering the questions of whoever inherits the workflow —what it exists for, how it turns on, what it needs, what it does, and what to watch— not writing a lot. You built the per-workflow README in docs/ with its fixed sections —purpose, trigger, dependencies, required credentials (no values), variables, node diagram, and notes/assumptions— and saw how to build the diagram with Mermaid, which GitHub renders from versionable text, with an ASCII fallback for wherever it doesn't render. You met sticky notes, the proximity documentation that lives inside the canvas and travels in the exported JSON —with the firm warning that it never carries a secret. And you named the module's standard: "good enough for someone else to pick up," measurable with the stranger test, which cuts excess as much as shortfall.

Before moving on you should be able to: name the sections of a per-workflow README; explain when a README applies and when a sticky note does; write a flowchart diagram in Mermaid; document a workflow's input contract and AI notes; and apply the stranger test to your own documentation.

With this, cumbre-automations is now a complete repository: versioned, secret-free, with clean diffs, structured, and documented. But everything you've done up to here you did by hand, command by command. Lesson 7 automates it: you're going to write a script —an export.sh— that exports with the CLI, normalizes the JSON, and leaves the repo ready to commit in a single command, to run before every commit and, if you want, hook as a git hook. You're also going to see the Enterprise alternative, n8n's native Git version control, and the honest criterion for deciding when it's worth paying for.

Resources