AutomationFlowsAI & RAG › Document Qa Agent

Document Qa Agent

Document-Qa-Agent. Uses ollama, httpRequest. Webhook trigger; 7 nodes.

Webhook trigger★★★★☆ complexityAI-powered7 nodesOllamaHTTP Request
AI & RAG Trigger: Webhook Nodes: 7 Complexity: ★★★★☆ AI nodes: yes Added:

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
{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "document-qa",
        "options": {}
      },
      "id": "webhook",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "model": "llama3",
        "operation": "embedding",
        "input": "={{ $json.question }}",
        "options": {}
      },
      "id": "generate_question_embedding",
      "name": "Generate Question Embedding",
      "type": "n8n-nodes-base.ollama",
      "typeVersion": 1,
      "position": [
        480,
        300
      ]
    },
    {
      "parameters": {
        "url": "=http://qdrant:6333/collections/documents/points/search",
        "method": "POST",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "vector",
              "value": "={{ $node[\"Generate Question Embedding\"].json.embedding }}"
            },
            {
              "name": "limit",
              "value": "={{ $json.max_results || 5 }}"
            },
            {
              "name": "with_payload",
              "value": true
            },
            {
              "name": "filter",
              "value": "={{ $json.document_ids && $json.document_ids.length > 0 ? {\"must\": [{\"key\": \"document_id\", \"match\": {\"any\": $json.document_ids}}]} : {} }}"
            }
          ]
        },
        "options": {}
      },
      "id": "search_documents",
      "name": "Search Documents",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        700,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "// Extract relevant information from search results\nconst results = $input.json.result || [];\n\n// Format the context from retrieved documents\nlet context = '';\nlet sources = [];\n\nif (results && results.length > 0) {\n  results.forEach((item, index) => {\n    if (item.payload && item.payload.text) {\n      context += `Document ${index + 1}: ${item.payload.text}\\n\\n`;\n      \n      // Add to sources\n      sources.push({\n        document_id: item.payload.document_id || 'unknown',\n        document_title: item.payload.document_title || 'Unknown Document',\n        page: item.payload.page || null,\n        text: item.payload.text.substring(0, 200) + '...'\n      });\n    }\n  });\n}\n\nreturn {\n  context,\n  sources,\n  question: $input.first().json.question,\n  conversation_id: $input.first().json.conversation_id || null\n};"
      },
      "id": "prepare_context",
      "name": "Prepare Context",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        920,
        300
      ]
    },
    {
      "parameters": {
        "model": "llama3",
        "operation": "chat",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a helpful document assistant. Your task is to answer questions based on the provided document context. If the context doesn't contain the information needed to answer the question, say that you don't have enough information. Always base your answers on the provided context and be specific about where the information comes from. If you quote or reference specific information, mention which document it's from."
            },
            {
              "role": "user",
              "content": "=Context information:\n{{ $json.context }}\n\nQuestion: {{ $json.question }}"
            }
          ]
        },
        "options": {
          "temperature": 0.3
        }
      },
      "id": "generate_answer",
      "name": "Generate Answer",
      "type": "n8n-nodes-base.ollama",
      "typeVersion": 1,
      "position": [
        1140,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "// Determine confidence based on response\nconst responseText = $input.json.message.content;\nconst lowerResponse = responseText.toLowerCase();\n\n// Check for phrases indicating the AI couldn't answer\nconst lowConfidence = [\n  \"i don't have enough information\",\n  \"i don't know\",\n  \"i'm not sure\",\n  \"cannot provide\",\n  \"unable to assist\",\n  \"not mentioned in the context\",\n  \"not specified in the documents\"\n].some(phrase => lowerResponse.includes(phrase));\n\n// Calculate confidence score\nlet confidence = lowConfidence ? 0.3 : 0.85;\n\nreturn {\n  answer: responseText,\n  sources: $input.first().json.sources || [],\n  confidence,\n  conversation_id: $input.first().json.conversation_id || null\n};"
      },
      "id": "format_answer",
      "name": "Format Answer",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1360,
        300
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "answer",
              "value": "={{ $json.answer }}"
            }
          ],
          "number": [
            {
              "name": "confidence",
              "value": "={{ $json.confidence }}"
            }
          ],
          "array": [
            {
              "name": "sources",
              "value": "={{ $json.sources }}"
            }
          ]
        },
        "options": {}
      },
      "id": "set",
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.2,
      "position": [
        1580,
        300
      ]
    }
  ],
  "connections": {
    "webhook": {
      "main": [
        [
          {
            "node": "generate_question_embedding",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "generate_question_embedding": {
      "main": [
        [
          {
            "node": "search_documents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "search_documents": {
      "main": [
        [
          {
            "node": "prepare_context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "prepare_context": {
      "main": [
        [
          {
            "node": "generate_answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "generate_answer": {
      "main": [
        [
          {
            "node": "format_answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "format_answer": {
      "main": [
        [
          {
            "node": "set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

Document-Qa-Agent. Uses ollama, httpRequest. Webhook trigger; 7 nodes.

Source: https://github.com/konfio/Nova.K-AI-Starter-Kit/blob/ceb30794de099859c8309b0e632ed8046543e341/examples/document-qa/document-qa-agent.json — 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

VEP WAPP. Uses openAi, lmChatOpenAi, toolCalculator, agent. Webhook trigger; 100 nodes.

OpenAI, OpenAI Chat, Tool Calculator +7
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

ANIS_HUB 1. Uses gmail, googleDrive, googleSheets, httpRequest. Webhook trigger; 89 nodes.

Gmail, Google Drive, Google Sheets +3
AI & RAG

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

Postgres, Mcp Client Tool, Google Drive Tool +14