n8n Workflows skill for Codex

n8n flows that fail loudly and deploy cleanly. Codex builds n8n workflows around the item model, so nodes stop receiving fifty items when they expected one. It sets retries and error outputs per node, assigns an Error Workflow, keeps secrets in credentials, and exports workflows as JSON for git. For self-hosting it writes a Postgres-backed Docker setup with a backed-up encryption key and pruning.

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- n8n-workflows

Installs to ~/.agents/skills/n8n-workflows/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $n8n-workflows, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Designs, debugs and self-hosts n8n workflows - webhook and schedule triggers, expressions, Code nodes, Loop Over Items batching, credentials, error workflows and retries - and runs n8n in Docker with Postgres, a fixed encryption key, queue mode and execution pruning. Use when asked to build an n8n workflow, fix a failing node or expression, export or version workflows as JSON, move n8n to production, or upgrade a self-hosted instance.

Use it when

  • You are building or debugging an n8n workflow or Code node
  • Workflows fail silently and nobody notices
  • You self-host n8n and need a production setup, backup or upgrade path
  • Workflows should live in git and deploy between instances

Use something else when

How to check the result

Run every branch with pinned data including an invalid payload, call the production webhook with curl, and force one failure to confirm the Error Workflow alert arrives.

The mistake it prevents

Losing or changing N8N_ENCRYPTION_KEY during a migration, which leaves every stored credential unreadable.

~/.agents/skills/n8n-workflows/SKILL.md

--- name: n8n-workflows description: Designs, debugs and self-hosts n8n workflows - webhook and schedule triggers, expressions, Code nodes, Loop Over Items batching, credentials, error… license: MIT ---

A production n8n workflow has one clear trigger, handles partial failures per item, reports its own errors to someone, contains no secrets outside the credential store, and exists as JSON in version control. A production instance has a backed-up encryption key, Postgres, a public WEBHOOK_URL, and pruning turned on.

Orient first

  1. Ask which version and edition (n8n Cloud or self-hosted, and n8n --version). The 2.x line changed defaults: Code nodes run in task runners, environment variable access from Code nodes is blocked by default, and the Execute Command and Local File Trigger nodes are disabled by default. Check the official breaking-changes page before suggesting either node.
  2. Get the workflow JSON (editor: select all, copy; or n8n export:workflow --id=<id>), or the failing execution’s error text and input data. Do not guess from a screenshot.
  3. Check whether the target service has a built-in node. Prefer it over the HTTP Request node: it handles auth, pagination and rate limits for you.

Data model in one paragraph

Every node receives and emits an array of items, each { "json": {...}, "binary": {...} }. Most nodes run once per item automatically. Expressions are {{ ... }} JavaScript: {{ $json.email }} is the current item, {{ $('Get Customer').item.json.id }} reaches an earlier node’s paired item, {{ $now.toISO() }} uses Luxon. Most bugs are a node receiving 50 items when the author expected 1, or the reverse.

Building a workflow

- [ ] Trigger: Webhook, Schedule, app trigger, or Execute Workflow Trigger (sub-workflow)
- [ ] Validate input early (IF / Filter node) and stop with a clear message on bad payloads
- [ ] Fetch and transform with built-in nodes; Code node only for logic nodes cannot express
- [ ] Batch large sets with Loop Over Items; add a Wait node when the API rate-limits
- [ ] Per-node error behaviour set deliberately (see table)
- [ ] Workflow settings: Error Workflow assigned, timezone set, save execution data policy
- [ ] Test with pinned data, then publish/activate and test the production URL
- [ ] Export JSON to the repo

Code node patterns

“Run Once for All Items” mode returns an array of items:

const out = [];
for (const item of $input.all()) {
  const { email, plan } = item.json;
  if (!email) continue;                        // drop invalid rows explicitly
  out.push({ json: { email: email.trim().toLowerCase(), plan: plan ?? 'free' } });
}
return out;

“Run Once for Each Item” mode returns one object: return { json: { ...$json, total: $json.qty * $json.price } };. Keep Code nodes short and pure. No secrets in them; reference credentials through nodes. On 2.x, $env access in Code nodes is blocked unless the admin allows it.

Error handling decisions

SituationSetting
Transient API errors (429, 5xx, timeouts)Node settings: Retry On Fail, 3 to 5 tries, wait 2000 to 5000 ms
One bad item should not stop the restOn Error: Continue (using error output), route errors to a log/notify branch
Any unhandled failureWorkflow settings, Error Workflow: a workflow starting with Error Trigger that posts to Slack or email
Webhook caller needs a responseRespond to Webhook node, with an explicit error response on the failure branch
Duplicate deliveries possibleDedupe on an id (Remove Duplicates node across executions, or a lookup table)

Messages and emails the workflow sends are outward-facing: before activating a workflow that sends to customers or public channels, confirm recipients and content with the user and test against a sandbox channel or your own address.

Webhooks

  • Test URL (/webhook-test/...) only works while the editor is listening; production URL (/webhook/...) only works once the workflow is active/published.
  • Behind a reverse proxy, set WEBHOOK_URL=https://n8n.example.com/ or n8n will print internal URLs.
  • Authenticate inbound webhooks (Header Auth credential or verify the sender’s HMAC signature in a Code node) and respond quickly; push slow work to a sub-workflow.

Self-hosting

# docker-compose.yml (minimal production shape)
services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: n8n
    volumes: [pgdata:/var/lib/postgresql/data]
  n8n:
    image: docker.n8n.io/n8nio/n8n:<pinned-version>
    ports: ["127.0.0.1:5678:5678"]          # expose through a TLS reverse proxy
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_DATABASE: n8n
      DB_POSTGRESDB_USER: n8n
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      N8N_HOST: n8n.example.com
      N8N_PROTOCOL: https
      WEBHOOK_URL: https://n8n.example.com/
      GENERIC_TIMEZONE: Europe/Berlin
      TZ: Europe/Berlin
      EXECUTIONS_DATA_PRUNE: "true"
      EXECUTIONS_DATA_MAX_AGE: "336"      # hours
    volumes: [n8ndata:/home/node/.n8n]
    depends_on: [postgres]
volumes: { pgdata: {}, n8ndata: {} }
  • N8N_ENCRYPTION_KEY encrypts every stored credential. Generate once (openssl rand -hex 32), store it in the secret manager, back it up. Losing it makes all credentials unreadable; changing it on an existing database breaks them.
  • Pin the image tag; read release notes before bumping, back up Postgres first.
  • Scale with queue mode (EXECUTIONS_MODE=queue, Redis via QUEUE_BULL_REDIS_HOST, separate worker containers running n8n worker) only when one instance is saturated.
  • Pulling images and starting containers needs network and Docker access; ask before running them from a Codex sandbox. Restarting a production instance requires the user’s go-ahead.

Version control and migration

n8n export:workflow --all --separate --output=workflows/      # one JSON file per workflow
n8n import:workflow --separate --input=workflows/
n8n export:credentials --all --output=creds/                  # encrypted with the instance key

Inside Docker prefix with docker compose exec n8n. Commit workflow JSON; never commit --decrypted credential exports. Imported workflows reference credentials by id, so recreate or import credentials on the target instance before activating. The public REST API (X-N8N-API-KEY header, /api/v1/workflows) suits CI-driven deploys.

Gotchas

  • Item pairing breaks after Code nodes that build new items; $('Node').item then errors. Carry needed fields forward in the item, or use $('Node').first() deliberately.
  • Schedule triggers use the workflow timezone, falling back to GENERIC_TIMEZONE.
  • Large binary files in executions bloat the database; set N8N_DEFAULT_BINARY_DATA_MODE=filesystem (or S3 in enterprise setups) and prune.
  • The HTTP Request node’s pagination option exists; do not hand-roll loops for cursor APIs.
  • “Always Output Data” hides empty results that should stop the flow; use it sparingly.
  • Saving execution data for successful runs on high-volume workflows fills the database.

Verification

  • Run each branch with pinned test data, including an invalid payload and an API error.
  • Trigger the production webhook with curl -X POST https://n8n.example.com/webhook/<path> -H 'Content-Type: application/json' -d '{"test":true}'.
  • Force a failure and confirm the Error Workflow notification arrives.
  • After an upgrade or migration, open three credentials and run one workflow per credential type.

Output

Deliver the workflow as importable JSON plus a short note: trigger, required credentials (names and types, no values), environment variables, error routing, and how to test it.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "n8n Workflows"
  short_description: "n8n flows that fail loudly and deploy cleanly"
  default_prompt: "$n8n-workflows Build an n8n workflow that takes Typeform submissions and adds them to HubSpot and Slack"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc