{
  "name": "RFP 03 - Evidence Retrieval and Drafting Engine",
  "nodes": [
    {
      "id": "b6d9ca904a233087",
      "name": "Grounding Policy",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1320,
        -500
      ],
      "parameters": {
        "content": "## Evidence Retrieval & Drafting Engine\nSearches only approved evidence, asks NVIDIA to draft with explicit evidence IDs, then applies deterministic gates. The model cannot self-approve. Missing evidence, expired evidence, low confidence, guarantees, pricing, legal terms, or unsupported claims are escalated.",
        "width": 860,
        "height": 350,
        "color": 5
      }
    },
    {
      "id": "3b37ea069e8d0d33",
      "name": "Manual Retrieval Test",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1240,
        0
      ],
      "parameters": {}
    },
    {
      "id": "1263000598f50c75",
      "name": "Load Test Requirement",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -980,
        0
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "return [{json:{project_id:\"RFP-DEMO-001\",requirement_id:\"RFP-DEMO-001-REQ-001\",requirement_text:\"Describe your security certifications and encryption controls.\",retrieval_query:\"security certifications encryption at rest transit access controls\",category:\"SECURITY\",mandatory:true,permitted_classifications:\"PUBLIC,INTERNAL\",region:\"GLOBAL\"}}];"
      }
    },
    {
      "id": "5f582aa2987ab59b",
      "name": "Retrieve Approved Evidence",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "typeVersion": 1.3,
      "position": [
        -700,
        0
      ],
      "parameters": {
        "mode": "load",
        "qdrantCollection": {
          "mode": "id",
          "value": "rfp_sales_evidence"
        },
        "prompt": "={{ $('Load Test Requirement').item.json.retrieval_query }}",
        "topK": 6,
        "includeDocumentMetadata": true,
        "useReranker": false,
        "options": {
          "searchFilterJson": "={{ JSON.stringify({ must: [{ key: \"metadata.status\", match: { value: \"APPROVED\" } }] }) }}"
        }
      }
    },
    {
      "id": "67a5ee88818eabb9",
      "name": "NVIDIA Query Embeddings",
      "type": "@n8n/n8n-nodes-langchain.embeddingsNvidia",
      "typeVersion": 1,
      "position": [
        -700,
        260
      ],
      "parameters": {
        "model": {
          "mode": "id",
          "value": "nvidia/nv-embedqa-e5-v5"
        },
        "options": {
          "batchSize": 50,
          "stripNewLines": true,
          "timeout": 60000
        }
      }
    },
    {
      "id": "72a88f5457d347ce",
      "name": "Build Grounded Draft Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -410,
        0
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const req=$(\"Load Test Requirement\").item.json; const docs=$input.all().map(i=>i.json);\nconst allowed=new Set(String(req.permitted_classifications||\"PUBLIC,INTERNAL\").split(\",\").map(x=>x.trim().toUpperCase()));\nconst requestedRegion=String(req.region||\"GLOBAL\").toUpperCase(); const now=new Date();\nconst evidence=docs.map(d=>{const doc=d.document??d; return {text:doc.pageContent??doc.content??\"\",metadata:doc.metadata??{}};}).filter(d=>{const docRegion=String(d.metadata.region||\"\").toUpperCase(); const regionAllowed=docRegion===\"GLOBAL\"||docRegion===requestedRegion; return regionAllowed&&allowed.has(String(d.metadata.classification||\"\").toUpperCase())&&String(d.metadata.status||\"\").toUpperCase()===\"APPROVED\"&&(!d.metadata.valid_until||new Date(d.metadata.valid_until)>=now);});\nreturn [{json:{...req,evidence_count:evidence.length,evidence,grounded_prompt:`Answer the requirement using only the evidence below. Never infer certifications, commitments, prices, dates, legal positions, or capabilities. If evidence is insufficient, say so. Cite every material sentence with [document_id]. Return confidence from 0 to 1 and list unsupported claims.\\n\\nREQUIREMENT:\\n${req.requirement_text}\\n\\nAPPROVED EVIDENCE:\\n${evidence.map((d,i)=>`[${i+1}] ID=${d.metadata.document_id}; TITLE=${d.metadata.title}; VALID_UNTIL=${d.metadata.valid_until}\\n${d.text}`).join(\"\\n\\n\")}`}}];"
      }
    },
    {
      "id": "4a6eec5167a036a7",
      "name": "Draft Evidence-Bound Answer",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.9,
      "position": [
        -120,
        0
      ],
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.grounded_prompt + '\\n\\nReturn exactly one JSON object and no Markdown: {\"answer\":\"string\",\"evidence_ids\":[\"DOC-ID\"],\"confidence\":0.0,\"unsupported_claims\":[],\"reviewer_note\":\"string\"}' }}",
        "hasOutputParser": false,
        "needsFallback": false,
        "batching": {
          "batchSize": 1,
          "delayBetweenBatches": 0
        }
      }
    },
    {
      "id": "bcdcd08204c1bc96",
      "name": "NVIDIA Grounded Draft Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatNvidia",
      "typeVersion": 1,
      "position": [
        -170,
        260
      ],
      "parameters": {
        "model": "nvidia/llama-3.3-nemotron-super-49b-v1.5",
        "options": {
          "maxTokens": 4096,
          "temperature": 0.1,
          "topP": 1,
          "maxRetries": 2,
          "timeout": 180000,
          "responseFormat": "json_object"
        }
      }
    },
    {
      "id": "a4f143b6c90e469a",
      "name": "Apply Deterministic Control Policy",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        210,
        0
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const req=$(\"Build Grounded Draft Prompt\").item.json; let d=$json.output??$json; if(typeof d===\"string\"){d=JSON.parse(d.slice(d.indexOf(\"{\"),d.lastIndexOf(\"}\")+1));} else if(typeof d.text===\"string\"){d=JSON.parse(d.text.slice(d.text.indexOf(\"{\"),d.text.lastIndexOf(\"}\")+1));} const answer=String(d.answer??\"\");\nconst ids=[...new Set((d.evidence_ids??[]).map(String))]; const known=new Set(req.evidence.map(e=>String(e.metadata.document_id))); const invalid=ids.filter(id=>!known.has(id));\nconst sensitive=[\"LEGAL\",\"COMMERCIAL\"].includes(String(req.category).toUpperCase())||/price|discount|guarantee|indemn|liabil|penalt|warrant|zero incident|unlimited/i.test(req.requirement_text+\" \"+answer);\nconst unsupported=Array.isArray(d.unsupported_claims)?d.unsupported_claims:[]; const confidence=Math.max(0,Math.min(1,Number(d.confidence)||0));\nconst reasons=[]; if(req.evidence_count===0) reasons.push(\"NO_APPROVED_EVIDENCE\"); if(!ids.length) reasons.push(\"NO_CITATION\"); if(invalid.length) reasons.push(\"INVALID_CITATION\"); if(unsupported.length) reasons.push(\"UNSUPPORTED_CLAIM\"); if(confidence<0.78) reasons.push(\"LOW_CONFIDENCE\"); if(sensitive) reasons.push(\"SENSITIVE_COMMITMENT\");\nconst route=reasons.length?\"REVIEW\":\"AUTO_APPROVED\"; return [{json:{...req,draft_answer:answer,evidence_ids:ids.join(\",\"),confidence,unsupported_claims:unsupported.join(\" | \"),reviewer_note:String(d.reviewer_note??\"\"),control_reasons:reasons.join(\",\"),route,status:route===\"REVIEW\"?\"PENDING_REVIEW\":\"APPROVED\",updated_at:new Date().toISOString()}}];"
      }
    },
    {
      "id": "46e197c07d8d20c2",
      "name": "Human Review Required?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        500,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "Human Review Required?-condition",
              "leftValue": "={{ $json.route }}",
              "rightValue": "REVIEW",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "a5f592e37288508e",
      "name": "Upsert Review Queue",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        760,
        -100
      ],
      "parameters": {
        "authentication": "oAuth2",
        "resource": "sheet",
        "operation": "appendOrUpdate",
        "documentId": {
          "mode": "id",
          "value": "SET_OPERATIONS_WORKBOOK_ID"
        },
        "sheetName": {
          "mode": "name",
          "value": "Review Queue"
        },
        "dataMode": "autoMapInputData",
        "columnToMatchOn": "requirement_id",
        "options": {
          "handlingExtraData": "ignoreIt"
        }
      },
      "alwaysOutputData": false
    },
    {
      "id": "1d5720368270d90a",
      "name": "Upsert Auto-Approved Requirement",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        760,
        100
      ],
      "parameters": {
        "authentication": "oAuth2",
        "resource": "sheet",
        "operation": "appendOrUpdate",
        "documentId": {
          "mode": "id",
          "value": "SET_OPERATIONS_WORKBOOK_ID"
        },
        "sheetName": {
          "mode": "name",
          "value": "Requirement Matrix"
        },
        "dataMode": "autoMapInputData",
        "columnToMatchOn": "requirement_id",
        "options": {
          "handlingExtraData": "ignoreIt"
        }
      },
      "alwaysOutputData": false
    }
  ],
  "connections": {
    "Manual Retrieval Test": {
      "main": [
        [
          {
            "node": "Load Test Requirement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Test Requirement": {
      "main": [
        [
          {
            "node": "Retrieve Approved Evidence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NVIDIA Query Embeddings": {
      "ai_embedding": [
        [
          {
            "node": "Retrieve Approved Evidence",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Approved Evidence": {
      "main": [
        [
          {
            "node": "Build Grounded Draft Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Grounded Draft Prompt": {
      "main": [
        [
          {
            "node": "Draft Evidence-Bound Answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NVIDIA Grounded Draft Model": {
      "ai_languageModel": [
        [
          {
            "node": "Draft Evidence-Bound Answer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Draft Evidence-Bound Answer": {
      "main": [
        [
          {
            "node": "Apply Deterministic Control Policy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Apply Deterministic Control Policy": {
      "main": [
        [
          {
            "node": "Human Review Required?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Human Review Required?": {
      "main": [
        [
          {
            "node": "Upsert Review Queue",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Upsert Auto-Approved Requirement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "timezone": "Africa/Lagos",
    "saveManualExecutions": true,
    "saveExecutionProgress": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all",
    "executionTimeout": 600
  }
}
