Skip to content

Add an opt-in Amazon Bedrock backend for composer - #300

Draft
shellygr wants to merge 7 commits into
masterfrom
shelly/bedrock-phase1
Draft

shellygr wants to merge 7 commits into
masterfrom
shelly/bedrock-phase1

Conversation

@shellygr

@shellygr shellygr commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR lets composer send its Claude requests to Amazon Bedrock instead of the Anthropic API. It covers composer only. certora_autosetup keeps calling the Anthropic API. The setting AUTOPROVER_LLM_BACKEND=bedrock turns it on. The default is anthropic, which builds the same chat model as master, so the merge changes nothing until someone sets the variable.

Composer reaches Bedrock through its "Mantle" endpoint, which accepts the Anthropic Messages API. The branch does not add langchain-aws, because that package needs langchain-core>=1.7.6 and this repo keeps langchain_core<1.3.3. A small subclass of ChatAnthropic uses the Anthropic SDK's own Bedrock Mantle clients instead.

Commits

  1. Bump anthropic to a release with the Bedrock Mantle client (a77dc02). The anthropic pin becomes >=0.122.0,<1.0 with the bedrock extra. 0.122.0 is the first release whose async client signs requests and refreshes AWS credentials outside the event loop. The lock moves anthropic from 0.88.0 to 0.125.0 and changes no other package.

  2. Add a Bedrock backend for Claude behind AUTOPROVER_LLM_BACKEND (39dbd7a). With bedrock, the chat model sends requests to the Mantle endpoint. The region comes from AWS_REGION or AWS_DEFAULT_REGION, and the default AWS credential chain signs the requests. Model ids stay logical (claude-opus-5-5) outside the client. Requests carry anthropic.<id>, and responses report the logical id, so usage, pricing and by_model do not change. Bedrock mode does not use the Files API uploader or its beta header.

  3. Send PDFs inline on Bedrock within a request-size budget (3f6a84f). Bedrock has no Files API, so PDFs go inline as base64 document blocks that keep cache_control, also inside tool results. AUTOPROVER_BEDROCK_MAX_DOCUMENT_BYTES (8,000,000) and AUTOPROVER_BEDROCK_MAX_REQUEST_BYTES (16,000,000) keep each request under the 20 MB Bedrock limit. A document that does not fit becomes a short text note with its name, so a run never fails on size. A thread checkpointed with Files API references stops with a clear message before its first Bedrock request.

  4. Cap max_tokens on Bedrock and retry its transient errors (9432d72). Bedrock counts max_tokens against the input-token quota before the model answers. So Bedrock requests use AUTOPROVER_BEDROCK_MAX_TOKENS (64,000 by default), and the Anthropic path keeps 128,000. The code retries throttling, model-not-ready, 5xx, timeouts, transient stream errors and short credential-fetch failures. It does not retry access denied, unknown model or validation errors.

  5. Document Claude on Bedrock and guard AWS credentials in the sandbox (b618f1a). The README has a Bedrock section: the switch, the region, credentials, the IAM permission, the token cap, the PDF limits and the logical model ids. The Docker wrapper and compose file pass the Bedrock settings through. The sandbox escape test makes sure that confined code cannot see AWS_* variables or reach the container credential endpoint or the IPv6 metadata endpoint.

  6. Fix Bedrock credential, retry and log handling (bfb5191). This commit holds the fixes from a review of the whole branch. With no AWS credentials, a request fails with BedrockCredentialsError, and the run does not retry it. The chat model replaces every model name in a response, including versioned and ARN forms, with its own id. If an error body has no type, the retry check reads the x-amzn-errortype header. Each dropped document gets one WARNING. The Docker wrapper accepts a Bedrock API key in place of static AWS keys.

  7. Name the copied types in the payload-walk docstring (920532b). A wording change in one docstring. No code changes.

Testing

  • python -m pytest tests -q -m "not expensive": 2238 passed, 10 skipped.
  • pyright composer/: 0 errors.
  • No Bedrock account was used. All Bedrock tests use mocked clients and transports.

Not tested against a live account

  • The Mantle wire format: base64 PDF blocks inside tool_result, the shape of error bodies, and the model name in a response. The code does not depend on that name.
  • The 64,000 max_tokens default comes from reading the call sites, not from a measurement.
  • The IAM statement in the README comes from the AWS docs.

Notes for review

  • The SDK bump (0.88.0 to 0.125.0) also affects the default Anthropic path and certora_autosetup. The tests pass. Master reaches prod automatically, so one dev run on the default backend before the merge is worth it.
  • In Bedrock mode, each checkpoint stores the inline PDF bytes, not a file id. OpenRouter already works this way. A large design PDF in a long run makes the checkpoint database grow.

🤖 Generated with Claude Code

shellygr and others added 7 commits November 9, 2026 00:42
Raise the anthropic pin to >=0.122.0,<1.0 and add the bedrock extra.
The SDK added the Bedrock Mantle clients in 0.91.0. From 0.122.0, the
async client does SigV4 signing outside the event loop. The bedrock
extra installs boto3 and botocore, which do that signing. The upper
bound matches the anthropic<1.0 requirement of langchain-anthropic 1.4.
The lock moves anthropic from 0.88.0 to 0.125.0 and changes no other
package version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If AUTOPROVER_LLM_BACKEND=bedrock, composer sends its Claude requests to
the Amazon Bedrock Mantle endpoint in the region from AWS_REGION or
AWS_DEFAULT_REGION. The client signs them with SigV4 from the default AWS
credential chain and uses one shared connection pool for each region.
Model ids stay logical outside the chat client. The request carries
"anthropic." plus the logical id, and the client maps the model name in
each response back to the logical id, so usage and pricing get the
logical name. In Bedrock mode, composer does not send the Files API beta
and does not build a first-party Anthropic client. Text documents stay
inline, and binary documents raise NotImplementedError for now. The
default anthropic backend builds the same ChatAnthropic as before. The
registry refuses Bedrock ids and ARNs, so they cannot go to OpenRouter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bedrock has no Files API. In bedrock mode, composer sends each PDF as a base64 document block that keeps its cache_control, also inside tool results. Two byte budgets keep each request under the 20 MB cap of Bedrock: AUTOPROVER_BEDROCK_MAX_DOCUMENT_BYTES for one document and AUTOPROVER_BEDROCK_MAX_REQUEST_BYTES for one request. If a document does not fit, composer replaces it with a short text block that names it and logs a warning. If a request refers to a Files API upload, for example from a thread checkpointed under the anthropic backend, the request fails before composer sends it, and the error tells how to resume. The anthropic backend does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bedrock counts max_tokens against the input-token quota before the model
answers. Thus Bedrock requests cap max_tokens at AUTOPROVER_BEDROCK_MAX_TOKENS,
which is 64,000 by default. The Anthropic path keeps 128,000. If interleaved
thinking is off and a fixed thinking budget does not fit under the cap, the
model build fails. The client retries errors with Bedrock's transient exception
names and short failures to get AWS credentials, but not missing credentials,
access denied or validation errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README gets a section on the Bedrock backend. It covers the environment
variables, the AWS credentials, the IAM permission, the logical model ids, the
max_tokens cap and how PDFs are sent inline. The Docker wrapper and the compose
file pass the Bedrock settings and the exported AWS credentials into the
container. The wrapper stops early when bedrock mode has no region or no
credentials. A test fixture runs every test on the default backend, whatever
the shell exports. The sandbox escape test also makes sure that confined code
sees no AWS_* variables and cannot connect to the container credential endpoint
or to the IPv6 instance metadata endpoint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If the AWS credential chain has no credentials, a Bedrock request now
fails with a clear error that the run does not retry. The chat model
replaces each model name in a response with the id the request used.
If an error body has no type, the retry check reads the exception name
from the x-amzn-errortype header. The chat model warns once about each
document that it leaves out, and logs later cases at DEBUG. The Docker
scripts pass the Bedrock API keys and the endpoint variable into the
container.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The docstring now says that the walk copies only the dicts and lists
on its path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant