Mi flujo de trabajo 4
Este es unSupport Chatbot, AI Chatbotflujo de automatización del dominio deautomatización que contiene 24 nodos.Utiliza principalmente nodos como Code, Switch, Webhook, Agent, RespondToWebhook. Hermosa interfaz web para chat multiagente con GPT-4 y asistente profesional, con IA
- •Punto final de HTTP Webhook (n8n generará automáticamente)
- •Clave de API de OpenAI
Nodos utilizados (24)
Categoría
{
"id": "paV8EK0gI9osnTJo",
"meta": {
"instanceId": "b35269c8495db354f1459fb10ec8f343e34cd6c71fb24a004bb668ccda72b4e6",
"templateCredsSetupCompleted": true
},
"name": "My workflow 4",
"tags": [],
"nodes": [
{
"id": "fcec0359-3e21-4953-b3be-781671b20151",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
0,
0
],
"webhookId": "b6f698e9-c16c-4273-8af2-20a958f691c1",
"parameters": {
"path": "b6f698e9-c16c-4273-8af2-20a958f691c1",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "bf62e968-3190-4337-b5da-822fe7db3ebf",
"name": "Código en JavaScript",
"type": "n8n-nodes-base.code",
"position": [
192,
0
],
"parameters": {
"jsCode": "// =========================================================\n// === n8n GRAPHICAL INPUT TEMPLATE - AI AGENT INTERFACE ===\n// =========================================================\n//\n// This template demonstrates how to create a beautiful graphical\n// interface for your n8n workflows, allowing your clients to\n// interact with your AI agents through a user-friendly web UI.\n//\n// HOW IT WORKS:\n// 1. Webhook node (GET) receives the request\n// 2. Code node generates the HTML interface\n// 3. Respond to Webhook node returns the HTML as a binary file\n//\n// =========================================================\n\n// === Example: Retrieving data from previous nodes ===\n// const userData = $items(\"Get User Data\")[0].json;\n// const apiKey = userData.api_key || \"default-key\";\n\nconst projectName = \"AI Agent Interface\";\nconst projectVersion = \"1.0\";\n\n// === HTML Generation ===\nconst html = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${projectName} - Powered by n8n</title>\n <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\">\n <style>\n /* === CSS VARIABLES === */\n :root {\n --background: #ffffff;\n --foreground: #000000;\n --card: #f8f9fa;\n --card-foreground: #000000;\n --primary: #6366f1;\n --primary-hover: #4f46e5;\n --secondary: #3b82f6;\n --muted: #9ca3af;\n --border: #e5e7eb;\n }\n\n body.dark {\n --background: #0b142c;\n --foreground: #f1f5f9;\n --card: #1e293b;\n --card-foreground: #f1f5f9;\n --primary: #818cf8;\n --primary-hover: #6366f1;\n --secondary: #60a5fa;\n --muted: #64748b;\n --border: #334155;\n }\n\n /* === BASE STYLES === */\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n\n body {\n background: var(--background);\n color: var(--foreground);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n padding: 20px;\n transition: background-color 0.3s ease, color 0.3s ease;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .container {\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n }\n\n /* === HEADER === */\n .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 20px;\n margin-bottom: 40px;\n border-bottom: 2px solid var(--border);\n flex-wrap: wrap;\n gap: 16px;\n }\n\n .header h1 {\n font-size: 2.5rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .header h1 i {\n color: var(--primary);\n }\n\n .header-actions {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n /* === BUTTONS === */\n .info-button {\n background: #6366f1;\n color: white;\n border: none;\n border-radius: 8px;\n padding: 10px 18px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 8px;\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);\n }\n\n .info-button:hover {\n background: #4f46e5;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);\n }\n\n /* === THEME TOGGLE === */\n .theme-toggle {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n user-select: none;\n }\n\n .toggle-switch {\n width: 48px;\n height: 24px;\n background: var(--border);\n border-radius: 12px;\n position: relative;\n cursor: pointer;\n transition: background-color 0.3s ease;\n }\n\n .toggle-switch::after {\n content: '';\n position: absolute;\n width: 20px;\n height: 20px;\n background: var(--card);\n border-radius: 50%;\n top: 2px;\n left: 2px;\n transition: transform 0.3s ease;\n box-shadow: 0 1px 3px rgba(0,0,0,0.3);\n }\n\n body.dark .toggle-switch::after {\n transform: translateX(24px);\n }\n\n .theme-icon {\n font-size: 1.2rem;\n }\n\n /* === MAIN CONTENT === */\n .main-content {\n background: var(--card);\n border-radius: 16px;\n padding: 32px;\n border: 1px solid var(--border);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n margin-bottom: 32px;\n }\n\n .section-title {\n font-size: 1.75rem;\n font-weight: 600;\n margin-bottom: 24px;\n display: flex;\n align-items: center;\n gap: 12px;\n color: var(--foreground);\n }\n\n .section-title i {\n color: var(--primary);\n }\n\n .section-subtitle {\n font-size: 0.95rem;\n color: var(--muted);\n margin-bottom: 24px;\n line-height: 1.6;\n }\n\n /* === TEXT INPUT === */\n .input-area {\n margin-bottom: 24px;\n }\n\n .input-label {\n display: block;\n font-size: 0.95rem;\n font-weight: 600;\n margin-bottom: 8px;\n color: var(--foreground);\n }\n\n .text-input {\n width: 100%;\n min-height: 140px;\n padding: 16px;\n font-size: 15px;\n font-family: inherit;\n background: var(--background);\n color: var(--foreground);\n border: 2px solid var(--border);\n border-radius: 12px;\n resize: vertical;\n transition: all 0.3s ease;\n }\n\n .text-input:focus {\n outline: none;\n border-color: var(--primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n\n .text-input::placeholder {\n color: var(--muted);\n }\n\n /* === SEND BUTTON === */\n .send-button {\n width: 100%;\n background: linear-gradient(135deg, var(--primary), var(--primary-hover));\n color: white;\n border: none;\n border-radius: 12px;\n padding: 16px 24px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 10px;\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n margin-bottom: 32px;\n }\n\n .send-button:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);\n }\n\n .send-button:active {\n transform: translateY(0);\n }\n\n /* === AGENT SECTION === */\n .agent-section-title {\n font-size: 1.3rem;\n font-weight: 600;\n margin-bottom: 16px;\n color: var(--foreground);\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .agent-section-subtitle {\n font-size: 0.9rem;\n color: var(--muted);\n margin-bottom: 20px;\n line-height: 1.5;\n }\n\n .agent-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n gap: 16px;\n }\n\n /* === AGENT CARDS === */\n .agent-card {\n background: var(--background);\n border: 2px solid var(--border);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n\n .agent-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);\n }\n\n .agent-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n transition: transform 0.3s ease;\n transform: scaleY(0);\n }\n\n .agent-card:hover::before {\n transform: scaleY(1);\n }\n\n .agent-card.db-agent::before { background: #3b82f6; }\n .agent-card.web-agent::before { background: #10b981; }\n .agent-card.rag-agent::before { background: #8b5cf6; }\n\n .agent-card.db-agent:hover { border-color: #3b82f6; }\n .agent-card.web-agent:hover { border-color: #10b981; }\n .agent-card.rag-agent:hover { border-color: #8b5cf6; }\n\n .agent-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 12px;\n font-size: 1.5rem;\n color: white;\n }\n\n .agent-icon.db-icon { background: linear-gradient(135deg, #3b82f6, #2563eb); }\n .agent-icon.web-icon { background: linear-gradient(135deg, #10b981, #059669); }\n .agent-icon.rag-icon { background: linear-gradient(135deg, #8b5cf6, #7c3aed); }\n\n .agent-title {\n font-size: 1.1rem;\n font-weight: 600;\n margin-bottom: 8px;\n color: var(--foreground);\n }\n\n .agent-description {\n font-size: 0.875rem;\n color: var(--muted);\n line-height: 1.5;\n }\n\n /* === RESPONSE AREA === */\n .response-area {\n background: var(--card);\n border-radius: 16px;\n padding: 32px;\n border: 1px solid var(--border);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n margin-top: 32px;\n animation: slideUp 0.3s ease;\n }\n\n .response-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 2px solid var(--border);\n }\n\n .response-header h3 {\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--foreground);\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .response-header h3 i {\n color: var(--primary);\n }\n\n .clear-button {\n background: var(--border);\n color: var(--foreground);\n border: none;\n border-radius: 8px;\n padding: 8px 16px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .clear-button:hover {\n background: var(--muted);\n transform: translateY(-1px);\n }\n\n .response-content {\n background: var(--background);\n border-radius: 12px;\n padding: 20px;\n color: var(--foreground);\n line-height: 1.7;\n font-size: 0.95rem;\n white-space: pre-wrap;\n word-wrap: break-word;\n max-height: 500px;\n overflow-y: auto;\n }\n\n .response-agent-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border-radius: 6px;\n font-size: 0.85rem;\n font-weight: 600;\n margin-bottom: 12px;\n }\n\n .response-agent-badge.db-badge {\n background: rgba(59, 130, 246, 0.1);\n color: #3b82f6;\n }\n\n .response-agent-badge.web-badge {\n background: rgba(16, 185, 129, 0.1);\n color: #10b981;\n }\n\n .response-agent-badge.rag-badge {\n background: rgba(139, 92, 246, 0.1);\n color: #8b5cf6;\n }\n\n .response-agent-badge.general-badge {\n background: rgba(99, 102, 241, 0.1);\n color: #6366f1;\n }\n\n .loading-spinner {\n display: inline-block;\n width: 16px;\n height: 16px;\n border: 2px solid var(--border);\n border-top-color: var(--primary);\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n }\n\n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n /* === MODAL === */\n .modal {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(4px);\n z-index: 1000;\n align-items: center;\n justify-content: center;\n animation: fadeIn 0.3s ease;\n }\n\n .modal.active {\n display: flex;\n }\n\n .modal-content {\n background: var(--card);\n border-radius: 16px;\n padding: 32px;\n max-width: 700px;\n width: 90%;\n max-height: 85vh;\n overflow-y: auto;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n animation: slideUp 0.3s ease;\n border: 1px solid var(--border);\n }\n\n .modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 24px;\n padding-bottom: 16px;\n border-bottom: 2px solid var(--border);\n }\n\n .modal-header h2 {\n font-size: 1.75rem;\n color: var(--foreground);\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .modal-header h2 i {\n color: #6366f1;\n }\n\n .modal-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n color: var(--muted);\n cursor: pointer;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n transition: all 0.2s ease;\n }\n\n .modal-close:hover {\n background: var(--border);\n color: var(--foreground);\n }\n\n .modal-body h3 {\n color: var(--primary);\n font-size: 1.25rem;\n margin-top: 24px;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .modal-body h3:first-child {\n margin-top: 0;\n }\n\n .modal-body p {\n color: var(--foreground);\n line-height: 1.7;\n margin-bottom: 16px;\n font-size: 0.95rem;\n }\n\n .modal-body ul {\n margin: 12px 0 16px 24px;\n color: var(--foreground);\n }\n\n .modal-body li {\n margin-bottom: 10px;\n line-height: 1.6;\n }\n\n .modal-body strong {\n color: var(--primary);\n font-weight: 600;\n }\n\n .modal-body code {\n background: var(--background);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 0.9em;\n color: var(--primary);\n }\n\n /* === ANIMATIONS === */\n @keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n /* === RESPONSIVE === */\n @media (max-width: 768px) {\n .header {\n flex-direction: column;\n align-items: flex-start;\n }\n\n .header h1 {\n font-size: 2rem;\n }\n\n .header-actions {\n width: 100%;\n justify-content: space-between;\n }\n\n .agent-grid {\n grid-template-columns: 1fr;\n }\n\n .modal-content {\n padding: 24px;\n width: 95%;\n }\n }\n </style>\n</head>\n<body class=\"dark\">\n <div class=\"container\">\n <!-- === HEADER === -->\n <div class=\"header\">\n <h1>\n <i class=\"fas fa-robot\"></i>\n ${projectName}\n </h1>\n <div class=\"header-actions\">\n <button class=\"info-button\" onclick=\"openModal()\">\n <i class=\"fas fa-info-circle\"></i>\n Project Guide\n </button>\n <div class=\"theme-toggle\" onclick=\"toggleTheme()\">\n <i class=\"fas fa-moon theme-icon\"></i>\n <div class=\"toggle-switch\"></div>\n <i class=\"fas fa-sun theme-icon\"></i>\n </div>\n </div>\n </div>\n\n <!-- === MAIN CONTENT === -->\n <div class=\"main-content\">\n <div class=\"section-title\">\n <i class=\"fas fa-comments\"></i>\n Chat with AI Agents\n </div>\n <p class=\"section-subtitle\">\n Enter your message below and select one of our specialized AI agents to get the most accurate response.\n </p>\n\n <!-- Text input area -->\n <div class=\"input-area\">\n <label class=\"input-label\" for=\"messageInput\">\n <i class=\"fas fa-edit\"></i> Your Message\n </label>\n <textarea\n id=\"messageInput\"\n class=\"text-input\"\n placeholder=\"Type your question or message here...\"\n ></textarea>\n </div>\n\n <!-- Send button -->\n <button class=\"send-button\" onclick=\"sendMessage()\">\n <i class=\"fas fa-paper-plane\"></i>\n Send Message\n </button>\n\n <!-- === AGENT SELECTION === -->\n <div class=\"agent-section-title\">\n <i class=\"fas fa-brain\"></i>\n Or Select a Specialized Agent\n </div>\n <p class=\"agent-section-subtitle\">\n Choose an agent that best fits your needs. Each agent has access to different tools and data sources.\n </p>\n\n <div class=\"agent-grid\">\n <!-- Database Agent -->\n <div class=\"agent-card db-agent\" onclick=\"sendToAgent('database')\">\n <div class=\"agent-icon db-icon\">\n <i class=\"fas fa-database\"></i>\n </div>\n <div class=\"agent-title\">Database Search Agent</div>\n <div class=\"agent-description\">\n Specialized in searching and querying your database. Perfect for finding specific records or analyzing stored data.\n </div>\n </div>\n\n <!-- Web Agent -->\n <div class=\"agent-card web-agent\" onclick=\"sendToAgent('web')\">\n <div class=\"agent-icon web-icon\">\n <i class=\"fas fa-globe\"></i>\n </div>\n <div class=\"agent-title\">Web Search Agent</div>\n <div class=\"agent-description\">\n Searches the internet for real-time information, news, and public data. Ideal for current events and research.\n </div>\n </div>\n\n <!-- RAG Agent -->\n <div class=\"agent-card rag-agent\" onclick=\"sendToAgent('rag')\">\n <div class=\"agent-icon rag-icon\">\n <i class=\"fas fa-book\"></i>\n </div>\n <div class=\"agent-title\">RAG Knowledge Agent</div>\n <div class=\"agent-description\">\n Uses RAG to search your documents and knowledge base. Best for company-specific information.\n </div>\n </div>\n </div>\n </div>\n\n <!-- === AI RESPONSE DISPLAY AREA === -->\n <div id=\"responseArea\" class=\"response-area\" style=\"display: none;\">\n <div class=\"response-header\">\n <h3>\n <i class=\"fas fa-robot\"></i>\n AI Response\n </h3>\n <button class=\"clear-button\" onclick=\"clearResponse()\">\n <i class=\"fas fa-times\"></i>\n Clear\n </button>\n </div>\n <div id=\"responseBadge\"></div>\n <div id=\"responseContent\" class=\"response-content\">\n <!-- AI response will be displayed here -->\n </div>\n </div>\n </div>\n\n <!-- === PROJECT GUIDE MODAL === -->\n <div id=\"infoModal\" class=\"modal\" onclick=\"closeModal(event)\">\n <div class=\"modal-content\" onclick=\"event.stopPropagation()\">\n <div class=\"modal-header\">\n <h2><i class=\"fas fa-book-open\"></i> Template Guide</h2>\n <button class=\"modal-close\" onclick=\"closeModal()\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <h3><i class=\"fas fa-lightbulb\"></i> What is this Template?</h3>\n <p>\n This is a <strong>n8n graphical input template</strong> that creates beautiful user interfaces\n for your workflows. Instead of API calls, your users get a clean interface to interact with your AI agents.\n </p>\n\n <h3><i class=\"fas fa-cogs\"></i> How it Works</h3>\n <p>Simple 3-node workflow in n8n:</p>\n <ul>\n <li><strong>Webhook Node (GET):</strong> Receives the HTTP request</li>\n <li><strong>Code Node:</strong> Generates the HTML interface</li>\n <li><strong>Respond to Webhook Node:</strong> Returns HTML as binary file</li>\n </ul>\n\n <h3><i class=\"fas fa-robot\"></i> The Agent Buttons</h3>\n <p>Three specialized agents for different tasks:</p>\n <ul>\n <li><strong>Database Agent:</strong> Searches your database, runs SQL queries</li>\n <li><strong>Web Agent:</strong> Searches the internet for current information</li>\n <li><strong>RAG Agent:</strong> Searches your documents and knowledge base</li>\n </ul>\n\n <h3><i class=\"fas fa-plug\"></i> Connecting to Your Workflow</h3>\n <p>\n Update the JavaScript functions <code>sendMessage()</code> and <code>sendToAgent()</code>\n to point to your n8n webhook URLs. The message and agent type will be sent to your workflow\n where you can process it with your AI agents.\n </p>\n\n <h3><i class=\"fas fa-palette\"></i> Customization</h3>\n <ul>\n <li>Change colors in the CSS variables section</li>\n <li>Add more agent types by copying the agent-card structure</li>\n <li>Modify the layout and design to match your brand</li>\n <li>Update this guide with your own instructions</li>\n </ul>\n\n <p style=\"margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.9rem;\">\n <strong>Version:</strong> ${projectVersion} | <strong>Powered by:</strong> n8n\n </p>\n </div>\n </div>\n </div>\n\n <!-- === JAVASCRIPT === -->\n <script>\n // === Modal Functions ===\n function openModal() {\n document.getElementById('infoModal').classList.add('active');\n document.body.style.overflow = 'hidden';\n }\n\n function closeModal(event) {\n if (!event || event.target.id === 'infoModal') {\n document.getElementById('infoModal').classList.remove('active');\n document.body.style.overflow = 'auto';\n }\n }\n\n // Close modal with Escape key\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape') {\n const modal = document.getElementById('infoModal');\n if (modal && modal.classList.contains('active')) {\n closeModal();\n }\n }\n });\n\n // === Theme Toggle ===\n function toggleTheme() {\n document.body.classList.toggle('dark');\n const isDark = document.body.classList.contains('dark');\n localStorage.setItem('theme', isDark ? 'dark' : 'light');\n }\n\n // Restore theme on page load\n if (localStorage.getItem('theme') === 'light') {\n document.body.classList.remove('dark');\n }\n\n // === UNIFIED WEBHOOK URL ===\n // TODO: Replace this URL with your n8n webhook endpoint\n // All agents will send to the same URL with different agent_type\n const WEBHOOK_URL = 'https://primary-production-e46f.up.railway.app/webhook/webhook-endpoint';\n\n // === Send Message Function ===\n async function sendMessage() {\n const messageInput = document.getElementById('messageInput');\n const message = messageInput.value.trim();\n\n if (!message) {\n alert('Please enter a message before sending.');\n return;\n }\n\n // Show loading state\n showLoading('general');\n\n try {\n const response = await fetch(WEBHOOK_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n message: message,\n agent_type: 'general',\n timestamp: new Date().toISOString()\n })\n });\n\n if (!response.ok) {\n throw new Error('Failed to send message');\n }\n\n const result = await response.json();\n\n // Display the AI response in the interface\n displayResponse(result.response || result.message || result.output, 'general');\n\n // Clear input\n messageInput.value = '';\n\n } catch (error) {\n console.error('Error:', error);\n displayError('Error sending message. Please try again.');\n }\n }\n\n // === Send to Specific Agent ===\n async function sendToAgent(agentType) {\n const messageInput = document.getElementById('messageInput');\n const message = messageInput.value.trim();\n\n if (!message) {\n alert('Please enter a message before selecting an agent.');\n return;\n }\n\n // Show loading state\n showLoading(agentType);\n\n try {\n const response = await fetch(WEBHOOK_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n message: message,\n agent_type: agentType,\n timestamp: new Date().toISOString()\n })\n });\n\n if (!response.ok) {\n throw new Error('Failed to send message');\n }\n\n const result = await response.json();\n\n // Display the AI response in the interface\n displayResponse(result.response || result.message || result.output, agentType);\n\n // Clear input\n messageInput.value = '';\n\n } catch (error) {\n console.error('Error:', error);\n displayError(\\`Error with \\${agentType} agent. Please try again.\\`);\n }\n }\n\n // === Display Response Function ===\n function displayResponse(responseText, agentType) {\n const responseArea = document.getElementById('responseArea');\n const responseBadge = document.getElementById('responseBadge');\n const responseContent = document.getElementById('responseContent');\n\n // Agent names and badge classes\n const agentInfo = {\n 'database': { name: 'Database Search Agent', icon: 'fa-database', class: 'db-badge' },\n 'web': { name: 'Web Search Agent', icon: 'fa-globe', class: 'web-badge' },\n 'rag': { name: 'RAG Knowledge Agent', icon: 'fa-book', class: 'rag-badge' },\n 'general': { name: 'AI Assistant', icon: 'fa-robot', class: 'general-badge' }\n };\n\n const info = agentInfo[agentType] || agentInfo['general'];\n\n // Display agent badge\n responseBadge.innerHTML = \\`\n <div class=\"response-agent-badge \\${info.class}\">\n <i class=\"fas \\${info.icon}\"></i>\n \\${info.name}\n </div>\n \\`;\n\n // Display response text\n responseContent.textContent = responseText;\n\n // Show response area with animation\n responseArea.style.display = 'block';\n\n // Scroll to response smoothly\n setTimeout(() => {\n responseArea.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }, 100);\n }\n\n // === Show Loading Function ===\n function showLoading(agentType) {\n const responseArea = document.getElementById('responseArea');\n const responseBadge = document.getElementById('responseBadge');\n const responseContent = document.getElementById('responseContent');\n\n const agentInfo = {\n 'database': { name: 'Database Search Agent', icon: 'fa-database', class: 'db-badge' },\n 'web': { name: 'Web Search Agent', icon: 'fa-globe', class: 'web-badge' },\n 'rag': { name: 'RAG Knowledge Agent', icon: 'fa-book', class: 'rag-badge' },\n 'general': { name: 'AI Assistant', icon: 'fa-robot', class: 'general-badge' }\n };\n\n const info = agentInfo[agentType] || agentInfo['general'];\n\n responseBadge.innerHTML = \\`\n <div class=\"response-agent-badge \\${info.class}\">\n <i class=\"fas \\${info.icon}\"></i>\n \\${info.name}\n </div>\n \\`;\n\n responseContent.innerHTML = \\`\n <div style=\"display: flex; align-items: center; gap: 10px; color: var(--muted);\">\n <div class=\"loading-spinner\"></div>\n Processing your request...\n </div>\n \\`;\n\n responseArea.style.display = 'block';\n\n setTimeout(() => {\n responseArea.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }, 100);\n }\n\n // === Display Error Function ===\n function displayError(errorMessage) {\n const responseArea = document.getElementById('responseArea');\n const responseBadge = document.getElementById('responseBadge');\n const responseContent = document.getElementById('responseContent');\n\n responseBadge.innerHTML = \\`\n <div class=\"response-agent-badge\" style=\"background: rgba(239, 68, 68, 0.1); color: #ef4444;\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n Error\n </div>\n \\`;\n\n responseContent.textContent = errorMessage;\n responseArea.style.display = 'block';\n\n setTimeout(() => {\n responseArea.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }, 100);\n }\n\n // === Clear Response Function ===\n function clearResponse() {\n const responseArea = document.getElementById('responseArea');\n responseArea.style.display = 'none';\n }\n\n // === Enter key to send ===\n document.getElementById('messageInput').addEventListener('keydown', function(e) {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n sendMessage();\n }\n });\n </script>\n</body>\n</html>\n`;\n\n// === Binary Conversion for n8n ===\nconst buffer = Buffer.from(html, \"utf8\");\n\nreturn [\n {\n json: {\n message: \"AI Agent Interface generated successfully\",\n version: projectVersion\n },\n binary: {\n data: {\n data: buffer.toString(\"base64\"),\n mimeType: \"text/html\"\n },\n },\n },\n];\n"
},
"typeVersion": 2
},
{
"id": "d0fa19da-d969-4484-b1b4-c876851a8e46",
"name": "Responder a Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
384,
0
],
"parameters": {
"options": {},
"respondWith": "binary"
},
"typeVersion": 1.4
},
{
"id": "a32db689-90a0-4e80-a0a1-02c5ccdadedf",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
-80
],
"parameters": {
"color": 5,
"width": 640,
"height": 224,
"content": "## Module - Create UI interface"
},
"typeVersion": 1
},
{
"id": "6e5fecbb-b0d3-4e11-8729-030c1786d27a",
"name": "Nota adhesiva1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-752,
-80
],
"parameters": {
"width": 672,
"height": 1168,
"content": "# 🎨 n8n AI Agent Interface Template\n\nBeautiful web UI for your AI agents - no frontend skills needed!\n\n## ⚡ Quick Setup (2 workflows)\n\n### Workflow 1: Display Interface (3 nodes)\n```\nWebhook (GET) → Code Node → Respond to Webhook\n```\n1. **Webhook**: GET, path `/your-interface`\n2. **Code Node**: Paste entire `main.js`\n3. **Respond**: Binary, property `data`\n\n### Workflow 2: Process Requests (5+ nodes)\n```\nWebhook (POST) → Switch → AI Agents → Code → Respond\n```\n1. **Webhook (POST)**: path `/webhook-endpoint`\n2. **Switch**: Route by `{{ $json.body.agent_type }}`\n3. **AI Agents**: 4 nodes (general, database, web, rag)\n4. **Code Node**:\n```javascript\nconst webhookData = $('Webhook').first().json.body;\nconst aiResponse = $input.first().json;\n\nreturn [{\n json: {\n response: aiResponse.output || aiResponse.text || aiResponse.response,\n agent_type: webhookData.agent_type\n }\n}];\n```\n5. **Respond**: Return JSON\n\n## 🔧 Update in main.js\n\n**Line 847**: Change webhook URL\n```javascript\nconst WEBHOOK_URL = '/webhook/webhook-endpoint';\n```\n\n## ✨ Features\n✅ Real-time AI responses \n✅ Loading animations \n✅ 4 agent types \n✅ Dark/light mode \n✅ Mobile responsive\n\n"
},
"typeVersion": 1
},
{
"id": "f963c77a-0296-4e46-a8c1-94c73913ce40",
"name": "Nota adhesiva2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
176
],
"parameters": {
"color": 3,
"width": 1376,
"height": 1184,
"content": "## Module - AI Agent"
},
"typeVersion": 1
},
{
"id": "ec32a56d-3fe8-4155-b47e-da1032c6eadf",
"name": "Webhook1",
"type": "n8n-nodes-base.webhook",
"position": [
0,
656
],
"webhookId": "e0181c5e-25b5-498a-b409-49fdacabd523",
"parameters": {
"path": "webhook-endpoint",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "5031a89a-723a-4a70-a945-2190249e224c",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
256,
624
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e3cd26ff-42a1-4f9a-b720-78db8d579196",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.agent_type }}",
"rightValue": "general"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c0e4c5ff-0c06-4cbb-97ba-def595e4fff1",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.agent_type }}",
"rightValue": "database"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9a756446-f021-4d74-bc6b-e4a8fa64bcbe",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.agent_type }}",
"rightValue": "web"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e61d61c2-7819-4c22-b70f-7410c87a98d7",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.body.agent_type }}",
"rightValue": "rag"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.3
},
{
"id": "14ab7851-36f6-4d61-a43e-f3ceaf45123b",
"name": "Agente de IA - General",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
528,
240
],
"parameters": {
"text": "c'est un test simplement",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "71c05943-b548-4d56-9b02-b4c394612d2f",
"name": "Modelo de Chat OpenAI",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
496,
384
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Eyt0iPqZCLeZxqlC",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "20bfc5c1-8093-4533-85fa-49f9f5eff917",
"name": "Modelo de Chat OpenAI1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
496,
656
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Eyt0iPqZCLeZxqlC",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "1f1fc350-0ed9-433f-9527-a8c356f23d4a",
"name": "Modelo de Chat OpenAI2",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
496,
944
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Eyt0iPqZCLeZxqlC",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "21e8e7c1-4b78-46c0-98ba-24006592a737",
"name": "Modelo de Chat OpenAI3",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
496,
1232
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "Eyt0iPqZCLeZxqlC",
"name": "OpenAi account"
}
},
"typeVersion": 1.2
},
{
"id": "02e03088-7c40-421d-ab15-ccacdb2735c7",
"name": "Responder a Webhook1",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
240
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "988aa029-e110-42b3-b62e-156ee79d08c7",
"name": "Responder a Webhook2",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
512
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "6dbf918b-fdb9-4032-95a5-ece4aee5c63f",
"name": "Responder a Webhook3",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
784
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "477b257c-d283-4783-a505-29f0c2f50782",
"name": "Responder a Webhook4",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
1072
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "e28c1572-dec7-4b90-be86-46b434366678",
"name": "Base de Datos de Agente de IA",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
528,
512
],
"parameters": {
"text": "Configure Database Agent",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "1bda319b-4aff-47bd-9350-0e337ecef08e",
"name": "Agente de IA - Web",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
528,
784
],
"parameters": {
"text": "Configure Web Agent",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "d0a6542a-bea2-472f-b254-7d30c95fc8f9",
"name": "Agente de IA - Rag",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
528,
1072
],
"parameters": {
"text": "Configure Rag Agent",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "4c290b16-aac4-4dad-8e29-8df886a191f5",
"name": "Formatear Respuesta - Código",
"type": "n8n-nodes-base.code",
"position": [
880,
240
],
"parameters": {
"jsCode": "// Récupère les données du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// Récupère la réponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de réponse de l'IA (les agents IA peuvent renvoyer différents formats)\nconst aiResponseText = aiAgentOutput.output || \n aiAgentOutput.text || \n aiAgentOutput.response || \n aiAgentOutput.message ||\n JSON.stringify(aiAgentOutput);\n\n// Formate la réponse pour l'interface utilisateur\nreturn [{\n json: {\n response: aiResponseText, // La réponse de l'IA\n agent_type: webhookData.agent_type, // Type d'agent utilisé\n user_message: webhookData.message, // Message original de l'utilisateur\n timestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "10e971ac-4ddd-4d4b-b746-4ea1e3adae80",
"name": "Formatear Respuesta - Código1",
"type": "n8n-nodes-base.code",
"position": [
880,
512
],
"parameters": {
"jsCode": "// Récupère les données du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// Récupère la réponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de réponse de l'IA (les agents IA peuvent renvoyer différents formats)\nconst aiResponseText = aiAgentOutput.output || \n aiAgentOutput.text || \n aiAgentOutput.response || \n aiAgentOutput.message ||\n JSON.stringify(aiAgentOutput);\n\n// Formate la réponse pour l'interface utilisateur\nreturn [{\n json: {\n response: aiResponseText, // La réponse de l'IA\n agent_type: webhookData.agent_type, // Type d'agent utilisé\n user_message: webhookData.message, // Message original de l'utilisateur\n timestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "bfbd9514-cde8-4b90-bff4-af935251126d",
"name": "Formatear Respuesta - Código2",
"type": "n8n-nodes-base.code",
"position": [
880,
784
],
"parameters": {
"jsCode": "// Récupère les données du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// Récupère la réponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de réponse de l'IA (les agents IA peuvent renvoyer différents formats)\nconst aiResponseText = aiAgentOutput.output || \n aiAgentOutput.text || \n aiAgentOutput.response || \n aiAgentOutput.message ||\n JSON.stringify(aiAgentOutput);\n\n// Formate la réponse pour l'interface utilisateur\nreturn [{\n json: {\n response: aiResponseText, // La réponse de l'IA\n agent_type: webhookData.agent_type, // Type d'agent utilisé\n user_message: webhookData.message, // Message original de l'utilisateur\n timestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "60586be5-536a-4561-bfbf-7643d70eedf1",
"name": "Formatear Respuesta - Código3",
"type": "n8n-nodes-base.code",
"position": [
880,
1072
],
"parameters": {
"jsCode": "// Récupère les données du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// Récupère la réponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de réponse de l'IA (les agents IA peuvent renvoyer différents formats)\nconst aiResponseText = aiAgentOutput.output || \n aiAgentOutput.text || \n aiAgentOutput.response || \n aiAgentOutput.message ||\n JSON.stringify(aiAgentOutput);\n\n// Formate la réponse pour l'interface utilisateur\nreturn [{\n json: {\n response: aiResponseText, // La réponse de l'IA\n agent_type: webhookData.agent_type, // Type d'agent utilisé\n user_message: webhookData.message, // Message original de l'utilisateur\n timestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
}
],
"active": true,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "91970e2d-6858-4881-8f5b-eea4c3a82eb1",
"connections": {
"5031a89a-723a-4a70-a945-2190249e224c": {
"main": [
[
{
"node": "14ab7851-36f6-4d61-a43e-f3ceaf45123b",
"type": "main",
"index": 0
}
],
[
{
"node": "e28c1572-dec7-4b90-be86-46b434366678",
"type": "main",
"index": 0
}
],
[
{
"node": "1bda319b-4aff-47bd-9350-0e337ecef08e",
"type": "main",
"index": 0
}
],
[
{
"node": "d0a6542a-bea2-472f-b254-7d30c95fc8f9",
"type": "main",
"index": 0
}
]
]
},
"fcec0359-3e21-4953-b3be-781671b20151": {
"main": [
[
{
"node": "bf62e968-3190-4337-b5da-822fe7db3ebf",
"type": "main",
"index": 0
}
]
]
},
"ec32a56d-3fe8-4155-b47e-da1032c6eadf": {
"main": [
[
{
"node": "5031a89a-723a-4a70-a945-2190249e224c",
"type": "main",
"index": 0
}
]
]
},
"d0a6542a-bea2-472f-b254-7d30c95fc8f9": {
"main": [
[
{
"node": "60586be5-536a-4561-bfbf-7643d70eedf1",
"type": "main",
"index": 0
}
]
]
},
"1bda319b-4aff-47bd-9350-0e337ecef08e": {
"main": [
[
{
"node": "bfbd9514-cde8-4b90-bff4-af935251126d",
"type": "main",
"index": 0
}
]
]
},
"e28c1572-dec7-4b90-be86-46b434366678": {
"main": [
[
{
"node": "10e971ac-4ddd-4d4b-b746-4ea1e3adae80",
"type": "main",
"index": 0
}
]
]
},
"71c05943-b548-4d56-9b02-b4c394612d2f": {
"ai_languageModel": [
[
{
"node": "14ab7851-36f6-4d61-a43e-f3ceaf45123b",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"14ab7851-36f6-4d61-a43e-f3ceaf45123b": {
"main": [
[
{
"node": "4c290b16-aac4-4dad-8e29-8df886a191f5",
"type": "main",
"index": 0
}
]
]
},
"bf62e968-3190-4337-b5da-822fe7db3ebf": {
"main": [
[
{
"node": "d0fa19da-d969-4484-b1b4-c876851a8e46",
"type": "main",
"index": 0
}
]
]
},
"20bfc5c1-8093-4533-85fa-49f9f5eff917": {
"ai_languageModel": [
[
{
"node": "e28c1572-dec7-4b90-be86-46b434366678",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"1f1fc350-0ed9-433f-9527-a8c356f23d4a": {
"ai_languageModel": [
[
{
"node": "1bda319b-4aff-47bd-9350-0e337ecef08e",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"21e8e7c1-4b78-46c0-98ba-24006592a737": {
"ai_languageModel": [
[
{
"node": "d0a6542a-bea2-472f-b254-7d30c95fc8f9",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"4c290b16-aac4-4dad-8e29-8df886a191f5": {
"main": [
[
{
"node": "02e03088-7c40-421d-ab15-ccacdb2735c7",
"type": "main",
"index": 0
}
]
]
},
"10e971ac-4ddd-4d4b-b746-4ea1e3adae80": {
"main": [
[
{
"node": "988aa029-e110-42b3-b62e-156ee79d08c7",
"type": "main",
"index": 0
}
]
]
},
"bfbd9514-cde8-4b90-bff4-af935251126d": {
"main": [
[
{
"node": "6dbf918b-fdb9-4032-95a5-ece4aee5c63f",
"type": "main",
"index": 0
}
]
]
},
"60586be5-536a-4561-bfbf-7643d70eedf1": {
"main": [
[
{
"node": "477b257c-d283-4783-a505-29f0c2f50782",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Avanzado - Chatbot de soporte, Chatbot de IA
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Hugo
@hugo-miseryGrowth engineer focused on AI, data automation, and custom integrations. Use to turn complex ideas into simple, and scalable workflows with solid infrastructure
Compartir este flujo de trabajo