Skip to main content

awerouter: Smart LLM Router

Route cheap/fast tasks to Flash, hard decisions to Pro.

Transparent Anthropic proxy that routes Claude Code requests by structural signals — no keyword guessing, no LLM classifier.

English · 简体中文

Version Python License

Status pip Platform Downloads Stars

Ko-fi

Transparent proxy that splits Claude Code traffic across providers by cost and capability.

Install

pip install awerouter

Quick Start

# 1. Init config (creates ~/.config/awerouter/{providers,routing}.json)
awerouter init

# 2. Interactively add a profile (writes both files, references stay consistent)
awerouter add
#    or edit by hand: providers.json for keys (${ENV_VAR}), routing.json for flash/pro

# 3. Start the daemon (profile name optional when only one exists)
awerouter serve [cc-router-1]     # shorthand: awerouter cc-router-1

# 4. Point CC at it — the serve banner prints both lines below
export ANTHROPIC_BASE_URL=http://127.0.0.1:20128
# aweswitch profile env: ANTHROPIC_MODEL=auto, _HAIKU_=flash, _OPUS_=pro

Config

Two files in ~/.config/awerouter/ (override with AWEROUTER_CONFIG_DIR):

providers.json — endpoints + keys, grouped by agent (redacted in config show):

{
  "claude": {
    "stepfun":   { "base_url": "https://api.stepfun.com/step_plan", "auth": "${STEPFUN_AUTH_TOKEN}" },
    "anthropic": { "base_url": "https://api.anthropic.com",          "auth": "${ANTHROPIC_KEY}" }
  },
  "codex": {
    "stepfun": { "base_url": "https://api.stepfun.com/v1", "auth": "${STEPFUN_AUTH_TOKEN}" }
  }
}

The auth header is auto-detected from base_url: anthropic.comx-api-key (bare token); everyone else → Authorization (auto-prefixes Bearer ). No auth_header field needed unless the heuristic is wrong.

routing.json — strategy, no secrets (safe to commit):

{
  "settings": {
    "backgroundModel": "flash",
    "thinkModel": "pro"
  },
  "cc-router-1": {
    "agent": "claude",
    "longContextThreshold": 8000,
    "destinations": {
      "flash": "stepfun,step-3.7-flash",
      "pro":   "anthropic,claude-opus-5"
    }
  }
}

settings is optional (defaults: flash/pro). It defines the model ids CC sends for background (Haiku) and think (Opus) tiers. The main loop uses auto — routed by difficulty by L3. Set these in your aweswitch profile: ANTHROPIC_DEFAULT_HAIKU_MODEL=flash, ANTHROPIC_MODEL=auto, ANTHROPIC_DEFAULT_OPUS_MODEL=pro.

Keys reference ${ENV_VAR} syntax. Missing env vars die with a clear message at startup.

Profile-based routing: routing.json groups configs under profile ids (like aweswitch). awerouter serve <profile> starts one; with a single profile it auto-selects. agent maps the profile to a providers.json group.

How It Routes

Three-layer first-match-wins pipeline, evaluated per request:

Layer Signal Decision
L1 Capability web_search tool in body pro (flash can't run it)
L2 Tier label model == c1/flash or c1/think flash / pro respectively
L3 Difficulty token count > threshold, or has image pro; else flash

CC's /model picker sets the tier model id (c1/flash / c1/pro / c1/think). awerouter reads it and routes accordingly — no keyword parsing, no LLM classifier.

Commands

awerouter init                        # create default config (= config init)
awerouter add                         # interactively add a profile (and new providers)
awerouter list                        # list profiles (name, agent, flash, pro, threshold)
awerouter show [PROFILE]              # show one profile or all config (redacted)
awerouter serve [PROFILE] [--port 20128] [--host 127.0.0.1]
awerouter <PROFILE>                   # shorthand for serve PROFILE
awerouter config path | show | edit | init
awerouter log [--lines 20]
awerouter stats
awerouter calibrate

calibrate shows the message-token distribution of L3 traffic (the threshold-sensitive layer; messages only — system prompt and tools are excluded) and suggests candidate longContextThreshold values at p90/p95/p99. Run it after some real traffic, then edit routing.json.

Troubleshooting

CC shows 502 status code (no body) right after launch — a shell proxy (Clash etc.) is hijacking loopback traffic. Requests to 127.0.0.1:20128 go into the proxy, whose 127.0.0.1 is itself, so nothing is listening and the proxy returns an empty 502. serve prints a warning when it detects this; fix it by exempting loopback in your shell config:

export no_proxy=127.0.0.1,localhost NO_PROXY=127.0.0.1,localhost

Then open a new terminal and relaunch CC.

Development

git clone https://github.com/mugpeng/awerouter
cd awerouter
pip install -e ".[dev]"
pytest

See docs/CONTRIBUTING.md for architecture notes, config semantics, and the release process.

Support

If awerouter saves you money, consider supporting it:

  • ⭐ Star the repo — it helps others find it.
  • Ko-fi — buy me a coffee.
  • 💬 WeChat — scan the QR code below.

WeChat Pay

awerouter is free and open source. Sponsors keep it maintained — thank you.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

awerouter-0.2.0.tar.gz (150.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

awerouter-0.2.0-py3-none-any.whl (24.1 kB view details)

Uploaded Python 3

File details

Details for the file awerouter-0.2.0.tar.gz.

File metadata

  • Download URL: awerouter-0.2.0.tar.gz
  • Upload date:
  • Size: 150.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for awerouter-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3978b33e0f3545168e5dfaf9288ba4d4c58b33b0fa5be58a8c2c830f07964ab2
MD5 26e6769e06a94a9075dbef8a88df2130
BLAKE2b-256 5427778a968ef29bd5dd27161df373e084b8fc71f64b9135f964601a4ad2cf73

See more details on using hashes here.

File details

Details for the file awerouter-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: awerouter-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 24.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for awerouter-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1ae2cea1a8e3bee7d2a02a03261d120a8de3476912a9e049c900630bef831345
MD5 4fd5651337616c210b97df20aea09728
BLAKE2b-256 44b1058992c69520f4cb0df70c8bbd482d6ca18d4196c8e2ec56e878e57289cf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page