我的工作流4
高级
这是一个Support Chatbot, AI Chatbot领域的自动化工作流,包含 24 个节点。主要使用 Code, Switch, Webhook, Agent, RespondToWebhook 等节点。 具有专业助手的 GPT-4 多智能体聊天的精美 Web 界面
前置要求
- •HTTP Webhook 端点(n8n 会自动生成)
- •OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "paV8EK0gI9osnTJo",
"meta": {
"instanceId": "b35269c8495db354f1459fb10ec8f343e34cd6c71fb24a004bb668ccda72b4e6",
"templateCredsSetupCompleted": true
},
"name": "我的工作流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": "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": "响应 Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
384,
0
],
"parameters": {
"options": {},
"respondWith": "binary"
},
"typeVersion": 1.4
},
{
"id": "a32db689-90a0-4e80-a0a1-02c5ccdadedf",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
-80
],
"parameters": {
"color": 5,
"width": 640,
"height": 224,
"content": "## 模块 - 创建用户界面"
},
"typeVersion": 1
},
{
"id": "6e5fecbb-b0d3-4e11-8729-030c1786d27a",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-752,
-80
],
"parameters": {
"width": 672,
"height": 1168,
"content": "# 🎨 n8n AI智能体界面模板"
},
"typeVersion": 1
},
{
"id": "f963c77a-0296-4e46-a8c1-94c73913ce40",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
176
],
"parameters": {
"color": 3,
"width": 1376,
"height": 1184,
"content": "## 模块 - AI智能体"
},
"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": "Google Calendar MCP",
"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": "AI智能体 - 通用",
"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": "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": "OpenAI 聊天模型1",
"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": "OpenAI 聊天模型2",
"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": "OpenAI 聊天模型",
"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": "响应Webhook1",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
240
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "988aa029-e110-42b3-b62e-156ee79d08c7",
"name": "响应Webhook2",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
512
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "6dbf918b-fdb9-4032-95a5-ece4aee5c63f",
"name": "响应Webhook3",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
784
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "477b257c-d283-4783-a505-29f0c2f50782",
"name": "响应Webhook4",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1088,
1072
],
"parameters": {
"options": {}
},
"typeVersion": 1.4
},
{
"id": "e28c1572-dec7-4b90-be86-46b434366678",
"name": "AI智能体数据库",
"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": "AI智能体 - 网络",
"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": "AI智能体 - 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": "格式化响应 - 代码",
"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": "格式化响应 - 代码1",
"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": "格式化响应 - 代码2",
"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": "格式化响应 - 代码3",
"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": {
"Switch": {
"main": [
[
{
"node": "AI Agent - General",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent Database",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent - Web",
"type": "main",
"index": 0
}
],
[
{
"node": "AI Agent - Rag",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Webhook1": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"AI Agent - Rag": {
"main": [
[
{
"node": "Format Response - Code3",
"type": "main",
"index": 0
}
]
]
},
"AI Agent - Web": {
"main": [
[
{
"node": "Format Response - Code2",
"type": "main",
"index": 0
}
]
]
},
"AI Agent Database": {
"main": [
[
{
"node": "Format Response - Code1",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent - General",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"AI Agent - General": {
"main": [
[
{
"node": "Format Response - Code",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model1": {
"ai_languageModel": [
[
{
"node": "AI Agent Database",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"OpenAI Chat Model2": {
"ai_languageModel": [
[
{
"node": "AI Agent - Web",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"OpenAI Chat Model3": {
"ai_languageModel": [
[
{
"node": "AI Agent - Rag",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Format Response - Code": {
"main": [
[
{
"node": "Respond to Webhook1",
"type": "main",
"index": 0
}
]
]
},
"Format Response - Code1": {
"main": [
[
{
"node": "Respond to Webhook2",
"type": "main",
"index": 0
}
]
]
},
"Format Response - Code2": {
"main": [
[
{
"node": "Respond to Webhook3",
"type": "main",
"index": 0
}
]
]
},
"Format Response - Code3": {
"main": [
[
{
"node": "Respond to Webhook4",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 客服机器人, AI 聊天机器人
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
[模板] - 仪表板聊天
AI模型使用仪表板:追踪LLM工作流的令牌指标和成本
N8n
Set
Code
+12
30 节点Hugo
客户支持
AI驱动的电商客户支持聊天机器人,集成GPT-4和Supabase
Code
Switch
Webhook
+8
27 节点Sehar Nazeer
客服机器人
AI 社交媒体自动回复插件(Instagram、Facebook 和 WhatsApp)
基于 Llama 3.2 的 AI 社交媒体消息自动回复系统(Instagram、Facebook、WhatsApp)
Code
Switch
Webhook
+7
12 节点Oneclick AI Squad
客服机器人
使用WhatsApp AI助手和Google文档及Gemini自动处理客户支持
使用WhatsApp AI助手和Google文档及Gemini自动处理客户支持
If
Code
Webhook
+9
14 节点Jamot
客服机器人
具备多步骤工具执行的AI驱动HVAC排程代理
通过AI代理、Google日历和Gmail自动化HVAC服务排程
Wait
Gmail
Webhook
+11
30 节点Bhuvanesh R
客服机器人
客户响应器 IG/TG
使用 GPT-4 和 Google Sheets 的自动化产品咨询响应器
Code
Webhook
Google Sheets
+4
10 节点Dmytro
客服机器人
工作流信息
难度等级
高级
节点数量24
分类2
节点类型7
作者
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
外部链接
在 n8n.io 查看 →
分享此工作流