AWS Bedrock integration
Call AWS Bedrock through the ACE gateway: endpoint, zero-trust credential headers, stored-key alternative and runnable examples.
Send AWS Bedrock traffic to https://engine.acefleet.dev/bedrock/converse with your ACE developer key in Authorization: Bearer ace_dev_... and the provider credential on the zero-trust headers below. The request body is the vendor's own, relayed as written, and the vendor's answer comes back verbatim.
The same headers also serve:
https://engine.acefleet.dev/bedrock/converse-streamhttps://engine.acefleet.dev/bedrock/model/{modelId}/conversehttps://engine.acefleet.dev/bedrock/model/{modelId}/converse-streamhttps://engine.acefleet.dev/v1/chat/completionshttps://engine.acefleet.dev/anthropic/v1/messages
Zero-trust headers
| Header | Required | What it carries |
|---|---|---|
x-ace-bedrock-api-key |
situational | An Amazon Bedrock API key (long-term ABSK… or short-term). Use this OR the access-key pair below, never both — a key beside a pair, or half a pair, is a 400 naming both headers. ACE sends it upstream as Authorization: Bearer and signs nothing, so no AWS secret or STS token leaves your side. Not read off Authorization, which carries your ACE key. |
x-ace-bedrock-key |
situational | AWS access key id, half of the SigV4 pair — the alternative to x-ace-bedrock-api-key; one of the two is required. ACE computes the SigV4 signature per request — there is no local AWS CLI, profile or assumed role involved. |
x-ace-aws-secret-access-key |
situational | AWS secret access key, the other half of the pair. Bedrock is signed rather than forwarded on this path, so unlike every other provider here the credential is a pair, not a single token — unless you send the API key instead. |
x-ace-aws-region |
yes | Region the model is served from. With the pair it is part of the SigV4 scope (defaults to us-east-1 when absent); with an API key it is required — a short-term key is bound to the region it was minted in, and a missing region is a 400, never a defaulted host. |
x-ace-aws-session-token |
situational | Only for temporary STS credentials with the pair. Omit it for a long-lived key pair or an API key. |
x-ace-provider |
situational | Pin the channel to bedrock on /v1/chat/completions (an OpenAI body translated to Converse) or /anthropic/v1/messages (a Messages body sent to InvokeModel as Anthropic's Bedrock SDK sends it); the /bedrock/… paths imply it. |
Stored key instead
A stored bedrock vendor key replaces the credential headers; region is stored with it. POST /api/v1/vendor_key/create with provider: bedrock takes the packed access-key pair as api_key by default, or an Amazon Bedrock API key when the body says credential_kind: "api_key"; a pair stored before that field existed is unchanged. A pass-through pair beats a stored API key, as a pass-through key beats a stored one everywhere else. An AWS SDK or the AI SDK's Bedrock provider pointed at /bedrock builds /model/{modelId}/converse[-stream] with the id percent-encoded in the path (ARNs included); the gateway serves that path and lifts modelId into the body, so the SDK needs only a base URL and these headers — see the Vercel AI SDK quickstart.
Example request
curl -X POST https://engine.acefleet.dev/bedrock/converse \
-H "Authorization: Bearer ace_dev_<your-dev-key>" \
-H "x-ace-bedrock-api-key: ABSK..." \
-H "x-ace-aws-region: us-east-1" \
-H "Content-Type: application/json" \
-d '{ "modelId": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"messages": [{ "role": "user", "content": [{ "text": "ping" }] }] }'
# The SigV4 pair instead (never both), at the path an AWS SDK builds:
curl -X POST https://engine.acefleet.dev/bedrock/model/anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse \
-H "Authorization: Bearer ace_dev_<your-dev-key>" \
-H "x-ace-bedrock-key: AKIAIOSFODNN7EXAMPLE" \
-H "x-ace-aws-secret-access-key: wJalrXUtnFEMI/K7MDENG/..." \
-H "x-ace-aws-region: us-east-1" \
-H "Content-Type: application/json" \
-d '{ "messages": [{ "role": "user", "content": [{ "text": "ping" }] }] }'
Quickstarts
AWS Bedrock proxy (cURL)
# An Amazon Bedrock API key: sent upstream as a bearer, nothing signed, no AWS secret
# leaves your side. The region is required with it.
curl -X POST https://engine.acefleet.dev/bedrock/converse \
-H "Authorization: Bearer ace_dev_<your-dev-key>" \
-H "x-ace-bedrock-api-key: ABSK..." \
-H "x-ace-aws-region: us-east-1" \
-H "Content-Type: application/json" \
-d '{
"modelId": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"messages": [
{ "role": "user", "content": [{ "text": "Optimize GPU allocations." }] }
]
}'
# The SigV4 pair instead (never both): ACE signs the request for the AWS host.
# modelId may also travel in the path, as an AWS SDK sends it (percent-encoded).
curl -X POST https://engine.acefleet.dev/bedrock/model/anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse \
-H "Authorization: Bearer ace_dev_<your-dev-key>" \
-H "x-ace-bedrock-key: AKIAIOSFODNN7EXAMPLE" \
-H "x-ace-aws-secret-access-key: wJalrXUtnFEMI/K7MDENG/..." \
-H "x-ace-aws-region: us-east-1" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": [{ "text": "Optimize GPU allocations." }] }
]
}'
Vercel AI SDK: Bedrock (@ai-sdk/amazon-bedrock)
baseURL is the gateway's /bedrock prefix and nothing else changes: the provider builds {baseURL}/model/{modelId}/converse[-stream] with the id percent-encoded in the path (: as %3A; an inference-profile ARN with / as %2F), and the gateway serves exactly that path, lifting modelId from it into the body. No request-rewriting fetch. The upstream credential is one of two on the zero-trust headers, never both: an Amazon Bedrock API key on x-ace-bedrock-api-key, which ACE sends upstream as a bearer with nothing signed, or the access-key pair on x-ace-bedrock-key + x-ace-aws-secret-access-key, which ACE SigV4-signs for the real AWS host. x-ace-aws-region names the region either way (required with the key). The ACE dev key rides on Authorization: Bearer — the provider's apiKey option sends it there and signs nothing — or on x-api-key, which the surface promotes to the bearer when none is present. That second shape is for a client that SigV4-signs against the gateway's host (accessKeyId / secretAccessKey set instead of apiKey): ACE never reads a credential out of a SigV4 Authorization and never forwards it — that signature was computed over the gateway's host and is useless upstream — so the ACE identity has to travel on x-api-key and the AWS credential on the x-ace-* headers. The streaming reply is AWS's binary event-stream framing, which is what a Converse client parses; Accept: application/x-ndjson asks for newline-delimited JSON instead.
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
const bedrock = createAmazonBedrock({
baseURL: 'https://engine.acefleet.dev/bedrock', // the SDK builds /model/{modelId}/converse[-stream]
apiKey: 'ace_dev_<your-dev-key>', // Authorization: Bearer — your ACE identity
headers: {
'x-ace-bedrock-api-key': 'ABSK...', // zero-trust: sent upstream as a bearer, nothing signed
'x-ace-aws-region': 'us-east-1', // required with an API key
},
});
// model: bedrock('anthropic.claude-3-5-sonnet-20241022-v2:0')
//
// With the SigV4 pair instead: drop apiKey and x-ace-bedrock-api-key, set
// 'x-api-key': 'ace_dev_<your-dev-key>',
// 'x-ace-bedrock-key': 'AKIAIOSFODNN7EXAMPLE',
// 'x-ace-aws-secret-access-key': 'wJalrXUtnFEMI/K7MDENG/...',
// in headers; the client-side signature the SDK adds is ignored and ACE signs for AWS itself.