Metadata-Version: 2.4
Name: bedrockrouter
Version: 0.1.3
Summary: Python SDK and CLI for BedrockRouter — use every AWS Bedrock model through a self-hosted proxy with friendly aliases and cost tracking
Project-URL: Homepage, https://bedrockrouter.com
Project-URL: Repository, https://github.com/HolboxAI/bedrockrouter-sdk.git
Project-URL: Bug Tracker, https://github.com/HolboxAI/bedrockrouter-sdk/issues
License: MIT
License-File: LICENSE.TXT
Keywords: ai,anthropic,aws,bedrock,claude,llm,proxy,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: boto3>=1.34
Requires-Dist: httpx>=0.27
Requires-Dist: rich>=13
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-asyncio; extra == 'dev'
Requires-Dist: respx; extra == 'dev'
Requires-Dist: twine; extra == 'dev'
Description-Content-Type: text/markdown

# bedrockrouter

[![PyPI version](https://img.shields.io/pypi/v/bedrockrouter?style=flat&logo=pypi&logoColor=white)](https://pypi.org/project/bedrockrouter/)
[![Python](https://img.shields.io/pypi/pyversions/bedrockrouter?style=flat&logo=python&logoColor=white)](https://pypi.org/project/bedrockrouter/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Official Python SDK and CLI for **[BedrockRouter](https://bedrockrouter.com)** — route requests to every AWS Bedrock model through your self-hosted proxy, with friendly model aliases, automatic model routing, cost tracking, and streaming support.

## Install

```bash
pip install bedrockrouter
```

---

## Quick Start

### Anthropic-compatible client

```python
from bedrockrouter import BedrockRouter, Models

# base_url is optional — defaults to the BedrockRouter proxy automatically
client = BedrockRouter(api_key="sk_m11_...")

msg = client.messages.create(
    model=Models.CLAUDE_SONNET_4_6,
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=1024,
)
print(msg.content[0].text)
```

### OpenAI-compatible client

```python
from bedrockrouter import BedrockOpenAI, Models

# base_url is optional — defaults to the BedrockRouter proxy automatically
client = BedrockOpenAI(api_key="sk_m11_...")

resp = client.chat.completions.create(
    model=Models.CLAUDE_SONNET_4_6,
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=1024,
)
print(resp.choices[0].message.content)
```

### Auto-routing — let the proxy pick the best model

```python
from bedrockrouter import BedrockRouter, Models

client = BedrockRouter(api_key="sk_m11_...")

# Pass Models.AUTO — the proxy classifies the task and routes automatically
msg = client.messages.create(
    model=Models.AUTO,
    messages=[{"role": "user", "content": "Write a binary search in Python"}],
    max_tokens=1024,
)
print(msg.content[0].text)
```

---

## Auto-Routing

Pass `model="auto"` (or `Models.AUTO`) and the proxy automatically classifies your prompt using Amazon Nova Micro and routes it to the best model — balancing cost and accuracy.

### How it works

```
Your request (model="auto")
        ↓
Nova Micro classifies the task (~$0.000007)
        ↓
Routes to the best model:
  SIMPLE_CHAT     → nova-micro          (cheapest)
  FACTUAL_QA      → nova-lite
  CODING          → qwen3-coder-30b
  MATH_REASONING  → deepseek-r1
  CREATIVE        → claude-sonnet-4-6
  ANALYSIS        → llama-4-maverick-17b
  COMPLEX         → claude-sonnet-4-6
  HIGH_STAKES     → claude-opus-4-6     (most capable)
```

### Usage

```python
from bedrockrouter import BedrockRouter, Models

client = BedrockRouter(api_key="sk_m11_...")

# Anthropic format
msg = client.messages.create(
    model=Models.AUTO,   # or model="auto"
    messages=[{"role": "user", "content": "Explain quicksort"}],
    max_tokens=1024,
)
print(msg.content[0].text)
```

```python
from bedrockrouter import BedrockOpenAI, Models

client = BedrockOpenAI(api_key="sk_m11_...")

# OpenAI format
resp = client.chat.completions.create(
    model=Models.AUTO,   # or model="auto"
    messages=[{"role": "user", "content": "Explain quicksort"}],
    max_tokens=1024,
)
print(resp.choices[0].message.content)
```

### Auto-routing constants

| Constant | String value | Notes |
|----------|-------------|-------|
| `Models.AUTO` | `"auto"` | Primary alias |
| `Models.BR_AUTO` | `"br-auto"` | Alternative alias, same behaviour |

---

## CLI — Model Discovery

All 100+ AWS Bedrock models are built into the package as static values (no AWS credentials needed for listing).

### List all models

```bash
bedrockrouter models list
```

### Filter by provider

```bash
bedrockrouter models list --provider anthropic
bedrockrouter models list --provider amazon
bedrockrouter models list --provider meta
bedrockrouter models list --provider mistral
bedrockrouter models list --provider cohere
bedrockrouter models list --provider minimax
bedrockrouter models list --provider moonshot
bedrockrouter models list --provider google
bedrockrouter models list --provider nvidia
bedrockrouter models list --provider openai
bedrockrouter models list --provider qwen
bedrockrouter models list --provider zai
```

### Filter by keyword

```bash
bedrockrouter models list --filter sonnet
bedrockrouter models list --filter llama
bedrockrouter models list --filter nova
bedrockrouter models list --filter minimax
bedrockrouter models list --filter deepseek
bedrockrouter models list --filter gemma
bedrockrouter models list --filter qwen
bedrockrouter models list --filter nemotron
```

### Show only thinking / reasoning models

```bash
bedrockrouter models list --thinking
```

### Show only models with short aliases

```bash
bedrockrouter models list --alias-only
```

### Search by name

```bash
bedrockrouter models find "sonnet 4.5"
bedrockrouter models find "opus thinking"
bedrockrouter models find "haiku"
bedrockrouter models find "kimi"
bedrockrouter models find "llama 70b"
bedrockrouter models find "llama 4"
bedrockrouter models find "gemma"
bedrockrouter models find "glm"
```

### Live-fetch from AWS Bedrock (requires AWS credentials)

```bash
bedrockrouter models fetch
bedrockrouter models fetch --filter sonnet
bedrockrouter models fetch --filter minimax
bedrockrouter models fetch --region us-west-2
bedrockrouter models fetch --ids-only        # one model ID per line
```

---

## SDK Usage

### Basic (non-streaming) — Anthropic format

```python
from bedrockrouter import BedrockRouter, Models

# api_key is all you need — base_url defaults to the BedrockRouter proxy
client = BedrockRouter(api_key="sk_m11_...")

msg = client.messages.create(
    model=Models.CLAUDE_SONNET_4_5,
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=1024,
)
print(msg.content[0].text)
```

### Streaming — Anthropic format

```python
with client.messages.stream(
    model=Models.CLAUDE_SONNET_4_6,
    messages=[{"role": "user", "content": "Tell me a story"}],
    max_tokens=1024,
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
```

### Basic (non-streaming) — OpenAI format

```python
from bedrockrouter import BedrockOpenAI, Models

# api_key is all you need — base_url defaults to the BedrockRouter proxy
client = BedrockOpenAI(api_key="sk_m11_...")

resp = client.chat.completions.create(
    model=Models.NOVA_PRO,
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=1024,
)
print(resp.choices[0].message.content)
```

### Streaming — OpenAI format

```python
stream = client.chat.completions.create(
    model="meta.llama4-maverick-17b-instruct-v1:0",
    messages=[{"role": "user", "content": "Tell me a joke"}],
    max_tokens=512,
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
```

### With system prompt

```python
msg = client.messages.create(
    model=Models.CLAUDE_OPUS_4_6,
    system="You are a helpful Python tutor.",
    messages=[{"role": "user", "content": "Explain list comprehensions."}],
    max_tokens=512,
)
```

### Thinking / reasoning models

```python
msg = client.messages.create(
    model=Models.CLAUDE_SONNET_4_6_THINKING,
    messages=[{"role": "user", "content": "Solve: 2x + 5 = 13"}],
    max_tokens=2048,
)
```

### Use any Bedrock model (native ID)

All 100+ Bedrock models work through the proxy — just pass the native model ID directly:

```python
# Meta Llama 4
msg = client.messages.create(
    model="meta.llama4-maverick-17b-instruct-v1:0",
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=512,
)

# Google Gemma 3
msg = client.messages.create(
    model="google.gemma-3-27b-it",
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=512,
)

# Qwen3
msg = client.messages.create(
    model="qwen.qwen3-32b-v1:0",
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=512,
)

# NVIDIA Nemotron
msg = client.messages.create(
    model="nvidia.nemotron-super-3-120b",
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=512,
)
```

---

## Available Models

### Anthropic Claude (short aliases via BedrockRouter proxy)

| Constant | Alias | Model |
|----------|-------|-------|
| `Models.CLAUDE_HAIKU_4_5` | `claude-haiku-4-5` | Claude Haiku 4.5 |
| `Models.CLAUDE_HAIKU_4_5_THINKING` | `claude-4.5-haiku-thinking` | Claude Haiku 4.5 (thinking) |
| `Models.CLAUDE_SONNET_4_5` | `claude-sonnet-4-5` | Claude Sonnet 4.5 |
| `Models.CLAUDE_SONNET_4_5_THINKING` | `claude-4.5-sonnet-thinking` | Claude Sonnet 4.5 (thinking) |
| `Models.CLAUDE_SONNET_4_6` | `claude-sonnet-4-6` | Claude Sonnet 4.6 |
| `Models.CLAUDE_SONNET_4_6_THINKING` | `claude-4.6-sonnet-medium-thinking` | Claude Sonnet 4.6 (thinking) |
| `Models.CLAUDE_OPUS_4_5` | `claude-opus-4-5` | Claude Opus 4.5 |
| `Models.CLAUDE_OPUS_4_5_THINKING` | `claude-4.5-opus-high-thinking` | Claude Opus 4.5 (thinking) |
| `Models.CLAUDE_OPUS_4_6` | `claude-opus-4-6` | Claude Opus 4.6 |
| `Models.CLAUDE_OPUS_4_6_THINKING` | `claude-4.6-opus-high-thinking` | Claude Opus 4.6 (thinking) |

### Anthropic Claude (native Bedrock IDs)

| Constant | Model ID |
|----------|----------|
| `Models.CLAUDE_SONNET_4` | `anthropic.claude-sonnet-4-20250514-v1:0` |
| `Models.CLAUDE_OPUS_4` | `anthropic.claude-opus-4-20250514-v1:0` |
| `Models.CLAUDE_35_SONNET_V2` | `anthropic.claude-3-5-sonnet-20241022-v2:0` |
| `Models.CLAUDE_35_SONNET_V1` | `anthropic.claude-3-5-sonnet-20240620-v1:0` |
| `Models.CLAUDE_35_HAIKU` | `anthropic.claude-3-5-haiku-20241022-v1:0` |
| `Models.CLAUDE_3_OPUS` | `anthropic.claude-3-opus-20240229-v1:0` |
| `Models.CLAUDE_3_SONNET` | `anthropic.claude-3-sonnet-20240229-v1:0` |
| `Models.CLAUDE_3_HAIKU` | `anthropic.claude-3-haiku-20240307-v1:0` |

### Amazon

| Constant | Model ID |
|----------|----------|
| `Models.NOVA_MICRO` | `amazon.nova-micro-v1:0` |
| `Models.NOVA_LITE` | `amazon.nova-lite-v1:0` |
| `Models.NOVA_PRO` | `amazon.nova-pro-v1:0` |
| `Models.NOVA_PREMIER` | `amazon.nova-premier-v1:0` |
| `Models.NOVA_2_LITE` | `amazon.nova-2-lite-v1:0` |
| `Models.TITAN_TEXT_LITE` | `amazon.titan-text-lite-v1` |
| `Models.TITAN_TEXT_EXPRESS` | `amazon.titan-text-express-v1` |
| `Models.TITAN_TEXT_PREMIER` | `amazon.titan-text-premier-v1:0` |

### Meta Llama

| Constant | Model ID |
|----------|----------|
| `Models.LLAMA4_MAVERICK_17B` | `meta.llama4-maverick-17b-instruct-v1:0` |
| `Models.LLAMA4_SCOUT_17B` | `meta.llama4-scout-17b-instruct-v1:0` |
| `Models.LLAMA33_70B` | `meta.llama3-3-70b-instruct-v1:0` |
| `Models.LLAMA32_90B` | `meta.llama3-2-90b-instruct-v1:0` |
| `Models.LLAMA32_11B` | `meta.llama3-2-11b-instruct-v1:0` |
| `Models.LLAMA31_405B` | `meta.llama3-1-405b-instruct-v1:0` |
| `Models.LLAMA31_70B` | `meta.llama3-1-70b-instruct-v1:0` |
| `Models.LLAMA31_8B` | `meta.llama3-1-8b-instruct-v1:0` |

### Mistral

| Constant | Model ID |
|----------|----------|
| `Models.MISTRAL_LARGE_3` | `mistral.mistral-large-3-v1:0` |
| `Models.MISTRAL_LARGE` | `mistral.mistral-large-2407-v1:0` |
| `Models.MAGISTRAL_SMALL` | `mistral.magistral-small-2506-v1:0` |
| `Models.DEVSTRAL_2` | `mistral.devstral-2-v1:0` |
| `Models.PIXTRAL_LARGE` | `mistral.pixtral-large-2411-v1:0` |
| `Models.MISTRAL_NEMO` | `mistral.mistral-nemo-2407-v1:0` |
| `Models.MINISTRAL_8B` | `mistral.ministral-8b-2410-v1:0` |
| `Models.MINISTRAL_3B` | `mistral.ministral-3b-2410-v1:0` |
| `Models.MIXTRAL_8X7B` | `mistral.mixtral-8x7b-instruct-v0:1` |

### Google

| Constant | Model ID |
|----------|----------|
| `Models.GEMMA_3_27B` | `google.gemma-3-27b-it` |
| `Models.GEMMA_3_12B` | `google.gemma-3-12b-it` |
| `Models.GEMMA_3_4B` | `google.gemma-3-4b-it` |

### NVIDIA

| Constant | Model ID |
|----------|----------|
| `Models.NEMOTRON_SUPER_120B` | `nvidia.nemotron-super-3-120b` |
| `Models.NEMOTRON_NANO_30B` | `nvidia.nemotron-nano-3-30b` |
| `Models.NEMOTRON_NANO_12B` | `nvidia.nemotron-nano-12b-v2` |
| `Models.NEMOTRON_NANO_9B` | `nvidia.nemotron-nano-9b-v2` |

### Qwen

| Constant | Model ID |
|----------|----------|
| `Models.QWEN3_VL_235B` | `qwen.qwen3-vl-235b-a22b` |
| `Models.QWEN3_NEXT_80B` | `qwen.qwen3-next-80b-a3b` |
| `Models.QWEN3_CODER_NEXT` | `qwen.qwen3-coder-next` |
| `Models.QWEN3_CODER_30B` | `qwen.qwen3-coder-30b-a3b-v1:0` |
| `Models.QWEN3_32B` | `qwen.qwen3-32b-v1:0` |

### Z.AI (GLM)

| Constant | Model ID |
|----------|----------|
| `Models.GLM_5` | `zai.glm-5` |
| `Models.GLM_4_7` | `zai.glm-4.7` |
| `Models.GLM_4_7_FLASH` | `zai.glm-4.7-flash` |

### Other Providers

| Constant | Model ID | Provider |
|----------|----------|----------|
| `Models.COMMAND_R_PLUS` | `cohere.command-r-plus-v1:0` | Cohere |
| `Models.COMMAND_R` | `cohere.command-r-v1:0` | Cohere |
| `Models.JAMBA_15_LARGE` | `ai21.jamba-1-5-large-v1:0` | AI21 Labs |
| `Models.DEEPSEEK_R1` | `us.deepseek.r1-v1:5` | DeepSeek |
| `Models.DEEPSEEK_V3_2` | `deepseek.v3.2` | DeepSeek |
| `Models.GPT_OSS_120B` | `openai.gpt-oss-120b-1:0` | OpenAI OSS |
| `Models.GPT_OSS_20B` | `openai.gpt-oss-20b-1:0` | OpenAI OSS |
| `Models.KIMI_K2_5` | `kimi-k2.5` | Moonshot |
| `Models.KIMI_K2_THINKING` | `kimi-k2-thinking` | Moonshot |
| `Models.KIMI_K2_6` | `kimi-k2.6` | Moonshot |
| `Models.MINIMAX_M2_5` | `minimax-m2.5` | MiniMax |
| `Models.PALMYRA_X5` | `writer.palmyra-x5-v1:0` | Writer |
| `Models.PALMYRA_X4` | `writer.palmyra-x4-v1:0` | Writer |

> Run `bedrockrouter models list` to see all 100+ models with pricing.

---

## Two Clients — One Proxy

BedrockRouter exposes two fully compatible clients so you can use whichever SDK style you prefer:

| | `BedrockRouter` | `BedrockOpenAI` |
|-|----------------|----------------|
| Format | Anthropic Messages API | OpenAI Chat Completions API |
| Response | `msg.content[0].text` | `resp.choices[0].message.content` |
| Streaming | `client.messages.stream(...)` | `stream=True` iterator |
| Models | All 100+ Bedrock models | All 100+ Bedrock models |

---

## SDK vs Anthropic SDK

| Feature | Anthropic SDK | bedrockrouter |
|---------|--------------|---------------|
| Install | `pip install anthropic` | `pip install bedrockrouter` |
| Import | `from anthropic import Anthropic` | `from bedrockrouter import BedrockRouter` |
| Client | `Anthropic(api_key=...)` | `BedrockRouter(api_key=...)` — `base_url` optional |
| API call | `client.messages.create(...)` | `client.messages.create(...)` (identical) |
| Models | Anthropic only | 100+ models: Anthropic, Meta, Amazon, Mistral, Cohere, Google, NVIDIA, Qwen, MiniMax, Kimi, DeepSeek, Z.AI, OpenAI OSS... |
| Auto-routing | No | `model=Models.AUTO` — proxy picks best model automatically |
| CLI | None | `bedrockrouter models list` |
| Cost tracking | None | Built into proxy — classifier + routed model tracked separately |
| OpenAI format | No | `BedrockOpenAI` client included |

Migrating from the Anthropic SDK requires only changing the import — `base_url` is pre-configured.

---

## Links

- Website: [bedrockrouter.com](https://bedrockrouter.com)
- PyPI: [pypi.org/project/bedrockrouter](https://pypi.org/project/bedrockrouter/)
