AutomationFlowsAI & RAG › Corvus 3.2 Beta

Corvus 3.2 Beta

Corvus 3.2 Beta. Uses httpRequest, agent, lmChatOpenAi, vectorStoreSupabase. Webhook trigger; 48 nodes.

Webhook trigger★★★★★ complexityAI-powered48 nodesHTTP RequestAgentOpenAI ChatSupabase Vector StoreMemory Postgres ChatOpenAI EmbeddingsForm TriggerPostgres
AI & RAG Trigger: Webhook Nodes: 48 Complexity: ★★★★★ AI nodes: yes Added:

This workflow follows the Agent → OpenAI Embeddings 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
{
  "name": "Corvus 3.2 Beta",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "corvus3",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "ddb38a93-53cd-409e-8179-acbb00645a50",
      "name": "Webhook Chat",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        188256,
        70544
      ]
    },
    {
      "parameters": {
        "jsCode": "\nconst rawBody = $json.body ?? $json;\nconst message = (rawBody.message ?? rawBody.text ?? '').toString().trim();\nconst userId = (rawBody.userId ?? rawBody.user ?? 'anonymous').toString().trim();\nconst sessionId = (rawBody.sessionId ?? rawBody.conversationId ?? userId).toString().trim();\nconst userContext = rawBody.userContext ?? {};\nconst modo = (rawBody.modo ?? 'auto').toString().toLowerCase().trim();\n\nconst rawImages = Array.isArray(rawBody.imageAttachments)\n  ? rawBody.imageAttachments\n  : (Array.isArray(rawBody.images) ? rawBody.images : []);\nconst imageAttachments = rawImages\n  .filter((item) => item && (item.dataUrl || item.imageUrl || item.url || item.signedUrl) && item.type && item.type.startsWith('image/'))\n  .slice(0, 4)\n  .map((item) => {\n    const imageUrl = (item.dataUrl || item.imageUrl || item.url || item.signedUrl || '').toString();\n    return {\n      name: (item.name ?? 'imagem').toString(),\n      type: (item.type ?? 'image/*').toString(),\n      size: Number(item.size ?? 0),\n      signedUrl: (item.signedUrl || item.imageUrl || item.url || imageUrl).toString(),\n      imageUrl,\n      url: imageUrl,\n      dataUrl: item.dataUrl ? item.dataUrl.toString() : undefined,\n    };\n  });\n\nconst rawDocuments = Array.isArray(rawBody.documentAttachments)\n  ? rawBody.documentAttachments\n  : (Array.isArray(rawBody.documents) ? rawBody.documents : []);\nconst documentAttachments = rawDocuments\n  .filter((item) => item && item.name && item.type)\n  .slice(0, 4)\n  .map((item) => ({\n    name: (item.name ?? 'documento').toString(),\n    type: (item.type ?? 'application/octet-stream').toString(),\n    size: Number(item.size ?? 0),\n    signedUrl: (item.signedUrl || item.url || '').toString(),\n    url: (item.url || item.signedUrl || '').toString(),\n    text: item.text ? item.text.toString() : '',\n    extractionError: item.extractionError ? item.extractionError.toString() : '',\n  }));\n\nconst rawAudios = Array.isArray(rawBody.audioAttachments)\n  ? rawBody.audioAttachments\n  : (Array.isArray(rawBody.audios) ? rawBody.audios : []);\nconst audioAttachments = rawAudios\n  .filter((item) => item && item.name && item.type)\n  .slice(0, 3)\n  .map((item) => ({\n    name: (item.name ?? 'audio').toString(),\n    type: (item.type ?? 'audio/*').toString(),\n    size: Number(item.size ?? 0),\n    signedUrl: (item.signedUrl || item.url || '').toString(),\n    url: (item.url || item.signedUrl || '').toString(),\n    text: item.text ? item.text.toString() : '',\n    provider: item.provider ? item.provider.toString() : '',\n    model: item.model ? item.model.toString() : '',\n    language: item.language ? item.language.toString() : '',\n    confidence: Number(item.confidence ?? 0) || undefined,\n    transcriptionError: item.transcriptionError ? item.transcriptionError.toString() : '',\n  }));\n\nconst documentContext = rawBody.documentContext || null;\nconst documentCtxString = (rawBody.documentCtxString || documentContext?.text || '').toString().trim();\nconst audioContext = rawBody.audioContext || null;\nconst audioCtxString = (rawBody.audioCtxString || audioContext?.text || '').toString().trim();\nconst visualContext = rawBody.visualContext || null;\nconst visualCtxString = (rawBody.visualCtxString || '').toString().trim();\n\nif (!message && imageAttachments.length === 0 && documentAttachments.length === 0 && audioAttachments.length === 0) {\n  return [{ ok: false, error: \"Missing 'message'\" }];\n}\n\nconst memoryKey = userId + '__' + sessionId;\nreturn [{\n  ok: true,\n  message,\n  userId,\n  sessionId,\n  memoryKey,\n  userContext,\n  modo,\n  imageAttachments,\n  hasImages: imageAttachments.length > 0 || rawBody.hasImages === true,\n  visualContext,\n  visualCtxString,\n  usedVision: rawBody.usedVision === true || Boolean(visualContext || visualCtxString),\n  documentAttachments,\n  documentContext,\n  documentCtxString,\n  hasDocuments: documentAttachments.length > 0 || rawBody.hasDocuments === true || Boolean(documentContext || documentCtxString),\n  audioAttachments,\n  audioContext,\n  audioCtxString,\n  hasAudio: audioAttachments.length > 0 || rawBody.hasAudio === true || Boolean(audioContext || audioCtxString),\n  usedAudioTranscription: rawBody.usedAudioTranscription === true || Boolean(audioContext || audioCtxString),\n  receivedAt: new Date().toISOString(),\n}];\n"
      },
      "id": "c0a76d44-02b9-40e4-8ca6-9e4b91fe1f09",
      "name": "Normalize Input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        188496,
        70544
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openAiApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"temperature\": 0,\n  \"max_tokens\": 256,\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"Voce e um classificador de mensagens para um sistema de IA institucional chamado Corvus da Ordem Masayoshi (MSY). Analise mensagem, contexto visual, documentos e audio transcrito, se houver. Retorne SOMENTE JSON valido, sem markdown, com: tipo, area, complexidade, usarBase, usarMemoria, modo_sugerido, ehSimulacao, ehDecisao. Modos validos: corvus, fenrir, cipher, conselho, simulacao. Use usarBase=true para contexto institucional MSY. Use simulacao para cenarios hipoteticos. Use conselho apenas para decisoes estrategicas complexas.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"Mensagem: {{ $json.message }}\\n\\nContexto visual: {{ JSON.stringify($json.visualContext || null) }}\\n\\nContexto documental: {{ $json.documentCtxString || \"\" }}\\n\\nContexto de audio: {{ $json.audioCtxString || \"\" }}\"\n    }\n  ]\n}",
        "options": {}
      },
      "id": "025bfba4-bd20-4556-9de5-f18ace811715",
      "name": "LLM Classifier",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        188736,
        70544
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "\nconst routedInput = $('Fast Router').item.json;\nconst classifierResponse = $json;\n\nlet cls = routedInput.fastRoute?.classifier || {};\nif (!routedInput.fastRoute?.skipClassifier) {\n  try {\n    const raw = classifierResponse.choices[0].message.content.trim();\n    const fence = String.fromCharCode(96, 96, 96);\n    const clean = raw.replace(new RegExp(fence + 'json|' + fence, 'g'), '').trim();\n    cls = JSON.parse(clean);\n  } catch {\n    cls = routedInput.fastRoute?.classifier || {\n      tipo:'geral', area:'geral', complexidade:'media', usarBase:false,\n      usarMemoria:true, modo_sugerido:'corvus', ehSimulacao:false, ehDecisao:false\n    };\n  }\n}\n\nconst validModes = ['corvus','fenrir','cipher','conselho','simulacao'];\nconst modoManual = routedInput.modo;\nlet resolvedMode = validModes.includes(modoManual) ? modoManual : (cls.modo_sugerido || 'corvus');\nif (cls.ehSimulacao && modoManual === 'auto') resolvedMode = 'simulacao';\nif (resolvedMode === 'conselho' && cls.complexidade !== 'alta') resolvedMode = 'cipher';\n\nconst topKMap = { baixa: 3, media: 5, alta: 8 };\nconst topK = topKMap[cls.complexidade] || 5;\nconst baseConf = { baixa: 0.92, media: 0.78, alta: 0.65 };\nconst typeMod = { pergunta:0.05, decisao:-0.05, simulacao:-0.10, ideia:-0.08, criativo:-0.06, problema:0, geral:0 };\nconst fastConfidence = routedInput.fastRoute?.confidence || 0;\nconst estimatedConfidence = Math.min(0.99, Math.max(0.40,\n  fastConfidence || ((baseConf[cls.complexidade] || 0.75) + (typeMod[cls.tipo] || 0))\n)).toFixed(2);\n\nconst userContext = routedInput.userContext || {};\nconst userCtxString = [\n  'Nome: ' + (userContext.nome || 'Desconhecido'),\n  'Cargo: ' + (userContext.cargo || '-'),\n  'Sigla: ' + (userContext.sigla || '-'),\n  'Tipo: ' + (userContext.tipo || 'convidado')\n].join(' | ');\n\nconst visualContext = routedInput.visualContext || null;\nconst documentContext = routedInput.documentContext || null;\nconst documentCtxString = (routedInput.documentCtxString || documentContext?.text || '').toString();\nconst audioContext = routedInput.audioContext || null;\nconst audioCtxString = (routedInput.audioCtxString || audioContext?.text || '').toString();\nconst visualCtxString = routedInput.visualCtxString\n  || (visualContext\n    ? [\n        'OCR: ' + (visualContext.ocrText || 'sem texto detectado'),\n        'Descricao: ' + (visualContext.description || ''),\n        'Itens: ' + ((visualContext.relevantItems || []).join(', ') || '-'),\n        'Limitacoes: ' + (visualContext.limitations || '-')\n      ].join('\\n')\n    : '');\n\nreturn [{\n  message: routedInput.message,\n  userId: routedInput.userId,\n  sessionId: routedInput.sessionId,\n  memoryKey: routedInput.memoryKey,\n  userContext,\n  userCtxString,\n  visualContext,\n  visualCtxString,\n  usedVision: Boolean(visualContext || visualCtxString),\n  imageAttachments: routedInput.imageAttachments || [],\n  documentContext,\n  documentCtxString,\n  hasDocuments: Boolean(documentCtxString),\n  documentAttachments: routedInput.documentAttachments || [],\n  audioContext,\n  audioCtxString,\n  hasAudio: Boolean(audioCtxString),\n  usedAudioTranscription: Boolean(audioContext || audioCtxString),\n  audioAttachments: routedInput.audioAttachments || [],\n  receivedAt: routedInput.receivedAt,\n  visionError: routedInput.visionError || '',\n  orchestrator: {\n    tipo: cls.tipo || 'geral', area: cls.area || 'geral',\n    complexidade: cls.complexidade || 'media',\n    usarBase: cls.usarBase !== false,\n    usarMemoria: cls.usarMemoria !== false,\n    modoSugerido: cls.modo_sugerido || 'corvus',\n    ehSimulacao: cls.ehSimulacao === true,\n    ehDecisao: cls.ehDecisao === true,\n    requestedMode: routedInput.modo,\n    resolvedMode,\n    topK,\n    fastPath: routedInput.fastRoute?.skipClassifier === true,\n    estimatedConfidence: parseFloat(estimatedConfidence)\n  }\n}];\n"
      },
      "id": "f8b9b2cd-4e53-4d19-9261-83d21666e8a3",
      "name": "Orchestrator",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        188976,
        70544
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.orchestrator.resolvedMode }}",
                    "rightValue": "fenrir",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-fenrir"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.orchestrator.resolvedMode }}",
                    "rightValue": "cipher",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-cipher"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.orchestrator.resolvedMode }}",
                    "rightValue": "conselho",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-conselho"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.orchestrator.resolvedMode }}",
                    "rightValue": "corvus",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-corvus"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.orchestrator.resolvedMode }}",
                    "rightValue": "simulacao",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "r-sim"
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "7513f01d-efbb-4cab-b0d5-60e1af639df5",
      "name": "Mode Switch",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        189216,
        70544
      ]
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "corvus_system",
              "value": "=Voc\u00c3\u00aa \u00c3\u00a9 CORVUS em modo FENRIR \u00e2\u20ac\u201d o lado criativo, expansivo e vision\u00c3\u00a1rio da Ordem Masayoshi.\n\nVers\u00c3\u00a3o: 3.1 Beta\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nMISS\u00c3\u0192O\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nAuxiliar na cria\u00c3\u00a7\u00c3\u00a3o de ideias, campanhas, textos, projetos e brainstorming no contexto da MSY. Pensar de forma ampla, sem restri\u00c3\u00a7\u00c3\u00b5es criativas, mas dentro da identidade da Ordem.\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCONSULTA DE BASE\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n{{ $json.orchestrator.usarBase ? 'ATIVO: Consulte a tool buscar_base_msy para embasar a cria\u00c3\u00a7\u00c3\u00a3o com a identidade da MSY.' : 'DESATIVADO: Responda com criatividade sem consultar a base \u00e2\u20ac\u201d foco na gera\u00c3\u00a7\u00c3\u00a3o de ideias.' }}\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCONTEXTO\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n{{ $json.userCtxString }}\nTipo: {{ $json.orchestrator.tipo }} | \u00c3\u0081rea: {{ $json.orchestrator.area }} | Complexidade: {{ $json.orchestrator.complexidade }}\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCOMPORTAMENTO\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n- Respostas longas, ricas, elaboradas\n- Explore m\u00c3\u00baltiplas possibilidades antes de concluir\n- Use linguagem expressiva e com personalidade\n- Proponha varia\u00c3\u00a7\u00c3\u00b5es e alternativas\n- Conecte ideias de forma n\u00c3\u00a3o \u00c3\u00b3bvia\n- Seja ousado e memor\u00c3\u00a1vel\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nTOM\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nOusado. Expansivo. Inspirador. Ainda institucional, mas com liberdade criativa total.\n\nCONTEXTO VISUAL\n{{ $json.visualCtxString ? $json.visualCtxString : (($json.hasImages || $json.usedVision) ? 'Imagem anexada, mas a analise visual nao retornou detalhes suficientes.' : 'Nenhuma imagem foi anexada nesta mensagem.') }}\n\nSe houver contexto visual, use-o como fonte visual da resposta. Se estiver ilegivel ou ambiguo, declare apenas a incerteza especifica sem inventar.\n\nCONTEXTO DOCUMENTAL\n{{ $json.documentCtxString ? $json.documentCtxString : ($json.hasDocuments ? 'Documento anexado, mas nenhum texto legivel foi extraido.' : 'Nenhum documento foi anexado nesta mensagem.') }}\n\nSe houver contexto documental, use-o como fonte do arquivo anexado. Nao diga que nao consegue acessar o documento quando este bloco tiver conteudo.\n\nCONTEXTO DE AUDIO\n{{ $json.audioCtxString ? $json.audioCtxString : ($json.hasAudio ? 'Audio anexado, mas nenhuma fala legivel foi transcrita.' : 'Nenhum audio foi anexado nesta mensagem.') }}\n\nSe houver contexto de audio, trate a transcricao como conteudo do anexo. Nao diga que nao consegue ouvir ou acessar o audio quando este bloco tiver conteudo."
            },
            {
              "name": "chatInput",
              "value": "={{ $json.message }}"
            },
            {
              "name": "sessionId",
              "value": "={{ $json.sessionId }}"
            },
            {
              "name": "usarBase",
              "value": "={{ $json.orchestrator.usarBase }}"
            },
            {
              "name": "orchestratorData",
              "value": "={{ JSON.stringify($json.orchestrator) }}"
            },
            {
              "name": "memoryKey",
              "value": "={{ $json.memoryKey }}"
            },
            {
              "name": "topK",
              "value": "={{ $json.orchestrator.topK }}"
            },
            {
              "name": "resolvedMode",
              "value": "fenrir"
            },
            {
              "name": "visualContext",
              "value": "={{ JSON.stringify($json.visualContext || null) }}"
            },
            {
              "name": "visualCtxString",
              "value": "={{ $json.visualCtxString || \"\" }}"
            },
            {
              "name": "usedVision",
              "value": "={{ $json.usedVision === true }}"
            },
            {
              "name": "documentContext",
              "value": "={{ JSON.stringify($json.documentContext || null) }}"
            },
            {
              "name": "documentCtxString",
              "value": "={{ $json.documentCtxString || \"\" }}"
            },
            {
              "name": "hasDocuments",
              "value": "={{ $json.hasDocuments === true }}"
            },
            {
              "name": "hasImages",
              "value": "={{ $json.hasImages === true }}"
            },
            {
              "name": "visionError",
              "value": "={{ $json.visionError || \"\" }}"
            },
            {
              "name": "imageAttachments",
              "value": "={{ JSON.stringify($json.imageAttachments || []) }}"
            },
            {
              "name": "audioContext",
              "value": "={{ JSON.stringify($json.audioContext || null) }}"
            },
            {
              "name": "audioCtxString",
              "value": "={{ $json.audioCtxString || \"\" }}"
            },
            {
              "name": "hasAudio",
              "value": "={{ $json.hasAudio === true }}"
            },
            {
              "name": "usedAudioTranscription",
              "value": "={{ $json.usedAudioTranscription === true }}"
            },
            {
              "name": "audioAttachments",
              "value": "={{ JSON.stringify($json.audioAttachments || []) }}"
            }
          ]
        },
        "options": {}
      },
      "id": "87824ca8-68bc-42bc-9c46-df5947cbc56c",
      "name": "Set Fenrir Prompt",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        189712,
        69760
      ]
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "corvus_system",
              "value": "=Voc\u00c3\u00aa \u00c3\u00a9 CORVUS em modo CIPHER \u00e2\u20ac\u201d o estrategista anal\u00c3\u00adtico da Ordem Masayoshi.\n\nVers\u00c3\u00a3o: 3.1 Beta\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nMISS\u00c3\u0192O\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nApoiar decis\u00c3\u00b5es complexas, an\u00c3\u00a1lises de risco e planejamento estrat\u00c3\u00a9gico. Voc\u00c3\u00aa pensa como um conselheiro s\u00c3\u00aanior \u00e2\u20ac\u201d calculado, preciso, com vis\u00c3\u00a3o sist\u00c3\u00aamica.\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCONSULTA DE BASE\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n{{ $json.orchestrator.usarBase ? 'ATIVO: Consulte buscar_base_msy para embasar a an\u00c3\u00a1lise com contexto institucional real.' : 'DESATIVADO: Use racioc\u00c3\u00adnio estrat\u00c3\u00a9gico puro.' }}\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCONTEXTO\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n{{ $json.userCtxString }}\nTipo: {{ $json.orchestrator.tipo }} | \u00c3\u0081rea: {{ $json.orchestrator.area }} | Complexidade: {{ $json.orchestrator.complexidade }}\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nESTRUTURA OBRIGAT\u00c3\u201cRIA DE RESPOSTA\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nSempre que poss\u00c3\u00advel, estruture sua resposta assim:\n\n**An\u00c3\u00a1lise**\n(diagn\u00c3\u00b3stico objetivo da situa\u00c3\u00a7\u00c3\u00a3o)\n\n**Riscos**\n(o que pode dar errado, grau de impacto)\n\n**Recomenda\u00c3\u00a7\u00c3\u00a3o**\n(a\u00c3\u00a7\u00c3\u00a3o concreta e direta)\n\n**Pr\u00c3\u00b3ximos Passos**\n(2 a 3 a\u00c3\u00a7\u00c3\u00b5es priorit\u00c3\u00a1rias)\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCOMPORTAMENTO\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n- Racioc\u00c3\u00adnio de primeira e segunda ordem\n- Apresente trade-offs claros quando h\u00c3\u00a1 m\u00c3\u00baltiplas rotas\n- Quantifique quando poss\u00c3\u00advel\n- Nunca romantize decis\u00c3\u00b5es dif\u00c3\u00adceis\n- Direto, sem floreios\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nTOM\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nEstrat\u00c3\u00a9gico. Anal\u00c3\u00adtico. Preciso. Fale como um conselheiro s\u00c3\u00aanior da Ordem.\n\nCONTEXTO VISUAL\n{{ $json.visualCtxString ? $json.visualCtxString : (($json.hasImages || $json.usedVision) ? 'Imagem anexada, mas a analise visual nao retornou detalhes suficientes.' : 'Nenhuma imagem foi anexada nesta mensagem.') }}\n\nSe houver contexto visual, use-o como fonte visual da resposta. Se estiver ilegivel ou ambiguo, declare apenas a incerteza especifica sem inventar.\n\nCONTEXTO DOCUMENTAL\n{{ $json.documentCtxString ? $json.documentCtxString : ($json.hasDocuments ? 'Documento anexado, mas nenhum texto legivel foi extraido.' : 'Nenhum documento foi anexado nesta mensagem.') }}\n\nSe houver contexto documental, use-o como fonte do arquivo anexado. Nao diga que nao consegue acessar o documento quando este bloco tiver conteudo.\n\nCONTEXTO DE AUDIO\n{{ $json.audioCtxString ? $json.audioCtxString : ($json.hasAudio ? 'Audio anexado, mas nenhuma fala legivel foi transcrita.' : 'Nenhum audio foi anexado nesta mensagem.') }}\n\nSe houver contexto de audio, trate a transcricao como conteudo do anexo. Nao diga que nao consegue ouvir ou acessar o audio quando este bloco tiver conteudo."
            },
            {
              "name": "chatInput",
              "value": "={{ $json.message }}"
            },
            {
              "name": "sessionId",
              "value": "={{ $json.sessionId }}"
            },
            {
              "name": "usarBase",
              "value": "={{ $json.orchestrator.usarBase }}"
            },
            {
              "name": "orchestratorData",
              "value": "={{ JSON.stringify($json.orchestrator) }}"
            },
            {
              "name": "memoryKey",
              "value": "={{ $json.memoryKey }}"
            },
            {
              "name": "topK",
              "value": "={{ $json.orchestrator.topK }}"
            },
            {
              "name": "resolvedMode",
              "value": "cipher"
            },
            {
              "name": "visualContext",
              "value": "={{ JSON.stringify($json.visualContext || null) }}"
            },
            {
              "name": "visualCtxString",
              "value": "={{ $json.visualCtxString || \"\" }}"
            },
            {
              "name": "usedVision",
              "value": "={{ $json.usedVision === true }}"
            },
            {
              "name": "documentContext",
              "value": "={{ JSON.stringify($json.documentContext || null) }}"
            },
            {
              "name": "documentCtxString",
              "value": "={{ $json.documentCtxString || \"\" }}"
            },
            {
              "name": "hasDocuments",
              "value": "={{ $json.hasDocuments === true }}"
            },
            {
              "name": "hasImages",
              "value": "={{ $json.hasImages === true }}"
            },
            {
              "name": "visionError",
              "value": "={{ $json.visionError || \"\" }}"
            },
            {
              "name": "imageAttachments",
              "value": "={{ JSON.stringify($json.imageAttachments || []) }}"
            },
            {
              "name": "audioContext",
              "value": "={{ JSON.stringify($json.audioContext || null) }}"
            },
            {
              "name": "audioCtxString",
              "value": "={{ $json.audioCtxString || \"\" }}"
            },
            {
              "name": "hasAudio",
              "value": "={{ $json.hasAudio === true }}"
            },
            {
              "name": "usedAudioTranscription",
              "value": "={{ $json.usedAudioTranscription === true }}"
            },
            {
              "name": "audioAttachments",
              "value": "={{ JSON.stringify($json.audioAttachments || []) }}"
            }
          ]
        },
        "options": {}
      },
      "id": "0baee3c3-cfed-49d6-b067-bf80012768a2",
      "name": "Set Cipher Prompt",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        189664,
        70320
      ]
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "corvus_system",
              "value": "=Voc\u00c3\u00aa \u00c3\u00a9 CORVUS \u00e2\u20ac\u201d o agente institucional oficial da Ordem Masayoshi (MSY).\n\nVers\u00c3\u00a3o: 3.1 Beta\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nPROTOCOLO DE CONSULTA\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n{{ $json.orchestrator.usarBase ? 'ATIVO: Execute buscar_base_msy ANTES de formular qualquer resposta sobre a MSY.' : 'DESATIVADO: Responda com base no conhecimento institucional consolidado \u00e2\u20ac\u201d sem consulta \u00c3\u00a0 base.' }}\n\nRegra de integridade: \u00c3\u2030 proibido inventar nomes de membros, cargos, datas, decis\u00c3\u00b5es ou eventos formais.\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nIDENTIDADE\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nNome: Corvus | Vers\u00c3\u00a3o: 3.1 Beta\nCriadores: T4 Masayoshi (Fundador) e Xitter (Coordenador Geral)\nVoc\u00c3\u00aa existe exclusivamente para servir \u00c3\u00a0 MSY. Voc\u00c3\u00aa fala como a institui\u00c3\u00a7\u00c3\u00a3o fala.\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCONTEXTO\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n{{ $json.userCtxString }}\nTipo: {{ $json.orchestrator.tipo }} | \u00c3\u0081rea: {{ $json.orchestrator.area }} | Complexidade: {{ $json.orchestrator.complexidade }}\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nCONDUTA\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\n- Nunca mencione bastidores t\u00c3\u00a9cnicos, banco de dados, APIs ou tools\n- Nunca pe\u00c3\u00a7a esclarecimentos \u00c3\u00b3bvios\n- 1 pergunta objetiva se necess\u00c3\u00a1rio\n\nPADRAO DE ENTREGA\n\nVoce deve escolher o formato da resposta de acordo com o pedido.\n\nPara perguntas simples:\n-> Responda curto, direto e sem enfeitar.\n\nPara pedidos que pedem comparacao, explicacao, ranking, decisao, plano, estudo, diagnostico, estrategia ou analise:\n-> Entregue resposta premium, organizada e visualmente clara.\n-> Abra com uma sintese objetiva.\n-> Use tabelas quando houver comparacao real.\nREGRA FORTE PARA COMPARATIVOS\nSe o pedido usar palavras como compare, comparativo, ranking, maior para menor, menor para maior, melhores, piores, hierarquia, cargos, funcoes ou diferencas, a resposta DEVE usar tabela markdown.\nNao responda comparativos em lista numerada quando uma tabela puder mostrar melhor a informacao.\nPara ranking/hierarquia, use colunas como: Posicao | Item/Cargo | Responsavel (se houver) | Funcao principal | Importancia | Observacao.\nDepois da tabela, escreva uma conclusao curta com a leitura estrategica principal.\n-> Use criterios quando precisar avaliar opcoes.\n-> Use ranking quando existir hierarquia.\n-> Use checklist ou plano de acao quando houver execucao.\n-> Feche com conclusao, recomendacao ou proximos passos.\n\nNao alongue respostas simples.\nNao use tabela se ela nao melhorar a resposta.\nNao exponha raciocinio interno literal; mostre apenas conclusoes, criterios e etapas uteis.\nNao copie estilo de outro assistente; adapte a entrega ao tom do Corvus: firme, estrategico, institucional e elegante.\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nVALORES\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nLealdade \u00e2\u20ac\u201d Uni\u00c3\u00a3o \u00e2\u20ac\u201d Justi\u00c3\u00a7a \u00e2\u20ac\u201d Liberdade\n\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nTOM\n\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\u00e2\u201d\u0081\nFirme. Estrat\u00c3\u00a9gico. Institucional. Direto. Sem hesita\u00c3\u00a7\u00c3\u00a3o.\n\nCONTEXTO VISUAL\n{{ $json.visualCtxString ? $json.visualCtxString : (($json.hasImages || $json.usedVision) ? 'Imagem anexada, mas a analise visual nao retornou detalhes suficientes.' : 'Nenhuma imagem foi anexada nesta mensagem.') }}\n\nSe houver contexto visual, use-o como fonte visual da resposta. Se estiver ilegivel ou ambiguo, declare apenas a incerteza especifica sem inventar.\n\nCONTEXTO DOCUMENTAL\n{{ $json.documentCtxString ? $json.documentCtxString : ($json.hasDocuments ? 'Documento anexado, mas nenhum texto legivel foi extraido.' : 'Nenhum documento foi anexado nesta mensagem.') }}\n\nSe houver contexto documental, use-o como fonte do arquivo anexado. Nao diga que nao consegue acessar o documento quando este bloco tiver conteudo.\n\nCONTEXTO DE AUDIO\n{{ $json.audioCtxString ? $json.audioCtxString : ($json.hasAudio ? 'Audio anexado, mas nenhuma fala legivel foi transcrita.' : 'Nenhum audio foi anexado nesta mensagem.') }}\n\nSe houver contexto de audio, trate a transcricao como conteudo do anexo. Nao diga que nao consegue ouvir ou acessar o audio quando este bloco tiver conteudo."
            },
            {
              "name": "chatInput",
              "value": "={{ $json.message }}"
            },
            {
              "name": "sessionId",
              "value": "={{ $json.sessionId }}"
            },
            {
              "name": "usarBase",
              "value": "={{ $json.orchestrator.usarBase }}"
            },
            {
              "name": "orchestratorData",
              "value": "={{ JSON.stringify($json.orchestrator) }}"
            },
            {
              "name": "memoryKey",
              "value": "={{ $json.memoryKey }}"
            },
            {
              "name": "topK",
              "value": "={{ $json.orchestrator.topK }}"
            },
            {
              "name": "resolvedMode",
              "value": "corvus"
            },
            {
              "name": "visualContext",
              "value": "={{ JSON.stringify($json.visualContext || null) }}"
            },
            {
              "name": "visualCtxString",
              "value": "={{ $json.visualCtxString || \"\" }}"
            },
            {
              "name": "usedVision",
              "value": "={{ $json.usedVision === true }}"
            },
            {
              "name": "documentContext",
              "value": "={{ JSON.stringify($json.documentContext || null) }}"
            },
            {
              "name": "documentCtxString",
              "value": "={{ $json.documentCtxString || \"\" }}"
            },
            {
              "name": "hasDocuments",
              "value": "={{ $json.hasDocuments === true }}"
            },
            {
              "name": "hasImages",
              "value": "={{ $json.hasImages === true }}"
            },
            {
              "name": "visionError",
              "value": "={{ $json.visionError || \"\" }}"
            },
            {
              "name": "imageAttachments",
              "value": "={{ JSON.stringify($json.imageAttachments || []) }}"
            },
            {
              "name": "audioContext",
              "value": "={{ JSON.stringify($json.audioContext || null) }}"
            },
            {
              "name": "audioCtxString",
              "value": "={{ $json.audioCtxString || \"\" }}"
            },
            {
              "name": "hasAudio",
              "value": "={{ $json.hasAudio === true }}"
            },
            {
              "name": "usedAudioTranscription",
              "value": "={{ $json.usedAudioTranscription === true }}"
            },
            {
              "name": "audioAttachments",
              "value": "={{ JSON.stringify($json.audioAttachments || []) }}"
            }
          ]
        },
        "options": {}
      },
      "id": "d82a5185-e437-4a29-8007-318a46d73f36",
      "name": "Set Corvus Prompt",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [
        190128,
        70768
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.chatInput }}\n",
        "options": {
          "systemMessage": "={{ $json.corvus_system }}"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        189952,
        69760
      ],
      "id": "e1866493-1c03-4f36-9ca1-6bde5906e38f",
      "name": "AI Agent (Fenrir)"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4o",
          "mode": "list",
          "cachedResultName": "gpt-4o"
        },
        "builtInTools": {},
        "options": {
          "temperature": 1
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        189824,
        69904
      ],
      "id": "40c081b5-fffc-4d68-b472-ea78c9a0d337",
      "name": "GPT-4o (Fenrir)",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "retrieve-as-tool",
        "toolDescription": "CONDICIONAL. Use esta tool APENAS se o campo usarBase for true. Busca contexto institucional da MSY: membros, cargos, valores, estrutura, hist\u00c3\u00b3ria, eventos, Corvus, NeverMind, Britannia.",
        "tableName": {
          "__rl": true,
          "value": "msy_knowledge",
          "mode": "id"
        },
        "topK": 6,
        "options": {
          "queryName": "buscar_msy"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "typeVersion": 1.3,
      "position": [
        190112,
        69952
      ],
      "id": "b3f39c21-a4bd-4fa0-aaa1-f16140740807",
      "name": "VectorStore (Fenrir)",
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $json.memoryKey }}",
        "tableName": "msy_memoria_chat"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.3,
      "position": [
        189952,
        69904
      ],
      "id": "e5dc66de-284f-4563-99fd-8d82d6649b97",
      "name": "Memory (Fenrir)",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "typeVersion": 1.2,
      "position": [
        190192,
        70080
      ],
      "id": "65dddae3-1e51-4a1e-85b0-bee2da894b14",
      "name": "Embeddings (Fenrir)",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.chatInput }}\n",
        "options": {
          "systemMessage": "={{ $json.corvus_system }}"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        189856,
        70048
      ],
      "id": "98c7d9b9-a346-4321-b827-8d1f79a2de9d",
      "name": "AI Agent (Cipher)"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4o",
          "mode": "list",
          "cachedResultName": "gpt-4o"
        },
        "builtInTools": {},
        "options": {
          "temperature": 0.5
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        189840,
        70240
      ],
      "id": "1c28fde2-658a-43a5-86d7-cc7f140d0265",
      "name": "GPT-4o (Cipher)",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "retrieve-as-tool",
        "toolDescription": "CONDICIONAL. Use esta tool APENAS se o campo usarBase for true. Busca contexto institucional da MSY: membros, cargos, valores, estrutura, hist\u00c3\u00b3ria, eventos, Corvus, NeverMind, Britannia.",
        "tableName": {
          "__rl": true,
          "value": "msy_knowledge",
          "mode": "id"
        },
        "topK": 8,
        "options": {
          "queryName": "buscar_msy"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "typeVersion": 1.3,
      "position": [
        190080,
        70240
      ],
      "id": "8a152a6d-af93-4697-be44-e12d0ae7f9d2",
      "name": "VectorStore (Cipher)",
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $json.memoryKey }}",
        "tableName": "msy_memoria_chat"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.3,
      "position": [
        189952,
        70240
      ],
      "id": "617a5ef0-33b1-4cd5-b329-d47e4d52d52d",
      "name": "Memory (Cipher)",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "typeVersion": 1.2,
      "position": [
        190080,
        70416
      ],
      "id": "467a7a33-2cca-429c-be0d-b9e3d41b6fd8",
      "name": "Embeddings (Cipher)",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.chatInput }}\n",
        "options": {
          "systemMessage": "={{ $json.corvus_system }}"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        190528,
        70768
      ],
      "id": "c814bcaf-27e4-430e-934b-aff8691f4c61",
      "name": "AI Agent (Corvus)"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4o",
          "mode": "list",
          "cachedResultName": "gpt-4o"
        },
        "builtInTools": {},
        "options": {
          "temperature": 0.3
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        190528,
        70976
      ],
      "id": "3ddd8aed-fdff-4215-a610-50367ef42a4d",
      "name": "GPT-4o (Corvus)",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "retrieve-as-tool",
        "toolDescription": "CONDICIONAL. Use esta tool APENAS se o campo usarBase for true. Busca contexto institucional da MSY: membros, cargos, valores, estrutura, hist\u00c3\u00b3ria, eventos, Corvus, NeverMind, Britannia.",
        "tableName": {
          "__rl": true,
          "value": "msy_knowledge",
          "mode": "id"
        },
        "topK": 5,
        "options": {
          "queryName": "buscar_msy"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStoreSupabase",
      "typeVersion": 1.3,
      "position": [
        190960,
        70880
      ],
      "id": "f036ffae-ba23-48e3-b5ed-ad9d4898b805",
      "name": "VectorStore (Corvus)",
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $json.memoryKey }}",
        "tableName": "msy_memoria_chat"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.3,
      "position": [
        190624,
        70976
      ],
      "id": "d473e8c3-1962-4c00-9bf5-18a48757ca8d",
      "name": "Memory (Corvus)",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "typeVersion": 1.2,
      "position": [
        190880,
        71120
      ],
      "id": "a04e2a87-22a8-43fc-b8c4-3f9fa2847255",
      "name": "Embeddings (Corvus)",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "\nconst agentOutput = $input.first().json;\nlet oc = {};\ntry { oc = agentOutput.orchestrator || JSON.parse(agentOutput.orchestratorData || '{}'); } catch {}\nif (oc.ehDecisao === true) {\n  console.log('[corvus:decision]', JSON.stringify({\n    msg: (agentOutput.message||'').substring(0,200),\n    tipo: oc.tipo, area: oc.area, modo: oc.resolvedMode, ts: new Date().toISOString()\n  }));\n}\nreturn [agentOutput];\n"
      },
      "id": "b2ec32e3-24e8-43ce-af13-10c3a9b577b6",
      "name": "Decision Log",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        190848,
        70368
      ]
    },
    {
      "parameters": {
        "jsCode": "\nconst agentOutput = $input.first()?.json || {};\n\nlet oc = {};\ntry {\n  oc = agentOutput.orchestrator || JSON.parse(agentOutput.orchestratorData || '{}');\n} catch {}\n\nconst resolvedMode = agentOutput.resolvedMode || oc.resolvedMode || 'corvus';\nconst modeLabels = {\n  corvus:'Corvus - Institucional', fenrir:'Fenrir - Criativo',\n  cipher:'Cipher - Estrategico', conselho:'Conselho - Perspectiva Tripla',\n  simulacao:'Simulacao - Analise de Cenarios'\n};\n\nfunction parseMaybeJson(value, fallback = null) {\n  if (!value) return fallback;\n  if (typeof value === 'object') return value;\n  try { return JSON.parse(value); } catch { return fallback; }\n}\n\nconst base = oc.estimatedConfidence || 0.75;\nconst ragBonus = oc.usarBase ? 0.05 : 0;\nconst cxPenalty = oc.complexidade === 'alta' ? -0.08 : (oc.complexidade === 'baixa' ? 0.04 : 0);\nconst confidence = Math.min(0.99, Math.max(0.40, base + ragBonus + cxPenalty));\nconst visualContext = parseMaybeJson(agentOutput.visualContext, agentOutput.visualContext || null);\nconst documentContext = parseMaybeJson(agentOutput.documentContext, agentOutput.documentContext || null);\nconst audioContext = parseMaybeJson(agentOutput.audioContext, agentOutput.audioContext || null);\nconst usedVision = Boolean(agentOutput.usedVision || visualContext || agentOutput.visualCtxString);\nconst usedDocuments = Boolean(agentOutput.hasDocuments || agentOutput.documentCtxString || documentContext);\nconst usedAudio = Boolean(agentOutput.hasAudio || agentOutput.audioCtxString || audioContext);\nconst audioSummary = (agentOutput.audioCtxString || audioContext?.text || '').toString().slice(0, 240);\nconst documentSummary = (agentOutput.documentCtxString || documentContext?.text || '').toString().slice(0, 240);\n\nconst suggestionsMap = {\n  decisao: ['Simular cenario', 'Ver alternativas', 'Analisar riscos com Cipher'],\n  problema: ['Analisar com Cipher', 'Simular solucao', 'Consultar Conselho'],\n  ideia: ['Expandir com Fenrir', 'Analisar viabilidade', 'Simular impacto'],\n  audio: ['Transcrever integralmente', 'Resumir audio', 'Extrair acoes'],\n  simulacao: ['Analisar decisao', 'Consultar Conselho', 'Salvar como decisao'],\n  conselho: ['Aprofundar com Cipher', 'Expandir com Fenrir', 'Simular cenario'],\n  geral: ['Gerar ideia', 'Analisar decisao', 'Simular cenario']\n};\nconst suggestions = suggestionsMap[oc.tipo] || suggestionsMap.geral;\n\nfunction cleanText(value) {\n  return (value || '').toString().replace(/\\s+/g, ' ').trim();\n}\nfunction makeTags() {\n  const tags = new Set();\n  if (oc.area && oc.area !== 'geral') tags.add(oc.area);\n  if (oc.tipo && oc.tipo !== 'geral') tags.add(oc.tipo);\n  if (resolvedMode && resolvedMode !== 'corvus') tags.add(resolvedMode);\n  if (usedVision) tags.add('imagem');\n  if (usedDocuments) tags.add('documento');\n  if (usedAudio) tags.add('audio');\n  if (oc.usarBase) tags.add('msy');\n  return Array.from(tags).slice(0, 5);\n}\nfunction makeNextActions(reply) {\n  const lines = reply.split('\n').map(cleanText).filter(Boolean);\n  const actionLines = lines.filter((line) => /^(\\d+\\.|-|\\*)?\\s*(definir|validar|revisar|criar|enviar|priorizar|analisar|executar|documentar|alinhar)/i.test(line));\n  return (actionLines.length ? actionLines : suggestions).slice(0, 4);\n}\nfunction makeMeta(replyText, mode) {\n  return {\n    agent:'Corvus 3.2 Beta', model:'gpt-4o', mode,\n    modeLabel: modeLabels[mode] ?? mode,\n    complexity: oc.complexidade || 'media', usedRAG: oc.usarBase === true,\n    usedVision, visualSummary: visualContext?.description || '',\n    usedDocuments, documentSummary,\n    usedAudio, audioSummary,\n    confidence: parseFloat(confidence.toFixed(2)), tipo: oc.tipo || 'geral',\n    summaryCandidate: cleanText(replyText).slice(0, 360),\n    tags: makeTags(),\n    nextActions: makeNextActions(replyText),\n    decisionCandidate: oc.ehDecisao === true,\n    timestamp: new Date().toISOString(), suggestions, visionError: agentOutput.visionError || ''\n  };\n}\n\nif (agentOutput.consiliumPayload?.isConselho) {\n  const consiliumText = agentOutput.consiliumPayload.blocks.map((block) => block.label + ': ' + block.reply).join('\n');\n  return [{\n    json: {\n      ok: true,\n      reply: consiliumText,\n      consilium: agentOutput.consiliumPayload.blocks,\n      meta: { ...makeMeta(consiliumText, 'conselho'), usedRAG: oc.usarBase || false }\n    }\n  }];\n}\n\nlet reply = (\n  agentOutput.reply ?? agentOutput.output ?? agentOutput.text ?? agentOutput.response ??\n  agentOutput.message ?? (agentOutput.choices && agentOutput.choices[0]?.message?.content) ?? ''\n).toString().trim();\n\nif (!reply && usedAudio && audioSummary) {\n  reply = [\n    'Recebi e transcrevi o audio. O workflow nao retornou uma resposta do agente, entao segue a transcricao para continuidade:',\n    '',\n    audioSummary\n  ].join('\n');\n}\n\nif (!reply) {\n  reply = 'Recebi a mensagem, mas o agente nao retornou uma resposta. Verifique o ultimo node executado no n8n.';\n}\n\nreturn [{\n  json: {\n    ok: true,\n    reply,\n    consilium: null,\n    

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

Corvus 3.2 Beta. Uses httpRequest, agent, lmChatOpenAi, vectorStoreSupabase. Webhook trigger; 48 nodes.

Source: https://github.com/T4Msy/Corvus-2.0/blob/main/n8n/workflow2.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

Hi! I’m Amanda, a creator of intelligent automations using n8n and Make. I’ve been building AI-powered workflows for over 2 years, always focused on usability and innovation. This one here is very spe

OpenAI Chat, Redis, OpenAI +11
AI & RAG

HeyDinastia. Uses executeCommand, httpRequest, youTube, postgres. Webhook trigger; 66 nodes.

Execute Command, HTTP Request, YouTube +15
AI & RAG

This workflow automates multi-channel AI-driven sales engagement for lead qualification, service information delivery, and consultation booking. It integrates WhatsApp, Facebook Messenger, Instagram D

Agent, OpenAI Embeddings, OpenAI Chat +11
AI & RAG

Agente_Atendimento_E_commerce. Uses baserow, redis, openAi, httpRequest. Webhook trigger; 52 nodes.

Baserow, Redis, OpenAI +9
AI & RAG

Indoor Farming Agent. Uses lmChatOpenAi, documentDefaultDataLoader, embeddingsOpenAi, toolVectorStore. Webhook trigger; 36 nodes.

OpenAI Chat, Document Default Data Loader, OpenAI Embeddings +16