{"_id":"@auwra/n8n-nodes-ai-router","_rev":"6-baf95ed1eae88c465b25cc9c2a161a95","name":"@auwra/n8n-nodes-ai-router","dist-tags":{"latest":"0.1.6"},"versions":{"0.1.0":{"name":"@auwra/n8n-nodes-ai-router","version":"0.1.0","keywords":["n8n-community-node-package"],"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"license":"MIT","_id":"@auwra/n8n-nodes-ai-router@0.1.0","maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"n8n":{"nodes":["dist/nodes/AiRouter/AiRouter.node.js"],"credentials":["dist/credentials/AiRouterApi.credentials.js"],"n8nNodesApiVersion":1},"dist":{"shasum":"132a2b25e5c8eefd0c7e17fe406e09fb60b1f19b","tarball":"https://registry.npmjs.org/@auwra/n8n-nodes-ai-router/-/n8n-nodes-ai-router-0.1.0.tgz","fileCount":31,"integrity":"sha512-hJVTr5lrgzuXC4rQzuJ8yXFLDqenKEUhlO/V7ZgpYRpR3naA2dxdyne2eKibD7iEiA4t4EZkiJoQlXaVFQyP+Q==","signatures":[{"sig":"MEYCIQCa5OpoWCwOIrp6kw/Gd2LXb6SeZZwkgh6Vwvo8GS3A9AIhALU9QI6X0/nqtHwAHCZG9kKmSK3PVOWAL/9oWDKC98PM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@auwra%2fn8n-nodes-ai-router@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":218198},"main":"index.js","gitHead":"1e7653491c2008e873e3b11bef9d0fd982abd870","scripts":{"dev":"n8n-node dev","lint":"n8n-node lint","test":"vitest run","build":"n8n-node build","lint:fix":"n8n-node lint --fix","test:real":"node test-real/run.mjs","test:watch":"vitest","sync:models":"node scripts/sync-models.mjs","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"auwra","email":"grzegorzhandzel992@gmail.com"},"overrides":{"eslint":"^9.0.0"},"repository":{"url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git","type":"git"},"_npmVersion":"10.9.4","description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","directories":{},"_nodeVersion":"22.22.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.7.0","@n8n/node-cli":"*","@vitest/coverage-v8":"^3.0.0"},"peerDependencies":{"n8n-workflow":"*"},"_npmOperationalInternal":{"tmp":"tmp/n8n-nodes-ai-router_0.1.0_1774976997678_0.2405765050863693","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@auwra/n8n-nodes-ai-router","version":"0.1.1","keywords":["n8n-community-node-package"],"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"license":"MIT","_id":"@auwra/n8n-nodes-ai-router@0.1.1","maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"n8n":{"nodes":["dist/nodes/AiRouter/AiRouter.node.js"],"credentials":["dist/credentials/AiRouterApi.credentials.js"],"n8nNodesApiVersion":1},"dist":{"shasum":"3fcc5a9caf9821681e70be34159936c0bb0513be","tarball":"https://registry.npmjs.org/@auwra/n8n-nodes-ai-router/-/n8n-nodes-ai-router-0.1.1.tgz","fileCount":31,"integrity":"sha512-UhR8aHe508jhpEHu32wTwK993D6Pbb9u87gswuJmC9KdBRMDAieUqDUbTCkgZCbQybRK3MlspiVkPiTVP+3sKQ==","signatures":[{"sig":"MEYCIQCMbYasX3+OOWEtaw1neFwwSQwslOoN5StxE1sIfD7dhwIhAICd8Is15mHNReRgBsbqaYOPMGESWBU4GLMORFTejPX0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@auwra%2fn8n-nodes-ai-router@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":218311},"main":"index.js","gitHead":"b775a74393e542b6d8d865cdb4461fcff45b9a2f","scripts":{"dev":"n8n-node dev","lint":"n8n-node lint","test":"vitest run","build":"n8n-node build","lint:fix":"n8n-node lint --fix","test:real":"node test-real/run.mjs","test:watch":"vitest","sync:models":"node scripts/sync-models.mjs","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"auwra","email":"grzegorzhandzel992@gmail.com"},"overrides":{"eslint":"^9.0.0"},"repository":{"url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git","type":"git"},"_npmVersion":"10.9.4","description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","directories":{},"_nodeVersion":"22.22.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.7.0","@n8n/node-cli":"*","@vitest/coverage-v8":"^3.0.0"},"peerDependencies":{"n8n-workflow":"*"},"_npmOperationalInternal":{"tmp":"tmp/n8n-nodes-ai-router_0.1.1_1774978113267_0.24931775454786043","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@auwra/n8n-nodes-ai-router","version":"0.1.2","keywords":["n8n-community-node-package"],"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"license":"MIT","_id":"@auwra/n8n-nodes-ai-router@0.1.2","maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"n8n":{"nodes":["dist/nodes/AiRouter/AiRouter.node.js"],"credentials":["dist/credentials/AiRouterApi.credentials.js"],"n8nNodesApiVersion":1},"dist":{"shasum":"fc2e2ee85c50ebfda6519f91e0f29a946f6c6a69","tarball":"https://registry.npmjs.org/@auwra/n8n-nodes-ai-router/-/n8n-nodes-ai-router-0.1.2.tgz","fileCount":31,"integrity":"sha512-lbxAj8pcrut6o5SyTUa3adahHuhCTxU12ZptUy969rrJs001Tp43R3JPkqZaLoy59P1+2bFScmeI2tGsg5xzBQ==","signatures":[{"sig":"MEUCIEQrFSwyHPBnb+NzuA1AS5Wu1EUSMOQK5hNXnAXA/cthAiEA2Yq30NvOsXEa8BAsbDNTqia4+1j4QwTUzM1bMQonA5s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@auwra%2fn8n-nodes-ai-router@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":218311},"main":"index.js","gitHead":"164933a8aedb03d61b9a7ed7c41bb614fc7293d9","scripts":{"dev":"n8n-node dev","lint":"n8n-node lint","test":"vitest run","build":"n8n-node build","lint:fix":"n8n-node lint --fix","test:real":"node test-real/run.mjs","test:watch":"vitest","sync:models":"node scripts/sync-models.mjs","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"auwra","email":"grzegorzhandzel992@gmail.com"},"overrides":{"eslint":"^9.0.0"},"repository":{"url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git","type":"git"},"_npmVersion":"10.9.4","description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","directories":{},"_nodeVersion":"22.22.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.7.0","@n8n/node-cli":"*","@vitest/coverage-v8":"^3.0.0"},"peerDependencies":{"n8n-workflow":"*"},"_npmOperationalInternal":{"tmp":"tmp/n8n-nodes-ai-router_0.1.2_1774978969441_0.8822343446854846","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@auwra/n8n-nodes-ai-router","version":"0.1.4","keywords":["n8n-community-node-package"],"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"license":"MIT","_id":"@auwra/n8n-nodes-ai-router@0.1.4","maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"n8n":{"nodes":["dist/nodes/AiRouter/AiRouter.node.js"],"credentials":["dist/credentials/AiRouterApi.credentials.js"],"n8nNodesApiVersion":1},"dist":{"shasum":"0838b73c90ecba9058411bcb6720745f2139a67d","tarball":"https://registry.npmjs.org/@auwra/n8n-nodes-ai-router/-/n8n-nodes-ai-router-0.1.4.tgz","fileCount":31,"integrity":"sha512-bcLJT/lu2RiFpeIGWbaUbme/uR+b6UYOhHncJmirMbLo4F7RdJ7yEx3894vyjNUeRGHPmcenS+Y3V3tucwgW2w==","signatures":[{"sig":"MEQCIEQOWwEZEefFSlEcNg1N3fgowFHt+ccJiVm95w8h+l+yAiBk5JzoYb4TesbDNruZBZcomNg7zSPqUEzQdVyramBoVw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@auwra%2fn8n-nodes-ai-router@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":222745},"main":"index.js","gitHead":"f3ee4aaa0c4e9e72b9c13908be21a99d5b5d5555","scripts":{"dev":"n8n-node dev","lint":"n8n-node lint","test":"vitest run","build":"n8n-node build","lint:fix":"n8n-node lint --fix","test:real":"node test-real/run.mjs","test:watch":"vitest","sync:models":"node scripts/sync-models.mjs","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"auwra","email":"grzegorzhandzel992@gmail.com"},"overrides":{"eslint":"^9.0.0"},"repository":{"url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git","type":"git"},"_npmVersion":"10.9.4","description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","directories":{},"_nodeVersion":"22.22.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.7.0","@n8n/node-cli":"*","@vitest/coverage-v8":"^3.0.0"},"peerDependencies":{"n8n-workflow":"*"},"_npmOperationalInternal":{"tmp":"tmp/n8n-nodes-ai-router_0.1.4_1775078774109_0.4392077191683619","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@auwra/n8n-nodes-ai-router","version":"0.1.5","keywords":["n8n-community-node-package"],"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"license":"MIT","_id":"@auwra/n8n-nodes-ai-router@0.1.5","maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"n8n":{"nodes":["dist/nodes/AiRouter/AiRouter.node.js"],"credentials":["dist/credentials/AiRouterApi.credentials.js"],"n8nNodesApiVersion":1},"dist":{"shasum":"fb084242c810fb058ab217123cce9385eed6fd04","tarball":"https://registry.npmjs.org/@auwra/n8n-nodes-ai-router/-/n8n-nodes-ai-router-0.1.5.tgz","fileCount":31,"integrity":"sha512-7Io9gADVXaDqUeBZ1e7ANKhxvFgJyoOs1k2vHM9MMCKexPx4LqTaPrpcH6yZbiMGMhNkOP/16i6OCMTj46ZgIw==","signatures":[{"sig":"MEUCID5Xq4HRz5pe+dXaVsbh60ZLDYaFcRRmRx77aSUcqmCDAiEAg+bUtwPZnU61AqYE/92vr5n5DPRFjkw3wn4xHq9pauo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@auwra%2fn8n-nodes-ai-router@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":226696},"main":"index.js","gitHead":"ad5eaeb8fc5a43e9b248e55f0954cecd8466b47e","scripts":{"dev":"n8n-node dev","lint":"n8n-node lint","test":"vitest run","build":"n8n-node build","lint:fix":"n8n-node lint --fix","test:real":"node test-real/run.mjs","test:watch":"vitest","sync:models":"node scripts/sync-models.mjs","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"auwra","email":"grzegorzhandzel992@gmail.com"},"overrides":{"eslint":"^9.0.0"},"repository":{"url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git","type":"git"},"_npmVersion":"10.9.7","description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","directories":{},"_nodeVersion":"22.22.2","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.7.0","@n8n/node-cli":"*","@vitest/coverage-v8":"^3.0.0"},"peerDependencies":{"n8n-workflow":"*"},"_npmOperationalInternal":{"tmp":"tmp/n8n-nodes-ai-router_0.1.5_1775079387661_0.434759578146954","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@auwra/n8n-nodes-ai-router","version":"0.1.6","description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","license":"MIT","keywords":["n8n-community-node-package"],"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"repository":{"type":"git","url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git"},"homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"main":"index.js","scripts":{"build":"n8n-node build","dev":"n8n-node dev","lint":"n8n-node lint","lint:fix":"n8n-node lint --fix","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","test:real":"node test-real/run.mjs","sync:models":"node scripts/sync-models.mjs"},"n8n":{"n8nNodesApiVersion":1,"credentials":["dist/credentials/AiRouterApi.credentials.js"],"nodes":["dist/nodes/AiRouter/AiRouter.node.js"]},"peerDependencies":{"n8n-workflow":"*"},"devDependencies":{"@n8n/node-cli":"*","@vitest/coverage-v8":"^3.0.0","typescript":"^5.7.0","vitest":"^3.0.0"},"overrides":{"eslint":"^9.0.0"},"_id":"@auwra/n8n-nodes-ai-router@0.1.6","gitHead":"ae35ccd96298c0519d6ed0addac5e59a3bf50a72","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-vy7VrcvTNkUbys09wtd7njLf6hcqe79KGlSMQwbaKp0tHDE+BKZWhV7AcHGeM9o1G4E/u2W1APxLEcC7YwM55w==","shasum":"ae39971a9ba7abeaf9fe353c954c0be3e42f3a08","tarball":"https://registry.npmjs.org/@auwra/n8n-nodes-ai-router/-/n8n-nodes-ai-router-0.1.6.tgz","fileCount":31,"unpackedSize":242539,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@auwra%2fn8n-nodes-ai-router@0.1.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHmcFWqQ26kk/CDPFJwz/MyKLMeySNWoe9n8ZVzRIWpyAiBePATRRNtSRangLr8U9rMcSTvADy2ikg5D2+13mtSL7g=="}]},"_npmUser":{"name":"auwra","email":"grzegorzhandzel992@gmail.com"},"directories":{},"maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/n8n-nodes-ai-router_0.1.6_1775154376661_0.7640327562315838"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-31T17:09:57.579Z","modified":"2026-04-02T18:26:17.124Z","0.1.0":"2026-03-31T17:09:57.866Z","0.1.1":"2026-03-31T17:28:33.476Z","0.1.2":"2026-03-31T17:42:49.593Z","0.1.4":"2026-04-01T21:26:14.265Z","0.1.5":"2026-04-01T21:36:27.883Z","0.1.6":"2026-04-02T18:26:16.808Z"},"bugs":{"url":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER/issues"},"author":{"name":"Auwra","email":"grzegorzhandzel992@gmail.com"},"license":"MIT","homepage":"https://github.com/AuwraCode/N8N-NODES-AI-ROUTER#readme","keywords":["n8n-community-node-package"],"repository":{"type":"git","url":"git+https://github.com/AuwraCode/N8N-NODES-AI-ROUTER.git"},"description":"Automatically route AI tasks to the most appropriate and cost-effective model across multiple providers","maintainers":[{"name":"auwra","email":"grzegorzhandzel992@gmail.com"}],"readme":"# @auwra/n8n-nodes-ai-router\n\n[![npm version](https://img.shields.io/npm/v/@auwra/n8n-nodes-ai-router.svg)](https://www.npmjs.com/package/@auwra/n8n-nodes-ai-router)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![n8n community node](https://img.shields.io/badge/n8n-community%20node-orange)](https://docs.n8n.io/integrations/community-nodes/)\n\nAn n8n community node that **automatically routes each prompt to the best AI model** across Anthropic, OpenAI, Google Gemini, Mistral AI, Groq, and local Ollama — based on what the task actually needs.\n\nInstead of hardcoding one model, the AI Router detects whether a prompt is a coding task, analysis, creative writing, summarization, vision, or chat, then picks the optimal model for your priority: cheapest, fastest, highest quality, or balanced. It falls back to the next-best model automatically if the first one fails.\n\n## Table of contents\n\n- [Quick start](#quick-start)\n- [Installation](#installation)\n- [Configuration](#configuration)\n- [How routing works](#how-routing-works)\n- [Choosing the right mode](#choosing-the-right-mode)\n- [Model registry](#model-registry)\n- [Keeping the registry up to date](#keeping-the-registry-up-to-date)\n- [Adding a custom model](#adding-a-custom-model)\n- [Example workflows](#example-workflows)\n- [Changelog](#changelog)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Quick start\n\n1. Install the node (see [Installation](#installation))\n2. Add the **AI Router** node to any workflow\n3. Set up credentials — paste in at least one API key (Groq has a free tier)\n4. Connect your prompt source and run\n\nThat's it. The node detects the task, picks the best model, calls it, and returns `response`. No configuration required for basic use.\n\n---\n\n## Installation\n\n### Via n8n Community Nodes UI (recommended)\n\n1. Go to **Settings → Community Nodes**\n2. Click **Install**\n3. Enter `@auwra/n8n-nodes-ai-router`\n4. Click **Install** and restart if prompted\n\n### Via npm (self-hosted)\n\n```bash\ncd ~/.n8n\nnpm install @auwra/n8n-nodes-ai-router\n# Restart n8n\n```\n\n### Credentials setup\n\nThe node uses a **single credential object** called **AI Router Credentials** that holds all your API keys in one place. Fill in only the providers you have — the router automatically skips providers with no key.\n\n| Field | Where to get it |\n|---|---|\n| Anthropic API Key | [console.anthropic.com](https://console.anthropic.com/) |\n| OpenAI API Key | [platform.openai.com](https://platform.openai.com/) |\n| Google Gemini API Key | [aistudio.google.com](https://aistudio.google.com/) |\n| Mistral AI API Key | [console.mistral.ai](https://console.mistral.ai/) |\n| Groq API Key (free tier) | [console.groq.com](https://console.groq.com/) |\n| Ollama Base URL | `http://localhost:11434` (no key needed) |\n\n**One provider is enough to get started.** Groq is the easiest: free tier, no credit card.\n\n---\n\n## Configuration\n\n### Input\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| **Prompt** | string | — | The user message to send to the AI model |\n| **System Prompt** | string | — | Optional system-level instruction: persona, output format, constraints |\n| **Temperature** | number | `0.7` | Sampling temperature 0–2. 0 = deterministic, 2 = very creative. Ignored by reasoning models. |\n\n### Routing\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| **Routing Mode** | enum | `auto` | How to prioritise model selection |\n| **Task Hint** | enum | auto-detect | Override automatic task detection |\n\n### Filtering / budget\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| **Allowed Providers** | multiselect | all | Which providers are eligible |\n| **Max Cost Per 1K Tokens** | number | `0` (no limit) | Hard budget cap in USD — models above this are excluded |\n\n### Generation\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| **Max Tokens** | number | `0` (provider default) | Maximum tokens to generate |\n\n### Behaviour\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| **Enable Fallback** | boolean | `true` | Retry with next-best model on 429/5xx errors (up to 3 attempts) |\n| **Dry Run (Routing Only)** | boolean | `false` | Select the best model and return routing info but do NOT call any API — no tokens spent |\n| **Max Items Per Execution** | number | `10` | Hard cap on items per run. Set to `0` to disable. |\n\n### Output options\n\n| Parameter | Type | Default | What it adds to output |\n|---|---|---|---|\n| **Include Model Info** | boolean | `false` | `modelUsed`, `providerUsed`, `attemptsTaken`, `inputTokens`, `outputTokens` |\n| **Include Detected Task** | boolean | `false` | `detectedTask`, `detectedTaskConfidence` |\n| **Include Score Breakdown** | boolean | `false` | `scoreBreakdown` — top-3 candidates with final score and per-criterion sub-scores |\n| **Include Estimated Cost** | boolean | `false` | `estimatedCostUSD` — calculated from token counts × registry pricing |\n\n### Routing modes\n\n| Mode | Best for | What it optimises |\n|---|---|---|\n| `auto` | General-purpose workflows | Balanced mix of quality, cost, and speed |\n| `quality` | Critical outputs, production content | Task-specific model quality above all else |\n| `cost` | High-volume, budget-sensitive workflows | Cheapest model that can do the job |\n| `speed` | Real-time, latency-sensitive workflows | Lowest-latency model first |\n| `local` | Privacy-sensitive data, offline use | Ollama only — zero cost, no data leaves your machine |\n\n### Task hint values\n\n| Value | Auto-detected when prompt contains |\n|---|---|\n| `coding` | Code snippets, language names, file extensions, debug/refactor/implement |\n| `writing` | write/draft/compose + document type (email, blog, essay, story, ad copy…) |\n| `analysis` | analyze, evaluate, compare, pros and cons, explain why, root cause |\n| `summarization` | summarize, tl;dr, key points, in N bullets, executive summary |\n| `classification` | classify, categorize, sentiment, true/false, spam detection |\n| `vision` | Image URLs, base64 image data, OCR, visual content |\n| `embeddings` | embed, vector, semantic search, RAG, cosine similarity |\n| `chat` | Greetings, open-ended questions (default fallback) |\n\n---\n\n## How routing works\n\n```mermaid\nflowchart TD\n    A([Prompt received]) --> B{Task hint set?}\n    B -- Yes --> D[Use hint as task type]\n    B -- No --> C[taskDetector\\nweighted regex patterns]\n    C --> D\n    D --> E[scoreModels\\nfilter + score all candidates]\n\n    E --> F{allowedProviders filter}\n    F --> G{maxCostPer1K budget cap}\n    G --> H{capability requirements\\nvision / embeddings}\n    H --> I{context window\\n≥ prompt length}\n    I --> J[Score each model\\ntaskFit · cost · latency · contextSize]\n    J --> K[Sort descending — best first]\n\n    K --> L[executeWithFallback\\nattempt 1: top model]\n    L -- success --> M([Output])\n    L -- 429 / 5xx / network --> N{fallback enabled?}\n    N -- Yes --> O[attempt 2: next model]\n    O -- success --> M\n    O -- fail --> P[attempt 3: next model]\n    P -- success --> M\n    P -- all fail --> Q([Error])\n    N -- No --> Q\n    L -- 400 / 401 / 403 --> Q\n```\n\n### Scoring formula\n\nEach candidate model gets a score (0–1):\n\n```\nscore = w_taskFit  × taskAffinity[task]\n      + w_cost     × (1 − blendedPer1K / maxInPool)\n      + w_latency  × (1 − (latencyTier − 1) / 2)\n      + w_context  × log(contextWindow + 1) / log(maxInPool + 1)\n```\n\nContext uses log normalization so a single model with a huge context window (e.g. 10M tokens) doesn't collapse every other model's score to near zero.\n\nWeights by mode:\n\n| Mode | taskFit | cost | latency | contextSize |\n|---|---|---|---|---|\n| auto | 0.35 | 0.25 | 0.20 | 0.20 |\n| quality | **0.70** | 0.05 | 0.05 | 0.20 |\n| cost | 0.20 | **0.60** | 0.10 | 0.10 |\n| speed | 0.25 | 0.15 | **0.50** | 0.10 |\n| local | 0.40 | 0.40 | 0.10 | 0.10 |\n\n---\n\n## Choosing the right mode\n\n**Use `quality` when:** output accuracy matters (production content, customer-facing responses, complex reasoning). The router will pick the model most specialised for the detected task — Claude Opus for analysis, Devstral for code, Gemini Pro for vision.\n\n**Use `cost` when:** you're running high volume and the task is simple (classification, summarization, short chat). Expect Groq or Gemini Flash Lite to win most of the time.\n\n**Use `speed` when:** you need sub-second responses (real-time chat, live autocomplete). All tier-1 models are fast; the router picks the most capable one among them.\n\n**Use `auto` when:** you're unsure. It's a sensible middle ground — it won't pick the most expensive model for a simple greeting, but it won't use the cheapest one for a complex analysis either.\n\n**Use `local` when:** prompts contain sensitive data you can't send to cloud APIs, or you're working offline.\n\n**Combine mode with `Allowed Providers`** for precise control: `quality` mode with only `anthropic` + `openai` ensures only flagship models are used.\n\n---\n\n## Model registry\n\nPricing verified April 2026. `blendedPer1K = (input×0.7 + output×0.3) / 1000`.\n\n### Anthropic\n\n| Model ID | Input/1M | Output/1M | Context | Best for |\n|---|---|---|---|---|\n| `claude-opus-4-6` | $5.00 | $25.00 | 1M | Complex analysis, deep reasoning |\n| `claude-sonnet-4-6` | $3.00 | $15.00 | 1M | Balanced quality across all tasks |\n| `claude-haiku-4-5-20251001` | $1.00 | $5.00 | 200K | Fast chat, classification, vision |\n\n### OpenAI\n\n| Model ID | Input/1M | Output/1M | Context | Best for |\n|---|---|---|---|---|\n| `gpt-4.1` | $2.00 | $8.00 | 1M | General chat, coding, vision |\n| `gpt-4o` | $2.50 | $10.00 | 128K | Multimodal, vision-heavy tasks |\n| `o3` | $2.00 | $8.00 | 200K | Deep reasoning, complex analysis (no streaming) |\n| `o4-mini` | $1.10 | $4.40 | 200K | Cheaper reasoning, STEM, code |\n| `gpt-4o-mini` | $0.15 | $0.60 | 128K | Cheap chat, classification, vision |\n\n### Google Gemini\n\n| Model ID | Input/1M | Output/1M | Context | Best for |\n|---|---|---|---|---|\n| `gemini-3.1-pro-preview` | $2.00 | $12.00 | 1M | Cutting-edge quality (preview) |\n| `gemini-2.5-pro` | $1.25 | $10.00 | 1M | Long-context analysis, vision |\n| `gemini-3-flash-preview` | $0.50 | $3.00 | 1M | Fast next-gen tasks (preview) |\n| `gemini-2.5-flash` | $0.30 | $2.50 | 1M | Fast summarization, cheap vision |\n| `gemini-2.5-flash-lite` | $0.10 | $0.40 | 1M | Ultra-cheap classification |\n\n### Mistral\n\n| Model ID | Input/1M | Output/1M | Context | Best for |\n|---|---|---|---|---|\n| `mistral-large-2512` | $0.50 | $1.50 | 262K | Cost-efficient coding, analysis |\n| `mistral-medium-3` | $0.40 | $2.00 | 131K | Balanced general tasks |\n| `mistral-small-4-0-26-03` | $0.10 | $0.30 | 262K | Creative writing, chat |\n| `devstral-2-25-12` | $0.10 | $0.30 | 256K | Code generation (SWE-bench 72.2%) |\n\n### Groq (ultra-fast inference)\n\n| Model ID | Input/1M | Output/1M | Context | Best for |\n|---|---|---|---|---|\n| `moonshotai/kimi-k2-instruct` | $1.00 | $3.00 | 1M | Long-context analysis, agentic |\n| `llama-3.3-70b-versatile` | $0.59 | $0.79 | 128K | Low-latency general tasks |\n| `qwen/qwen3-32b` | $0.29 | $0.59 | 128K | Coding, multilingual, reasoning |\n| `openai/gpt-oss-120b` | $0.15 | $0.60 | 128K | Balanced quality at ~500 t/s |\n| `meta-llama/llama-4-scout-17b-16e-instruct` | $0.11 | $0.34 | 10M | Huge-context vision, ultra-cheap |\n| `openai/gpt-oss-20b` | $0.075 | $0.30 | 128K | Fastest throughput (~1000 t/s) |\n| `llama-3.1-8b-instant` | $0.05 | $0.08 | 128K | Cheapest, sub-100ms responses |\n\n### Ollama (local)\n\nAny model you've pulled via `ollama pull <model>` works. Set **Ollama Model** to the model name and **Ollama Base URL** to your instance address.\n\n---\n\n## Keeping the registry up to date\n\nProvider APIs change quickly. Use the built-in sync script to check for stale or new model IDs:\n\n```bash\nnpm run build\nnpm run sync:models\n```\n\nThe script hits each provider's live `/models` endpoint and reports:\n- **Stale** — IDs in the registry that no longer exist\n- **New** — IDs available on the provider not yet in the registry\n\nWhat must still be updated manually in `modelRegistry.ts`:\n- Pricing (check each provider's pricing page)\n- Task affinity scores\n- Latency tier and context window size\n\nRecommended cadence: run `sync:models` monthly or after a major model release.\n\n---\n\n## Adding a custom model\n\nEdit only one file: `nodes/AiRouter/router/modelRegistry.ts`. Append a new entry to `MODEL_REGISTRY`:\n\n```typescript\n{\n  id: 'your-model-api-id',   // exact string sent in API requests\n  provider: 'openai',         // must match an existing ProviderType\n  displayName: 'My Model',\n  pricing: {\n    inputPer1M: 1.00,\n    outputPer1M: 4.00,\n    blendedPer1K: 0.0019,   // (1.00×0.7 + 4.00×0.3) / 1000\n  },\n  capabilities: {\n    supportsVision: false,\n    supportsEmbeddings: false,\n    supportsStreaming: true,\n    supportsReasoningMode: false,\n    isLocal: false,\n    contextWindow: 128_000,\n  },\n  latencyTier: 1,             // 1=fast  2=moderate  3=slow/reasoning\n  taskAffinity: {\n    coding: 0.88,\n    chat: 0.85,\n    // Omit tasks where the model has no particular strength (defaults to 0.5)\n  },\n},\n```\n\nThen rebuild: `npm run build`\n\nFor a new provider (new API format), see [CONTRIBUTING.md](CONTRIBUTING.md#adding-a-new-provider).\n\n---\n\n## Example workflows\n\n### Basic chatbot with smart routing\n\n1. **Webhook** → receives `{ \"message\": \"...\" }`\n2. **AI Router**\n   - Prompt: `{{ $json.message }}`\n   - Mode: `auto`\n   - Enable Fallback: on\n3. **Respond to Webhook** → `{{ $json.response }}`\n\nThe router detects whether the message is a coding question, analysis request, or casual chat and picks accordingly.\n\n---\n\n### Quality-first content pipeline\n\n1. **Schedule Trigger** → fires daily\n2. **HTTP Request** → fetches data to process\n3. **AI Router**\n   - Prompt: `Analyze the following data and write a professional summary: {{ $json.data }}`\n   - Mode: `quality`\n   - Allowed Providers: Anthropic, OpenAI, Google\n   - Include Model Info: on\n4. **Google Sheets** → saves `response`, `modelUsed`, token counts\n\nMode `quality` with flagship providers ensures you always get the best model for the task. Token counts let you track spend.\n\n---\n\n### Budget-capped high-volume classification\n\n1. **Spreadsheet Trigger** → rows to classify\n2. **AI Router**\n   - Prompt: `Classify this support ticket as \"billing\", \"technical\", or \"general\": {{ $json.ticket }}`\n   - Task Hint: `classification`\n   - Mode: `cost`\n   - Max Cost Per 1K Tokens: `0.001`\n   - Max Items Per Execution: `100`\n3. **Spreadsheet** → write back `{{ $json.response }}`\n\nHard-coding `classification` as the task hint skips detection overhead and ensures the cost-efficient classification models are preferred. The budget cap keeps costs bounded.\n\n---\n\n### Full output (all options enabled)\n\n```json\n{\n  \"response\": \"Here is the TypeScript function you requested:\\n\\n```typescript\\nfunction debounce...\",\n  \"modelUsed\": \"devstral-2-25-12\",\n  \"providerUsed\": \"mistral\",\n  \"attemptsTaken\": 1,\n  \"inputTokens\": 25,\n  \"outputTokens\": 459,\n  \"estimatedCostUSD\": 0.0000073,\n  \"detectedTask\": \"coding\",\n  \"detectedTaskConfidence\": 0.91,\n  \"scoreBreakdown\": [\n    { \"model\": \"devstral-2-25-12\",            \"provider\": \"mistral\", \"score\": 0.9289, \"breakdown\": { \"taskFit\": 1.000, \"cost\": 0.985, \"latency\": 0.500, \"contextSize\": 0.772 } },\n    { \"model\": \"moonshotai/kimi-k2-instruct\", \"provider\": \"groq\",    \"score\": 0.8800, \"breakdown\": { \"taskFit\": 0.880, \"cost\": 0.855, \"latency\": 1.000, \"contextSize\": 0.857 } },\n    { \"model\": \"o3\",                          \"provider\": \"openai\",   \"score\": 0.8632, \"breakdown\": { \"taskFit\": 0.970, \"cost\": 0.655, \"latency\": 0.000, \"contextSize\": 0.757 } }\n  ]\n}\n```\n\n### Dry-run output\n\nWhen **Dry Run** is enabled, no API call is made and the output is:\n\n```json\n{\n  \"dryRun\": true,\n  \"selectedModel\": \"devstral-2-25-12\",\n  \"selectedProvider\": \"mistral\",\n  \"selectedScore\": 0.9289,\n  \"detectedTask\": \"coding\",\n  \"detectedTaskConfidence\": 0.91,\n  \"scoreBreakdown\": [ ... ]\n}\n```\n\n---\n\n## Changelog\n\n### v0.1.6\n- **Add:** `System Prompt` parameter — optional system-level instruction passed to all providers\n- **Add:** `Temperature` parameter (0–2, default 0.7) — ignored automatically for reasoning models\n- **Add:** `Dry Run` toggle — returns routing decision without spending any tokens; includes selected model, score, detected task, and score breakdown\n- **Add:** `Include Detected Task` output option — exposes `detectedTask` and `detectedTaskConfidence` in the output\n- **Add:** `Include Score Breakdown` output option — exposes top-3 ranked candidates with final scores and per-criterion sub-scores (taskFit, cost, latency, contextSize)\n- **Add:** `Include Estimated Cost` output option — computes `estimatedCostUSD` from token counts × registry pricing\n\n### v0.1.5\n- **Fix:** Quality mode now reliably selects flagship models — context score uses log normalization (prevents a single 10M-context model from collapsing all 1M-context scores to 0.1), and quality-mode weights raised `taskFit` to 0.70\n- **Add:** `Max Items Per Execution` parameter (default `10`) — hard cap on items processed per run to prevent cost drain from accidental loops or large batches\n\n### v0.1.4\n- **Fix:** Anthropic requests no longer hang indefinitely — timeout now correctly catches `AbortError` in Node.js\n- **Fix:** `max_tokens` always included in Anthropic requests (required by the API)\n- **Fix:** Anthropic responses from reasoning models parsed correctly — text block found by type, not position\n\n### v0.1.2\n- Initial public release\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for:\n- How to add a new model (one object in an array)\n- How to add a new provider adapter\n- Commit conventions\n- How to test locally\n\n---\n\n## License\n\n[MIT](LICENSE)\n","readmeFilename":"README.md"}