Metadata-Version: 2.4
Name: bedrockrouter
Version: 1.0.1
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: python-dotenv
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 Multi-Modal CLI for **[BedrockRouter](https://bedrockrouter.com)**.

BedrockRouter gives you immediate terminal access to every AI modality on AWS Bedrock—text, vision, video, and embeddings—all routed through your single `sk_m11_...` key and self-hosted proxy. You can also bring your own OpenAI or Anthropic API keys and route through the same proxy.

## Install

```bash
pip install bedrockrouter
```

---

## ⚡ The Multi-Modal CLI

Before you write a single line of code, `bedrockrouter` gives you a frictionless terminal interface to every Bedrock model.

Set your proxy key once:

```bash
export BEDROCKROUTER_API_KEY="sk_m11_..."
```

### Interactive Chat

Start a continuous conversation with any model (defaults to auto-routing):

```bash
bedrockrouter chat
bedrockrouter chat --model claude-3.5-sonnet
```

### One-Shot Questions (Text & Vision)

Ask quick questions or process local documents and images directly in your terminal:

```bash
# Standard text prompt
bedrockrouter ask "Write a bash script to zip all python files"

# Vision (Image-to-text)
bedrockrouter ask "What is in this architectural diagram?" --file architecture.png
```

### Video Understanding

Analyze video files natively (routes to Nova Pro by default):

```bash
bedrockrouter video "Summarize this meeting" --file zoom_recording.mp4
```

### Generate Embeddings

```bash
bedrockrouter embed "Hello world" --model amazon.titan-embed-text-v2:0
```

---

## SDK Quick Start

Your single API key seamlessly unlocks standard SDK usage. `base_url` defaults to the BedrockRouter proxy automatically.

### Anthropic-compatible client

```python
from bedrockrouter import BedrockRouter, Models

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

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)
```

---

## Bring Your Own Key (3rd Party Providers)

Route requests to external providers using your own API keys. Pass your provider key as `api_key` and your BedrockRouter identity key as `mach11_key`.

| Header | Value | Purpose |
|--------|-------|---------|
| `Authorization` | `Bearer {api_key}` | Your 3rd party provider key (OpenAI, Anthropic, etc.) |
| `X-Mach11-Key` | `{mach11_key}` | Your BedrockRouter identity key (`sk_m11_...`) |

Use the `provider` parameter on each request to tell the proxy which provider to route to.

### OpenAI (OpenAI-compatible client)

```python
from bedrockrouter import BedrockOpenAI

client = BedrockOpenAI(
    api_key="sk-...",           # Your OpenAI API key
    mach11_key="sk_m11_...",    # Your BedrockRouter identity key
)

resp = client.chat.completions.create(
    model="gpt-4o-mini",
    provider="openai",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.choices[0].message.content)
```

### Anthropic (Anthropic-compatible client)

```python
from bedrockrouter import BedrockRouter

client = BedrockRouter(
    api_key="sk-ant-...",       # Your Anthropic API key
    mach11_key="sk_m11_...",    # Your BedrockRouter identity key
)

msg = client.messages.create(
    model="claude-haiku-4-5",
    provider="anthropic",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
print(msg.content[0].text)
```

### Native AWS Bedrock (default)

When using only your BedrockRouter key — no `mach11_key`, no `provider` flag — requests route to AWS Bedrock through your linked AWS account:

```python
from bedrockrouter import BedrockRouter, Models

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)
```

---

## 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)
```

### Cost tracking

Both the classifier call and the routed model call are tracked separately on your dashboard:

| Entry | What |
|-------|------|
| `nova-micro (classifier)` | ~$0.000007 per request |
| `claude-sonnet-4-6` (or chosen model) | normal model cost |

### 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 |
| BYOK | `provider="anthropic"` + `mach11_key` | `provider="openai"` + `mach11_key` |

---

## 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... |
| BYOK (3rd party keys) | No | `mach11_key` + `provider` — route with your own OpenAI or Anthropic keys |
| Auto-routing | No | `model=Models.AUTO` — proxy picks best model automatically |
| CLI | None | `bedrockrouter chat`, `ask`, `video`, `embed`, and `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/)