data/skills/n8n-code-tool/README.md
Expert guidance for writing code inside the n8n Custom Code Tool (@n8n/n8n-nodes-langchain.toolCode) — the AI-agent-callable tool, not the regular Code node.
Same editor UI, completely different contract:
| Code node | Code Tool | |
|---|---|---|
| Node type | n8n-nodes-base.code | @n8n/n8n-nodes-langchain.toolCode |
| Invoked by | Previous node | AI Agent (LangChain) |
| Input | $input.all() | query variable |
| Return | [{json: {...}}] | A string |
$fromAI() | N/A | Not available |
$helpers | Via this.helpers (bare $helpers global is undefined) | Not exposed |
If you carry over Code-node habits, it fails with cryptic errors. This skill teaches the Code Tool's actual contract.
JSON.stringify() for structured outputquery (JS) or _query (Python)$fromAI() — doesn't exist in this sandbox"Cannot assign to read only property 'name'..." — $fromAI() misuse"Wrong output type returned" — returning [{json:{...}}]"The response property should be a string, but it is an object" — unstringified objectquery — no schema, no exampleActivates when you:
"Wrong output type returned" or "No execution data available" errorsquery parsing and specifyInputSchema$fromAI() or $helpers.httpRequest() don't worktoolWorkflowExample queries:
$fromAI work in @n8n/n8n-nodes-langchain.toolCode?"specifyInputSchema for structured tool input?"Main skill content — loaded when the skill activates.
query vs structured schema$input, $helpers, $fromAI, state)toolWorkflow vs HTTP Request ToolStructured-input deep dive — specifyInputSchema: true.
DynamicStructuredTool vs DynamicTool)fromJson (infer schema from an example, v≥1.3)manual (write the JSON Schema yourself)query behaves with vs without schematoolWorkflowFull error catalog with exact strings, causes, and fixes.
query vs _queryreturn `You asked: ${query}`;
return f"You asked: {_query}"
return JSON.stringify({
result: 42,
currency: "SEK"
});
const params = typeof query === 'string' ? JSON.parse(query) : query;
const price = Number(params.price);
specifyInputSchema: true)const { price, months, residual_percent } = query;
[A-Za-z0-9_]+ — snake_case, no spaces/hyphens/emojicalculate_car_loan, not Code Tooln8n-code-javascript (Code node): most JS patterns transfer, but I/O is different — don't copy $input.all() or [{json:{...}}] return.
n8n-node-configuration: specifyInputSchema is a typical conditional-field pattern — use get_node({detail: "standard"}) on toolCode to explore.
n8n-workflow-patterns: Code Tool sits inside the AI-Agent-with-tools pattern. Usually alongside HTTP Request Tool, toolWorkflow, and memory.
n8n-validation-expert: the three signature errors have exact strings that map cleanly to fixes — if you see them in validation output, the fix is mechanical.
| Need | Use |
|---|---|
| Pure computation (math, parsing, formatting) | Code Tool |
Multiple typed params with $fromAI() | toolWorkflow (sub-workflow tool) |
| Single API call | HTTP Request Tool |
Access to this.helpers, credentials, other nodes | toolWorkflow |
| Persistent state across calls | toolWorkflow with Data Table / Redis |
| Reusable logic across multiple agents | toolWorkflow |
Rule of thumb: if you catch yourself reaching for $fromAI(), you want toolWorkflow instead.
After using this skill, you should be able to:
JSON.stringify() result) — never a bare object or items arrayquery/_query without reaching for $fromAIspecifyInputSchema) patternstoolWorkflow vs HTTP Request Tool)Authoritative facts in this skill come from:
query binding, return handlingDynamicTool / DynamicStructuredTool semanticsVersion: 1.0.0
Compatibility: n8n with @n8n/n8n-nodes-langchain.toolCode v1.1+; structured fromJson requires v≥1.3.
Part of the n8n-skills project.
Remember: Code Tool is a LangChain tool wearing a Code-node UI. Contract is string in, string out. Everything else follows from that.