[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F994BP42DC2J3R46KGHVFC":3,"skill-same:01M6F994BP42DC2J3R46KGHVFC":84},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":35,"commitSha":54,"skillDirectory":55,"forksCount":56,"repositoryHtmlUrl":57,"repositoryHomepageUrl":6,"ownerHtmlUrl":58,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":59,"install":60,"resources":73},"01M6F994BP42DC2J3R46KGHVFC","n8n-code-tool",null,"Write and debug JavaScript or Python for the AI-callable n8n Custom Code Tool, including schemas, sandbox limits, and return formats.","boisenoise\u002Fskills-collections","boisenoise","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F193180?v=4","01M6CDBDQK6BDN55ZMA6B6PKBM","01M6CDBDVSJ3JPTBYN26FZ7TZK",12,"MIT","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-n8n-code-tool\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"code","tool","n8n code tool","n8n","community","2026","limits","custom","for","tree","formats","critical","main","python","write","https","license","debug","javascript","sandbox","github","2026-11-10 10:12:30",false,"---\nname: n8n-code-tool\ndescription: Write and debug JavaScript or Python for the AI-callable n8n Custom Code Tool, including schemas, sandbox limits, and return formats.\nrisk: critical\nsource: https:\u002F\u002Fgithub.com\u002Fczlonkowski\u002Fn8n-skills\u002Ftree\u002Fmain\u002Fskills\u002Fn8n-code-tool\nsource_repo: czlonkowski\u002Fn8n-skills\nsource_type: community\ndate_added: \"2026-07-21\"\nauthor: Romuald Czlonkowski\nlicense: MIT\nlicense_source: https:\u002F\u002Fgithub.com\u002Fczlonkowski\u002Fn8n-skills\u002Fblob\u002Fmain\u002FLICENSE\n---\n\n# n8n Custom Code Tool\n\n## When to Use\n\nUse this skill specifically for code executed by the AI-agent-callable n8n Custom Code Tool. Use the separate JavaScript or Python Code-node skills for ordinary workflow Code nodes.\n\nDo not hardcode secrets or accept arbitrary executable code from untrusted input. Constrain inputs with a schema, validate outputs, allowlist any network destinations, and ask before testing a tool whose code can write data or invoke an external service.\n\nExpert guidance for writing code inside `@n8n\u002Fn8n-nodes-langchain.toolCode` — the tool an AI Agent can invoke, **not** the regular workflow Code node.\n\n---\n\n## ⚠️ This is NOT the Code node\n\nThe Custom Code Tool looks like a Code node in the editor — same JavaScript editor, similar layout — but it is a **completely different node** from a different package with a **different runtime contract**.\n\n| | Code node | Custom Code Tool |\n|---|---|---|\n| **Node type** | `n8n-nodes-base.code` | `@n8n\u002Fn8n-nodes-langchain.toolCode` |\n| **Package** | `n8n-nodes-base` | `@n8n\u002Fn8n-nodes-langchain` |\n| **Invoked by** | Previous node (workflow flow) | AI Agent (LangChain) |\n| **Input** | `$input.all()` — item stream | `query` — string or object from LLM |\n| **Return** | `[{json: {...}}]` (items array) | **A string** |\n| **`$fromAI()`** | N\u002FA | **Not available** (see Errors) |\n| **HTTP helper** | `this.helpers.httpRequest` (auth helpers blocked) | Not exposed to the tool sandbox |\n| **State** | Per-run execution data | No `getContext`, no `$getWorkflowStaticData` |\n\n**If you treat it like a Code node, it fails.** The rest of this skill covers the Code Tool's actual contract.\n\n---\n\n## Quick Start\n\n### Minimal JavaScript Code Tool\n\n```javascript\n\u002F\u002F `query` is whatever the AI sent (a string by default)\nreturn `You asked: ${query}`;\n```\n\n### Minimal Python Code Tool\n\n```python\n# `_query` is whatever the AI sent (a string by default)\nreturn f\"You asked: {_query}\"\n```\n\n### Essential Rules\n\n1. **Return a string.** Numbers are auto-converted. Anything else throws `\"The response property should be a string, but it is an object\"`.\n2. **Input variable is fixed**: `query` (JS), `_query` (Python). You cannot rename it.\n3. **Do NOT use `$fromAI()`** inside the Code Tool sandbox — it throws `\"No execution data available\"`.\n4. **Do NOT use `[{json: {...}}]`** return format — that's for Code nodes. Throws `\"Wrong output type returned\"`.\n5. **Use a descriptive tool name** (letters\u002Fnumbers\u002Funderscores, v1.1+). The agent calls the tool by its name.\n6. **Write a precise description** — the LLM decides whether to invoke the tool based on it.\n\n---\n\n## The Two Input Modes\n\nThe Code Tool has two input shapes, controlled by `specifyInputSchema`:\n\n### Mode 1: Unstructured (default, `specifyInputSchema: false`)\n\nThe AI passes **a single string** as `query`. If you need multiple fields, the AI has to stuff them into that one string and you parse them out. In practice, LLMs will happily pass a JSON string if your description tells them to.\n\n```javascript\n\u002F\u002F Parse a JSON string the AI sent\nlet params;\ntry {\n  params = typeof query === 'string' ? JSON.parse(query) : query;\n} catch (e) {\n  throw new Error('Expected a JSON object. Parser said: ' + e.message);\n}\nconst price = Number(params.price);\nconst months = Number(params.months);\n\u002F\u002F ...\nreturn JSON.stringify({ monthly_payment: \u002F* ... *\u002F });\n```\n\n**Pros**: simplest to set up, one field to describe.\n**Cons**: no schema validation — if the LLM forgets a field, the tool throws at runtime.\n\n**Best for**: quick prototypes, tools with one natural input (a question, a URL, a text blob).\n\n### Mode 2: Structured (`specifyInputSchema: true`)\n\nThe tool becomes a LangChain `DynamicStructuredTool`. The LLM sees a typed argument schema and passes a **validated object** as `query`. You access fields directly.\n\n```javascript\n\u002F\u002F query is now an object matching your schema\nconst price = query.price;\nconst months = query.months;\nconst residual_percent = query.residual_percent;\n\nconst monthly = computeAnnuity(price, months, residual_percent);\nreturn JSON.stringify({ monthly_payment: monthly });\n```\n\nSchema is defined via either:\n- `schemaType: \"fromJson\"` + `jsonSchemaExample` (n8n v≥1.3) — paste an example JSON, n8n infers the schema\n- `schemaType: \"manual\"` + `inputSchema` — write a full JSON Schema yourself\n\n**Pros**: LLM gets type hints, invalid calls rejected before your code runs, cleaner code.\n**Cons**: a little more setup; requires n8n version with schema support.\n\n**Best for**: production tools with multiple typed parameters (calculators, API wrappers, anything with numeric fields the LLM tends to stringify).\n\n**See**: [references\u002FINPUT_SCHEMA.md](references\u002FINPUT_SCHEMA.md) for complete schema setup.\n\n---\n\n## Return Format\n\n**The return value must be a string.** The LLM reads it as the tool's observation.\n\n```javascript\n\u002F\u002F ✅ String\nreturn \"42\";\n\n\u002F\u002F ✅ Number (auto-converted to string by n8n)\nreturn 42;\n\n\u002F\u002F ✅ JSON-encoded structured result (recommended for rich output)\nreturn JSON.stringify({ result: 42, currency: \"SEK\" });\n\n\u002F\u002F ❌ Raw object → \"The response property should be a string, but it is an object\"\nreturn { result: 42 };\n\n\u002F\u002F ❌ Workflow item format → \"Wrong output type returned\"\nreturn [{ json: { result: 42 } }];\n\n\u002F\u002F ❌ Array → \"The response property should be a string, but it is an object\"\nreturn [1, 2, 3];\n```\n\n### Best practice: JSON-stringify structured results\n\nWhen your tool has more than a trivial scalar output, return a JSON string:\n\n```javascript\nreturn JSON.stringify({\n  monthly_payment_sek: 5405,\n  loan_amount: 351920,\n  total_cost_of_credit: 63295\n});\n```\n\nThe LLM parses JSON reliably and can pick the fields it needs to present to the user.\n\n### Error handling: the agent reads your failures\n\nErrors don't just stop the workflow — they go back to the LLM, which usually corrects its call and retries. Use that:\n\n```javascript\n\u002F\u002F Option A: throw — n8n surfaces the message to the agent\nif (!isFinite(price)) throw new Error('price must be a number, e.g. 439900');\n\n\u002F\u002F Option B: return an error string — agent reads it like any tool result\nif (!isFinite(price)) return JSON.stringify({ error: 'price must be a number, e.g. 439900' });\n```\n\nEither way, write error messages **for the LLM**: state what was wrong and what a valid call looks like. A bare `throw new Error('invalid input')` wastes the retry; an instructive message usually fixes the next call.\n\n---\n\n## Tool Name and Description\n\nThese fields are NOT documentation — they are the **tool contract the LLM sees**. Treat them as prompt engineering.\n\n### Name\n- Must match `[A-Za-z0-9_]+` (v1.1+). No spaces, no hyphens, no emoji.\n- Use a verb-y descriptive name: `calculate_car_loan`, `get_weather`, `search_orders`.\n- The agent calls the tool by this name. `Code Tool` (the default) is useless — the agent won't know when to call it.\n\n### Description\n- Explain **when** to use it and **what** to send.\n- If unstructured mode, **include an example of the JSON string** the LLM should send.\n- If structured mode, the schema speaks for itself — just describe purpose.\n\n**Unstructured example (JSON-in-string pattern):**\n```\nDeterministiskt beräknar månadskostnad för billån. Anropa med EN JSON-sträng:\n{\"price\":439900,\"down_payment\":87980,\"interest_rate\":6.95,\"months\":36,\"residual_percent\":50}\nFält: price (SEK), down_payment (SEK), interest_rate (% per år), months, residual_percent (0-99).\n```\n\n**Structured example (schema-defined):**\n```\nDeterministically computes the monthly car-loan payment given price, down payment,\nannual interest rate, term, and residual percent. Use whenever the user asks for\nmonthly cost, total credit cost, or loan breakdown.\n```\n\n---\n\n## Top Errors and Fixes\n\n### Error 1: `\"There was an error: 'Cannot assign to read only property \\\"name\\\" of object: Error: No execution data available'\"`\n\n**Cause**: you called `$fromAI()` inside the Code Tool sandbox.\n\n**Fix**: `$fromAI()` is a helper for **other** tool-enabled nodes (HTTP Request Tool, SendGrid Tool, `toolWorkflow`, etc.) — it's not exposed inside `toolCode`. Read the AI's input from `query` directly (or use `specifyInputSchema` for structured fields).\n\n### Error 2: `\"Wrong output type returned\"`\n\n**Cause**: you returned a workflow-style array like `[{ json: { ... } }]`. That's the Code **node** contract, not the Code **Tool** contract.\n\n**Fix**: return a string. For structured data, `return JSON.stringify(output)`.\n\n### Error 3: `\"The response property should be a string, but it is an object\"`\n\n**Cause**: you returned a plain object or array.\n\n**Fix**: `JSON.stringify()` the result, or coerce to a string.\n\n### Error 4: AI never calls the tool\n\n**Cause**: tool name is generic (`Code Tool`, `My Tool`) or description doesn't clearly state when to use it.\n\n**Fix**: rename to a verb-y name (`calculate_car_loan`), and rewrite the description to explicitly state the trigger conditions (e.g. \"Use this whenever the user asks about monthly cost\").\n\n### Error 5: AI sends garbage into `query`\n\n**Cause**: unstructured tool with a vague description. The LLM guesses at the format.\n\n**Fix**: either (a) include a concrete JSON example in the description, or (b) switch to `specifyInputSchema: true` so the LLM gets a typed schema.\n\n**See**: [references\u002FERROR_PATTERNS.md](references\u002FERROR_PATTERNS.md) for full catalog with reproductions.\n\n---\n\n## What's NOT Available in the Sandbox\n\nThe Code Tool sandbox is **narrower** than the Code node sandbox. Don't assume helpers carry over:\n\n| Helper | Code node | Code Tool |\n|---|---|---|\n| `$input.all()`, `$input.first()`, `$input.item` | ✅ | ❌ |\n| `$node[\"NodeName\"]` | ✅ | ❌ |\n| `$json`, `$binary` | ✅ | ❌ |\n| `$fromAI()` | ❌ | ❌ (despite sitting next to an AI agent) |\n| `this.helpers.httpRequest()` | ✅ | ❌ |\n| `DateTime` (Luxon) | ✅ | ✅ (standard in JS sandbox) |\n| `$jmespath()` | ✅ | ❌ |\n| `this.getContext(...)` | ✅ | ❌ |\n| `$getWorkflowStaticData(...)` | ✅ | ❌ |\n\n**Implication**: the Code Tool is for **pure computation**. If you need an HTTP call, an API lookup, or cross-invocation state, use a different tool node:\n- HTTP Request Tool for external API calls\n- `toolWorkflow` (Call Sub-workflow Tool) for multi-step logic with access to the full Code node sandbox\n- MCP \u002F database tools for persistent state\n\n---\n\n## When to Use Code Tool vs Alternatives\n\nUse **Code Tool** when:\n- ✅ Pure deterministic computation (math, parsing, formatting, validation)\n- ✅ Lightweight transformations the LLM shouldn't do itself (precision math, regex)\n- ✅ You want the code inline in the workflow, not in a separate sub-workflow\n\nUse **`toolWorkflow`** (Call Sub-workflow Tool) when:\n- ✅ You need multiple parameters with clean `$fromAI()` typing\n- ✅ You need access to `this.helpers`, credentials, or other nodes\n- ✅ Logic is reusable across agents\n- ✅ You want structured typed inputs WITHOUT writing a JSON Schema\n\nUse **HTTP Request Tool** when:\n- ✅ The tool is fundamentally a single API call\n- ✅ You want per-parameter `$fromAI()` bindings in URL\u002Fquery\u002Fbody\n\n**Rule of thumb**: if you find yourself wanting `$fromAI()`, you probably want `toolWorkflow` instead of `toolCode`.\n\n---\n\n## Calculator assumptions\n\nThe example computes nominal annuity\u002Fballoon payments, not statutory APR or a lending recommendation. Currency is illustrative, rounding shown is whole-unit display only, and real contracts require exact minor-unit rounding, fee timing and rate conventions. Type\u002Fschema hints do not enforce business constraints; validate finite values, positive integer months, fees and balloon\u002Fprincipal compatibility in code.\n\n## Complete Working Example\n\nAn illustrative calculator fragment requiring installed-version and numerical validation (unstructured, JSON-in-string pattern):\n\n```json\n{\n  \"parameters\": {\n    \"name\": \"calculate_car_loan\",\n    \"description\": \"Computes monthly car-loan payment using an annuity formula with residual\u002Fballoon. Call with a single JSON string. Example: {\\\"price\\\":439900,\\\"down_payment\\\":87980,\\\"interest_rate\\\":6.95,\\\"months\\\":36,\\\"residual_percent\\\":50,\\\"setup_fee\\\":695,\\\"monthly_admin_fee\\\":59}. Required: price, down_payment, interest_rate, months, residual_percent. Optional: setup_fee, monthly_admin_fee (default 0).\",\n    \"language\": \"javaScript\",\n    \"jsCode\": \"if (!query || (typeof query !== 'string' && (typeof query !== 'object' || Array.isArray(query)))) throw new Error('Expected object input');\\nlet params;\\ntry {\\n  params = typeof query === 'string' ? JSON.parse(query) : query;\\n} catch (e) {\\n  throw new Error('Invalid JSON: ' + e.message);\\n}\\n\\nif (!params || typeof params !== 'object' || Array.isArray(params)) throw new Error('Expected object');\\nfor (const key of ['price','down_payment','interest_rate','months','residual_percent']) {\\n  if (typeof params[key] !== 'number' || !Number.isFinite(params[key])) throw new Error(key + ' must be a finite number');\\n}\\nconst price           = Number(params.price);\\nconst down_payment    = Number(params.down_payment);\\nconst interest_rate   = Number(params.interest_rate);\\nconst months          = Number(params.months);\\nconst residual_percent= Number(params.residual_percent);\\nconst setup_fee       = Number(params.setup_fee ?? 0);\\nconst monthly_admin_fee = Number(params.monthly_admin_fee ?? 0);\\n\\nif (!isFinite(price) || price \u003C= 0) throw new Error('price must be > 0');\\nif (down_payment \u003C 0 || down_payment >= price) throw new Error('down_payment must be in [0, price)');\\n\\nif (![price, down_payment, interest_rate, months, residual_percent, setup_fee, monthly_admin_fee].every(Number.isFinite) || price \u003C= 0 || down_payment \u003C 0 || down_payment >= price || interest_rate \u003C 0 || !Number.isInteger(months) || months \u003C 1 || months > 1200 || residual_percent \u003C 0 || residual_percent > 99 || setup_fee \u003C 0 || monthly_admin_fee \u003C 0) throw new Error('Invalid loan inputs');\\nconst principal = price - down_payment;\\nconst residual  = price * (residual_percent \u002F 100);\\nconst r = interest_rate \u002F 100 \u002F 12;\\nconst growth = Math.pow(1 + r, months);\\nconst base = r === 0\\n  ? (principal - residual) \u002F months\\n  : (principal - residual \u002F growth) * r \u002F (1 - 1 \u002F growth);\\nconst monthly_payment = base + monthly_admin_fee;\\nif (!Number.isFinite(monthly_payment) || monthly_payment \u003C 0) throw new Error('Invalid payment; review balloon\u002Fprincipal assumptions');\\n\\nreturn JSON.stringify({\\n  monthly_payment_sek: Math.round(monthly_payment),\\n  loan_amount: Math.round(principal),\\n  residual_value_sek: Math.round(residual),\\n  total_cost_of_credit: Math.round(monthly_payment * months + residual + setup_fee - principal)\\n});\"\n  },\n  \"type\": \"@n8n\u002Fn8n-nodes-langchain.toolCode\",\n  \"typeVersion\": 1.3,\n  \"name\": \"calculate_car_loan\"\n}\n```\n\nWire it into an AI Agent via the `ai_tool` connection type.\n\n---\n\n## Integration with Other Skills\n\n**n8n-code-javascript**: the Code **node** skill. Most JavaScript patterns (arrays, map\u002Ffilter, DateTime) transfer — but I\u002FO contract is different. Don't copy data-access code.\n\n**n8n-node-configuration**: `specifyInputSchema` is a classic displayOptions-driven conditional field. Use `get_node({detail: \"standard\"})` on `@n8n\u002Fn8n-nodes-langchain.toolCode` to see schema-related properties.\n\n**n8n-workflow-patterns**: Code Tool sits inside the \"AI Agent with tools\" pattern. An agent typically has several tools; Code Tool is the \"local compute\" option.\n\n**n8n-validation-expert**: the three Code Tool errors listed above have clear signatures — if validation surfaces \"Wrong output type returned\", you know to switch from array-of-items to a string.\n\n---\n\n## Quick Reference Checklist\n\nBefore deploying a Code Tool:\n\n- [ ] **Node type** is `@n8n\u002Fn8n-nodes-langchain.toolCode` (not `nodes-base.code`)\n- [ ] **Tool name** is descriptive, verb-y, snake_case (e.g. `calculate_car_loan`)\n- [ ] **Description** states when to use the tool and (if unstructured) shows a JSON example\n- [ ] **Input** read from `query` (JS) or `_query` (Python)\n- [ ] **No `$fromAI()`** in the code body\n- [ ] **No `$input` \u002F `$json` \u002F `$helpers`** — those aren't in the sandbox\n- [ ] **Return** is a string (use `JSON.stringify()` for structured output)\n- [ ] **Wired** into an AI Agent via `ai_tool` connection\n- [ ] **Tested** with the exact kind of input the LLM will send (JSON in a string, or schema-validated object)\n\n---\n\n## Additional Resources\n\n- [references\u002FINPUT_SCHEMA.md](references\u002FINPUT_SCHEMA.md) — structured input (DynamicStructuredTool) in depth\n- [references\u002FERROR_PATTERNS.md](references\u002FERROR_PATTERNS.md) — full error catalog with causes and fixes\n\n### Official sources\n- [n8n Custom Code Tool docs](https:\u002F\u002Fdocs.n8n.io\u002Fintegrations\u002Fbuiltin\u002Fcluster-nodes\u002Fsub-nodes\u002Fn8n-nodes-langchain.toolcode\u002F)\n- [ToolCode source](https:\u002F\u002Fgithub.com\u002Fn8n-io\u002Fn8n\u002Fblob\u002Fmaster\u002Fpackages\u002F%40n8n\u002Fnodes-langchain\u002Fnodes\u002Ftools\u002FToolCode\u002FToolCode.node.ts) — the sandbox contract\n- [LangChain tool docs](https:\u002F\u002Fjs.langchain.com\u002Fdocs\u002Fmodules\u002Fagents\u002Ftools\u002F) — DynamicTool \u002F DynamicStructuredTool\n\n---\n\n**Remember**: distinguish unstructured string input from schema-defined object input; output must satisfy the installed Code Tool contract. Node typeVersion is not the same as the n8n application release.\n\n## Limitations\n\n- The Custom Code Tool sandbox and available globals can change with n8n releases; verify the installed node version.\n- Static review cannot establish runtime permissions, network reachability, or the behavior of external services.\n- This skill does not authorize arbitrary code execution or testing against production data.\n","# n8n Custom Code Tool\n\n## When to Use\n\nUse this skill specifically for code executed by the AI-agent-callable n8n Custom Code Tool. Use the separate JavaScript or Python Code-node skills for ordinary workflow Code nodes.\n\nDo not hardcode secrets or accept arbitrary executable code from untrusted input. Constrain inputs with a schema, validate outputs, allowlist any network destinations, and ask before testing a tool whose code can write data or invoke an external service.\n\nExpert guidance for writing code inside `@n8n\u002Fn8n-nodes-langchain.toolCode` — the tool an AI Agent can invoke, **not** the regular workflow Code node.\n\n---\n\n## ⚠️ This is NOT the Code node\n\nThe Custom Code Tool looks like a Code node in the editor — same JavaScript editor, similar layout — but it is a **completely different node** from a different package with a **different runtime contract**.\n\n| | Code node | Custom Code Tool |\n|---|---|---|\n| **Node type** | `n8n-nodes-base.code` | `@n8n\u002Fn8n-nodes-langchain.toolCode` |\n| **Package** | `n8n-nodes-base` | `@n8n\u002Fn8n-nodes-langchain` |\n| **Invoked by** | Previous node (workflow flow) | AI Agent (LangChain) |\n| **Input** | `$input.all()` — item stream | `query` — string or object from LLM |\n| **Return** | `[{json: {...}}]` (items array) | **A string** |\n| **`$fromAI()`** | N\u002FA | **Not available** (see Errors) |\n| **HTTP helper** | `this.helpers.httpRequest` (auth helpers blocked) | Not exposed to the tool sandbox |\n| **State** | Per-run execution data | No `getContext`, no `$getWorkflowStaticData` |\n\n**If you treat it like a Code node, it fails.** The rest of this skill covers the Code Tool's actual contract.\n\n---\n\n## Quick Start\n\n### Minimal JavaScript Code Tool\n\n```javascript\n\u002F\u002F `query` is whatever the AI sent (a string by default)\nreturn `You asked: ${query}`;\n```\n\n### Minimal Python Code Tool\n\n```python\n# `_query` is whatever the AI sent (a string by default)\nreturn f\"You asked: {_query}\"\n```\n\n### Essential Rules\n\n1. **Return a string.** Numbers are auto-converted. Anything else throws `\"The response property should be a string, but it is an object\"`.\n2. **Input variable is fixed**: `query` (JS), `_query` (Python). You cannot rename it.\n3. **Do NOT use `$fromAI()`** inside the Code Tool sandbox — it throws `\"No execution data available\"`.\n4. **Do NOT use `[{json: {...}}]`** return format — that's for Code nodes. Throws `\"Wrong output type returned\"`.\n5. **Use a descriptive tool name** (letters\u002Fnumbers\u002Funderscores, v1.1+). The agent calls the tool by its name.\n6. **Write a precise description** — the LLM decides whether to invoke the tool based on it.\n\n---\n\n## The Two Input Modes\n\nThe Code Tool has two input shapes, controlled by `specifyInputSchema`:\n\n### Mode 1: Unstructured (default, `specifyInputSchema: false`)\n\nThe AI passes **a single string** as `query`. If you need multiple fields, the AI has to stuff them into that one string and you parse them out. In practice, LLMs will happily pass a JSON string if your description tells them to.\n\n```javascript\n\u002F\u002F Parse a JSON string the AI sent\nlet params;\ntry {\n  params = typeof query === 'string' ? JSON.parse(query) : query;\n} catch (e) {\n  throw new Error('Expected a JSON object. Parser said: ' + e.message);\n}\nconst price = Number(params.price);\nconst months = Number(params.months);\n\u002F\u002F ...\nreturn JSON.stringify({ monthly_payment: \u002F* ... *\u002F });\n```\n\n**Pros**: simplest to set up, one field to describe.\n**Cons**: no schema validation — if the LLM forgets a field, the tool throws at runtime.\n\n**Best for**: quick prototypes, tools with one natural input (a question, a URL, a text blob).\n\n### Mode 2: Structured (`specifyInputSchema: true`)\n\nThe tool becomes a LangChain `DynamicStructuredTool`. The LLM sees a typed argument schema and passes a **validated object** as `query`. You access fields directly.\n\n```javascript\n\u002F\u002F query is now an object matching your schema\nconst price = query.price;\nconst months = query.months;\nconst residual_percent = query.residual_percent;\n\nconst monthly = computeAnnuity(price, months, residual_percent);\nreturn JSON.stringify({ monthly_payment: monthly });\n```\n\nSchema is defined via either:\n- `schemaType: \"fromJson\"` + `jsonSchemaExample` (n8n v≥1.3) — paste an example JSON, n8n infers the schema\n- `schemaType: \"manual\"` + `inputSchema` — write a full JSON Schema yourself\n\n**Pros**: LLM gets type hints, invalid calls rejected before your code runs, cleaner code.\n**Cons**: a little more setup; requires n8n version with schema support.\n\n**Best for**: production tools with multiple typed parameters (calculators, API wrappers, anything with numeric fields the LLM tends to stringify).\n\n**See**: [references\u002FINPUT_SCHEMA.md](references\u002FINPUT_SCHEMA.md) for complete schema setup.\n\n---\n\n## Return Format\n\n**The return value must be a string.** The LLM reads it as the tool's observation.\n\n```javascript\n\u002F\u002F ✅ String\nreturn \"42\";\n\n\u002F\u002F ✅ Number (auto-converted to string by n8n)\nreturn 42;\n\n\u002F\u002F ✅ JSON-encoded structured result (recommended for rich output)\nreturn JSON.stringify({ result: 42, currency: \"SEK\" });\n\n\u002F\u002F ❌ Raw object → \"The response property should be a string, but it is an object\"\nreturn { result: 42 };\n\n\u002F\u002F ❌ Workflow item format → \"Wrong output type returned\"\nreturn [{ json: { result: 42 } }];\n\n\u002F\u002F ❌ Array → \"The response property should be a string, but it is an object\"\nreturn [1, 2, 3];\n```\n\n### Best practice: JSON-stringify structured results\n\nWhen your tool has more than a trivial scalar output, return a JSON string:\n\n```javascript\nreturn JSON.stringify({\n  monthly_payment_sek: 5405,\n  loan_amount: 351920,\n  total_cost_of_credit: 63295\n});\n```\n\nThe LLM parses JSON reliably and can pick the fields it needs to present to the user.\n\n### Error handling: the agent reads your failures\n\nErrors don't just stop the workflow — they go back to the LLM, which usually corrects its call and retries. Use that:\n\n```javascript\n\u002F\u002F Option A: throw — n8n surfaces the message to the agent\nif (!isFinite(price)) throw new Error('price must be a number, e.g. 439900');\n\n\u002F\u002F Option B: return an error string — agent reads it like any tool result\nif (!isFinite(price)) return JSON.stringify({ error: 'price must be a number, e.g. 439900' });\n```\n\nEither way, write error messages **for the LLM**: state what was wrong and what a valid call looks like. A bare `throw new Error('invalid input')` wastes the retry; an instructive message usually fixes the next call.\n\n---\n\n## Tool Name and Description\n\nThese fields are NOT documentation — they are the **tool contract the LLM sees**. Treat them as prompt engineering.\n\n### Name\n- Must match `[A-Za-z0-9_]+` (v1.1+). No spaces, no hyphens, no emoji.\n- Use a verb-y descriptive name: `calculate_car_loan`, `get_weather`, `search_orders`.\n- The agent calls the tool by this name. `Code Tool` (the default) is useless — the agent won't know when to call it.\n\n### Description\n- Explain **when** to use it and **what** to send.\n- If unstructured mode, **include an example of the JSON string** the LLM should send.\n- If structured mode, the schema speaks for itself — just describe purpose.\n\n**Unstructured example (JSON-in-string pattern):**\n```\nDeterministiskt beräknar månadskostnad för billån. Anropa med EN JSON-sträng:\n{\"price\":439900,\"down_payment\":87980,\"interest_rate\":6.95,\"months\":36,\"residual_percent\":50}\nFält: price (SEK), down_payment (SEK), interest_rate (% per år), months, residual_percent (0-99).\n```\n\n**Structured example (schema-defined):**\n```\nDeterministically computes the monthly car-loan payment given price, down payment,\nannual interest rate, term, and residual percent. Use whenever the user asks for\nmonthly cost, total credit cost, or loan breakdown.\n```\n\n---\n\n## Top Errors and Fixes\n\n### Error 1: `\"There was an error: 'Cannot assign to read only property \\\"name\\\" of object: Error: No execution data available'\"`\n\n**Cause**: you called `$fromAI()` inside the Code Tool sandbox.\n\n**Fix**: `$fromAI()` is a helper for **other** tool-enabled nodes (HTTP Request Tool, SendGrid Tool, `toolWorkflow`, etc.) — it's not exposed inside `toolCode`. Read the AI's input from `query` directly (or use `specifyInputSchema` for structured fields).\n\n### Error 2: `\"Wrong output type returned\"`\n\n**Cause**: you returned a workflow-style array like `[{ json: { ... } }]`. That's the Code **node** contract, not the Code **Tool** contract.\n\n**Fix**: return a string. For structured data, `return JSON.stringify(output)`.\n\n### Error 3: `\"The response property should be a string, but it is an object\"`\n\n**Cause**: you returned a plain object or array.\n\n**Fix**: `JSON.stringify()` the result, or coerce to a string.\n\n### Error 4: AI never calls the tool\n\n**Cause**: tool name is generic (`Code Tool`, `My Tool`) or description doesn't clearly state when to use it.\n\n**Fix**: rename to a verb-y name (`calculate_car_loan`), and rewrite the description to explicitly state the trigger conditions (e.g. \"Use this whenever the user asks about monthly cost\").\n\n### Error 5: AI sends garbage into `query`\n\n**Cause**: unstructured tool with a vague description. The LLM guesses at the format.\n\n**Fix**: either (a) include a concrete JSON example in the description, or (b) switch to `specifyInputSchema: true` so the LLM gets a typed schema.\n\n**See**: [references\u002FERROR_PATTERNS.md](references\u002FERROR_PATTERNS.md) for full catalog with reproductions.\n\n---\n\n## What's NOT Available in the Sandbox\n\nThe Code Tool sandbox is **narrower** than the Code node sandbox. Don't assume helpers carry over:\n\n| Helper | Code node | Code Tool |\n|---|---|---|\n| `$input.all()`, `$input.first()`, `$input.item` | ✅ | ❌ |\n| `$node[\"NodeName\"]` | ✅ | ❌ |\n| `$json`, `$binary` | ✅ | ❌ |\n| `$fromAI()` | ❌ | ❌ (despite sitting next to an AI agent) |\n| `this.helpers.httpRequest()` | ✅ | ❌ |\n| `DateTime` (Luxon) | ✅ | ✅ (standard in JS sandbox) |\n| `$jmespath()` | ✅ | ❌ |\n| `this.getContext(...)` | ✅ | ❌ |\n| `$getWorkflowStaticData(...)` | ✅ | ❌ |\n\n**Implication**: the Code Tool is for **pure computation**. If you need an HTTP call, an API lookup, or cross-invocation state, use a different tool node:\n- HTTP Request Tool for external API calls\n- `toolWorkflow` (Call Sub-workflow Tool) for multi-step logic with access to the full Code node sandbox\n- MCP \u002F database tools for persistent state\n\n---\n\n## When to Use Code Tool vs Alternatives\n\nUse **Code Tool** when:\n- ✅ Pure deterministic computation (math, parsing, formatting, validation)\n- ✅ Lightweight transformations the LLM shouldn't do itself (precision math, regex)\n- ✅ You want the code inline in the workflow, not in a separate sub-workflow\n\nUse **`toolWorkflow`** (Call Sub-workflow Tool) when:\n- ✅ You need multiple parameters with clean `$fromAI()` typing\n- ✅ You need access to `this.helpers`, credentials, or other nodes\n- ✅ Logic is reusable across agents\n- ✅ You want structured typed inputs WITHOUT writing a JSON Schema\n\nUse **HTTP Request Tool** when:\n- ✅ The tool is fundamentally a single API call\n- ✅ You want per-parameter `$fromAI()` bindings in URL\u002Fquery\u002Fbody\n\n**Rule of thumb**: if you find yourself wanting `$fromAI()`, you probably want `toolWorkflow` instead of `toolCode`.\n\n---\n\n## Calculator assumptions\n\nThe example computes nominal annuity\u002Fballoon payments, not statutory APR or a lending recommendation. Currency is illustrative, rounding shown is whole-unit display only, and real contracts require exact minor-unit rounding, fee timing and rate conventions. Type\u002Fschema hints do not enforce business constraints; validate finite values, positive integer months, fees and balloon\u002Fprincipal compatibility in code.\n\n## Complete Working Example\n\nAn illustrative calculator fragment requiring installed-version and numerical validation (unstructured, JSON-in-string pattern):\n\n```json\n{\n  \"parameters\": {\n    \"name\": \"calculate_car_loan\",\n    \"description\": \"Computes monthly car-loan payment using an annuity formula with residual\u002Fballoon. Call with a single JSON string. Example: {\\\"price\\\":439900,\\\"down_payment\\\":87980,\\\"interest_rate\\\":6.95,\\\"months\\\":36,\\\"residual_percent\\\":50,\\\"setup_fee\\\":695,\\\"monthly_admin_fee\\\":59}. Required: price, down_payment, interest_rate, months, residual_percent. Optional: setup_fee, monthly_admin_fee (default 0).\",\n    \"language\": \"javaScript\",\n    \"jsCode\": \"if (!query || (typeof query !== 'string' && (typeof query !== 'object' || Array.isArray(query)))) throw new Error('Expected object input');\\nlet params;\\ntry {\\n  params = typeof query === 'string' ? JSON.parse(query) : query;\\n} catch (e) {\\n  throw new Error('Invalid JSON: ' + e.message);\\n}\\n\\nif (!params || typeof params !== 'object' || Array.isArray(params)) throw new Error('Expected object');\\nfor (const key of ['price','down_payment','interest_rate','months','residual_percent']) {\\n  if (typeof params[key] !== 'number' || !Number.isFinite(params[key])) throw new Error(key + ' must be a finite number');\\n}\\nconst price           = Number(params.price);\\nconst down_payment    = Number(params.down_payment);\\nconst interest_rate   = Number(params.interest_rate);\\nconst months          = Number(params.months);\\nconst residual_percent= Number(params.residual_percent);\\nconst setup_fee       = Number(params.setup_fee ?? 0);\\nconst monthly_admin_fee = Number(params.monthly_admin_fee ?? 0);\\n\\nif (!isFinite(price) || price \u003C= 0) throw new Error('price must be > 0');\\nif (down_payment \u003C 0 || down_payment >= price) throw new Error('down_payment must be in [0, price)');\\n\\nif (![price, down_payment, interest_rate, months, residual_percent, setup_fee, monthly_admin_fee].every(Number.isFinite) || price \u003C= 0 || down_payment \u003C 0 || down_payment >= price || interest_rate \u003C 0 || !Number.isInteger(months) || months \u003C 1 || months > 1200 || residual_percent \u003C 0 || residual_percent > 99 || setup_fee \u003C 0 || monthly_admin_fee \u003C 0) throw new Error('Invalid loan inputs');\\nconst principal = price - down_payment;\\nconst residual  = price * (residual_percent \u002F 100);\\nconst r = interest_rate \u002F 100 \u002F 12;\\nconst growth = Math.pow(1 + r, months);\\nconst base = r === 0\\n  ? (principal - residual) \u002F months\\n  : (principal - residual \u002F growth) * r \u002F (1 - 1 \u002F growth);\\nconst monthly_payment = base + monthly_admin_fee;\\nif (!Number.isFinite(monthly_payment) || monthly_payment \u003C 0) throw new Error('Invalid payment; review balloon\u002Fprincipal assumptions');\\n\\nreturn JSON.stringify({\\n  monthly_payment_sek: Math.round(monthly_payment),\\n  loan_amount: Math.round(principal),\\n  residual_value_sek: Math.round(residual),\\n  total_cost_of_credit: Math.round(monthly_payment * months + residual + setup_fee - principal)\\n});\"\n  },\n  \"type\": \"@n8n\u002Fn8n-nodes-langchain.toolCode\",\n  \"typeVersion\": 1.3,\n  \"name\": \"calculate_car_loan\"\n}\n```\n\nWire it into an AI Agent via the `ai_tool` connection type.\n\n---\n\n## Integration with Other Skills\n\n**n8n-code-javascript**: the Code **node** skill. Most JavaScript patterns (arrays, map\u002Ffilter, DateTime) transfer — but I\u002FO contract is different. Don't copy data-access code.\n\n**n8n-node-configuration**: `specifyInputSchema` is a classic displayOptions-driven conditional field. Use `get_node({detail: \"standard\"})` on `@n8n\u002Fn8n-nodes-langchain.toolCode` to see schema-related properties.\n\n**n8n-workflow-patterns**: Code Tool sits inside the \"AI Agent with tools\" pattern. An agent typically has several tools; Code Tool is the \"local compute\" option.\n\n**n8n-validation-expert**: the three Code Tool errors listed above have clear signatures — if validation surfaces \"Wrong output type returned\", you know to switch from array-of-items to a string.\n\n---\n\n## Quick Reference Checklist\n\nBefore deploying a Code Tool:\n\n- [ ] **Node type** is `@n8n\u002Fn8n-nodes-langchain.toolCode` (not `nodes-base.code`)\n- [ ] **Tool name** is descriptive, verb-y, snake_case (e.g. `calculate_car_loan`)\n- [ ] **Description** states when to use the tool and (if unstructured) shows a JSON example\n- [ ] **Input** read from `query` (JS) or `_query` (Python)\n- [ ] **No `$fromAI()`** in the code body\n- [ ] **No `$input` \u002F `$json` \u002F `$helpers`** — those aren't in the sandbox\n- [ ] **Return** is a string (use `JSON.stringify()` for structured output)\n- [ ] **Wired** into an AI Agent via `ai_tool` connection\n- [ ] **Tested** with the exact kind of input the LLM will send (JSON in a string, or schema-validated object)\n\n---\n\n## Additional Resources\n\n- [references\u002FINPUT_SCHEMA.md](references\u002FINPUT_SCHEMA.md) — structured input (DynamicStructuredTool) in depth\n- [references\u002FERROR_PATTERNS.md](references\u002FERROR_PATTERNS.md) — full error catalog with causes and fixes\n\n### Official sources\n- [n8n Custom Code Tool docs](https:\u002F\u002Fdocs.n8n.io\u002Fintegrations\u002Fbuiltin\u002Fcluster-nodes\u002Fsub-nodes\u002Fn8n-nodes-langchain.toolcode\u002F)\n- [ToolCode source](https:\u002F\u002Fgithub.com\u002Fn8n-io\u002Fn8n\u002Fblob\u002Fmaster\u002Fpackages\u002F%40n8n\u002Fnodes-langchain\u002Fnodes\u002Ftools\u002FToolCode\u002FToolCode.node.ts) — the sandbox contract\n- [LangChain tool docs](https:\u002F\u002Fjs.langchain.com\u002Fdocs\u002Fmodules\u002Fagents\u002Ftools\u002F) — DynamicTool \u002F DynamicStructuredTool\n\n---\n\n**Remember**: distinguish unstructured string input from schema-defined object input; output must satisfy the installed Code Tool contract. Node typeVersion is not the same as the n8n application release.\n\n## Limitations\n\n- The Custom Code Tool sandbox and available globals can change with n8n releases; verify the installed node version.\n- Static review cannot establish runtime permissions, network reachability, or the behavior of external services.\n- This skill does not authorize arbitrary code execution or testing against production data.\n",{"name":5,"risk":34,"author":49,"source":50,"license":14,"date_added":51,"description":7,"source_repo":52,"source_type":27,"license_source":53},"Romuald Czlonkowski","https:\u002F\u002Fgithub.com\u002Fczlonkowski\u002Fn8n-skills\u002Ftree\u002Fmain\u002Fskills\u002Fn8n-code-tool","2026-07-21","czlonkowski\u002Fn8n-skills","https:\u002F\u002Fgithub.com\u002Fczlonkowski\u002Fn8n-skills\u002Fblob\u002Fmain\u002FLICENSE","7bf2279c8a65758319526a721d5c4b75683aec9c","skills\u002Fantigravity-n8n-code-tool",3,"https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections","https:\u002F\u002Fgithub.com\u002Fboisenoise","2026-11-12 14:21:24",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add boisenoise\u002Fskills-collections --skill n8n-code-tool",{"tool":66,"command":67},"bunx","bunx skills add boisenoise\u002Fskills-collections --skill n8n-code-tool",{"tool":69,"command":70},"pnpm","pnpm dlx skills add boisenoise\u002Fskills-collections --skill n8n-code-tool","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-n8n-code-tool\u002FSKILL.md",true,[74,80],{"path":75,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":78,"sourceHtmlUrl":79},"references\u002FERROR_PATTERNS.md","REFERENCE","参考文档",6902,"https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-n8n-code-tool\u002Freferences\u002FERROR_PATTERNS.md",{"path":81,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":82,"sourceHtmlUrl":83},"references\u002FINPUT_SCHEMA.md",7032,"https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-n8n-code-tool\u002Freferences\u002FINPUT_SCHEMA.md",[85,113,139,161,180,203],{"skillNo":86,"name":87,"nameZh":6,"description":88,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":89,"licenseFileUrl":90,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":44},"01M6WNH92BHVFXHGPDZCPJ0AG0","web-access","Use Treg for public web or platform data only when existing search, browser and connected tools cannot cover the task, with explicit cost and data boundaries.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-web-access\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-web-access\u002FSKILL.md",[],[94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,34,109,110,111,112,28],"web","access","web access","official","development","browser","search","data","Tools","read","fetch","only","youtube","free tools","platform","free","cover","normal","when",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":89,"licenseFileUrl":117,"sourceHtmlUrl":118,"categories":119,"keywords":125,"publishedAt":44},"01M6WNF9XAYAB2CZDDJBAKNM93","treg","Use the Treg CLI or MCP catalog to discover, price and call authorized external tools with team-scoped credentials and a user-approved budget.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-treg\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-treg\u002FSKILL.md",[120],{"categoryNo":121,"categoryName":122,"taxonomyType":123,"taxonomyTypeDesc":124},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[115,126,127,43,97,98,39,102,128,129,130,131,132,133,134,34,135,136,137,138,28],"MCP","cli","Budget","credentials","team","catalog","use","call","discover","external tools","with","scoped","blob",{"skillNo":140,"name":141,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":89,"licenseFileUrl":143,"sourceHtmlUrl":144,"categories":145,"keywords":149,"publishedAt":44},"01M6WN93MEAZ4E41DYAHJRPHQT","recruit","Turn a job description into an evidence-linked candidate shortlist through Treg, with job-related ranking and optional authorized business contact enrichment.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-recruit\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-recruit\u002FSKILL.md",[146],{"categoryNo":147,"categoryName":148,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000038","人力资源",[141,43,97,39,38,150,151,152,153,154,34,155,156,157,136,31,158,159,160,138,115,28],"email","enrichment","business","evidence","phone","ranking","post","job description","person","candidate","reason",{"skillNo":162,"name":163,"nameZh":6,"description":164,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":89,"licenseFileUrl":165,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":44},"01M6WN8R5RXSMHM9B4D9FAFX42","rea-growth","Analyze a company’s public growth and content through Treg, distinguish observations from hypotheses, and produce an evidence-linked playbook within an approved budget.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-rea-growth\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-rea-growth\u002FSKILL.md",[],[169,170,171,43,97,39,172,173,38,174,128,175,176,177,153,34,178,179,138,115,28],"growth","rea","rea growth","produce","content","playbook","marketing","analyze","public","observations","company",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":89,"licenseFileUrl":184,"sourceHtmlUrl":185,"categories":186,"keywords":187,"publishedAt":44},"01M6WN2EVE3RQRGWAKBT4S7YT2","make-ugc","Create original AI UGC-style product videos through Treg: research hooks, approve a licensed presenter and voice, generate clips, add captions and report costs.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-make-ugc\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-make-ugc\u002FSKILL.md",[],[188,189,43,190,97,191,39,192,193,194,195,196,34,197,198,199,200,201,202,138],"make","make ugc","research","create","Video","Captions","ads","short","hooks","head","style","niche","trending","talking-head","approve",{"skillNo":204,"name":205,"nameZh":6,"description":206,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":89,"licenseFileUrl":207,"sourceHtmlUrl":208,"categories":209,"keywords":210,"publishedAt":44},"01M6WN10ARAA63Y8K1YNGXJ2RM","lead-signals","Find and qualify public buying signals through Treg, rank fitting business accounts and optionally enrich authorized business contact information.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-lead-signals\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-lead-signals\u002FSKILL.md",[],[211,212,213,43,97,39,214,215,152,216,217,34,218,219,220,221,222,223,224,138],"signals","lead","lead signals","how","find","ready","as","how to","qualify","people","information","enrich","changes","funding"]