Module: tramai-bedrock
One-liner: Provider for Amazon Bedrock using the InvokeModel API — translates TramAI's unified message model to the Claude (Anthropic) format. Module type:
providerSource files: 1 —BedrockProvider.kt(488 LOC) Test files: 2 —BedrockProviderTest.kt,BedrockProviderTckTest.ktGroup:dev.tramai, Version:0.6.0
L1: Quick Start (30-second read)
What
tramai-bedrock is a ModelProvider + StreamCapable implementation that connects Tramai to Amazon Bedrock via the InvokeModel API. It translates TramAI's unified message model into the Claude Messages format (Anthropic) and back.
Why
Amazon Bedrock is AWS's managed AI service, providing access to Claude, Llama, and other foundation models through a single API with AWS IAM authentication, VPC support, and enterprise governance. For European organizations already on AWS, Bedrock eliminates the need for separate API keys and provides data residency guarantees through region selection.
When to use
- AWS-native deployments — use
BedrockProvider(region = "eu-west-1")for European data residency - Claude via Bedrock — the default model is
anthropic.claude-3-sonnet-20240229-v1:0 - IAM-based auth — no API key management; authenticates via the AWS credentials chain
How to add
Gradle (Kotlin DSL):
dependencies {
implementation(platform("dev.tramai:tramai-bom:0.6.0"))
implementation("dev.tramai:tramai-bedrock")
}
Where to go next
| If you want to... | Go here |
|---|---|
| Wire a provider into a working app | tramai-standalone |
| Use Spring Boot auto-configuration | tramai-spring |
| Understand the Anthropic message format | tramai-anthropic |
L2: Usage Guide (5-minute read)
Quick usage
import dev.tramai.bedrock.BedrockProvider
import dev.tramai.core.annotations.AiService
import dev.tramai.core.annotations.Operation
import dev.tramai.standalone.Tramai
@AiService
interface ChatService {
@Operation(prompt = "What is GDPR?", model = "anthropic.claude-3-sonnet-20240229-v1:0")
suspend fun explain(): String
}
suspend fun main() {
val chat = Tramai
.builder()
.provider(
BedrockProvider(region = "eu-west-1"),
default = true,
)
.model("anthropic.claude-3-sonnet-20240229-v1:0", "bedrock")
.build()
.create<ChatService>()
println(chat.explain())
}
Authentication
By default, BedrockProvider uses DefaultCredentialsProvider.builder().build(), which resolves credentials from:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) ~/.aws/credentials- IAM roles (ECS task role, EC2 instance profile)
For custom credential providers:
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials
val provider = BedrockProvider(
region = "eu-west-1",
credentialsProvider = StaticCredentialsProvider.create(
AwsBasicCredentials.create("access-key", "secret-key")
),
)
Streaming
@AiService
interface StreamingService {
@Operation(prompt = "Write a poem", model = "anthropic.claude-3-sonnet-20240229-v1:0")
fun stream(): Flow<StreamChunk>
}
For Bedrock, streaming uses the async Bedrock Runtime surface (InvokeModelWithResponseStream) — the response event stream is parsed incrementally and emitted as tokens through a Flow.
Tool calling
The provider translates TramAI tool definitions to the Claude tools format and parses tool_use content blocks from the response:
@AiService
interface ToolService {
@Operation(prompt = "Calculate VAT", model = "anthropic.claude-3-sonnet-20240229-v1:0", tools = ["vat_calculator"])
suspend fun calculate(): VatResponse
}
Vision / Multimodal
The provider supports image inputs via ContentPart.ImagePart and ContentPart.ImageUrlContent, translating them to Claude's image content blocks with base64 encoding. Supported image types: image/png, image/jpeg, image/gif, image/webp.
Configuration reference
| Parameter | Type | Default | Description |
|---|---|---|---|
region | String | (required) | AWS region (e.g., "eu-west-1") |
modelId | String | "anthropic.claude-3-sonnet-20240229-v1:0" | Default Bedrock model ID |
credentialsProvider | AwsCredentialsProvider | DefaultCredentialsProvider.builder().build() | AWS credentials |
objectMapper | ObjectMapper | ObjectMapper() | Jackson ObjectMapper |
L3: Architecture & Mechanics (10-minute read)
Design philosophy
tramai-bedrock is a standalone provider — it implements its own transport layer using the AWS SDK (BedrockRuntimeAsyncClient) rather than delegating to OpenAiCompatibleProvider. This is necessary because Bedrock uses the InvokeModel API with model-specific payloads, not the OpenAI /chat/completions format.
Payload translation
The provider translates TramAI's unified message model to the Claude Messages format:
| TramAI | Claude (Bedrock) |
|---|---|
MessageRole.SYSTEM | Top-level system field |
MessageRole.USER | role: "user" |
MessageRole.ASSISTANT | role: "assistant" |
MessageRole.TOOL | role: "user" with tool_result content block |
ToolDefinition | tools[{name, description, input_schema}] |
ToolCall | tool_use content block with id, name, input |
Inner mechanics
Non-streaming flow:
1. Build Claude payload: { anthropic_version, max_tokens, messages, system?, tools?, temperature? }
2. Wrap in InvokeModelRequest with modelId and contentType: "application/json"
3. Call bedrockRuntimeClient.invokeModel()
4. Parse response body: content[] → extract text blocks and tool_use blocks
5. Map stop_reason → FinishReason (end_turn→STOP, max_tokens→LENGTH, tool_use→STOP, content_filtered→CONTENT_FILTER)
6. Return ModelResponse with usage (input_tokens, output_tokens)
Streaming flow:
1. Build the same Claude payload
2. invokeModelWithResponseStream — subscribe to the response event stream
3. Per event: message_start → capture input_tokens; content_block_delta (text_delta) → emit StreamChunk.Token; message_delta → update output_tokens
4. Emit exactly one terminal StreamChunk.Complete(fullText, usage) — or one StreamChunk.Error on a transport/parse failure (a single atomic owner of the terminal state)
Authentication model
Authentication uses AWS Signature V4 via the AwsCredentialsProvider interface. The default is the standard AWS credential provider chain — no API keys needed for IAM-role-based deployments.
Finish reason mapping
Claude stop_reason | Tramai FinishReason |
|---|---|
"end_turn" | STOP |
"max_tokens" | LENGTH |
"tool_use" | STOP |
"content_filtered" | CONTENT_FILTER |
"stop_sequence" | STOP |
| (anything else) | OTHER |
Class hierarchy
BedrockProvider (final) ← implements ModelProvider, StreamCapable
│
└── uses BedrockRuntimeAsyncClient (AWS SDK)
└── authenticated via AwsCredentialsProvider
Dependency graph
tramai-bedrock
Depends on:
- tramai-core (api) — ModelProvider, ModelRequest, ModelResponse,
StreamCapable, ProviderCapability
- aws-bedrockruntime (impl) — InvokeModel API
- aws-auth (impl) — credentials chain
- jackson-databind (impl) — JSON payload construction
Depended on by:
- tramai-standalone — wired via Tramai.builder().provider()
Capabilities
providerId() returns "bedrock". All four capabilities are supported: VISION, TOOL_CALLING, STRUCTURED_OUTPUT, STREAMING.
