Low-level Python ergonomics for AWS Bedrock + Anthropic Claude: retries, cost ledger, streaming-error normalization.
Project description
bedrockstack
Low-level Python ergonomics for AWS Bedrock + Anthropic Claude. Three primitives every team building on Bedrock ends up rewriting from scratch:
RetryPolicy— Bedrock-aware backoff that knows the difference between aThrottlingException(retry), aModelNotReadyException(wait longer), and aValidationException(never retry).Ledger— thread-safe cost tracking with scope tags, grouped totals, and Anthropic-on-Bedrock pricing baked in (override perLedger(prices=...)).wrap_stream()— normalize the streaming-error parity gap betweenAnthropicBedrockand the native Anthropic client into a single exception hierarchy.
This is the layer above boto3.client('bedrock-runtime'), not a replacement. Sibling library: bedrockcache for prompt-caching audits.
Install
pip install bedrockstack
Zero runtime dependencies. Works alongside whatever Bedrock client you already use (boto3, AnthropicBedrock, LiteLLM, Strands).
Retries
import boto3
from bedrockstack import bedrock_default
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
policy = bedrock_default() # 6 attempts, 0.5s..30s exponential w/ jitter
response = policy.call(
lambda: bedrock.converse(modelId="anthropic.claude-sonnet-4-5-v1:0", ...)
)
What it does and doesn't retry:
| Retries | Never retries |
|---|---|
| ThrottlingException | ValidationException |
| ServiceUnavailableException | AccessDeniedException |
| InternalServerException | ResourceNotFoundException |
| ModelNotReadyException (with longer initial delay) | InvalidRequestException |
| ModelTimeoutException | ModelErrorException |
| ModelStreamErrorException | (anything else not in the retryable list) |
| ServiceQuotaExceededException | |
| Connection / read timeouts (matched by class name) |
Cost ledger
from bedrockstack import Ledger, Usage
led = Ledger()
with led.scope(user_id="abc", feature="rag"):
led.record(
model="anthropic.claude-sonnet-4-5-v1:0",
usage=Usage(input_tokens=10_000, output_tokens=2_000,
cache_read_input_tokens=8_000),
)
print(led.dollars(user_id="abc")) # 0.027
print(led.dollars(feature="rag")) # 0.027
print(led.totals(group_by="model")) # {'anthropic.claude-sonnet-4-5-v1:0': 0.027}
Inference-profile model IDs (us.anthropic.claude-...) and LiteLLM-style prefixes (bedrock/anthropic.claude-...) are normalized automatically.
To override prices when AWS rebases:
from bedrockstack import Ledger, ModelPrice
led = Ledger(prices={
"anthropic.claude-sonnet-4-5-v1:0": ModelPrice(0.0025, 0.0125, 0.00025, 0.003125),
})
Streaming-error normalization
from anthropic import AnthropicBedrock
from bedrockstack import wrap_stream, StreamOverloadedError, StreamRateLimitError
client = AnthropicBedrock()
stream = client.messages.create(model="anthropic.claude-sonnet-4-5-v1:0",
stream=True, messages=[...])
try:
for event in wrap_stream(stream):
...
except StreamOverloadedError:
# 529 mid-stream — back off long
...
except StreamRateLimitError:
# 429 mid-stream — back off short
...
The same wrap_stream() works against the native Anthropic client and AnthropicBedrock. You handle one set of exceptions instead of two.
What it explicitly is not
- Not an agent framework. Use Strands or pydantic-ai for that.
- Not a router. LiteLLM exists.
- Not a prompt-caching auditor — that's bedrockcache.
- Bedrock + Anthropic-only. No OpenAI / Vertex / Azure surface.
Sibling libraries
Three independent libraries that compose around Anthropic-on-Bedrock:
- bedrockcache — static auditor for prompt caching.
- bedrockstack (this) — retry policy, cost ledger, streaming-error normalization.
- ragvitals — 5-dim drift detection for the RAG pipelines these models live inside.
Roadmap
- v0.2:
ToolRunnerwith AnthropicBedrock parity (matches the native client'smessages.tool_runner). - v0.3:
BedrockClientwrapper that bundles retry + ledger + streaming around a boto3 client. - v0.4: region failover for inference-profile model IDs.
- v0.5: SageMaker Async Inference helper.
Develop
pip install -e ".[dev]"
pytest -v
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bedrockstack-0.1.0.tar.gz.
File metadata
- Download URL: bedrockstack-0.1.0.tar.gz
- Upload date:
- Size: 11.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c76c48d4c8d177f5dcd10cb7d1ca546c02e5e1b0da6bef9af8f0786883972f2c
|
|
| MD5 |
1537293cfe93d3523a92b63952a5de3f
|
|
| BLAKE2b-256 |
b87be8979b3c60fd57b1d354a0d23aa0e7618bd7af3daef507f136a0020b9d32
|
File details
Details for the file bedrockstack-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bedrockstack-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
82101ed852f590553b200cffa232a1ac388961cff06e7a606e54c6295ec5cc94
|
|
| MD5 |
3711944d2ee52e3f533d6cf0bbd300cc
|
|
| BLAKE2b-256 |
970cfd0694bd9140760381c95bc42a792c8a3d9c27a093365c7c0310fade49ce
|