This workflow follows the Execute Workflow Trigger → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "W_LLM_INTENT - AI Intent Classification (Ollama)",
"active": false,
"settings": {
"executionTimeout": 15,
"saveManualExecutions": true
},
"nodes": [
{
"parameters": {},
"id": "llm-trigger-01",
"name": "IN - From Core",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"language": "javascript",
"jsCode": "const e = $json;\nconst userText = (e.userText || e.message?.text || '').toString().trim();\nconst locale = (e.l10n?.detectedLocale || e.state?.locale || 'fr');\nconst cartItems = (e.cart?.items || []).map(i => i.name).join(', ');\nconst stage = (e.state?.stage || 'START');\n\nconst systemPrompt = `You are RestoBot, a restaurant ordering assistant for an Algerian restaurant.\nYou classify customer messages into exactly ONE intent.\nValid intents: GREET, VIEW_MENU, ADD_ITEM, REMOVE_ITEM, VIEW_CART, CHECKOUT, DELIVERY, SUPPORT, FAQ, LANG_SWITCH, UNKNOWN.\nRespond ONLY with a JSON object: {\"intent\": \"...\", \"confidence\": 0.0-1.0, \"entities\": {}}\nDo NOT include any other text.`;\n\nconst userPrompt = `Customer message (locale: ${locale}, stage: ${stage}, cart: [${cartItems}]):\n\"${userText.substring(0, 500)}\"`;\n\nreturn [{ json: { ...e, _llm: { systemPrompt, userPrompt, userText } } }];"
},
"id": "llm-prepare-02",
"name": "Prepare LLM Prompt",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
220,
0
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $json._strapiConfig?.ollama_api_url || $env.LLM_API_URL || 'http://ollama:11434/api/chat' }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ model: $json._strapiConfig?.llm_model || $env.LLM_MODEL || 'llama3.1', messages: [{ role: 'system', content: $json._llm.systemPrompt }, { role: 'user', content: $json._llm.userPrompt }], stream: false, options: { temperature: $json._strapiConfig?.llm_temperature || 0.1, num_predict: $json._strapiConfig?.llm_max_tokens || 100 } }) }}",
"options": {
"timeout": 10000,
"response": {
"response": {
"fullResponse": true
}
}
}
},
"id": "llm-call-03",
"name": "Call Ollama API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
440,
0
],
"continueOnFail": true
},
{
"parameters": {
"language": "javascript",
"jsCode": "const e = $json;\nconst fallback = { intent: 'UNKNOWN', confidence: 0, entities: {}, llm_used: false };\n\ntry {\n const body = e.body || e.data || e;\n const content = (body?.message?.content || '').toString().trim();\n if (!content) return [{ json: { ...e, llmResult: { ...fallback, reason: 'empty_response' } } }];\n\n // Try to parse JSON from the LLM response\n const jsonMatch = content.match(/\\{[^}]+\\}/);\n if (!jsonMatch) return [{ json: { ...e, llmResult: { ...fallback, reason: 'no_json_in_response' } } }];\n\n const parsed = JSON.parse(jsonMatch[0]);\n const validIntents = ['GREET','VIEW_MENU','ADD_ITEM','REMOVE_ITEM','VIEW_CART','CHECKOUT','DELIVERY','SUPPORT','FAQ','LANG_SWITCH','UNKNOWN'];\n const intent = validIntents.includes(parsed.intent) ? parsed.intent : 'UNKNOWN';\n const confidence = Math.min(1, Math.max(0, Number(parsed.confidence) || 0));\n\n return [{ json: { ...e, llmResult: { intent, confidence, entities: parsed.entities || {}, llm_used: true } } }];\n} catch (err) {\n return [{ json: { ...e, llmResult: { ...fallback, reason: 'parse_error', error: err.message } } }];\n}"
},
"id": "llm-parse-04",
"name": "Parse LLM Response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
0
]
}
],
"connections": {
"IN - From Core": {
"main": [
[
{
"node": "Prepare LLM Prompt",
"type": "main",
"index": 0
}
]
]
},
"Prepare LLM Prompt": {
"main": [
[
{
"node": "Call Ollama API",
"type": "main",
"index": 0
}
]
]
},
"Call Ollama API": {
"main": [
[
{
"node": "Parse LLM Response",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
W_LLM_INTENT - AI Intent Classification (Ollama). Uses executeWorkflowTrigger, httpRequest. Event-driven trigger; 4 nodes.
Source: https://github.com/zerAda/RestaurantAgentAutomation/blob/41a4d42dcd66e57b1e87b4750c0fd5fbf7058f68/workflows/W_LLM_INTENT.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
[2/2] KNN classifier (lands dataset). Uses httpRequest, stickyNote, executeWorkflowTrigger. Event-driven trigger; 18 nodes.
Workflows from the webinar "Build production-ready AI Agents with Qdrant and n8n".
[3/3] Anomaly detection tool (crops dataset). Uses stickyNote, httpRequest, executeWorkflowTrigger. Event-driven trigger; 17 nodes.
Workflows from the webinar "Build production-ready AI Agents with Qdrant and n8n".
This sub-workflow is called via Execute Workflow and routes a prompt to Anthropic, Google Gemini, Mistral, or OpenAI, then normalizes the model output into a single response field while estimating tok