LLMWire
Lightweight multi-provider LLM client for Python. A single async interface to
OpenAI, Anthropic, and Ollama — with automatic fallback, exponential-backoff retry,
streaming, and structured Pydantic output. No provider SDK dependencies; all requests
go over plain httpx.
Features
- Unified API — one
LLMClientfor all supported providers - Async-first — built entirely on
asyncioandhttpx - Automatic fallback — on provider failure, tries the next provider in the list
- Exponential backoff — configurable retry with full jitter
- Streaming — token-by-token via
client.stream(), async generator interface - Structured output — pass any Pydantic
BaseModelasresponse_model - No provider SDKs — runtime deps are only
httpx,pydantic,pydantic-settings,pyyaml - Environment variable config — all settings readable from
LLMKIT_*env vars
Quick Start
pip install llmwire
Chat
import asyncio
from llmwire import LLMClient, LLMConfig, ProviderConfig
config = LLMConfig(
providers=[
ProviderConfig(name="openai", api_key="sk-...", model="gpt-4o"),
ProviderConfig(name="anthropic", api_key="sk-ant-...", model="claude-3-5-sonnet-20241022"),
]
)
async def main():
async with LLMClient(config) as client:
response = await client.chat("What is the capital of France?")
print(response.content)
# Provider: openai | Model: gpt-4o | Tokens: 42
asyncio.run(main())
Streaming
async def main():
async with LLMClient(config) as client:
async for chunk in client.stream("Write a haiku about async programming."):
print(chunk.content, end="", flush=True)
print()
Structured Output
from pydantic import BaseModel
class Sentiment(BaseModel):
label: str # "positive", "negative", or "neutral"
confidence: float
async def main():
async with LLMClient(config) as client:
result: Sentiment = await client.chat(
"Classify: 'I love this library!'",
response_model=Sentiment,
)
print(result.label, result.confidence) # positive 0.97
Configuration
Direct
from llmwire import LLMConfig, ProviderConfig
config = LLMConfig(
providers=[
ProviderConfig(name="openai", api_key="sk-...", model="gpt-4o"),
ProviderConfig(name="ollama", model="llama3.2"), # no key needed
],
fallback=True, # try next provider on failure (default: True)
max_retries=3, # per-provider retry attempts (default: 3)
timeout=30.0, # request timeout in seconds (default: 30.0)
)
Environment Variables
export LLMKIT_PROVIDERS__0__NAME=openai
export LLMKIT_PROVIDERS__0__API_KEY=sk-...
export LLMKIT_PROVIDERS__0__MODEL=gpt-4o
export LLMKIT_PROVIDERS__1__NAME=anthropic
export LLMKIT_PROVIDERS__1__API_KEY=sk-ant-...
export LLMKIT_PROVIDERS__1__MODEL=claude-3-5-sonnet-20241022
export LLMKIT_FALLBACK=true
export LLMKIT_MAX_RETRIES=3
config = LLMConfig() # reads from environment
Provider Support
| Provider | Chat | Streaming | Auth | Default endpoint |
|---|---|---|---|---|
| OpenAI | yes | yes | API key | https://api.openai.com/v1 |
| Anthropic | yes | yes | API key | https://api.anthropic.com/v1 |
| Ollama | yes | yes | none | http://localhost:11434 |
The base_url field on ProviderConfig lets you point any provider at a compatible
endpoint (e.g. Azure OpenAI, local OpenAI-compatible servers).
Further Reading
- ARCHITECTURE.md — design decisions, component overview, and provider protocol
- CONTRIBUTING.md — dev setup, code style, and how to add a new provider
- Documentation — full API reference and guides
License
MIT. See LICENSE.
Metadata
Release files for llmwire 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| llmwire-0.1.1.tar.gz | 20.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llmwire-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.2 kB
Release files / llmwire-0.1.1.tar.gz
| Download URL | llmwire-0.1.1.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eed67115fa124a3e24919acad10cbdb0895b318e9fd37746aa1a240b4e3cb252
|
|
BLAKE2b-256 checksum How to use checksums |
b65fdfb452e7b6dfa13a1896526d27c84c9bbee3e1860ce574299ce92f53a5ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / llmwire-0.1.1-py3-none-any.whl
| Download URL | llmwire-0.1.1-py3-none-any.whl |
|---|---|
| Size | 16.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87d57506fc1329ec6df35cc3719e039285d946cc88bb6cbd7940eb55f8049e78
|
|
BLAKE2b-256 checksum How to use checksums |
0c53ac7a5ccaf7fad3937416608d39de8c1d4e6b9b729c7e0a052ba4ac0d4938
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|