AutomationFlowsAI & RAG › GPT-4 Multi-agent Chat Web UI

GPT-4 Multi-agent Chat Web UI

Original n8n title: Beautiful Web UI for Gpt-4 Multi-agent Chat with Specialized Assistants

ByHugo @hugo-misery on n8n.io

A beautiful, ready-to-use HTML interface for n8n workflows that allows your users to interact with AI agents through a clean web UI. No frontend skills required! No Frontend Skills Required: Get a professional interface without writing React, Vue, or complex JavaScript Real-Time…

Webhook trigger★★★★☆ complexityAI-powered24 nodesAgentOpenAI Chat
AI & RAG Trigger: Webhook Nodes: 24 Complexity: ★★★★☆ AI nodes: yes Added:
GPT-4 Multi-agent Chat Web UI — n8n workflow card showing Agent, OpenAI Chat integration

This workflow corresponds to n8n.io template #9901 — we link there as the canonical source.

This workflow follows the Agent → OpenAI Chat 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 →

Download .json
{
  "id": "paV8EK0gI9osnTJo",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "My workflow 4",
  "tags": [],
  "nodes": [
    {
      "id": "fcec0359-3e21-4953-b3be-781671b20151",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        0,
        0
      ],
      "parameters": {
        "path": "b6f698e9-c16c-4273-8af2-20a958f691c1",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "bf62e968-3190-4337-b5da-822fe7db3ebf",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        192,
        0
      ],
      "parameters": {
        "jsCode": "// YOUR_AWS_SECRET_KEY_HERE=================\n// === n8n GRAPHICAL INPUT TEMPLATE - AI AGENT INTERFACE ===\n// YOUR_AWS_SECRET_KEY_HERE=================\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// YOUR_AWS_SECRET_KEY_HERE=================\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": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        384,
        0
      ],
      "parameters": {
        "options": {},
        "respondWith": "binary"
      },
      "typeVersion": 1.4
    },
    {
      "id": "a32db689-90a0-4e80-a0a1-02c5ccdadedf",
      "name": "Sticky Note",
      "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": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        -80
      ],
      "parameters": {
        "width": 672,
        "height": 1168,
        "content": "# \ud83c\udfa8 n8n AI Agent Interface Template\n\nBeautiful web UI for your AI agents - no frontend skills needed!\n\n## \u26a1 Quick Setup (2 workflows)\n\n### Workflow 1: Display Interface (3 nodes)\n```\nWebhook (GET) \u2192 Code Node \u2192 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) \u2192 Switch \u2192 AI Agents \u2192 Code \u2192 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## \ud83d\udd27 Update in main.js\n\n**Line 847**: Change webhook URL\n```javascript\nconst WEBHOOK_URL = '/webhook/webhook-endpoint';\n```\n\n## \u2728 Features\n\u2705 Real-time AI responses \n\u2705 Loading animations \n\u2705 4 agent types \n\u2705 Dark/light mode \n\u2705 Mobile responsive\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f963c77a-0296-4e46-a8c1-94c73913ce40",
      "name": "Sticky Note2",
      "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
      ],
      "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": "AI Agent - 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": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        496,
        384
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "20bfc5c1-8093-4533-85fa-49f9f5eff917",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        496,
        656
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1f1fc350-0ed9-433f-9527-a8c356f23d4a",
      "name": "OpenAI Chat Model2",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        496,
        944
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "21e8e7c1-4b78-46c0-98ba-24006592a737",
      "name": "OpenAI Chat Model3",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        496,
        1232
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "02e03088-7c40-421d-ab15-ccacdb2735c7",
      "name": "Respond to Webhook1",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1088,
        240
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "988aa029-e110-42b3-b62e-156ee79d08c7",
      "name": "Respond to Webhook2",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1088,
        512
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "6dbf918b-fdb9-4032-95a5-ece4aee5c63f",
      "name": "Respond to Webhook3",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1088,
        784
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "477b257c-d283-4783-a505-29f0c2f50782",
      "name": "Respond to Webhook4",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1088,
        1072
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "e28c1572-dec7-4b90-be86-46b434366678",
      "name": "AI Agent Database",
      "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 Agent - 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": "AI Agent - 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": "Format Response - Code",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        240
      ],
      "parameters": {
        "jsCode": "// R\u00e9cup\u00e8re les donn\u00e9es du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// R\u00e9cup\u00e8re la r\u00e9ponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de r\u00e9ponse de l'IA (les agents IA peuvent renvoyer diff\u00e9rents formats)\nconst aiResponseText = aiAgentOutput.output || \n                       aiAgentOutput.text || \n                       aiAgentOutput.response || \n                       aiAgentOutput.message ||\n                       JSON.stringify(aiAgentOutput);\n\n// Formate la r\u00e9ponse pour l'interface utilisateur\nreturn [{\n  json: {\n    response: aiResponseText,              // La r\u00e9ponse de l'IA\n    agent_type: webhookData.agent_type,    // Type d'agent utilis\u00e9\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": "Format Response - Code1",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        512
      ],
      "parameters": {
        "jsCode": "// R\u00e9cup\u00e8re les donn\u00e9es du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// R\u00e9cup\u00e8re la r\u00e9ponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de r\u00e9ponse de l'IA (les agents IA peuvent renvoyer diff\u00e9rents formats)\nconst aiResponseText = aiAgentOutput.output || \n                       aiAgentOutput.text || \n                       aiAgentOutput.response || \n                       aiAgentOutput.message ||\n                       JSON.stringify(aiAgentOutput);\n\n// Formate la r\u00e9ponse pour l'interface utilisateur\nreturn [{\n  json: {\n    response: aiResponseText,              // La r\u00e9ponse de l'IA\n    agent_type: webhookData.agent_type,    // Type d'agent utilis\u00e9\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": "Format Response - Code2",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        784
      ],
      "parameters": {
        "jsCode": "// R\u00e9cup\u00e8re les donn\u00e9es du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// R\u00e9cup\u00e8re la r\u00e9ponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de r\u00e9ponse de l'IA (les agents IA peuvent renvoyer diff\u00e9rents formats)\nconst aiResponseText = aiAgentOutput.output || \n                       aiAgentOutput.text || \n                       aiAgentOutput.response || \n                       aiAgentOutput.message ||\n                       JSON.stringify(aiAgentOutput);\n\n// Formate la r\u00e9ponse pour l'interface utilisateur\nreturn [{\n  json: {\n    response: aiResponseText,              // La r\u00e9ponse de l'IA\n    agent_type: webhookData.agent_type,    // Type d'agent utilis\u00e9\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": "Format Response - Code3",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        1072
      ],
      "parameters": {
        "jsCode": "// R\u00e9cup\u00e8re les donn\u00e9es du webhook (le message de l'utilisateur)\nconst webhookData = $('Webhook1').first().json.body;\n\n// R\u00e9cup\u00e8re la r\u00e9ponse de l'agent IA\nconst aiAgentOutput = $input.first().json;\n\n// Extrait le texte de r\u00e9ponse de l'IA (les agents IA peuvent renvoyer diff\u00e9rents formats)\nconst aiResponseText = aiAgentOutput.output || \n                       aiAgentOutput.text || \n                       aiAgentOutput.response || \n                       aiAgentOutput.message ||\n                       JSON.stringify(aiAgentOutput);\n\n// Formate la r\u00e9ponse pour l'interface utilisateur\nreturn [{\n  json: {\n    response: aiResponseText,              // La r\u00e9ponse de l'IA\n    agent_type: webhookData.agent_type,    // Type d'agent utilis\u00e9\n    user_message: webhookData.message,     // Message original de l'utilisateur\n    timestamp: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    }
  ],
  "active": true,
  "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
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

A beautiful, ready-to-use HTML interface for n8n workflows that allows your users to interact with AI agents through a clean web UI. No frontend skills required! No Frontend Skills Required: Get a professional interface without writing React, Vue, or complex JavaScript Real-Time…

Source: https://n8n.io/workflows/9901/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

⏺ 🚀 How it works

Agent, Anthropic Chat, Output Parser Structured +6
AI & RAG

L&D_AgentsAI_ATIVO. Uses httpRequest, agent, googleCalendarTool, toolSerpApi. Webhook trigger; 93 nodes.

HTTP Request, Agent, Google Calendar Tool +9
AI & RAG

CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.

Postgres, Mcp Client Tool, Google Drive Tool +14
AI & RAG

Remi 1.1. Uses lmChatOpenAi, memoryPostgresChat, openAi, postgres. Webhook trigger; 89 nodes.

OpenAI Chat, Memory Postgres Chat, OpenAI +7
AI & RAG

This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La

Google Sheets, HTTP Request, Slack +10