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.
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-5writes up to 64,000 tokens,claude-sonnet-5up to 128,000 andgemini-2.5-flashup 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-latestaliases. 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.
| Task | It reads | Downstream gets | Configured with |
|---|---|---|---|
| Agent | The user message | The answer — text, JSON or Structured JSON (Output tab) | System prompt, tools, memory, guardrails |
| Summarize | A text, however long | aiResponse with the summary | A strategy and, optionally, its prompts |
| Extract | A text, or an image | The fields you define, at the top of the payload | The fields and, optionally, instructions |
| Classify | A text | The input plus category; one output per category | Categories and an optional context |
| Sentiment | A text | The input plus sentiment; four outputs | A confidence floor, topics and an optional context |
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.
Pick Summarize
In Config → What this node does, pick Summarize. The strategy starts on Auto, which is right for most texts.
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.
Choose a strategy
| Strategy | How it works | Calls to the model |
|---|---|---|
| Auto | Stuff when the text fits the chunk size; Map-Reduce when it doesn't. | One, or one per chunk plus one |
| Stuff | The whole text in a single call. Cheapest and best — as long as it fits. | One |
| Map-Reduce | Each chunk is summarised in parallel, then one more call merges the partial summaries. Fast on long texts. | One per chunk, plus one |
| Refine | Walks 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 |
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.
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:
| Strategy | Prompt | Placeholder |
|---|---|---|
| Stuff | Stuff prompt | {{text}} — the whole text |
| Auto, Map-Reduce | Map prompt (per chunk) | {{chunk}} — one chunk |
| Auto, Map-Reduce | Combine prompt (final summary) | {{summaries}} — the partial summaries, numbered |
| Refine | Initial prompt (first chunk) | {{chunk}} |
| Refine | Refine 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.
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.
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.
Pick Extract
In Config → What this node does, pick Extract.
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.
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 (alwaysYYYY-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 outnullwhen 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.
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.
Use the fields downstream
{
"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}}.
null instead of missing.Classify, step by step
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}}.
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.
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.
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.
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}}.
Wire the four outputs
| Output | When |
|---|---|
| Negative | Complaints, frustration, criticism |
| Neutral | Factual, mixed, or no clear feeling |
| Positive | Praise, satisfaction, enthusiasm |
| Unclear | Below 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.
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.
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.
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.
What goes downstream
{
"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.
| Mode | You get | Use for |
|---|---|---|
| Text | aiResponse with the prose | Replies and drafts |
| JSON | The parsed object, spread at the top level | Free-form extraction |
| Structured | An object validated against a schema you define | Anything 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
{
"_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.
_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_datetimeanswers in the node's time zone — the one set on the node, or the workspace's — unless the model asks for another;wikipediasearches 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 forGETandHEAD, and in a JSON body forPOST,PUT,PATCHandDELETE. - 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.
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.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_rowin Sheets,update_documentanddelete_documentin MongoDB,execute_sqlin 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.
| Backend | Where it lives | Counts against your plan |
|---|---|---|
| Built-in | Managed by HostWebhook, semantic recall | Yes — text counts toward managed storage |
| External MongoDB | Your cluster, collection you name | No |
| External PostgreSQL | Your cluster, table you name | No |
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.
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.