AI
Turns unstructured text into something you can query. Give it a comment and a list of categories and it returns one of them; give it a paragraph and a set of fields and it returns them filled in.
Type: ai · Category: AI · Ports: one input · one output


When to use it
- Classifying free-text operator comments into a reportable column
- Extracting fields from a message a supplier sends in prose
- Summarising a long shift note into something a dashboard can show
Anything with a deterministic answer. If a rule can decide it, write the rule — it is faster, free, and it cannot change its mind.
Settings
| Setting | Key | Default | Purpose |
|---|---|---|---|
| Prompt | promptTemplate | — | The instruction, templated from the message. |
| Output mode | outputMode | fields | fields (structured) or a single choice. |
| Output fields | outputFields | [] | The structure to extract. |
| Choices | choices | [] | The permitted answers, for classification. |
| Output path | outputPath | payload.classification | Where the result is written. |
| Skills | skills | [] | What it may look up. At most eight; a warning past five. |
| Temperature | temperature | 0 | Determinism. Leave at 0 for classification. |
| Max tokens | maxTokens | 1024 | Ceiling on the answer. |
| Tool iterations | maxToolIterations | 3 | How many look-up rounds the node may take. Bounds the loop so an unattended node gives up rather than grinding. |
| Timeout | timeoutMs | 15000 | The node's own wall clock, independent of the AI service's much longer cap. |
| Cache | cache | on, 1 h | Reuse the answer for an identical prompt. Correct only because the temperature is 0. |
| On error | onError | fail | What to do when the model is unavailable — fail, passthrough or default. |
| Model | modelId | (empty) | Escape hatch. Empty uses the globally active provider profile. |
The four fences
Every fence is fail-closed: [] reaches nothing, ["*"] reaches everything, and anything
else is the list. They are separate questions because they genuinely are — a node fenced to Line 1's
tags may still need the maintenance database, and one reading the ERP may have no business reading
tags.
| Fence | Key | Limits |
|---|---|---|
| Tag scope | scope | Which namespace folders and tags it may read. |
| Connections | connections | Which database connections it may query. |
| External systems | endpoints | Which named endpoints it may call. |
| Specialists | specialists | Which saved specialists it may run. No * exists — one at a time. |
That is the opposite of the intuition. On the platform a human writes the prompt; this node's prompt is a vendor webhook, an MQTT payload or an email body that nobody read first — so text inside it can steer the model toward a different connection or a different external system on the same installation.
Free-form SQL and every write are therefore structurally unreachable from this node, whatever is configured: it emits a decision, and a deterministic node downstream performs any action. The pipeline graph you drew is the authorization artifact.
Give the node the one database and the one endpoint it needs. Never *.
Example — classifying a downtime comment
Operators type free text; reports need categories.
Prompt: Classify this downtime comment into one category.
Comment: {{payload.comment}}
Output mode: choice
Choices: mechanical, electrical, material, changeover, operator, other
Output path: payload.category
Temperature: 0
In
{ "payload": { "id": 8814, "comment": "infeed belt kept slipping, had to retension it" } }
Out
{
"payload": {
"id": 8814,
"comment": "infeed belt kept slipping, had to retension it",
"category": "mechanical"
}
}
Write it back with a SQL node and the pipeline has turned free text into a column you can group by.
{{payload.data}} against a message with no data field renders as nothing at all — you get
Value: rather than Value: {{payload.data}}. A raw token arriving in somebody's inbox looks
like data the author meant to send, so a blank is the safer failure.
The practical consequence is that a mistyped path is invisible: the message still sends, just missing a piece. Send one to yourself, or watch a Debug node, before wiring it to an escalation.
The database nodes do the opposite with the same syntax — there an unresolved token is left as literal text.
Gotchas
- Keep temperature at 0 for anything feeding a report. The same input should produce the same category every time.
- Set
onErrordeliberately.failstops the branch, which is right when the classification is the point and wrong when it is an enrichment and the row should be stored regardless. - Every fence and the skill list are empty by default — the node can reach nothing until you grant it. Grant the narrowest thing that works.
- Fewer skills answer better. Tool selection degrades well before fifty tools; a node needing more than a handful is a signal to split it in two, or to hand part of the question to a specialist.
maxToolIterationsis a budget, not a target. A classification needs none; three is enough for "look one thing up, then decide".