{
  "name": "Enroutia · Compare three models and keep the best",
  "nodes": [
    {
      "parameters": {},
      "name": "Run",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "prompt",
              "name": "prompt",
              "value": "Write the subject line and the first two sentences of a cold email to a hotel manager in Mallorca offering an AI tool that answers booking questions in six languages.",
              "type": "string"
            },
            {
              "id": "criteria",
              "name": "criteria",
              "value": "Specific to the reader, no hype, under 60 words, a clear reason to reply.",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "name": "Task",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "operation": "compare",
        "models": [
          "auto",
          "mistral-small",
          "gpt-oss-120b"
        ],
        "prompt": "={{ $json.prompt }}",
        "options": {
          "temperature": 0.7,
          "maxTokens": 400
        }
      },
      "name": "Compare models",
      "type": "n8n-nodes-enroutia.enroutia",
      "typeVersion": 1,
      "position": [
        440,
        0
      ],
      "credentials": {
        "enroutiaApi": {
          "name": "Enroutia account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// All the answers in one item, numbered, so a judge can read them side by side.\nconst runs = $input.all().map((item) => item.json);\nconst prompt = $('Task').first().json.prompt;\nconst answers = runs\n  .map((run, i) => `### Answer ${i + 1}\\n${run.error ? '(failed: ' + run.error + ')' : run.text}`)\n  .join('\\n\\n');\nreturn [{ json: { prompt, answers, runs } }];\n"
      },
      "name": "Line up answers",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "operation": "message",
        "model": "gpt-oss-120b",
        "prompt": "=Task given to each model:\n{{ $json.prompt }}\n\nCriteria:\n{{ $('Task').first().json.criteria }}\n\n{{ $json.answers }}",
        "options": {
          "systemMessage": "You judge answers to the same task against the criteria. A failed answer scores 0. Return a JSON object: {\"best\": <number of the best answer, starting at 1>, \"scores\": [<0-10 per answer, in order>], \"reason\": <one sentence>}.",
          "jsonOutput": true,
          "temperature": 0,
          "maxTokens": 300
        }
      },
      "name": "Judge",
      "type": "n8n-nodes-enroutia.enroutia",
      "typeVersion": 1,
      "position": [
        880,
        0
      ],
      "credentials": {
        "enroutiaApi": {
          "name": "Enroutia account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// The judge names the best answer; this keeps it with its model, latency and usage.\nconst { runs } = $('Line up answers').first().json;\nconst verdict = JSON.parse($json.text);\nconst index = Math.min(Math.max(Number(verdict.best) - 1, 0), runs.length - 1);\nconst best = runs[index];\nreturn [{ json: {\n  best_model: best.model,\n  resolved_model: best.resolvedModel,\n  answer: best.text,\n  latency_ms: best.latencyMs,\n  usage: best.usage,\n  reason: verdict.reason,\n  scores: verdict.scores,\n  compared: runs.map((run) => ({ model: run.model, resolvedModel: run.resolvedModel, latencyMs: run.latencyMs, error: run.error || null })),\n} }];\n"
      },
      "name": "Keep the best",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1100,
        0
      ]
    }
  ],
  "connections": {
    "Run": {
      "main": [
        [
          {
            "node": "Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Task": {
      "main": [
        [
          {
            "node": "Compare models",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare models": {
      "main": [
        [
          {
            "node": "Line up answers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Line up answers": {
      "main": [
        [
          {
            "node": "Judge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Judge": {
      "main": [
        [
          {
            "node": "Keep the best",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}
