Reference keel-llm-protocol adapter for AWS Bedrock — enterprise gateway. Use Claude / Llama / Titan / Mistral / Cohere models hosted on Bedrock with the Keel vendor-neutral protocol + reliability + OTel stack.
Project description
keel-llm-adapter-bedrock
A reference
keel-llm-protocoladapter for AWS Bedrock — the enterprise gateway. Use Claude / Llama / Titan / Mistral / Cohere models hosted on Bedrock with Keel's vendor-neutral protocol + reliability + observability stack.
Try it in 5 minutes: the agentic reference demo —
docker compose upbrings up Jaeger + an agent that exercises the full failover stack. (Swap inBedrockAdapterfor the enterprise version.)
Is this for you?
Adopt when — you're on AWS and your model access is via Bedrock (Anthropic Claude, Meta Llama, Mistral, Cohere, Amazon Titan, or other Bedrock-hosted models). You want one stack across direct providers + Bedrock — same ResilientClient, same typed errors, same observability — without writing AWS-specific glue throughout your codebase.
Skip when — you call Bedrock directly with boto3 in a simple single-model app and don't need failover / observability / vendor-neutral wiring. The official AWS SDKs have a wider surface (image generation, RAG knowledge bases, agents-for-bedrock features).
Install
pip install keel-llm-adapter-bedrock # pulls in keel-llm-protocol + httpx + botocore (for SigV4)
Note on dependencies: we use
botocore.auth.SigV4Authfor request signing but send viahttpx, not boto3. This keeps the [full] OTel story working —opentelemetry-instrumentation-httpx(fromkeel-llm-otel[full]) sees each Bedrock call as a real distributed-trace span withtraceparentpropagation.
Use
import os
import asyncio
from keel_llm_adapter_bedrock import BedrockAdapter
from keel_llm_protocol import user
from keel_llm_protocol.errors import RateLimitError, AdapterError
adapter = BedrockAdapter(
model="anthropic.claude-3-5-sonnet-20241022-v2:0",
region="us-east-1",
# Credentials: explicit kwargs OR env vars (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN).
aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
)
async def main() -> None:
try:
resp = await adapter.generate([user("Explain Bedrock briefly.")])
print(resp.text, resp.usage.total_tokens, resp.finish_reason)
except RateLimitError as e:
# Bedrock throttling — healthy but rate-limited; the keel-llm-reliability
# ResilientClient defers to the rate-limiter instead of tripping the breaker.
...
except AdapterError as e:
if e.retryable:
... # transient / timeout — retry or fail over
else:
raise # auth / bad-request / context / content — fail fast
asyncio.run(main())
In a multi-provider ResilientClient (the enterprise on-ramp)
The reason most enterprise teams reach for this package — mix Bedrock with direct providers in one ResilientClient:
from keel_llm_reliability import ResilientClient, Request
from keel_llm_adapter_bedrock import BedrockAdapter
from keel_llm_adapter_openai import OpenAIAdapter
from keel_llm_protocol import user
client = ResilientClient([
BedrockAdapter(model="anthropic.claude-3-5-sonnet-20241022-v2:0", region="us-east-1"),
OpenAIAdapter(model="gpt-4o-mini", api_key=os.environ["OPENAI_API_KEY"], provider="openai"),
])
result = await client.failover(Request(messages=[user("Hi")]))
# Bedrock throttles → fails over to OpenAI. Same agent code; same Attempt trail.
Tools
BedrockAdapter implements ToolCallingModelAdapter. The Converse API's toolConfig + toolUse/toolResult blocks are mapped to / from ToolSpec + ToolCall:
from keel_llm_protocol import ToolSpec
weather = ToolSpec(
name="get_weather",
description="Get weather for a city.",
parameters={"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
)
resp = await adapter.generate_with_tools([user("Weather in SF?")], [weather])
for call in resp.tool_calls:
print(call.name, call.arguments)
How Bedrock diverges — and where it's handled
| Bedrock divergence | Absorbed by |
|---|---|
| SigV4 request signing | adapter signs every request via botocore.auth.SigV4Auth (boto3 client not required) |
messages / system / content blocks shape (Converse) |
adapter rebuilds from Messages; system lifted to top-level |
toolUse / toolResult content blocks |
mapped to / from ToolCall + tool role messages |
toolConfig.toolChoice (auto / any / tool) |
mapped from ToolChoice |
Required maxTokens |
default_max_tokens (4096) supplied when unset |
AWS error envelope (__type + message) |
mapped to the standard error taxonomy below |
stopReason (end_turn / max_tokens / tool_use / content_filtered / guardrail_intervened / …) |
mapped to FinishReason (unmapped → unknown) |
Error mapping
| Bedrock exception / status | Raised |
|---|---|
ThrottlingException / ServiceQuotaExceededException / 429 |
RateLimitError(retry_after=…) — retryable |
AccessDeniedException / UnrecognizedClientException / InvalidSignatureException / 401 / 403 |
AuthenticationError — terminal (persistent model-level; records a breaker failure) |
ValidationException with context-length keywords |
ContextLengthError — terminal |
ValidationException (other) / ResourceNotFoundException |
BadRequestError — terminal |
ServiceUnavailableException / InternalServerException / ModelTimeoutException / ModelErrorException / 5xx |
TransientError — retryable |
| HTTP timeout / connection error | AdapterTimeoutError / TransientError — retryable |
Known limitation
Streaming via converse-stream is not in v0.1.0. Bedrock streams use AWS event-stream binary framing (not SSE), which needs its own parser. Planned for 0.2; capabilities correctly excludes "streaming" so consumers can route around it via capabilities introspection without surprise.
Status
0.1.0 — 0.x while the API stabilizes through year one (breaking changes possible at minor bumps, documented in the CHANGELOG; pin exact versions).
The Keel toolkit
Composable, vendor-neutral LLM reliability libraries on PyPI:
keel-llm-reliability · keel-llm-protocol · keel-llm-adapter-openai · keel-llm-adapter-anthropic · keel-llm-adapter-google · keel-llm-adapter-bedrock · keel-circuit-breaker · keel-llm-otel
MIT licensed.
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 keel_llm_adapter_bedrock-0.1.0.tar.gz.
File metadata
- Download URL: keel_llm_adapter_bedrock-0.1.0.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec89e3ddba03795e8db50660f51a447f511cea8b125806d32cc7a860814014a0
|
|
| MD5 |
6c6dece487dd9ef1680c8b2ca46b7bc4
|
|
| BLAKE2b-256 |
cb26c4697d57353ce2f47bdb90e7f7c7a093c65e9c9ecc3ed32ce36a3d45edea
|
Provenance
The following attestation bundles were made for keel_llm_adapter_bedrock-0.1.0.tar.gz:
Publisher:
publish-py.yml on keelplatform/keel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
keel_llm_adapter_bedrock-0.1.0.tar.gz -
Subject digest:
ec89e3ddba03795e8db50660f51a447f511cea8b125806d32cc7a860814014a0 - Sigstore transparency entry: 1623871715
- Sigstore integration time:
-
Permalink:
keelplatform/keel@92b2024a0c352159507b52e3b95c66e796345dfd -
Branch / Tag:
refs/tags/py-llm-adapter-bedrock-v0.1.0 - Owner: https://github.com/keelplatform
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-py.yml@92b2024a0c352159507b52e3b95c66e796345dfd -
Trigger Event:
push
-
Statement type:
File details
Details for the file keel_llm_adapter_bedrock-0.1.0-py3-none-any.whl.
File metadata
- Download URL: keel_llm_adapter_bedrock-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5b20dcbca29e540df9ea55a846247bbf944ca7c2b6832fa50a5a746c78a9262
|
|
| MD5 |
d44604f8e4391fa4a505efb134fd0689
|
|
| BLAKE2b-256 |
1daf7d524a621ea36b3dfe17e43e7f6f76cc15e71fee36834977b9c22e6e93bd
|
Provenance
The following attestation bundles were made for keel_llm_adapter_bedrock-0.1.0-py3-none-any.whl:
Publisher:
publish-py.yml on keelplatform/keel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
keel_llm_adapter_bedrock-0.1.0-py3-none-any.whl -
Subject digest:
d5b20dcbca29e540df9ea55a846247bbf944ca7c2b6832fa50a5a746c78a9262 - Sigstore transparency entry: 1623871816
- Sigstore integration time:
-
Permalink:
keelplatform/keel@92b2024a0c352159507b52e3b95c66e796345dfd -
Branch / Tag:
refs/tags/py-llm-adapter-bedrock-v0.1.0 - Owner: https://github.com/keelplatform
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-py.yml@92b2024a0c352159507b52e3b95c66e796345dfd -
Trigger Event:
push
-
Statement type: