Build

AWS Bedrock

bedrock() — model-agnostic provider via AWS Bedrock's Converse API. One adapter covers Claude, Llama, Mistral, Titan, Mixtral on Bedrock.

AWS Bedrock's Converse API is model-agnostic — same wire format whether you're calling Claude, Llama, Mistral, Titan, or Mixtral. agentfootprint's bedrock() factory wraps it as one LLMProvider. No format-specific code per model family.

Install

npm install @aws-sdk/client-bedrock-runtime

Peer dep, lazy-required, optional. AWS credentials resolved via the SDK's normal chain (env, profile, IAM role).

Use

import { Agent } from 'agentfootprint';
import { bedrock } from 'agentfootprint/providers';

const provider = bedrock({
  region: 'us-east-1',
});

const agent = Agent.create({
  provider,
  model: 'anthropic.claude-sonnet-4-5-20250929-v1:0',  // Bedrock-namespaced model id
}).build();

The model id is Bedrock's, not the upstream provider's. Cross-region inference profiles work as-is — just pass the profile id.

Tools (Converse tool_use blocks)

Converse API's tool_use / tool_result blocks map cleanly to agentfootprint's Tool[] + LLMMessage.toolCalls. ReAct correctness preserved.

The mapping holds on both paths — complete() and stream() produce the same toolCalls for the same logical response, and a parity test pins them together so they cannot drift apart.

Streaming

provider.stream(req) uses ConverseStream — text chunks land as they arrive, and the final chunk carries the authoritative LLMResponse.

Streamed tool calls are parsed. bedrock() accumulates the ConverseStream tool-use events — contentBlockStart (id + name), contentBlockDelta (JSON argument fragments), contentBlockStop — keyed by contentBlockIndex, so parallel tool calls whose fragments interleave are reassembled correctly. The completed calls arrive on the terminal chunk's response.toolCalls. Tools that take no arguments stream as args: {}.

Argument fragments are not yielded as chunks (LLMChunk has no field for them); they surface only on the terminal response.

Honest by construction: a response with stopReason: 'tool_use' and zero parsed tool calls is never returned quietly. The provider throws a BedrockProviderError with code: 'BEDROCK_STREAM_TOOLUSE_LOST' so a reliability rule can retry, instead of the agent confidently answering without running its tools.

Fixed in 7.6.1. Before this, stream() ignored the tool-use events entirely and returned toolCalls: [] — an agent on bedrock() with streaming enabled silently produced a final answer instead of calling its tools. The non-streaming path was always correct.

Production patterns

  • AWS SDK handles credential refresh + region routing automatically.
  • Wrap with withRetry (from agentfootprint/resilience) for transient throttling. The provider rethrows a BedrockProviderError; check .code to tell the failure classes apart:
.codeMeaningExtra fields
(absent)Generic AWS transport / service error.status — the AWS HTTP status code (err.$metadata.httpStatusCode)
BEDROCK_STREAM_TOOLUSE_LOSTstopReason 'tool_use' with zero parsed tool calls — a tripwire for future ConverseStream shape drift
BEDROCK_MALFORMED_TOOL_ARGSThe model emitted tool-argument JSON that does not parse. Thrown rather than swallowed to {}, so a tool is never executed with its arguments dropped.toolName, .toolUseId, .contentBlockIndex, .rawLength, .cause

All three are retryable through withRetry. A retry usually recovers malformed tool-args JSON (the model re-emits it cleanly); BEDROCK_STREAM_TOOLUSE_LOST is a tripwire for persistent stream-shape drift, so if it repeats, report it rather than retrying harder.

  • Tune the default model and token budget on the factory:
import { bedrock } from 'agentfootprint/providers';

const provider = bedrock({
  region: 'us-east-1',
  defaultModel: 'anthropic.claude-sonnet-4-5-20250929-v1:0', // used when LLMRequest.model is the shorthand 'bedrock'
  defaultMaxTokens: 4096,
});

Limitations

  • Multi-modal not exposed yet (text content only).
  • Bedrock Guardrails not exposed in the wrapper — pass via the SDK client directly if you need them.

Next steps

On this page