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 oneLLMProvider. No format-specific code per model family.
Install
npm install @aws-sdk/client-bedrock-runtimePeer 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(fromagentfootprint/resilience) for transient throttling. The provider rethrows aBedrockProviderError; check.codeto tell the failure classes apart:
.code | Meaning | Extra fields |
|---|---|---|
| (absent) | Generic AWS transport / service error | .status — the AWS HTTP status code (err.$metadata.httpStatusCode) |
BEDROCK_STREAM_TOOLUSE_LOST | stopReason 'tool_use' with zero parsed tool calls — a tripwire for future ConverseStream shape drift | — |
BEDROCK_MALFORMED_TOOL_ARGS | The 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
- Resilience — wrap with
withRetry/withFallback - AgentCore Memory — paired Bedrock memory adapter
OpenAI
openai() — GPT provider via the openai SDK. Also covers OpenAI-compatible endpoints (Ollama, llama.cpp, vLLM, Together, Groq, LM Studio) via baseURL.
Gemini
gemini() — Google's models through the native @google/genai SDK, on Vertex or the Gemini API. Honest cached- and thinking-token counts, JSON Schema tools with no OpenAPI translation, and a forced single tool that is actually forced.
