AI Node

Puts a language model in the middle of a flow. At its simplest it takes a payload, runs a prompt, and passes the answer downstream. At its most involved it is an agent: it decides which of your other nodes to call, remembers previous conversations, and returns a validated object rather than prose. The panel is organised in tabs, and so is this page.

ℹEvery call is billed against your provider credential. HostWebhook does not proxy through a shared key, and a node inside a Loop is one call per item.

Config — provider, credential, prompts

Provider and credential

Six providers: Anthropic, OpenAI, Google, Groq, OpenRouter and Ollama. Picking one filters the credential picker to keys of that type; switching provider clears the selected credential, because a key from one is meaningless to another. Ollama points at your own host, so it is the path for models that never leave your infrastructure.

A new AI Node starts with no provider and paused. Picking the provider unlocks the credential and the model; until it has one the node doesn't run, and a Run Test says so. Activate it once it's set up.

The model comes from the credential. You pick it when you create the credential, and every AI Node that uses that credential runs it — the node page shows it read-only, with a link to change it in the credential. Through the API it works the same way: if the node's credential sets a model, a model sent on create or update is replaced by the credential's. Only a node without a credential, or with one that sets no model, keeps the model you send — and a model from another provider (say claude-haiku-4-5 on an OpenAI node) is a 400.

When a provider retires a model, a node whose credential still names it fails with <Provider> retired the model "<id>". Pick another model in the credential this AI Node uses. — for example Groq retired the model "groq/compound". It says so for Groq, OpenAI, Google and what OpenRouter passes on; Anthropic answers a retired model the same way as a mistyped one, so there you get the provider's own error.

System prompt and user message

These two belong to the Agent task. The other tasks have their own instructions and call the user message by what it is — the text they read. See five tasks below.

The system prompt sets the role and the rules and is usually static. The user message is where the payload goes, through the same templating as everywhere else: {{payload.question}}, or a reference to another node's output. Both boxes autocomplete the fields the incoming payload actually has. Left empty, the model gets an empty message — the system prompt and none of the incoming data — and the panel warns you.

Audio transcription

Optional. When the payload carries an audio file, the node can transcribe it first and feed the text to the prompt — which is what turns “a voice note arrived” into a flow you can act on.

Images and videos

Any file in the payload reaches the model without extra wiring — under _file the way triggers and the HTTP node leave it, or moved to another field by a Transform. The same file is sent once even if the payload carries it twice. Images go to every provider as images. In the prompt, a file written with {{payload._file}} shows up as its name, not as its JSON.

Videos (up to 18 MB) are watched in full by Gemini: image and sound in the same call. Other providers can't watch videos; for them, connect a Google Gemini credential under Video on the node, and Gemini describes each video — what's on screen, in order, and what's said — before your model answers from that description. Without it, the model is told a video arrived that it can't see.

Settings

  • Max tokens — caps the answer, not the prompt. Left empty, Anthropic models get 8,192, because Anthropic needs a limit on every call; every other provider uses its own default, usually the model's maximum. A value above what the model can write in one answer is lowered to that maximum before the call, with no error: claude-haiku-4-5 writes up to 64,000 tokens, claude-sonnet-5 up to 128,000 and gemini-2.5-flash up to 65,536 — so 200,000 on a Gemini 2.5 Flash node goes out as 65,536. The panel shows the model's maximum under the field. HostWebhook knows it for the Anthropic, OpenAI and Gemini models in its list and for gpt-oss on Groq. With a model it doesn't know, and with any model through OpenRouter (which serves each model with its own limit) or Ollama, the value goes out as you wrote it: if the provider rejects it as too high, OpenAI, Groq, OpenRouter and Ollama models are asked once more without the cap and write their own maximum; Anthropic and Gemini return the provider's error.
  • Temperature — 0 to 1, in steps of 0.05. Low for extraction and classification, higher for drafting. The range is deliberately 0–1 across the whole dashboard even where a provider would accept more, so a value means the same thing whichever model you pick. A new node starts on the model's own default. Some models — OpenAI's gpt-5.x and o-series — only accept theirs: if the model rejects the value you set, the call is repeated once without it instead of failing. Gemini 3.6 and later ignore temperature, so HostWebhook doesn't send it — the panel says so under the slider. That covers gemini-3.6-flash, gemini-3.7-flash, every later version and the -latest aliases. Older Gemini models still get it, and if Google rejects it the call is repeated once without it.

What this node does — five tasks

Right under the credential, Config asks what this node does. It does one task at a time, and the panel shows only what that task uses.

TaskIt readsDownstream getsConfigured with
AgentThe user messageThe answer — text, JSON or Structured JSON (Output tab)System prompt, tools, memory, guardrails
SummarizeA text, however longaiResponse with the summaryA strategy and, optionally, its prompts
ExtractA text, or an imageThe fields you define, at the top of the payloadThe fields and, optionally, instructions
ClassifyA textThe input plus category; one output per categoryCategories and an optional context
SentimentA textThe input plus sentiment; four outputsA confidence floor, topics and an optional context
ℹOnly Agent is an agent. The other four read a text and answer: they don't call tools, don't read or write memory, don't apply agent guardrails, and don't send the agent's system prompt. While one of them is picked, the Tools, Guardrails and Memory tabs show off. Nothing is deleted: pick Agent again and everything you set up is still there.

Max tokens, temperature, and the audio and video settings apply to every task. The text a task reads is the same field as the Agent's user message, so the payload fields autocomplete there too.

Summarize, step by step

Turns a text of any length into a summary. A text that fits the model goes in one call; a longer one is cut into chunks, each chunk is summarised, and the partial summaries are merged.

1

Pick Summarize

In Config → What this node does, pick Summarize. The strategy starts on Auto, which is right for most texts.

2

Point it at the text

In Text to summarize, insert the field that holds it — {{payload.article}} — or paste the text. Left empty, the node looks for payload.text, content, body, message or transcript, in that order, and then for the longest text field in the payload. The text of attached files (PDF, CSV, documents) is added, and voice notes and videos are transcribed first. With nothing to read, the node stops with an error that says so.

3

Choose a strategy

StrategyHow it worksCalls to the model
AutoStuff when the text fits the chunk size; Map-Reduce when it doesn't.One, or one per chunk plus one
StuffThe whole text in a single call. Cheapest and best — as long as it fits.One
Map-ReduceEach chunk is summarised in parallel, then one more call merges the partial summaries. Fast on long texts.One per chunk, plus one
RefineWalks the chunks in order: summarises the first, then rewrites that summary with each new chunk. Slower, and keeps the thread of a story.One per chunk, one after another
4

Adjust the chunks (Auto, Map-Reduce and Refine)

  • Chunk size, in characters. Empty picks it from the model's context window, which is almost always what you want. Accepts 500 to 200,000. It is also the size Auto compares the text against.
  • Chunk overlap, in characters, default 200 (0 to 5,000). The end of each chunk is repeated at the start of the next, so a sentence cut in two isn't lost.
5

Change the prompts (optional)

Under Prompts each strategy shows its own. Empty uses the built-in one. Keep the placeholder — it is where the text goes:

StrategyPromptPlaceholder
StuffStuff prompt{{text}} — the whole text
Auto, Map-ReduceMap prompt (per chunk){{chunk}} — one chunk
Auto, Map-ReduceCombine prompt (final summary){{summaries}} — the partial summaries, numbered
RefineInitial prompt (first chunk){{chunk}}
RefineRefine prompt (next chunks){{existing}} — the summary so far, and {{chunk}}

The prompts also take payload fields, other nodes' data ({{$("CRM").customer}}) and the date. With the prompts left empty, the summary comes out in the same language as the text. To choose the language, length or format yourself, write it in the prompt that produces the final text: the Stuff prompt, the Combine prompt, or the Refine prompt. The agent's system prompt is not sent.

6

Run a test and wire what follows

The summary comes out as {{payload.aiResponse}}. The trace in Logs says which strategy Auto picked and how many chunks there were.

⚠Map-Reduce and Refine make one call per chunk, and every call is billed to your credential. A book-length text is dozens of calls.

Extract, step by step

Reads a text — an email, a PDF, a photo of an invoice — and returns the fields you define, ready for a Sheets row or a database insert. The provider enforces the shape: every field you list arrives, with the type you gave it.

1

Pick Extract

In Config → What this node does, pick Extract.

2

Point it at the text

In Text to extract from, insert the field — {{payload.email_body}}. The text of attached files is added, and images go to the model as images, so a photo of a receipt works on its own. With no text and no image or audio, the node stops with an error that says so instead of inventing values.

3

Define the fields

Three ways, under Fields:

  • Fields — one row per field. The name becomes the key downstream (letters, digits and _; a space turns into _). The type is Text, Number, Yes / No or Date (always YYYY-MM-DD). The description is what the model reads to know what goes there — the better it is, the better the result. Required on means the field always gets a value; off means it comes out null when the text doesn't say.
  • From example — paste what one result should look like. Every key becomes a required field with the type of its value; a list is read from its first item.
  • JSON Schema — the schema itself, with "type": "object" at the top. For lists and nested objects.
4

Adjust the instructions (optional)

Instructions start with the default: extract only what is in the text, and leave a field empty rather than guess. Add your own rules — “amounts in MXN, without the currency sign” — or replace them. The list of fields is added for you. Reset to default brings the original back.

5

Use the fields downstream

jsonOutput payload
{
  "company": "Acme S.A. de C.V.",
  "total": 1160.5,
  "due_date": null
}

Read them as {{payload.company}}. Only the fields go downstream; to reach the original data, use the node it came from — {{$("Webhook").body}}.

ℹIf you know n8n's Information Extractor: same three ways to define the fields, same editable instructions. The difference is that here the provider forces the schema, so there is no second call to repair a malformed answer, and a field that isn't required arrives as null instead of missing.

Classify, step by step

1

Pick Classify and point it at the text

In Config → What this node does, pick Classify, and in Text to classify insert the field — {{payload.message}}.

2

Write the categories

Each category has a name and a description; the model reads both. Each becomes an output on the canvas — wire what should happen for it. Let the classifier answer “Other” gives it a way out when nothing fits, and a confidence threshold sends weak picks there too. Other has no output: the item stops.

3

Add context (optional)

Context says who wrote the text and what it's about — “support tickets from a bank's customers”. It helps with borderline cases.

4

What goes downstream

The input, unchanged, with category on top and _classifier beside it (confidence and the model's one-line reasoning).

Sentiment, step by step

Reads how the author of a text feels — a review, a support message, a survey answer — and sends the item down one of four outputs.

1

Pick Sentiment and point it at the text

In Config → What this node does, pick Sentiment, and in Text to analyze insert the field — {{payload.review}}.

2

Wire the four outputs

OutputWhen
NegativeComplaints, frustration, criticism
NeutralFactual, mixed, or no clear feeling
PositivePraise, satisfaction, enthusiasm
UnclearBelow the confidence floor, or an answer that can't be read

The model only ever answers negative, neutral or positive. Unclear is where the node sends an item it isn't sure about — typically a person reviews it.

3

Set a confidence floor (optional)

Confidence floor is off by default: every item gets a label. Turn it on (it starts at 60%) and move the slider, in steps of 5%; below it, the item goes to Unclear. A provider that doesn't report the model's confidence never sends an item to Unclear because of the floor.

4

Read topics one by one (optional)

Under Per topic, add up to 12 topics — shipping, price, support. Each gets its own label and score on top of the overall one. Topics don't branch: a review can praise the price and hate the shipping, so routing follows the overall label. A topic the text doesn't mention is skipped.

5

Add context (optional)

Context says who wrote the text and what it's about. It helps with irony and with texts that are mostly facts.

6

What goes downstream

jsonOutput payload
{
  "review": "The package arrived two weeks late.",
  "sentiment": { "label": "negative", "score": -0.7, "confidence": 0.9 },
  "_sentiment": {
    "reasoning": "Complains about the delivery time.",
    "port": "negative",
    "aspects": [{ "aspect": "shipping", "label": "negative", "score": -0.8 }]
  }
}

The input stays as it came. Read the label as {{payload.sentiment.label}} and the score, from -1 to 1, as {{payload.sentiment.score}}. _sentiment.port says which output the item took, and the topics are in _sentiment.aspects.


Output — three formats (Agent)

The Output tab sets the shape of the Agent's answer. The other tasks have their own, described above.

ModeYou getUse for
TextaiResponse with the proseReplies and drafts
JSONThe parsed object, spread at the top levelFree-form extraction
StructuredAn object validated against a schema you defineAnything a later node depends on by field name

Prefer Structured over JSON whenever something downstream reads a specific field. JSON mode trusts the model to keep its shape; structured mode makes the shape a contract, and a parse failure becomes visible instead of arriving as prose in a field that expected a number.

What downstream nodes receive

jsonOutput payload
{
  "_meta": { "iterable": false, "count": 1 },
  "sentiment": "negative",
  "urgency": 4
}

The payload handed downstream is clean: every key the node uses for its own bookkeeping — tool calls, token counts — is stripped, so your templates read {{payload.sentiment}} and not a nested debug structure. When a JSON parse fails, the raw text comes through as aiResponse and _meta.parseError is set — worth a Filter node if the flow must not continue on garbage.

ℹThe chat widget and the trace panel see a richer shape, with _toolCalls and _tokens, because they exist to show that bookkeeping. Same call, two representations, on purpose.

Tools — what the model is allowed to do

Tools turn the node from “answer this” into an agent. The model decides which to call, with what arguments, and how many times. Seven kinds can be attached:

  • Built-in tools — the ones HostWebhook ships. current_datetime answers in the node's time zone — the one set on the node, or the workspace's — unless the model asks for another; wikipedia searches the Wikipedia of the question's language (lang, English by default).
  • Custom HTTP tools — a URL, a method, and the parameters you declare. A {param} in the URL is replaced with the model's argument of that name; the other arguments go in the query string for GET and HEAD, and in a JSON body for POST, PUT, PATCH and DELETE.
  • Node tools — another node in the workspace exposed as a callable. This is how an agent sends an email or writes a row.
  • MCP servers — a catalogue of tools from an MCP server: an external one (GitHub, a custom URL — managed in Settings → MCP Servers), or one of your own HostWebhook MCP servers. Pick a HostWebhook server from the list and the credential is minted for you — no token to copy. Nodes exposed in a server show In MCP · <server> on the canvas.
  • Tunnel tools — the same, over a reverse tunnel to a private host. Only these have a “Let AI handle path and method” switch, for APIs where the model should choose the route; a path that climbs out of the tunnel (.., also encoded) is refused and the model is told why.
  • Vector Stores — each store becomes a query_<store> tool. See Vector Stores.
  • Voice synthesis — lets the agent speak its answer.
⚠A node only appears in the picker if it has been made available to AI — exposure is opt-in per node, not automatic. If a node you expect is missing from the list, enable it on that node first.
ℹA node in AI toolkit mode runs only the tool it is asked for. An event that names none — a pipeline connection left over from before the switch, or a Run Test without an operation — is refused, instead of running the node's hidden single operation. To test a tool from the node's page, put its name in operation along with its arguments.
ℹDeleting a node removes its tools from every AI Node that used them, so the model stops seeing tools that can no longer run. The AI Node shows a notice naming the node and how many tools went with it, and its card on the canvas shows a ⚠, until you click Got it.

Guardrails

Two layers, and they are not the same thing:

  • Auto-applied — derived from the tools you attached. Give the agent a toolkit that can delete, and the matching rules appear on their own.
  • Agent guardrails — a checklist you opt into, spelling out what the agent must not do.
  • Block destructive tool calls — a hard switch in the Advanced tab. With it on, the agent refuses any tool that overwrites or deletes: tools whose names match the destructive patterns (delete_*, drop_*, force_push…) and every toolkit operation marked destructive — update_row in Sheets, update_document and delete_document in MongoDB, execute_sql in PostgreSQL. The switch lists which of this agent's tools it would stop, and each of them carries a destructive chip in the Tools tab. A refused call doesn't wait for anyone: nothing unlocks it from the chat, not even the user confirming. The model is told not to ask for confirmation, to say it can't do that here and to offer what it can do instead. To let the agent run those tools, turn the switch off.
  • Blocked on its node — every toolkit node can block tools for every agent that uses it: Gmail, Email, Calendar, Drive, Telegram, Discord, Slack, Sheets, Docs, Contacts, MongoDB and PostgreSQL, under Block these tool calls in the node's AI Toolkit section (see MongoDB). A blocked tool is not offered to the model or to an MCP client, shows blocked on its node in the Tools tab, and is refused if called anyway.

The panel nags with a banner when an agent has tools and no guardrails. That is deliberate: prompt text is a request, a blocked call is a rule.


Memory — three backends

Off by default. Turned on, the node recalls previous exchanges for the same session id — usually {{payload.sessionId}}, whatever identifies one conversation in your data.

BackendWhere it livesCounts against your plan
Built-inManaged by HostWebhook, semantic recallYes — text counts toward managed storage
External MongoDBYour cluster, collection you nameNo
External PostgreSQLYour cluster, table you nameNo

Alongside the backend: recall limit (how many past records enter the prompt), max records per session (when to start forgetting), and ingest mode (what gets written back).

If the memory store doesn't answer — an external database that is down, or a user that can read but not write — the node still answers, just without its memory, and Monitoring shows an AI Memory warning with the reason.

ℹMemory is not the same feature as a Vector Store. Memory is per-conversation and written by the node itself; a vector store is a corpus you curate and query. They live in different collections and are configured in different places.

Answering a webhook in Sync mode

When a webhook in Sync response mode feeds this node, the caller gets this node's answer: status 200 with the same output the next node receives, without its internal _ fields — or 500 with the reason if the AI call fails. The flow keeps running after the reply. If another AI Node or a Schema Validator comes later on the same path, that one answers instead. The Config tab says so when it applies. The whole contract, and how long the caller can wait, is in Sync responses.


Logs and audit

  • AI call logs — every call with its prompt, answer and token counts.
  • Tool call audit — what the agent invoked, with arguments, result and duration. The first place to look when an agent did something surprising.
  • Signals worth investigating — the panel's own reading of the logs: repeated failures, tools that always error, calls that stand out.

Gotchas

  • Text mode and Output mode used to fight. The canonical field is the Output tab's mode; if an old node behaves as though it were still returning JSON, re-pick the mode there once.
  • An agent with no guardrails will do what the prompt asks. Including the parts you did not mean literally. Attach the checklist.
  • Memory recall costs tokens on every call — each recalled record is prompt input you pay for. Keep the recall limit honest.
  • A tool the model never calls is usually a description problem. The model reads only the tool's name and description when deciding. Both are editable; make them say when to use it.