{
  "name": "Nodbot - OpenRouter model fallback",
  "nodes": [
    {
      "parameters": {
        "path": "openrouter-model-fallback",
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "id": "e21c4688-3718-416d-bfdf-392c39ea0f03",
      "name": "Webhook input",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        260
      ]
    },
    {
      "parameters": {
        "jsCode": "const src = $json.body ?? $json;\nconst input = String(src.input ?? '').trim();\nif (!input) throw new Error('input is required');\nif (input.length > 12000) throw new Error('input is too long for this fallback chain');\n\nconst allowedModels = [\n  'openai/gpt-4o-mini',\n  'anthropic/claude-3.5-haiku',\n  'google/gemini-flash-1.5'\n];\nconst requested = Array.isArray(src.model_priority) ? src.model_priority : allowedModels;\nconst models = requested.filter(m => allowedModels.includes(m));\nif (models.length === 0) throw new Error('No allowed models in model_priority');\n\nreturn [{\n  json: {\n    request_id: src.request_id ?? `ai-${Date.now()}`,\n    openrouter_body: {\n      models,\n      messages: [\n        { role: 'system', content: 'Верни только JSON с полями label, confidence, reason, next_action.' },\n        { role: 'user', content: input }\n      ],\n      temperature: 0.1,\n      max_tokens: 600\n    },\n    audit: { requested_models: models, max_budget_usd: Number(src.max_budget_usd ?? 0.05) }\n  }\n}];"
      },
      "id": "94eb6ab8-0180-4005-a56f-8b4738b706d4",
      "name": "Prepare OpenRouter request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        280,
        260
      ]
    },
    {
      "parameters": {
        "jsCode": "const src = $json.body ?? $json;\nconst input = String(src.input ?? '').trim();\nif (!input) throw new Error('input is required');\nif (input.length > 12000) throw new Error('input is too long for this fallback chain');\n\nconst allowedModels = [\n  'openai/gpt-4o-mini',\n  'anthropic/claude-3.5-haiku',\n  'google/gemini-flash-1.5'\n];\nconst requested = Array.isArray(src.model_priority) ? src.model_priority : allowedModels;\nconst models = requested.filter(m => allowedModels.includes(m));\nif (models.length === 0) throw new Error('No allowed models in model_priority');\n\nreturn [{\n  json: {\n    request_id: src.request_id ?? `ai-${Date.now()}`,\n    openrouter_body: {\n      models,\n      messages: [\n        { role: 'system', content: 'Верни только JSON с полями label, confidence, reason, next_action.' },\n        { role: 'user', content: input }\n      ],\n      temperature: 0.1,\n      max_tokens: 600\n    },\n    audit: { requested_models: models, max_budget_usd: Number(src.max_budget_usd ?? 0.05) }\n  }\n}];"
      },
      "id": "8de99de8-12d1-4d00-82a3-60b7abf4790a",
      "name": "Call OpenRouter chat completions",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        560,
        260
      ]
    },
    {
      "parameters": {
        "jsCode": "const src = $json.body ?? $json;\nconst input = String(src.input ?? '').trim();\nif (!input) throw new Error('input is required');\nif (input.length > 12000) throw new Error('input is too long for this fallback chain');\n\nconst allowedModels = [\n  'openai/gpt-4o-mini',\n  'anthropic/claude-3.5-haiku',\n  'google/gemini-flash-1.5'\n];\nconst requested = Array.isArray(src.model_priority) ? src.model_priority : allowedModels;\nconst models = requested.filter(m => allowedModels.includes(m));\nif (models.length === 0) throw new Error('No allowed models in model_priority');\n\nreturn [{\n  json: {\n    request_id: src.request_id ?? `ai-${Date.now()}`,\n    openrouter_body: {\n      models,\n      messages: [\n        { role: 'system', content: 'Верни только JSON с полями label, confidence, reason, next_action.' },\n        { role: 'user', content: input }\n      ],\n      temperature: 0.1,\n      max_tokens: 600\n    },\n    audit: { requested_models: models, max_budget_usd: Number(src.max_budget_usd ?? 0.05) }\n  }\n}];"
      },
      "id": "7418a9e8-785b-473c-a5a8-8c854a440844",
      "name": "Validate structured response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        840,
        260
      ]
    },
    {
      "parameters": {},
      "id": "6b034f9f-02af-41e8-87bc-e1c6c310c3a0",
      "name": "Audit model usage",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1120,
        260
      ]
    },
    {
      "parameters": {},
      "id": "6e42c73e-2447-44e0-b1f6-d3ac05019655",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 2,
      "position": [
        1400,
        260
      ]
    }
  ],
  "connections": {
    "Webhook input": {
      "main": [
        [
          {
            "node": "Prepare OpenRouter request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare OpenRouter request": {
      "main": [
        [
          {
            "node": "Call OpenRouter chat completions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call OpenRouter chat completions": {
      "main": [
        [
          {
            "node": "Validate structured response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate structured response": {
      "main": [
        [
          {
            "node": "Audit model usage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Audit model usage": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    "nodbot",
    "production",
    "template"
  ],
  "triggerCount": 1,
  "updatedAt": "2026-05-30T00:00:00.000Z",
  "versionId": "d84169ba-6acc-445e-8673-adab63733d2d",
  "meta": {
    "templateCredsSetupCompleted": false
  }
}