n8n-agents
Design n8n AI agents the right way. Use when building or editing any @n8n/n8n-nodes-langchain.* AI node — an AI Agent, LLM chain,…
Write Python in n8n Code nodes (native Python, `language` pythonNative, n8n 2.x). Use when the user explicitly wants Python in a Code node, when migrating old Pyodide/"Python (Beta)" code that used _input/_json/_node/_now, or when a Python Code node fails with NameError,
Claude Code
$ npx -y skills add czlonkowski/n8n-skills --skill n8n-code-python --agent claude-code
Codex
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a codex -y
Cursor
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a cursor -y
Gemini CLI
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a gemini-cli -y
GitHub Copilot
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a github-copilot -y
OpenCode
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a opencode -y
Windsurf
$ npx skills add czlonkowski/n8n-skills --skill n8n-code-python -a windsurf -y
name: n8n-code-python description: Write Python in n8n Code nodes (native Python, `language` pythonNative, n8n 2.x). Use when the user explicitly wants Python in a Code node, when migrating old Pyodide/"Python (Beta)" code that used _input/_json/_node/_now, or when a Python Code node fails with NameError, "Security violations detected", "Import of standard library module … is disallowed", "__build_class__ not found", "A 'json' property isn't a dictionary", or "Python runner unavailable". Covers the only two variables (_items/_item), dict-only access, imports blocked by default, the sandbox's denied builtins, accepted return shapes, and how errors interact with onError. JavaScript is the default for Code nodes — native Python has no n8n helpers and, by default, no imports. EXCEPTION — for Python in the AI-agent-callable Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode), use the n8n-code-tool skill instead (input is _query, return must be a string).
Since n8n 2.0 the Code node's Python runs as **native Python in a task runner** (`language: "pythonNative"`). The old Pyodide "Python (Beta)" is gone, and with it every n8n helper it had: `_input`, `_json`, `_node`, `_now`, `_today` and `_jmespath` all raise `NameError` now. Code copied from old templates, forum posts or older docs usually breaks on this.
---
Native Python gives you two variables and plain Python, and **by default no imports**: no `json`, `datetime` or `re`. Everything n8n-specific (`$('Node')`, `$jmespath`, Luxon, `this.helpers.httpRequest`, static data) exists only in JavaScript. Use Python only when the user explicitly asks for it. Even then, first check whether an expression, Edit Fields, or a native node (Crypto, Date & Time, HTML, XML) does the job. See **n8n-code-javascript** and the transform gatekeeper in **n8n-expression-syntax**.
---
# Run Once for All Items (default mode)
return [
{"json": {"name": it["json"]["name"], "revenue": it["json"]["revenue"]}}
for it in _items
if it["json"].get("active")
]# Run Once for Each Item
row = _item["json"]
return {"json": {**row, "name_upper": (row.get("name") or "").upper()}}Node config: `{"language": "pythonNative", "mode": "runOnceForAllItems" | "runOnceForEachItem", "pythonCode": "..."}` on `n8n-nodes-base.code` typeVersion 2.
---
| Mode | Variable | Shape | |---|---|---| | Run Once for All Items | `_items` | `list` of plain dicts `{"json": {...}, "pairedItem": {...}}` | | Run Once for Each Item | `_item` | one plain dict `{"json": {...}, "pairedItem": {...}}` |
all-items mode) raises `NameError`.
`AttributeError: 'dict' object has no attribute 'json'`.
branch, bring it in with Merge first, or read it in JavaScript.
uses `$('Node').item`, add `"pairedItem": {"item": i}` to each returned item. That isn't verified on native Python yet, so test-run before relying on it.
Migration table for legacy code:
| Legacy (Pyodide) | Native | |---|---| | `_input.all()` | `_items` | | `_input.first()["json"]` | `_items[0]["json"]` (guard `if _items`) | | `_input.item` / `_json` | `_item` / `_item["json"]` | | `_node["X"]` | not available: Merge upstream, or use JS | | `_now`, `_today` | not available: pass `{{ $now.toISO() }}` in via Edit Fields, or use JS | | `_jmespath(data, q)` | not available: `$jmespath` in an expression, or a comprehension | | `item.json.field` | `item["json"]["field"]` |
---
Every `import` (standard library and third-party) is checked against an allowlist **before the code runs**. The default allowlist is empty, so even `import json` rejects the whole node:
Security violations detected Line 1: Import of standard library module 'json' is disallowed. Allowed stdlib modules: none
**n8n-self-hosting** → `TASK_RUNNERS.md`). Some instances therefore allow `json`, `datetime` and `re`, and most don't.
one-line test node `import json` + `return [{"json": {"ok": True}}]`, or ask the user. Never assume.
Do date math with the Date & Time node or Luxon in an expression. ISO-8601 strings still compare and sort correctly as plain strings. Use the Crypto node for hashing.
image. Use the HTTP Request node for HTTP.
---
| You write | What happens | Use instead | |---|---|---| | `eval`, `exec`, `compile`, `open`, `input`, `type`, `getattr`, `setattr`, `hasattr`, `vars`, `dir`, `globals`, `locals`, `object`, `memoryview`, `breakpoint` | `NameError: name 'type' is not defined` (runtime) | `isinstance(x, dict)`; `key in d` / `d.get(key)` | | `class Foo: ...` | `__build_class__ not found` (runtime) | dicts + functions | | `x.__class__`, `"{0.__class__}".format(x)`, `__import__("json")` | `Security violations detected` (whole node rejecte
Expert Claude Code skills for building flawless n8n workflows using the n8n-mcp MCP server
Design n8n AI agents the right way. Use when building or editing any @n8n/n8n-nodes-langchain.* AI node — an AI Agent, LLM chain,…
Handle files and binary data in n8n correctly. Use when working with files, images, PDFs, attachments, uploads or downloads,…
Write, review, or debug JavaScript in an n8n Code node. Use when a Code node is already in the workflow (editing it, fixing an…
Write JavaScript or Python for the n8n Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode) — the AI-agent-callable tool, NOT the…
Wire n8n error handling so failures are loud, structured, and recoverable. Use when building any webhook/API workflow, a…
Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node…
Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…