styrr
Multi-model LLM router with automatic fallback — Python SDK.
Never crash because a single model is rate-limited or down. Styrr chains models in order and falls through automatically.
Install
pip install styrr
Optional extras:
pip install styrr[bedrock] # AWS Bedrock support (boto3)
pip install styrr[huggingface] # HuggingFace Inference Endpoints
pip install styrr[all] # Everything
Quick Start
import os
import asyncio
from styrr import StyrRouter
async def main():
router = StyrRouter(
models=[
{"id": "openai/gpt-4o-mini"},
{"id": "nvidia/nemotron:free"},
],
api_key=os.environ["OPENROUTER_API_KEY"],
)
result = await router.prompt("What is FinOps in 2 sentences?")
print(result)
asyncio.run(main())
Fallback Chain
Models are tried in order. If the first returns 429, 5xx, or times out, the next is tried automatically.
router = StyrRouter(
models=[
{"id": "anthropic.claude-sonnet-4"}, # Bedrock primary
{"id": "openai/gpt-4o-mini"}, # OpenRouter fallback
{"id": "nvidia/nemotron-3-super-120b:free"}, # Free fallback
],
api_key=os.environ["OPENROUTER_API_KEY"],
on_fallback=lambda f, e, n: print(f"Fell back: {f} -> {n}: {e}"),
)
Tool Calling
result = await router.call(
[
{"role": "system", "content": "You have access to tools."},
{"role": "user", "content": "What's the weather in Paris?"},
],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"}
},
"required": ["location"],
},
},
}],
)
if result.tool_calls:
for tc in result.tool_calls:
print(f"{tc['name']}({tc['arguments']})")
else:
print(result.text)
Providers
| Provider | Model prefix | Auth | Extra install |
|---|---|---|---|
| OpenRouter / OpenAI | openai/*, nvidia/*, meta-llama/*, etc. |
api_key |
— |
| AWS Bedrock | anthropic.claude-*, amazon.*, bedrock/* |
AWS credentials | styrr[bedrock] |
| HuggingFace | huggingface/*, hf_* |
HF token | styrr[huggingface] |
Provider detection is automatic based on model ID.
Streaming
async for event in router.stream([{"role": "user", "content": "Hi"}]):
if event["type"] == "text_delta":
print(event["delta"], end="", flush=True)
elif event["type"] == "done":
print(f'\nDone — model: {event["model_used"]}')
elif event["type"] == "error":
print(f'Error: {event["error"]}')
API
StyrRouter
| Method | Returns | Description |
|---|---|---|
call(messages, tools?, temperature?, max_tokens?) |
StyrResponse |
Non-streaming call with fallback |
stream(messages, tools?, temperature?, max_tokens?) |
AsyncGenerator[dict] |
Streaming with fallback |
prompt(user_message, system_prompt?, **kwargs) |
str |
Simple prompt helper |
StyrResponse
| Field | Type | Description |
|---|---|---|
text |
str |
Response text |
model_used |
str |
Which model responded |
latency_ms |
int |
Round-trip latency |
fallbacks_tried |
int |
How many models were tried before success |
tool_calls |
list[dict] | None |
Tool call requests (if any) |
usage |
dict | None |
Token usage if available |
Architecture
Your App
└─ StyrRouter
├─ OpenAICompatProvider (OpenRouter, OpenAI, NVIDIA, etc.)
├─ BedrockProvider (AWS Bedrock)
└─ HuggingFaceProvider (HF Inference Endpoints)
Running Tests
pip install pytest pytest-asyncio httpx
pytest tests/
License
Apache-2.0
Metadata
Release files for styrr 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| styrr-0.1.0.tar.gz | 8.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| styrr-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.9 kB
Release files / styrr-0.1.0.tar.gz
| Download URL | styrr-0.1.0.tar.gz |
|---|---|
| Size | 8.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
130f888f7bb7b4d15f2769b0840935a509a3fa28cd386272d3854d5de5b336e3
|
|
BLAKE2b-256 checksum How to use checksums |
d5677c918d2489a0725e38b0a50797b5a7cefb5dbab28c1f49e54f5571aea935
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.17
|
Release files / styrr-0.1.0-py3-none-any.whl
| Download URL | styrr-0.1.0-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3602d798c29dc543ce1e456fa257ec01e9e96fcd1ddc04f5afad5f518422905e
|
|
BLAKE2b-256 checksum How to use checksums |
35e4683dce5fac9a90e3dbf42cf0077a6ce761b0b00da327aaa84945400856ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.17
|
Security for styrr 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.