AWS Bedrock
aimock supports the AWS Bedrock Claude invoke and Converse API endpoints — both streaming and non-streaming. Point the AWS SDK at your aimock instance and fixtures match against the Bedrock-format requests, returning responses in the authentic Bedrock format including AWS Event Stream binary framing for streaming.
How It Works
AWS Bedrock uses URL patterns like
/model/{modelId}/invoke and
/model/{modelId}/invoke-with-response-stream to call foundation models. The
request body uses the Anthropic Messages format with an additional
anthropic_version field, and does not include a
model field in the body (the model is in the URL).
aimock detects the Bedrock URL pattern, extracts the model ID, translates the request to the internal fixture-matching format, and returns the response in the Anthropic Messages API format — which is identical to the Bedrock Claude response format. For streaming, responses use the AWS Event Stream binary framing protocol.
aimock also supports the Converse API (/model/{modelId}/converse
and /model/{modelId}/converse-stream), which uses a different
request/response format with camelCase field names.
URL Patterns
| Bedrock URL | Description |
|---|---|
POST /model/{modelId}/invoke |
Non-streaming Claude invoke |
POST /model/{modelId}/invoke-with-response-stream |
Streaming Claude invoke (AWS Event Stream binary) |
POST /model/{modelId}/converse |
Converse API (non-streaming) |
POST /model/{modelId}/converse-stream |
Converse API (streaming, AWS Event Stream binary) |
Request Format
Bedrock Claude requests use the Anthropic Messages format. The
anthropic_version field is accepted but not validated. The model is taken
from the URL path, not the request body.
{
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"messages": [
{ "role": "user", "content": "Hello" }
],
"system": "You are helpful"
}
Response Format
Bedrock Claude responses are identical to the Anthropic Messages API non-streaming responses:
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"content": [{ "type": "text", "text": "Hello!" }],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": { "input_tokens": 10, "output_tokens": 5 }
}
Model Resolution
The model ID is extracted from the URL path. This is used both for fixture matching and included in the response body. Bedrock model IDs typically look like:
anthropic.claude-3-5-sonnet-20241022-v2:0anthropic.claude-3-haiku-20240307-v1:0anthropic.claude-3-opus-20240229-v1:0
Write fixtures that match by Bedrock model ID:
{
"match": {
"model": "anthropic.claude-3-5-sonnet-20241022-v2:0",
"userMessage": "hello"
},
"response": {
"content": "Hello from Bedrock!"
}
}
SDK Configuration
To point the AWS SDK Bedrock Runtime client at aimock, configure the endpoint URL:
import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime";
const client = new BedrockRuntimeClient({
region: "us-east-1",
endpoint: "http://localhost:4005", // aimock URL
credentials: { accessKeyId: "mock", secretAccessKey: "mock" },
});
const response = await client.send(new InvokeModelCommand({
modelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
contentType: "application/json",
body: JSON.stringify({
anthropic_version: "bedrock-2023-05-31",
max_tokens: 512,
messages: [{ role: "user", content: "Hello" }],
}),
}));
Fixture Examples
{
"fixtures": [
{
"match": { "userMessage": "hello" },
"response": { "content": "Hi there!" }
},
{
"match": { "userMessage": "weather" },
"response": {
"toolCalls": [{
"name": "get_weather",
"arguments": "{\"city\":\"SF\"}"
}]
}
}
]
}
Fixtures are shared across all providers. The same fixture file works for OpenAI, Claude Messages, Gemini, Azure, and Bedrock endpoints — aimock translates each provider's request format to a common internal format before matching.
Streaming (invoke-with-response-stream)
The invoke-with-response-stream endpoint returns responses using the
AWS Event Stream binary protocol. aimock implements this protocol
natively — each response chunk is encoded as a binary frame with CRC32 checksums,
headers, and a JSON payload, exactly as the real Bedrock service sends them.
Streaming events follow the Bedrock Claude streaming sequence:
-
messageStart— opens the message withrole: "assistant" contentBlockStart— begins a content block-
contentBlockDelta— delivers text chunks (text_delta) or tool input (input_json_delta) contentBlockStop— closes the content block-
messageStop— closes the message with astopReason
import { BedrockRuntimeClient, InvokeModelWithResponseStreamCommand } from "@aws-sdk/client-bedrock-runtime";
const client = new BedrockRuntimeClient({
region: "us-east-1",
endpoint: "http://localhost:4005",
credentials: { accessKeyId: "mock", secretAccessKey: "mock" },
});
const response = await client.send(new InvokeModelWithResponseStreamCommand({
modelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
contentType: "application/json",
body: JSON.stringify({
anthropic_version: "bedrock-2023-05-31",
max_tokens: 512,
messages: [{ role: "user", content: "Hello" }],
}),
}));
AWS Event Stream Binary Format
Unlike SSE-based streaming used by OpenAI and Claude, AWS Bedrock streaming uses a binary event stream protocol. Each frame has the following layout:
[total_length: 4B uint32-BE]
[headers_length: 4B uint32-BE]
[prelude_crc32: 4B CRC32 of first 8 bytes]
[headers: variable-length string key-value pairs]
[payload: raw JSON bytes]
[message_crc32: 4B CRC32 of entire frame minus last 4 bytes]
aimock encodes these frames with proper CRC32 checksums, so the AWS SDK can decode them
natively. The :event-type header in each frame carries the event name (e.g.
chunk), and the :content-type header is set to
application/json.
Converse API
The Converse API is AWS Bedrock's provider-agnostic conversation interface. It uses
camelCase field names and a different request structure than the Claude-native invoke
endpoints. aimock supports both /model/{modelId}/converse (non-streaming) and
/model/{modelId}/converse-stream (streaming via Event Stream binary).
{
"messages": [
{
"role": "user",
"content": [{ "text": "Hello" }]
}
],
"system": [{ "text": "You are helpful" }],
"inferenceConfig": { "maxTokens": 512 }
}
{
"output": {
"message": {
"role": "assistant",
"content": [{ "text": "Hello!" }]
}
},
"stopReason": "end_turn",
"usage": { "inputTokens": 0, "outputTokens": 0, "totalTokens": 0 }
}
The Converse API also supports tool calls via toolUse and
toolResult content blocks, and tool definitions via the
toolConfig field. aimock translates all of these to the unified internal
format for fixture matching.