AutomationFlowsAI & RAG › Route AI Tasks Between Anthropic Claude Models

Route AI Tasks Between Anthropic Claude Models

Original n8n title: Route AI Tasks Between Anthropic Claude Models with Postgres Policies and Sla

ByResilNext @rnair1996 on n8n.io

This workflow implements a policy-driven LLM orchestration system that dynamically routes AI tasks to different language models based on task complexity, policies, and performance constraints.

Webhook trigger★★★★★ complexityAI-powered32 nodesAgentPostgresAnthropic ChatOutput Parser Structured
AI & RAG Trigger: Webhook Nodes: 32 Complexity: ★★★★★ AI nodes: yes Added:

This workflow corresponds to n8n.io template #14039 — we link there as the canonical source.

This workflow follows the Agent → Anthropic Chat 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
{
  "nodes": [
    {
      "id": "0becb529-f4bf-4033-b90f-f2f7caabae8a",
      "name": "Task Input Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1616,
        80
      ],
      "parameters": {
        "path": "llm-orchestrator",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "e46430e8-1081-4511-a38c-16d1fdbf54ae",
      "name": "Workflow Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        -1360,
        80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "maxLatencyMs",
              "type": "number",
              "value": 30000
            },
            {
              "id": "id-2",
              "name": "costCeiling",
              "type": "number",
              "value": 0.5
            },
            {
              "id": "id-3",
              "name": "timeoutMs",
              "type": "number",
              "value": 25000
            },
            {
              "id": "id-4",
              "name": "maxTokens",
              "type": "number",
              "value": 4000
            },
            {
              "id": "id-5",
              "name": "maxRetries",
              "type": "number",
              "value": 2
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "a298d196-218a-4cd0-8c4c-fdc00ab4ee40",
      "name": "Task Classifier Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1136,
        80
      ],
      "parameters": {
        "text": "={{ $json.task }}",
        "options": {
          "systemMessage": "You are a task classification expert. Analyze the provided task and classify it into one of these categories: extraction, classification, reasoning, or generation.\n\nProvide a confidence score (0-100) for your classification.\n\nConsider:\n- Extraction: pulling specific data from text\n- Classification: categorizing or labeling content\n- Reasoning: logical analysis or problem-solving\n- Generation: creating new content\n\nReturn your analysis in the structured format."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "6564841d-fb51-4a1d-8721-451ccf0fa77f",
      "name": "Load Policy Rules",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -784,
        80
      ],
      "parameters": {
        "query": "SELECT * FROM policy_rules WHERE task_type = $1 AND priority = $2",
        "options": {
          "queryReplacement": "={{ $json.taskType }},={{ $json.priority }}"
        },
        "operation": "executeQuery"
      },
      "typeVersion": 2.6
    },
    {
      "id": "d867f0a1-76e8-4df1-84c6-1f155b84bca5",
      "name": "Policy Engine Decision",
      "type": "n8n-nodes-base.code",
      "position": [
        -624,
        80
      ],
      "parameters": {
        "jsCode": "const config = $('Workflow Configuration').first().json;\nconst classification = $input.first().json;\nconst policy = $input.item.json;\n\n// Decision matrix based on policy rules\nconst decision = {\n  modelSize: policy.preferred_model || 'small',\n  allowTools: policy.allow_tools || false,\n  retryStrategy: policy.retry_strategy || 'fallback',\n  timeoutMs: Math.min(classification.priority === 'critical' ? config.timeoutMs * 0.8 : config.timeoutMs, policy.max_latency_ms || config.timeoutMs),\n  maxTokens: policy.max_tokens || config.maxTokens,\n  costBudget: Math.min(config.costCeiling, policy.cost_limit || config.costCeiling),\n  taskType: classification.taskType,\n  confidence: classification.confidence,\n  priority: classification.priority\n};\n\n// Override to large model for complex reasoning or low confidence\nif (classification.taskType === 'reasoning' && classification.confidence < 70) {\n  decision.modelSize = 'large';\n}\n\nif (classification.priority === 'critical') {\n  decision.modelSize = 'large';\n}\n\nreturn decision;"
      },
      "typeVersion": 2
    },
    {
      "id": "5cbd74df-80e5-4389-88e8-eefebafe5084",
      "name": "Route by Model Selection",
      "type": "n8n-nodes-base.switch",
      "position": [
        -272,
        64
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "small",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.modelSize }}",
                    "rightValue": "small"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "large",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.modelSize }}",
                    "rightValue": "large"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Fallback"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5b78b42d-1d6e-4c7f-a496-cce92e0e6e01",
      "name": "Large Model Execution",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        48,
        656
      ],
      "parameters": {
        "text": "={{ $json.task }}",
        "options": {
          "systemMessage": "=You are an advanced AI assistant capable of complex reasoning and detailed analysis. Process the task thoroughly and accurately.\n\nTask type: {{ $json.taskType }}\nPriority: {{ $json.priority }}\n\nProvide comprehensive, well-reasoned responses within the allocated time and token budget."
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "d40f3de4-3bce-448f-afc6-2a98801832f4",
      "name": "Store Telemetry",
      "type": "n8n-nodes-base.postgres",
      "position": [
        640,
        192
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "name",
          "value": "telemetry"
        },
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "columns": {
          "value": {
            "success": "={{ $json.success }}",
            "priority": "={{ $json.priority }}",
            "task_type": "={{ $json.task_type }}",
            "timestamp": "={{ $json.timestamp }}",
            "latency_ms": "={{ $json.latency_ms }}",
            "model_used": "={{ $json.model_used }}",
            "tokens_used": "={{ $json.tokens_used }}",
            "failure_type": "={{ $json.failure_type }}",
            "estimated_cost": "={{ $json.estimated_cost }}"
          },
          "schema": [
            {
              "id": "task_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "task_type",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "priority",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "priority",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "model_used",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "model_used",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "latency_ms",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "latency_ms",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "tokens_used",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "tokens_used",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "estimated_cost",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "estimated_cost",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "success",
              "type": "boolean",
              "display": true,
              "required": false,
              "displayName": "success",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "failure_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "failure_type",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "task_type",
            "priority",
            "model_used",
            "latency_ms",
            "tokens_used",
            "estimated_cost",
            "success",
            "failure_type",
            "timestamp"
          ]
        },
        "options": {}
      },
      "typeVersion": 2.6
    },
    {
      "id": "a40d7801-17d7-4f74-b00b-d5202126a41d",
      "name": "Return Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        992,
        192
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"result\": {{ $json.output }},\n  \"latency\": {{ $json.executionLatencyMs }},\n  \"model\": {{ $json.modelUsed }},\n  \"cost\": {{ $json.estimatedCost }}\n}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "527af998-2b05-4141-933e-1e8ffe960e44",
      "name": "Weekly Self-Tuning Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1584,
        768
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtHour": 2
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "14f9e6bb-1e94-4b89-81ff-5025b1aeddb1",
      "name": "Fetch Historical Data",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -1312,
        768
      ],
      "parameters": {
        "query": "SELECT task_type, model_used, AVG(latency_ms) as avg_latency, AVG(estimated_cost) as avg_cost, COUNT(*) as total_executions, SUM(CASE WHEN success = true THEN 1 ELSE 0 END) as successful_executions FROM telemetry WHERE timestamp > NOW() - INTERVAL '7 days' GROUP BY task_type, model_used",
        "options": {},
        "operation": "executeQuery"
      },
      "typeVersion": 2.6
    },
    {
      "id": "81d0b945-eb1d-4f6e-abaf-b4b37a2e0f98",
      "name": "Aggregate Success Metrics",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1040,
        768
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "task_type"
      },
      "typeVersion": 1
    },
    {
      "id": "50e7ded2-aa27-42d8-b72a-e005c6511f24",
      "name": "Calculate Routing Adjustments",
      "type": "n8n-nodes-base.code",
      "position": [
        -848,
        768
      ],
      "parameters": {
        "jsCode": "const metrics = $input.first().json;\n\n// Calculate success rates and performance\nconst adjustments = [];\n\nfor (const metric of metrics) {\n  const successRate = metric.successful_executions / metric.total_executions;\n  const avgLatency = metric.avg_latency;\n  const avgCost = metric.avg_cost;\n  \n  let recommendation = metric.model_used;\n  \n  // If small model has high success rate and low latency, prefer it\n  if (metric.model_used === 'large' && successRate > 0.95 && avgLatency < 5000) {\n    recommendation = 'small';\n  }\n  \n  // If small model has low success rate, upgrade to large\n  if (metric.model_used === 'small' && successRate < 0.80) {\n    recommendation = 'large';\n  }\n  \n  adjustments.push({\n    task_type: metric.task_type,\n    current_model: metric.model_used,\n    recommended_model: recommendation,\n    success_rate: successRate,\n    avg_latency: avgLatency,\n    avg_cost: avgCost,\n    adjustment_reason: recommendation !== metric.model_used ? 'Performance optimization' : 'No change needed'\n  });\n}\n\nreturn adjustments;"
      },
      "typeVersion": 2
    },
    {
      "id": "8186382f-38a1-4471-8433-bae6bff34298",
      "name": "Update Policy Rules",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -512,
        768
      ],
      "parameters": {
        "query": "UPDATE policy_rules SET preferred_model = $1 WHERE task_type = $2",
        "options": {
          "queryReplacement": "={{ $json.recommended_model }},={{ $json.task_type }}"
        },
        "operation": "executeQuery"
      },
      "typeVersion": 2.6
    },
    {
      "id": "bf404937-2cab-4730-9d3f-23bec52b23c7",
      "name": "Anthropic Chat Model - Classifier",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        -1168,
        288
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "claude-3-5-haiku-20241022"
        },
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "5b225513-a16e-44cb-b78c-d1e5e49246e5",
      "name": "Classification Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -912,
        304
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"taskType\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"The classified task type: extraction, classification, reasoning, or generation\"\n\t\t},\n\t\t\"confidence\": {\n\t\t\t\"type\": \"number\",\n\t\t\t\"description\": \"Confidence score from 0-100\"\n\t\t},\n\t\t\"priority\": {\n\t\t\t\"type\": \"string\",\n\t\t\t\"description\": \"Task priority from input\"\n\t\t}\n\t}\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "5c540c6b-5829-4306-bd9d-d5d3d17d583a",
      "name": "Anthropic Chat Model - Small",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        96,
        -192
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "claude-3-5-haiku-20241022"
        },
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "5163a1cc-433c-47f0-b7be-d38d92701f4a",
      "name": "Anthropic Chat Model - Large",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        -112,
        784
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "id",
          "value": "claude-3-5-sonnet-20241022"
        },
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "07413d00-5c68-415e-b92a-bde152e43f68",
      "name": "Prepare Telemetry Data",
      "type": "n8n-nodes-base.set",
      "position": [
        400,
        192
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "executionLatencyMs",
              "type": "number",
              "value": "={{ $now.diff($('Task Classifier Agent').first().json.startTime) }}"
            },
            {
              "id": "id-2",
              "name": "modelUsed",
              "type": "string",
              "value": "={{ $json.modelSize || 'unknown' }}"
            },
            {
              "id": "id-3",
              "name": "tokensUsed",
              "type": "number",
              "value": "={{ $json.usage?.total_tokens || 0 }}"
            },
            {
              "id": "id-4",
              "name": "estimatedCost",
              "type": "number",
              "value": "={{ ($json.usage?.total_tokens || 0) * 0.00001 }}"
            },
            {
              "id": "id-5",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "id-6",
              "name": "failureType",
              "type": "string",
              "value": "null"
            },
            {
              "id": "id-7",
              "name": "timestamp",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "b3e3e753-0909-40fb-b131-a3e39352fc5a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1248,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 800,
        "height": 592,
        "content": "## Policy Engine\n\nLoads routing policies from the database and combines them with task classification results.\n\nThe policy engine determines:\n\n\u2022 model size (small or large)  \n\u2022 token limits  \n\u2022 latency constraints  \n\u2022 cost budget"
      },
      "typeVersion": 1
    },
    {
      "id": "3050af39-dbed-4aa3-be9a-f5fd58e5c4df",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1728,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 320,
        "content": "## Weekly Optimization Trigger\n\nThis scheduled trigger runs once per week to analyze LLM execution performance."
      },
      "typeVersion": 1
    },
    {
      "id": "47a36f16-2712-4371-b065-cf785a833892",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1760,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 400,
        "content": "## Input\n\nEach request contains a task and optional priority metadata.  \nThis webhook acts as the API entry point for the LLM orchestration system."
      },
      "typeVersion": 1
    },
    {
      "id": "258ba5db-8fb4-44b8-8e1f-0adb7318e2d0",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1088,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 336,
        "content": "## Performance Aggregation\n\nTelemetry records are grouped by task type to calculate overall performance metrics.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7640f65e-389b-404f-b9f4-fc10cb428942",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1424,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 320,
        "content": "## Historical Telemetry Analysis\n\nExecution telemetry from the past 7 days is retrieved from the database."
      },
      "typeVersion": 1
    },
    {
      "id": "adf0417d-65c1-4c5e-a2e5-ab82c2ba1169",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -672,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 336,
        "content": "## Automatic Policy Optimization\n\nModel performance is analyzed to determine if routing policies should change.\nIf a smaller model performs well, it may replace a larger one."
      },
      "typeVersion": 1
    },
    {
      "id": "3e307f55-1408-4d9c-8794-3f6b59e7c29d",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 448,
        "content": "## Telemetry Collection\n\nExecution metrics are captured after each task:\n\n\u2022 latency  \n\u2022 tokens used  \n\u2022 estimated cost  \n\u2022 model used  \n\u2022 success status\n\nThese metrics are stored for monitoring and optimization."
      },
      "typeVersion": 1
    },
    {
      "id": "6854ce54-122a-496a-b142-baca4ad8b0e9",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 400,
        "content": " API Response\n\nThe workflow returns the AI response along with execution metadata including latency, model used, and estimated cost."
      },
      "typeVersion": 1
    },
    {
      "id": "0c5dbc16-ab23-436f-a95e-897cf410b776",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        464
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 448,
        "content": "## Large Model Execution\n\nProcesses complex tasks that require deeper reasoning or higher accuracy.\n\nUsed when the policy engine detects low confidence, high priority, or reasoning tasks."
      },
      "typeVersion": 1
    },
    {
      "id": "bc9d56ff-ecae-40d0-ad6a-62525ae1cbff",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 528,
        "content": "## Model Routing\n\nTasks are routed to different model pipelines depending on policy decisions.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1d11df13-0164-42b1-bdb5-c3147a097fbd",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -624
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 464,
        "content": "## Small Model Execution\n\nHandles lightweight tasks such as extraction or classification.\n\nOptimized for speed and cost efficiency while respecting token and latency limits."
      },
      "typeVersion": 1
    },
    {
      "id": "03475ddc-9a8d-49ee-8284-2dbd4e86aeca",
      "name": "Small Model Execution",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        0,
        -400
      ],
      "parameters": {
        "text": "={{ $json.task }}",
        "options": {
          "systemMessage": "=You are a fast, efficient AI assistant optimized for quick responses. Process the task accurately and concisely.\n\nTask type: {{ $json.taskType }}\nPriority: {{ $json.priority }}\n\nProvide your response within the allocated time and token budget."
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "49f091e1-1b4d-41a9-9c34-5733482af0b9",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2576,
        -64
      ],
      "parameters": {
        "width": 688,
        "height": 736,
        "content": "## Policy-Driven LLM Orchestrator with Self-Tuning Model Routing\n\nThis workflow acts as an intelligent orchestration layer for large language models. Instead of sending every task to a single model, it dynamically decides which model to use based on task complexity, policies, and historical performance.\n\n## How it works\n\nA webhook receives tasks and sends them to a classifier agent that determines the task type (extraction, classification, reasoning, or generation) along with a confidence score.\n\nThe workflow then loads policy rules from a database and applies a policy engine to determine the optimal execution strategy. These rules define model size, latency limits, token budgets, retry behavior, and cost ceilings.\n\nTasks are routed to either a small or large model depending on complexity and priority.\n\nTelemetry such as latency, tokens used, estimated cost, and success status is stored for every execution.\n\nA weekly optimization workflow analyzes this telemetry data to adjust routing policies automatically, improving cost efficiency and performance over time.\n\n## Setup steps\n\n1. Connect a Postgres database.\n2. Create tables: policy_rules and telemetry.\n3. Add Anthropic credentials for the LLM nodes.\n4. Configure latency, cost, and token limits in the configuration node.\n5. Send tasks to the webhook endpoint."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Store Telemetry": {
      "main": [
        [
          {
            "node": "Return Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Policy Rules": {
      "main": [
        [
          {
            "node": "Policy Engine Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Task Input Webhook": {
      "main": [
        [
          {
            "node": "Workflow Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Historical Data": {
      "main": [
        [
          {
            "node": "Aggregate Success Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Large Model Execution": {
      "main": [
        [
          {
            "node": "Prepare Telemetry Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Small Model Execution": {
      "main": [
        [
          {
            "node": "Prepare Telemetry Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Task Classifier Agent": {
      "main": [
        [
          {
            "node": "Load Policy Rules",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Policy Engine Decision": {
      "main": [
        [
          {
            "node": "Route by Model Selection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Telemetry Data": {
      "main": [
        [
          {
            "node": "Store Telemetry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Configuration": {
      "main": [
        [
          {
            "node": "Task Classifier Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Model Selection": {
      "main": [
        [
          {
            "node": "Small Model Execution",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Large Model Execution",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Success Metrics": {
      "main": [
        [
          {
            "node": "Calculate Routing Adjustments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Self-Tuning Schedule": {
      "main": [
        [
          {
            "node": "Fetch Historical Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model - Large": {
      "ai_languageModel": [
        [
          {
            "node": "Large Model Execution",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model - Small": {
      "ai_languageModel": [
        [
          {
            "node": "Small Model Execution",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Classification Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Task Classifier Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Routing Adjustments": {
      "main": [
        [
          {
            "node": "Update Policy Rules",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model - Classifier": {
      "ai_languageModel": [
        [
          {
            "node": "Task Classifier Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

This workflow implements a policy-driven LLM orchestration system that dynamically routes AI tasks to different language models based on task complexity, policies, and performance constraints.

Source: https://n8n.io/workflows/14039/ — 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

This workflow enables GDPR-compliant document processing by detecting, masking, and securely handling personally identifiable information (PII) before AI analysis.

Agent, Anthropic Chat, Output Parser Structured +2
AI & RAG

This workflow implements a privacy-preserving AI document processing pipeline that detects, masks, and securely manages Personally Identifiable Information (PII) before any AI processing occurs.

Agent, Output Parser Structured, Postgres +3
AI & RAG

This workflow automates end-to-end contract analysis using AI. It extracts clauses, evaluates risks, tracks obligations, and generates an executive summary from uploaded contracts.

Agent, Anthropic Chat, Output Parser Structured +3
AI & RAG

This workflow automates CSV data processing from upload to database insertion.

Agent, Anthropic Chat, Output Parser Structured +3
AI & RAG

⏺ 🚀 How it works

Agent, Anthropic Chat, Output Parser Structured +6