Building nodes
Nodes can be built using one of two styles. To identify which style an existing node uses: - **Declarative-style** — no `execute` method. Instead, the node has `requestDefaults` and parameters use `routing` (with `routing.request`, `routing.send.preSend`, `routing.output.postReceive`, etc.) to describe HTTP calls. See `.agents/nodes-declarative.md` - **Programmatic-style** — has an `async execute(
Overview
Building nodes
Overview
Community nodes depend on n8n-workflow package that has different interfaces,
classes and helper functions.
Nodes can be built using one of two styles. To identify which style an existing node uses:
- Declarative-style — no
executemethod. Instead, the node hasrequestDefaultsand parameters userouting(withrouting.request,routing.send.preSend,routing.output.postReceive, etc.) to describe HTTP calls. See.agents/nodes-declarative.md - Programmatic-style — has an
async execute(this: IExecuteFunctions)method that manually calls APIs (viathis.helpers.httpRequest/httpRequestWithAuthentication), loops over items, and builds the return array. See.agents/nodes-programmatic.md
Node description
Nodes have description which defines:
displayName,nameicon,group,versioninputs,outputsproperties- Optional
subtitle,usableAsTool, etc and an optionalexecutefunction for programmatic-style nodes.
Example node description (simplified, using WordPress only as an example):
description: INodeTypeDescription = {
displayName: 'Wordpress',
name: 'wordpress',
icon: 'file:wordpress.svg',
group: ['output'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Wordpress API',
defaults: {
name: 'Wordpress',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'wordpressApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{ name: 'Post', value: 'post' },
{ name: 'Page', value: 'page' },
{ name: 'User', value: 'user' },
],
default: 'post',
},
// other properties for specific resources and operations
],
};
Description fields
inputsandoutputsspecify which inputs and outputs a node has.- Most nodes will need only 1 main input and 1 main output, unless
there is specific reason to have something else (e.g. a node like
Ifthat has atrueandfalseoutputs).
- Most nodes will need only 1 main input and 1 main output, unless
there is specific reason to have something else (e.g. a node like
usableAsTool- Set to
trueto allow n8n to use this node as a tool for the AI agent. - Set to
falseor omit this if node works heavily with binary data which tools don't support
- Set to
propertiesdefine the UI parameters- Use the convention: first a "Resource" parameter and for each resource an "Operation" parameter.
- You can choose to not follow this convention ONLY if it's not applicable to the node you're developing (i.e. data transformation nodes, etc.)
Resource and operation pattern
Example "operations":
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['post'],
},
},
options: [
{ name: 'Create', value: 'create', description: 'Create a post', action: 'Create a post', },
{ name: 'Get', value: 'get', description: 'Get a post', action: 'Get a post', },
{ name: 'Get Many', value: 'getAll', description: 'Get many posts', action: 'Get many posts', },
{ name: 'Update', value: 'update', description: 'Update a post', action: 'Update a post', },
],
default: 'create',
},
];
In your implementation:
- Replace
postand operation names with the real resource and operations for the target API.
Example properties for "Create post" operation:
{
displayName: 'Title',
name: 'title',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
},
},
description: 'The title for the post',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['post'],
operation: ['create'],
},
},
options: [
{
displayName: 'Content',
name: 'content',
type: 'string',
default: '',
description: 'The content for the post',
},
// Add more fields as needed for the real API
],
},
];
Important:
- In a real node, replace
post,Title,Content, etc. with the real names from the target API. - Do not reuse these exact WordPress-specific field names unless the node is actually for WordPress.
- Remember that these examples are incomplete and n8n provides a lot of options for defining properties. Refer to their docs, when in doubt
General guidelines
iconproperty can either be a string, which starts withfile:and contains a path to a PNG or an SVG. That path is relative to the current file, you can reference icons in other folders:file:../icon.svg. If the node has different icons for light and dark mode, provide an object for theiconproperty:{ light: 'file:icon.light.svg', dark: 'file:icon.dark.svg' }- For operations that are supposed to return multiple items, like "Get Many
Posts", make sure you return those items, instead of single object that has
them. I.e. if you have an object like
{ data: [{ ... }, { ... }], count: 2 }, then return the items insidedataarray - If the API response is complex, you can add a "Simplify Output" toggle. When
it's
false- return the raw response. If it'strue- return a more user-friendly response with only the essential data - For "Get Many" operations add "Return All" toggle that would return all of
the items, and a "Limit" parameter to limit the number of items, if "Return
All" is
false - Don't forget to mark required properties as
required: true - Use camelCase for property names