LLM
September 21, 2026 · View on GitHub
The LLM node processes text with a language model or generates images. It supports text generation, vision (image input), image generation, structured JSON output, and provider-native Batch API execution for supported text models.
Overview
| Property | Value |
|---|---|
| Inputs | 1 |
| Outputs | 1, plus optional batchStatus when batch mode is enabled |
| Output | $nodeLabel.text (text), $nodeLabel.image (image), or batch result fields such as $nodeLabel.results |
Parameters
Credential & Model
| Parameter | Type | Description |
|---|---|---|
credentialId | UUID | LLM credential from Credentials |
model | string | Model name (e.g. gpt-4o, gemini-2.5-flash-lite, nanobanana for images) |
fallbackCredentialId | UUID (optional) | Fallback credential when primary fails |
fallbackModel | string (optional) | Fallback model when primary fails |
If the primary credential or model returns an error, the node automatically retries with the fallback credential and model before failing.
Heym also checks batch capability from the selected credential and model. Batch mode is available for:
- OpenAI credentials
- Custom / OpenAI-compatible credentials whose endpoint exposes the required
/v1/filesand/v1/batchesAPIs
If the selected provider or model does not support batch execution, the Properties panel shows that directly and disables the toggle.
Prompts (text mode)
| Parameter | Type | Description |
|---|---|---|
systemInstruction | string | System prompt. Supports expressions. |
userMessage | string | User message. Default: $input.text |
temperature | number | 0.0–2.0 (default: 0.7) |
maxTokens | number | Max response tokens (optional) |
requestTimeoutSeconds | number | Max seconds to wait for the model response before timing out (default: 60). Raise it for slow or self-hosted providers (LiteLLM, vLLM, local models). |
Image & Output
| Parameter | Type | Description |
|---|---|---|
outputType | "text" | "image" | Text or image generation |
imageInputEnabled | boolean | Include image with user message (vision) |
imageInput | expression | Base64 data URL or image URL |
jsonOutputEnabled | boolean | Structured JSON output |
jsonOutputSchema | string | JSON Schema for structured output |
extraBodyEnabled | boolean | Send provider-specific request parameters (default: false) |
extraBody | string | JSON object merged into the API request body |
Reasoning models (o1, o3)
| Parameter | Type | Description |
|---|---|---|
isReasoningModel | boolean | Enable for reasoning models |
reasoningEffort | "low" | "medium" | "high" | Reasoning depth |
Batch Mode
| Parameter | Type | Description |
|---|---|---|
batchModeEnabled | boolean | Use the provider-native Batch API instead of single-request execution |
Batch mode is available only on the LLM node. It does not apply to the Agent Node.
When batch mode is enabled:
outputTypemust staytextimageInputEnabledmust stayfalseuserMessagemust resolve to an array- each array item must resolve to a string or primitive value
Typical examples:
$input.items.map("item.text")$vars.promptList
If the expression resolves to a single string instead of an array, the run fails with a validation error before the provider call starts.
Batch Status Branch
When batch mode is enabled, the LLM node exposes a second output handle: batchStatus.
Use that branch for notifications, logging, Slack messages, or side effects while the batch is still running. The branch fires whenever the provider status meaningfully changes, including normalized states such as:
pendingprocessingcompletedfailed
The status branch payload is available as $input inside downstream nodes and includes:
$input.batchId$input.batchStatus$input.status$input.rawStatus$input.total$input.completed$input.failed$input.requestCounts.total$input.requestCounts.completed$input.requestCounts.failed$input.provider$input.model
Example edge:
{
"id": "edge-status",
"source": "batchLlmNode",
"sourceHandle": "batchStatus",
"target": "notifyProgress"
}
Example status mapper:
{
"type": "set",
"data": {
"label": "notifyProgress",
"mappings": [
{ "key": "status", "value": "$input.batchStatus" },
{ "key": "completed", "value": "$input.completed" },
{ "key": "total", "value": "$input.total" }
]
}
}
Batch Result Shape
On successful completion, the main LLM output contains:
$nodeLabel.text– concatenated successful texts$nodeLabel.batchId$nodeLabel.status$nodeLabel.rawStatus$nodeLabel.requestCounts$nodeLabel.total$nodeLabel.completed$nodeLabel.failed$nodeLabel.results– per-item results in original order$nodeLabel.usage
Each item in $nodeLabel.results includes fields such as:
indexcustomIdstatusstatusCodetexterrorusage
When JSON output is enabled together with batch mode, Heym parses each successful item separately. Parsed objects are exposed per item and collected on parsedResults.
Responses API
A Use Responses API checkbox routes the node's call through the Responses API instead of Chat Completions. It is off by default, and the node behaves the same either way: the same prompts, the same JSON output schema, the same result shape.
It works with an OpenAI credential, and with a custom credential whose gateway supports the endpoint, so a self-hosted or proxied setup can use it too. With a Google credential it stays disabled, and it cannot be combined with Batch mode - the node panel says where a given credential stands before you run anything.
If the endpoint turns out to be unavailable at run time, the node fails with a message naming the cause rather than quietly falling back, so a node configured for the Responses API is always running on it. To fall back to another credential or model deliberately, use the Fallback Credential and Fallback Model fields; they inherit this checkbox, so a fallback credential also needs to support the endpoint.
Image Generation
- Models:
nanobanana,gemini-2.0-flash-exp - Output:
$nodeLabel.image(base64 data URL) - When using Input for the prompt, use
$userPrompt.body.textinuserMessage
JSON Output
When jsonOutputEnabled is true, the LLM returns JSON matching the schema. Access fields via $nodeLabel.fieldName.
Extra Body
Some providers accept request parameters that the standard OpenAI-compatible fields do not cover, such as disabling a model's thinking mode. Tick Send extra request body in the node properties and enter a JSON object. It is merged into every API request this node makes.
{
"extraBodyEnabled": true,
"extraBody": "{ \"thinking\": { \"type\": \"disabled\" } }"
}
- Disabled by default. With the checkbox off, nothing extra is sent.
- Must be a JSON object. An array, a scalar, or malformed text fails the node with
Invalid extra body JSONrather than being silently dropped. - The Format button next to the checkbox reformats the JSON, and turns red reading
Invalidwhen the text does not parse. - Applied to the main completion, the fallback model attempt, and batch mode requests. Not applied to image generation or to guardrail checks, which use a different request shape and a separate model.
$expressions are resolved before parsing, so{"max_tokens": $prev.limit}works. Because this is textual substitution, a resolved value containing a double quote or a newline produces invalid JSON and fails the node.
Example – Text
{
"type": "llm",
"data": {
"label": "generateResponse",
"credentialId": "credential-uuid",
"model": "gpt-4o",
"systemInstruction": "You are a helpful assistant.",
"userMessage": "$userInput.body.text"
}
}
Example – Batch text
{
"nodes": [
{
"id": "var_1",
"type": "variable",
"position": { "x": 120, "y": 180 },
"data": {
"label": "batchPrompts",
"variableName": "promptList",
"variableType": "array",
"variableValue": "$array(\"Summarize this invoice\", \"Draft a follow-up email\", \"Classify the invoice status\")"
}
},
{
"id": "llm_1",
"type": "llm",
"position": { "x": 420, "y": 180 },
"data": {
"label": "batchLlm",
"credentialId": "credential-uuid",
"model": "gpt-4o-mini",
"batchModeEnabled": true,
"systemInstruction": "Answer each item briefly.",
"userMessage": "$vars.promptList"
}
},
{
"id": "set_1",
"type": "set",
"position": { "x": 760, "y": 70 },
"data": {
"label": "progressUpdate",
"mappings": [
{ "key": "status", "value": "$input.batchStatus" },
{ "key": "completed", "value": "$input.completed" }
]
}
},
{
"id": "out_1",
"type": "output",
"position": { "x": 760, "y": 280 },
"data": {
"label": "batchResult",
"outputKey": "responses"
}
}
],
"edges": [
{ "id": "e1", "source": "var_1", "target": "llm_1" },
{ "id": "e2", "source": "llm_1", "sourceHandle": "batchStatus", "target": "set_1" },
{ "id": "e3", "source": "llm_1", "target": "out_1" }
]
}
Example – Image generation
{
"type": "llm",
"data": {
"label": "generateImage",
"credentialId": "credential-uuid",
"model": "nanobanana",
"outputType": "image",
"userMessage": "$userPrompt.body.text"
}
}
Guardrails
Enable Guardrails in the node properties to block unsafe user messages before the LLM call. See Guardrails for the full reference.
Related
- Agent Node – LLM with tool calling
- Why Heym – AI-native features vs n8n, Zapier, Make.com
- Guardrails – Block unsafe content categories
- Node Types – Overview of all node types
- Expression DSL – Referencing data in prompts
- Expression Evaluation Dialog – Expandable editor with live backend preview for prompts
- Credentials Tab – Add LLM API keys
- Quick Start – Basic LLM workflow