Skip to main content

Low-level Python ergonomics for AWS Bedrock + Anthropic Claude: retries, cost ledger, streaming-error normalization.

Project description

bedrockstack

ci pypi python

Low-level Python ergonomics for AWS Bedrock + Anthropic Claude. Three primitives every team building on Bedrock ends up rewriting from scratch:

  1. RetryPolicy — Bedrock-aware backoff that knows the difference between a ThrottlingException (retry), a ModelNotReadyException (wait longer), and a ValidationException (never retry).
  2. Ledger — thread-safe cost tracking with scope tags, grouped totals, and Anthropic-on-Bedrock pricing baked in (override per Ledger(prices=...)).
  3. wrap_stream() — normalize the streaming-error parity gap between AnthropicBedrock and 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: ToolRunner with AnthropicBedrock parity (matches the native client's messages.tool_runner).
  • v0.3: BedrockClient wrapper 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bedrockstack-0.1.0.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bedrockstack-0.1.0-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

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

Hashes for bedrockstack-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c76c48d4c8d177f5dcd10cb7d1ca546c02e5e1b0da6bef9af8f0786883972f2c
MD5 1537293cfe93d3523a92b63952a5de3f
BLAKE2b-256 b87be8979b3c60fd57b1d354a0d23aa0e7618bd7af3daef507f136a0020b9d32

See more details on using hashes here.

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

Hashes for bedrockstack-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 82101ed852f590553b200cffa232a1ac388961cff06e7a606e54c6295ec5cc94
MD5 3711944d2ee52e3f533d6cf0bbd300cc
BLAKE2b-256 970cfd0694bd9140760381c95bc42a792c8a3d9c27a093365c7c0310fade49ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page