1 line
137 KiB
JSON
1 line
137 KiB
JSON
{"repo": "alexrudloff/llmrouter", "files": {"README.md": {"091c8513042e12358ea48e67033b62dadb4fd9d8": {"t": 1785674077.5925162, "n": 9117, "h": "196ddf3baefacc0f", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic, OpenAI, Google Gemini, Kimi/Moonshot, and Ollama.**\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification support**: It can use Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama (all tested)\n- **Full OpenAI support**: GPT and reasoning models with automatic API parameter handling\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n```yaml\n# Google Gemini routing\nmodels:\n super_easy: \"google:gemini-2.0-flash\"\n easy: \"google:gemini-2.0-flash\"\n medium: \"google:gemini-2.0-flash\"\n hard: \"google:gemini-2.0-flash\"\n super_hard: \"google:gemini-2.0-flash\"\n```\n\n```yaml\n# Kimi/Moonshot routing\nmodels:\n super_easy: \"kimi:moonshot-v1-8k\"\n easy: \"kimi:moonshot-v1-32k\"\n medium: \"kimi:kimi-k2.5\"\n hard: \"kimi:kimi-k2.5\"\n super_hard: \"kimi:kimi-k2.5\"\n```\n\n**Note:** OpenAI reasoning models are automatically detected and use the correct API parameters.\n\n### Tool Routing\n\nWhen requests include tools (function calling), you may want to use more capable models to reduce prompt injection risks. Configure this in `config.yaml`:\n\n```yaml\n# Option 1: Set minimum complexity floor when tools present\ntools:\n min_complexity: \"medium\" # Bumps super_easy/easy -> medium\n```\n\n```yaml\n# Option 2: Force specific model for ALL tool calls\ntools:\n model: \"anthropic:claude-opus-4-20250514\" # Always use Opus for tools\n```\n\nIf neither is set, defaults to bumping `super_easy` → `easy`.\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\n#### Google Classification\n\nUses Google Gemini for classification.\n\n```yaml\nclassifier:\n provider: \"google\"\n model: \"gemini-2.0-flash\"\n```\n\n#### Kimi Classification\n\nUses Kimi/Moonshot for classification.\n\n```yaml\nclassifier:\n provider: \"kimi\"\n model: \"moonshot-v1-8k\"\n```\n\nChoose remote (anthropic/openai/google/kimi) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*`, `openai:o1-*`, `openai:o3-*` - OpenAI models (tested)\n- `google:gemini-*` - Google Gemini models (tested)\n- `kimi:kimi-k2.5`, `kimi:moonshot-*` - Kimi/Moonshot models (tested)\n- `local:model-name` - Local Ollama models (tested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "e76efe0dba779c5c55f25db56970d512ba7f6ff6": {"t": 1785763338.4437358, "n": 9117, "h": "196ddf3baefacc0f", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic, OpenAI, Google Gemini, Kimi/Moonshot, and Ollama.**\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification support**: It can use Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama (all tested)\n- **Full OpenAI support**: GPT and reasoning models with automatic API parameter handling\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n```yaml\n# Google Gemini routing\nmodels:\n super_easy: \"google:gemini-2.0-flash\"\n easy: \"google:gemini-2.0-flash\"\n medium: \"google:gemini-2.0-flash\"\n hard: \"google:gemini-2.0-flash\"\n super_hard: \"google:gemini-2.0-flash\"\n```\n\n```yaml\n# Kimi/Moonshot routing\nmodels:\n super_easy: \"kimi:moonshot-v1-8k\"\n easy: \"kimi:moonshot-v1-32k\"\n medium: \"kimi:kimi-k2.5\"\n hard: \"kimi:kimi-k2.5\"\n super_hard: \"kimi:kimi-k2.5\"\n```\n\n**Note:** OpenAI reasoning models are automatically detected and use the correct API parameters.\n\n### Tool Routing\n\nWhen requests include tools (function calling), you may want to use more capable models to reduce prompt injection risks. Configure this in `config.yaml`:\n\n```yaml\n# Option 1: Set minimum complexity floor when tools present\ntools:\n min_complexity: \"medium\" # Bumps super_easy/easy -> medium\n```\n\n```yaml\n# Option 2: Force specific model for ALL tool calls\ntools:\n model: \"anthropic:claude-opus-4-20250514\" # Always use Opus for tools\n```\n\nIf neither is set, defaults to bumping `super_easy` → `easy`.\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\n#### Google Classification\n\nUses Google Gemini for classification.\n\n```yaml\nclassifier:\n provider: \"google\"\n model: \"gemini-2.0-flash\"\n```\n\n#### Kimi Classification\n\nUses Kimi/Moonshot for classification.\n\n```yaml\nclassifier:\n provider: \"kimi\"\n model: \"moonshot-v1-8k\"\n```\n\nChoose remote (anthropic/openai/google/kimi) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*`, `openai:o1-*`, `openai:o3-*` - OpenAI models (tested)\n- `google:gemini-*` - Google Gemini models (tested)\n- `kimi:kimi-k2.5`, `kimi:moonshot-*` - Kimi/Moonshot models (tested)\n- `local:model-name` - Local Ollama models (tested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "e1620d191a15ef02ac7f37fd660235e934556c1b": {"t": 1785763340.983779, "n": 9103, "h": "adcb57dd534c0fbb", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic, OpenAI, Google Gemini, Kimi/Moonshot, and Ollama.**\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama (all tested)\n- **Full OpenAI support**: GPT and reasoning models with automatic API parameter handling\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n```yaml\n# Google Gemini routing\nmodels:\n super_easy: \"google:gemini-2.0-flash\"\n easy: \"google:gemini-2.0-flash\"\n medium: \"google:gemini-2.0-flash\"\n hard: \"google:gemini-2.0-flash\"\n super_hard: \"google:gemini-2.0-flash\"\n```\n\n```yaml\n# Kimi/Moonshot routing\nmodels:\n super_easy: \"kimi:moonshot-v1-8k\"\n easy: \"kimi:moonshot-v1-32k\"\n medium: \"kimi:kimi-k2.5\"\n hard: \"kimi:kimi-k2.5\"\n super_hard: \"kimi:kimi-k2.5\"\n```\n\n**Note:** OpenAI reasoning models are automatically detected and use the correct API parameters.\n\n### Tool Routing\n\nWhen requests include tools (function calling), you may want to use more capable models to reduce prompt injection risks. Configure this in `config.yaml`:\n\n```yaml\n# Option 1: Set minimum complexity floor when tools present\ntools:\n min_complexity: \"medium\" # Bumps super_easy/easy -> medium\n```\n\n```yaml\n# Option 2: Force specific model for ALL tool calls\ntools:\n model: \"anthropic:claude-opus-4-20250514\" # Always use Opus for tools\n```\n\nIf neither is set, defaults to bumping `super_easy` → `easy`.\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\n#### Google Classification\n\nUses Google Gemini for classification.\n\n```yaml\nclassifier:\n provider: \"google\"\n model: \"gemini-2.0-flash\"\n```\n\n#### Kimi Classification\n\nUses Kimi/Moonshot for classification.\n\n```yaml\nclassifier:\n provider: \"kimi\"\n model: \"moonshot-v1-8k\"\n```\n\nChoose remote (anthropic/openai/google/kimi) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*`, `openai:o1-*`, `openai:o3-*` - OpenAI models (tested)\n- `google:gemini-*` - Google Gemini models (tested)\n- `kimi:kimi-k2.5`, `kimi:moonshot-*` - Kimi/Moonshot models (tested)\n- `local:model-name` - Local Ollama models (tested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "abf80751ac6c5cb40942651a88f8fd7f4ab99b50": {"t": 1785763347.2004142, "n": 8579, "h": "ccca5757c75f829c", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic, OpenAI, Google Gemini, Kimi/Moonshot, and Ollama.**\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama (all tested)\n- **Full OpenAI support**: GPT and reasoning models with automatic API parameter handling\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n```yaml\n# Google Gemini routing\nmodels:\n super_easy: \"google:gemini-2.0-flash\"\n easy: \"google:gemini-2.0-flash\"\n medium: \"google:gemini-2.0-flash\"\n hard: \"google:gemini-2.0-flash\"\n super_hard: \"google:gemini-2.0-flash\"\n```\n\n```yaml\n# Kimi/Moonshot routing\nmodels:\n super_easy: \"kimi:moonshot-v1-8k\"\n easy: \"kimi:moonshot-v1-32k\"\n medium: \"kimi:kimi-k2.5\"\n hard: \"kimi:kimi-k2.5\"\n super_hard: \"kimi:kimi-k2.5\"\n```\n\n**Note:** OpenAI reasoning models are automatically detected and use the correct API parameters.\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\n#### Google Classification\n\nUses Google Gemini for classification.\n\n```yaml\nclassifier:\n provider: \"google\"\n model: \"gemini-2.0-flash\"\n```\n\n#### Kimi Classification\n\nUses Kimi/Moonshot for classification.\n\n```yaml\nclassifier:\n provider: \"kimi\"\n model: \"moonshot-v1-8k\"\n```\n\nChoose remote (anthropic/openai/google/kimi) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*`, `openai:o1-*`, `openai:o3-*` - OpenAI models (tested)\n- `google:gemini-*` - Google Gemini models (tested)\n- `kimi:kimi-k2.5`, `kimi:moonshot-*` - Kimi/Moonshot models (tested)\n- `local:model-name` - Local Ollama models (tested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "ee203bdacefbd2a994e07d247a13ca7bdb134622": {"t": 1785763352.8507943, "n": 8801, "h": "378bbf555c3a0258", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic, OpenAI, Google Gemini, Kimi/Moonshot, and Ollama.**\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama (all tested)\n- **OpenAI o-series support**: Automatically handles o1, o3, o4-mini reasoning models with correct API parameters\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing (including o-series reasoning models)\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n```yaml\n# Google Gemini routing\nmodels:\n super_easy: \"google:gemini-2.0-flash\"\n easy: \"google:gemini-2.0-flash\"\n medium: \"google:gemini-2.0-flash\"\n hard: \"google:gemini-2.0-flash\"\n super_hard: \"google:gemini-2.0-flash\"\n```\n\n```yaml\n# Kimi/Moonshot routing\nmodels:\n super_easy: \"kimi:moonshot-v1-8k\"\n easy: \"kimi:moonshot-v1-32k\"\n medium: \"kimi:kimi-k2.5\"\n hard: \"kimi:kimi-k2.5\"\n super_hard: \"kimi:kimi-k2.5\"\n```\n\n**Note:** OpenAI o-series models (o1, o3, o4-mini) are automatically detected and use the correct API parameters (`max_completion_tokens` instead of `max_tokens`, `developer` role instead of `system`).\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\n#### Google Classification\n\nUses Google Gemini for classification.\n\n```yaml\nclassifier:\n provider: \"google\"\n model: \"gemini-2.0-flash\"\n```\n\n#### Kimi Classification\n\nUses Kimi/Moonshot for classification.\n\n```yaml\nclassifier:\n provider: \"kimi\"\n model: \"moonshot-v1-8k\"\n```\n\nChoose remote (anthropic/openai/google/kimi) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (tested)\n- `openai:o1-*`, `openai:o3-*`, `openai:o4-*` - OpenAI reasoning models (tested)\n- `google:gemini-*` - Google Gemini models (tested)\n- `kimi:kimi-k2.5`, `kimi:moonshot-*` - Kimi/Moonshot models (tested)\n- `local:model-name` - Local Ollama models (tested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "c7a2f1237c858e894833ddde75fa88a6071c19b9": {"t": 1785763366.15707, "n": 8434, "h": "1fee274632535056", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic, OpenAI, Google Gemini, and Ollama.**\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama (all tested)\n- **OpenAI o-series support**: Automatically handles o1, o3, o4-mini reasoning models with correct API parameters\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing (including o-series reasoning models)\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n```yaml\n# Google Gemini routing\nmodels:\n super_easy: \"google:gemini-2.0-flash\"\n easy: \"google:gemini-2.0-flash\"\n medium: \"google:gemini-2.0-flash\"\n hard: \"google:gemini-2.0-flash\"\n super_hard: \"google:gemini-2.0-flash\"\n```\n\n**Note:** OpenAI o-series models (o1, o3, o4-mini) are automatically detected and use the correct API parameters (`max_completion_tokens` instead of `max_tokens`, `developer` role instead of `system`).\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\n#### Google Classification\n\nUses Google Gemini for classification.\n\n```yaml\nclassifier:\n provider: \"google\"\n model: \"gemini-2.0-flash\"\n```\n\nChoose remote (anthropic/openai/google) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (tested)\n- `openai:o1-*`, `openai:o3-*`, `openai:o4-*` - OpenAI reasoning models (tested)\n- `google:gemini-*` - Google Gemini models (tested)\n- `local:model-name` - Local Ollama models (tested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n- `kimi:moonshot-*` - Kimi/Moonshot models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "5100c5c0c1c179ea37fd77dea3d0c5d6fb3a9980": {"t": 1785763368.1884618, "n": 8116, "h": "482559d46d4fb7bf", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Tested with Anthropic and OpenAI.** Google and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI (tested), Google Gemini, Ollama (untested)\n- **OpenAI o-series support**: Automatically handles o1, o3, o4-mini reasoning models with correct API parameters\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\nConfigure which model handles each complexity level:\n\n```yaml\n# Anthropic routing\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n```yaml\n# OpenAI routing (including o-series reasoning models)\nmodels:\n super_easy: \"openai:gpt-4o-mini\" # Fast, cheap\n easy: \"openai:gpt-4o-mini\" # Fast, cheap\n medium: \"openai:gpt-4o\" # Balanced\n hard: \"openai:o3-mini\" # Reasoning model\n super_hard: \"openai:o3\" # Most capable reasoning\n```\n\n**Note:** OpenAI o-series models (o1, o3, o4-mini) are automatically detected and use the correct API parameters (`max_completion_tokens` instead of `max_tokens`, `developer` role instead of `system`).\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\nChoose remote (anthropic/openai) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (tested)\n- `openai:o1-*`, `openai:o3-*`, `openai:o4-*` - OpenAI reasoning models (tested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n- `kimi:moonshot-*` - Kimi/Moonshot models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "bb6ce06d94b9b55f77ffd631fa9dc3df5bbb2cd9": {"t": 1785763374.6488547, "n": 7302, "h": "cc2105204d27187d", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Currently tested with Anthropic only.** OpenAI, Google, and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI, Google Gemini, Ollama (untested)\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n### Classifier\n\nThe classifier determines request complexity before routing. Three options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Anthropic Classification\n\nUses Anthropic Haiku for classification. Fast, low cost per classification.\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\n#### OpenAI Classification\n\nUses OpenAI for classification. Useful if you have OpenAI credits or prefer their models.\n\n```yaml\nclassifier:\n provider: \"openai\"\n model: \"gpt-4o-mini\"\n```\n\nChoose remote (anthropic/openai) if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (untested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n- `kimi:moonshot-*` - Kimi/Moonshot models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "348c048a5ccb162efd22f940011e3db7ca972345": {"t": 1785763380.1400218, "n": 7213, "h": "7b080f491c61fd7b", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Currently tested with Anthropic only.** OpenAI, Google, and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI, Google Gemini, Ollama (untested)\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n### Classifier\n\nThe classifier determines request complexity before routing. Two options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Remote Classification (API)\n\nUses a remote API for classification (currently Anthropic Haiku). No local hardware needed, small cost per classification. Supports both API keys and OAuth tokens (passed through from your request).\n\n```yaml\nclassifier:\n provider: \"api\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\nChoose remote if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider API Keys\n\nConfigure API keys per provider in `config.yaml`. Keys in config take priority over the request Authorization header.\n\n```yaml\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n api_key: \"sk-ant-...\" # Your Anthropic key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n api_key: \"sk-proj-...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n api_key: \"sk-...\"\n```\n\nThis allows routing to multiple providers without passing different keys per request.\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (untested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `deepseek:deepseek-*` - DeepSeek models (untested)\n- `kimi:moonshot-*` - Kimi/Moonshot models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility (rewrites model name in system prompt)\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## OpenClaw Integration\n\nTo use llmrouter with [OpenClaw](https://github.com/openclaw/openclaw), add a provider to your `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"models\": {\n \"providers\": {\n \"localrouter\": {\n \"baseUrl\": \"http://localhost:4001/v1\",\n \"apiKey\": \"via-router\",\n \"api\": \"openai-completions\",\n \"models\": [\n {\n \"id\": \"llm-router\",\n \"name\": \"LLM Router (Auto-routes by complexity)\",\n \"reasoning\": false,\n \"input\": [\"text\", \"image\"],\n \"cost\": {\n \"input\": 0,\n \"output\": 0,\n \"cacheRead\": 0,\n \"cacheWrite\": 0\n },\n \"contextWindow\": 200000,\n \"maxTokens\": 8192\n }\n ]\n }\n }\n }\n}\n```\n\nThen set it as your default model in `agents.defaults.model.primary`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": {\n \"primary\": \"localrouter/llm-router\"\n }\n }\n }\n}\n```\n\nStart the server with OpenClaw compatibility mode:\n\n```bash\npython server.py --openclaw\n```\n\nThe `--openclaw` flag enables model name rewriting in system prompts so OpenClaw displays the actual model being used (rewrites `model=localrouter/...` to the actual provider/model).\n\nNote: Tool name remapping for Claude Code OAuth tokens happens automatically when an OAuth token is detected.\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "6015c451b3d2bae31d5adc031506cfdf4a8b2f11": {"t": 1785763383.081346, "n": 5047, "h": "df084ec717ef045c", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Currently tested with Anthropic only.** OpenAI, Google, and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI, Google Gemini, Ollama (untested)\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n### Classifier\n\nThe classifier determines request complexity before routing. Two options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Remote Classification (API)\n\nUses a remote API for classification (currently Anthropic Haiku). No local hardware needed, small cost per classification. Supports both API keys and OAuth tokens (passed through from your request).\n\n```yaml\nclassifier:\n provider: \"api\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\nChoose remote if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (untested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "1ec794dfe1920825456b49dbe6654173f98d6e44": {"t": 1785763384.550922, "n": 5011, "h": "d8b90696b30a1813", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Currently tested with Anthropic only.** OpenAI, Google, and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI, Google Gemini, Ollama (untested)\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally (optional if using Anthropic for classification)\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n### Classifier\n\nThe classifier determines request complexity before routing. Two options:\n\n#### Local Classification (default)\n\nUses Ollama running on your machine. Free, but requires local hardware.\n\n```yaml\nclassifier:\n provider: \"local\"\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n```bash\n# Setup\nollama pull qwen2.5:3b\n```\n\n#### Remote Classification\n\nUses Anthropic Haiku via API. No local hardware needed, small cost per classification. Supports both API keys and OAuth tokens (passed through from your request).\n\n```yaml\nclassifier:\n provider: \"anthropic\"\n model: \"claude-haiku-4-5-20251001\"\n```\n\nChoose remote if:\n- Your machine can't run local models\n- You want simpler setup (no Ollama required)\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (untested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "af897c31ed8d5b4b7c76a1d730170c1a03ce2fe1": {"t": 1785763385.9967124, "n": 4338, "h": "0d42945c9dd3104c", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**Works with [OpenClaw](https://github.com/openclaw/openclaw)** to reduce token usage and API costs by routing simple requests to smaller models.\n\n## Status\n\n**Currently tested with Anthropic only.** OpenAI, Google, and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI, Google Gemini, Ollama (untested)\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n### Classifier Model\n\n```yaml\nclassifier:\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (untested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "a10f2f79392ab38023b551492407085a025b2fde": {"t": 1785763387.9850557, "n": 4191, "h": "fc2f80ae198b20e1", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n## Status\n\n**Currently tested with Anthropic only.** OpenAI, Google, and local Ollama providers are implemented but untested.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama to classify requests locally (no API costs for classification)\n- **Multi-provider support**: Anthropic (tested), OpenAI, Google Gemini, Ollama (untested)\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **Configurable classifier model**: Change the local model used for classification in config.yaml\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally\n- Anthropic API key (or Claude Code OAuth token)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install -r requirements.txt\n\n# Pull the classifier model (default: qwen2.5:3b, configurable in config.yaml)\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n```\n\n## Configuration\n\nEdit `config.yaml` to customize:\n\n### Model Routing\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\n### Classifier Model\n\n```yaml\nclassifier:\n model: \"qwen2.5:3b\" # Any Ollama model\n ollama_url: \"http://localhost:11434/api/generate\"\n```\n\n### Provider Formats\n\n- `anthropic:claude-*` - Anthropic Claude models (tested)\n- `openai:gpt-*` - OpenAI GPT models (untested)\n- `google:gemini-*` - Google Gemini models (untested)\n- `local:model-name` - Local Ollama models (untested)\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "1837168bf190dee51cc3629b34d045d476dd2a95": {"t": 1785763389.850734, "n": 3960, "h": "3854df014334e689", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\nThink of it like a locally hosted, minimalist OpenRouter alternative you can use to shave ClawdeBot/MoltBot/OpenClaw costs.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama + qwen2.5:3b to classify requests locally (no API costs)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **OpenClaw compatible**: Optional mode for OpenClaw integration\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally with `qwen2.5:3b` model\n- API key for your chosen provider(s)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install pyyaml requests\n\n# Pull the classifier model\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n# Edit config.yaml with your preferred model mappings\n```\n\n## Configuration\n\nEdit `config.yaml` to customize model routing:\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\nSupported provider formats:\n- `anthropic:claude-*` - Anthropic Claude models\n- `openai:gpt-*` - OpenAI GPT models\n- `google:gemini-*` - Google Gemini models\n- `local:model-name` - Local Ollama models\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "8545d1757388a9fafd219ecd122dd4e5e1b511d5": {"t": 1785763393.3987706, "n": 3907, "h": "2d05852305cc98b6", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\nThink of it like a locally hosted, minimalist OpenRouter alternative. \n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama + qwen2.5:3b to classify requests locally (no API costs)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **OpenClaw compatible**: Optional mode for OpenClaw integration\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally with `qwen2.5:3b` model\n- API key for your chosen provider(s)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install pyyaml requests\n\n# Pull the classifier model\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n# Edit config.yaml with your preferred model mappings\n```\n\n## Configuration\n\nEdit `config.yaml` to customize model routing:\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\nSupported provider formats:\n- `anthropic:claude-*` - Anthropic Claude models\n- `openai:gpt-*` - OpenAI GPT models\n- `google:gemini-*` - Google Gemini models\n- `local:model-name` - Local Ollama models\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "a33bb6a881501fc9a9d0f895a16ed112ec3efec6": {"t": 1785763395.4985344, "n": 3856, "h": "f109282ef4d5ccee", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n**WORK IN PROGRESS**\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama + qwen2.5:3b to classify requests locally (no API costs)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **OpenClaw compatible**: Optional mode for OpenClaw integration\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally with `qwen2.5:3b` model\n- API key for your chosen provider(s)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install pyyaml requests\n\n# Pull the classifier model\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n# Edit config.yaml with your preferred model mappings\n```\n\n## Configuration\n\nEdit `config.yaml` to customize model routing:\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\nSupported provider formats:\n- `anthropic:claude-*` - Anthropic Claude models\n- `openai:gpt-*` - OpenAI GPT models\n- `google:gemini-*` - Google Gemini models\n- `local:model-name` - Local Ollama models\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "d59400d9a44f9711c0dd46a888a5c956092bf9a0": {"t": 1785763396.9797378, "n": 3835, "h": "fda4aa831d8ca7e7", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama + qwen2.5:3b to classify requests locally (no API costs)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **OpenClaw compatible**: Optional mode for OpenClaw integration\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally with `qwen2.5:3b` model\n- API key for your chosen provider(s)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install pyyaml requests\n\n# Pull the classifier model\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n# Edit config.yaml with your preferred model mappings\n```\n\n## Configuration\n\nEdit `config.yaml` to customize model routing:\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\nSupported provider formats:\n- `anthropic:claude-*` - Anthropic Claude models\n- `openai:gpt-*` - OpenAI GPT models\n- `google:gemini-*` - Google Gemini models\n- `local:model-name` - Local Ollama models\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}, "ae0bedb0de195d65045c7b325bf5afe74db57c90": {"t": 1785763398.463635, "n": 3838, "h": "1b8084e9ee69c19e", "c": "# LLM Router\n\nAn intelligent proxy that classifies incoming requests by complexity and routes them to appropriate LLM models. Save money by using cheaper/faster models for simple tasks and reserving expensive models for complex ones.\n\n## Features\n\n- **5-tier complexity routing**: super_easy, easy, medium, hard, super_hard\n- **Local classification**: Uses Ollama + qwen2.5:3b to classify requests locally (no API costs)\n- **Multi-provider support**: Anthropic, OpenAI, Google Gemini, Ollama\n- **OAuth token support**: Works with Claude Code OAuth tokens (sk-ant-oat*)\n- **OpenAI-compatible API**: Drop-in replacement for existing integrations\n- **OpenClaw compatible**: Optional mode for OpenClaw integration\n\n## Requirements\n\n- Python 3.10+\n- [Ollama](https://ollama.ai) running locally with `qwen2.5:3b` model\n- API key for your chosen provider(s)\n\n## Installation\n\n```bash\n# Clone the repo\ngit clone https://github.com/alexrudloff/llmrouter.git\ncd llmrouter\n\n# Install dependencies\npip install pyyaml requests\n\n# Pull the classifier model\nollama pull qwen2.5:3b\n\n# Copy and customize config\ncp config.yaml.example config.yaml\n# Edit config.yaml with your preferred model mappings\n```\n\n## Configuration\n\nEdit `config.yaml` to customize model routing:\n\n```yaml\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n```\n\nSupported provider formats:\n- `anthropic:claude-*` - Anthropic Claude models\n- `openai:gpt-*` - OpenAI GPT models\n- `google:gemini-*` - Google Gemini models\n- `local:model-name` - Local Ollama models\n\n## Usage\n\n### Start the server\n\n```bash\npython server.py\n```\n\nOptions:\n- `--port PORT` - Port to listen on (default: 4001)\n- `--host HOST` - Host to bind to (default: 127.0.0.1)\n- `--config PATH` - Path to config file (default: config.yaml)\n- `--log` - Enable verbose request/response logging\n- `--openclaw` - Enable OpenClaw compatibility mode\n\n### Make requests\n\nThe router exposes an OpenAI-compatible API at `/v1/chat/completions`:\n\n```bash\ncurl http://localhost:4001/v1/chat/completions \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"llm-router\",\n \"messages\": [{\"role\": \"user\", \"content\": \"Hello!\"}]\n }'\n```\n\nThe router will:\n1. Classify the message complexity using the local qwen model\n2. Route to the appropriate provider/model based on `config.yaml`\n3. Return the response in OpenAI-compatible format\n\n### API Key Handling\n\nYour API key is passed through to the target provider. The router supports:\n- Standard Anthropic API keys (`sk-ant-api*`)\n- Claude Code OAuth tokens (`sk-ant-oat*`) - requires Claude Code identity headers\n\n## Running as a Service (macOS)\n\nCreate a LaunchAgent plist at `~/Library/LaunchAgents/com.llmrouter.plist`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.llmrouter</string>\n <key>ProgramArguments</key>\n <array>\n <string>/usr/bin/python3</string>\n <string>/path/to/llmrouter/server.py</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>WorkingDirectory</key>\n <string>/path/to/llmrouter</string>\n</dict>\n</plist>\n```\n\nThen load it:\n```bash\nlaunchctl load ~/Library/LaunchAgents/com.llmrouter.plist\n```\n\n## Classification Rules\n\nEdit `ROUTES.md` to customize how messages are classified. The classifier reads the table in this file to determine complexity levels.\n\n## License\n\nMIT\n"}}, "config.yaml.example": {"091c8513042e12358ea48e67033b62dadb4fd9d8": {"t": 1785746811.221865, "n": 2792, "h": "bb34a361b0a69a4f", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free), \"anthropic\", or \"openai\"\nclassifier:\n provider: \"local\" # Use \"anthropic\" or \"openai\" if you can't run local models\n model: \"qwen2.5:3b\" # local: any Ollama model, anthropic: claude-haiku-*, openai: gpt-4o-mini\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Tool routing - controls model selection when tools are present\n# Some recommend using more capable models for tool use to reduce prompt injection risks\ntools:\n # Option 1: Set minimum complexity floor when tools present\n min_complexity: \"easy\" # \"easy\", \"medium\", \"hard\", or \"super_hard\"\n\n # Option 2: Force specific model for ALL tool calls (overrides min_complexity)\n # model: \"anthropic:claude-opus-4-20250514\"\n\n # If neither set, defaults to bumping super_easy -> easy\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT/o-series models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\n# OpenAI models:\n# - gpt-4o, gpt-4o-mini: Fast, multimodal\n# - o1, o3, o4-mini: Reasoning models (auto-detected, uses different API params)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n\n# Alternative: OpenAI-only routing\n# models:\n# super_easy: \"openai:gpt-4o-mini\"\n# easy: \"openai:gpt-4o-mini\"\n# medium: \"openai:gpt-4o\"\n# hard: \"openai:o3\" # Reasoning model\n# super_hard: \"openai:o3\" # Reasoning model\n\n# Provider API endpoints and keys\n# api_key: Set per provider. If not set, falls back to request Authorization header.\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n # api_key: \"sk-ant-...\" # API key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n # api_key: \"sk-proj-...\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n # api_key: \"...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n # api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n # api_key: \"sk-...\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "e1620d191a15ef02ac7f37fd660235e934556c1b": {"t": 1785763333.0134678, "n": 2792, "h": "bb34a361b0a69a4f", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free), \"anthropic\", or \"openai\"\nclassifier:\n provider: \"local\" # Use \"anthropic\" or \"openai\" if you can't run local models\n model: \"qwen2.5:3b\" # local: any Ollama model, anthropic: claude-haiku-*, openai: gpt-4o-mini\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Tool routing - controls model selection when tools are present\n# Some recommend using more capable models for tool use to reduce prompt injection risks\ntools:\n # Option 1: Set minimum complexity floor when tools present\n min_complexity: \"easy\" # \"easy\", \"medium\", \"hard\", or \"super_hard\"\n\n # Option 2: Force specific model for ALL tool calls (overrides min_complexity)\n # model: \"anthropic:claude-opus-4-20250514\"\n\n # If neither set, defaults to bumping super_easy -> easy\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT/o-series models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\n# OpenAI models:\n# - gpt-4o, gpt-4o-mini: Fast, multimodal\n# - o1, o3, o4-mini: Reasoning models (auto-detected, uses different API params)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n\n# Alternative: OpenAI-only routing\n# models:\n# super_easy: \"openai:gpt-4o-mini\"\n# easy: \"openai:gpt-4o-mini\"\n# medium: \"openai:gpt-4o\"\n# hard: \"openai:o3\" # Reasoning model\n# super_hard: \"openai:o3\" # Reasoning model\n\n# Provider API endpoints and keys\n# api_key: Set per provider. If not set, falls back to request Authorization header.\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n # api_key: \"sk-ant-...\" # API key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n # api_key: \"sk-proj-...\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n # api_key: \"...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n # api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n # api_key: \"sk-...\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "3817f5f1f684bbeda9a8247701199abcbac59b84": {"t": 1785763337.4506319, "n": 2310, "h": "0029703bd6053edf", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free), \"anthropic\", or \"openai\"\nclassifier:\n provider: \"local\" # Use \"anthropic\" or \"openai\" if you can't run local models\n model: \"qwen2.5:3b\" # local: any Ollama model, anthropic: claude-haiku-*, openai: gpt-4o-mini\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT/o-series models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\n# OpenAI models:\n# - gpt-4o, gpt-4o-mini: Fast, multimodal\n# - o1, o3, o4-mini: Reasoning models (auto-detected, uses different API params)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap\n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Most capable\n\n# Alternative: OpenAI-only routing\n# models:\n# super_easy: \"openai:gpt-4o-mini\"\n# easy: \"openai:gpt-4o-mini\"\n# medium: \"openai:gpt-4o\"\n# hard: \"openai:o3\" # Reasoning model\n# super_hard: \"openai:o3\" # Reasoning model\n\n# Provider API endpoints and keys\n# api_key: Set per provider. If not set, falls back to request Authorization header.\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n # api_key: \"sk-ant-...\" # API key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n # api_key: \"sk-proj-...\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n # api_key: \"...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n # api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n # api_key: \"sk-...\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "bb6ce06d94b9b55f77ffd631fa9dc3df5bbb2cd9": {"t": 1785763339.1535227, "n": 1921, "h": "aa5a0f6fd8084bef", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free), \"anthropic\", or \"openai\"\nclassifier:\n provider: \"local\" # Use \"anthropic\" or \"openai\" if you can't run local models\n model: \"qwen2.5:3b\" # local: any Ollama model, anthropic: claude-haiku-*, openai: gpt-4o-mini\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap \n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Reserved for future\n\n# Provider API endpoints and keys\n# api_key: Set per provider. If not set, falls back to request Authorization header.\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n # api_key: \"sk-ant-...\" # API key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n # api_key: \"sk-proj-...\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n # api_key: \"...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n # api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n # api_key: \"sk-...\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "348c048a5ccb162efd22f940011e3db7ca972345": {"t": 1785763342.1792345, "n": 1914, "h": "83d3b515f1d1757e", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free) or \"api\" (remote, currently Anthropic)\nclassifier:\n provider: \"local\" # Use \"api\" if you can't run local models\n model: \"qwen2.5:3b\" # For local: any Ollama model. For api: e.g., claude-haiku-4-5-20251001\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap \n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Reserved for future\n\n# Provider API endpoints and keys\n# api_key: Set per provider. If not set, falls back to request Authorization header.\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n # api_key: \"sk-ant-...\" # API key or OAuth token\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n # api_key: \"sk-proj-...\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n # api_key: \"...\"\n deepseek:\n url: \"https://api.deepseek.com/v1/chat/completions\"\n # api_key: \"sk-...\"\n kimi:\n url: \"https://api.moonshot.cn/v1/chat/completions\"\n # api_key: \"sk-...\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "6015c451b3d2bae31d5adc031506cfdf4a8b2f11": {"t": 1785763344.4470031, "n": 1584, "h": "b6082bd73165fa26", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free) or \"api\" (remote, currently Anthropic)\nclassifier:\n provider: \"local\" # Use \"api\" if you can't run local models\n model: \"qwen2.5:3b\" # For local: any Ollama model. For api: e.g., claude-haiku-4-5-20251001\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap \n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Reserved for future\n\n# Provider API endpoints (don't change unless using custom deployments)\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "1ec794dfe1920825456b49dbe6654173f98d6e44": {"t": 1785763346.9399338, "n": 1600, "h": "a8878dba6747aaba", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\n# provider: \"local\" (Ollama, free) or \"anthropic\" (uses API key from request)\nclassifier:\n provider: \"local\" # Use \"anthropic\" if you can't run local models\n model: \"qwen2.5:3b\" # For local: any Ollama model. For anthropic: e.g., claude-haiku-4-5-20251001\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap \n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Reserved for future\n\n# Provider API endpoints (don't change unless using custom deployments)\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}, "9af70e8342d860f5af7a6d2b0d03626699e895a9": {"t": 1785763349.1501575, "n": 1374, "h": "185e561d33a6387b", "c": "# Router Configuration\n# Configure model routing for different complexity levels\n\n# Server settings\nserver:\n host: \"127.0.0.1\"\n port: 4001 # Default port, can be overridden with --port\n\n# Classifier settings\nclassifier:\n model: \"qwen2.5:3b\"\n ollama_url: \"http://localhost:11434/api/generate\"\n routes_file: \"ROUTES.md\"\n\n# Model routing by complexity level\n# Format: \"provider:model\" where provider is: local, anthropic, openai, google\n#\n# Providers:\n# - local: Ollama models (free, runs locally)\n# - anthropic: Claude models (requires ANTHROPIC_API_KEY)\n# - openai: GPT models (requires OPENAI_API_KEY)\n# - google: Gemini models (requires GOOGLE_API_KEY)\n#\nmodels:\n super_easy: \"anthropic:claude-haiku-4-5-20251001\" # Fast, cheap \n easy: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n medium: \"anthropic:claude-sonnet-4-20250514\" # Balanced\n hard: \"anthropic:claude-opus-4-20250514\" # Powerful\n super_hard: \"anthropic:claude-opus-4-20250514\" # Reserved for future\n\n# Provider API endpoints (don't change unless using custom deployments)\nproviders:\n anthropic:\n url: \"https://api.anthropic.com/v1/messages\"\n version: \"2023-06-01\"\n openai:\n url: \"https://api.openai.com/v1/chat/completions\"\n google:\n url: \"https://generativelanguage.googleapis.com/v1beta/models\"\n ollama:\n url: \"http://localhost:11434/api/chat\"\n"}}}} |