Skip to content
Mayura

Integrationsmodel providers

Amazon Bedrock models

Call Claude, Nova, Llama and Mistral models on Amazon Bedrock with @mayurajs/provider-bedrock: model ids, catalog prices, credentials and errors.

Package
@mayurajs/provider-bedrock
Install
npm install mayura @mayurajs/provider-bedrock
Vendor
Amazon Web Services ↗

Amazon Bedrock serves models from Anthropic, Amazon, Meta, Mistral and others in your AWS account. @mayurajs/provider-bedrock is a provider package for the model registry: every Bedrock model or inference profile gets an id such as bedrock/global.anthropic.claude-sonnet-5-5, which you price, bound and grant like any other registry model. It calls Bedrock's Converse API through the official AWS SDK, @aws-sdk/client-bedrock-runtime pinned at 3.1141.0, which is its only dependency (mayura is a peer). The SDK's HTTP handler is replaced with one built on fetch, and the package itself uses no Node built-in modules; its engines field names Node.js 22 (22.12 or later) and 24 (24.14.1 or later), and its tests run on Node.

Install

bash
npm install mayura @mayurajs/provider-bedrock

Credentials

Give the package one of:

  • AWS credentials, used to sign requests with SigV4: an access key id and secret access key (and a session token for temporary credentials), or a function that returns fresh ones, for example from your own STS call. Create them for an IAM user or role in the IAM console.
  • A Bedrock API key, sent as a bearer token instead of signing. Create one in the Bedrock console under API keys.

The package calls only Converse and, for streaming, ConverseStream, so the identity needs bedrock:InvokeModel and bedrock:InvokeModelWithResponseStream on the models and inference profiles you use. Turn on access to each model in your account first.

The package reads nothing from the environment, AWS config or credentials files, or instance metadata: not AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BEARER_TOKEN_BEDROCK, AWS_ENDPOINT_URL, AWS_MAX_ATTEMPTS or AWS_AUTH_SCHEME_PREFERENCE. Pass the region and credentials in yourself, for example from AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN, or AWS_BEARER_TOKEN_BEDROCK for an API key.

Use it

ts
import { createModels, createRuntime, defineAgent, z } from 'mayura';
import { bedrock } from '@mayurajs/provider-bedrock';

const models = createModels({
  providers: [bedrock({
    region: 'us-east-1',
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? '',
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? '',
    },
  })],
  prices: 'catalog',          // on-demand list prices in us-east-1 on the catalog's date
  maxCallCostMicros: 100_000, // at most $0.10 per model call
});

const id = 'bedrock/global.anthropic.claude-sonnet-5-5';
const agent = defineAgent({
  id: 'support', version: '1', instructions: 'Answer the customer in one or two sentences.',
  model: models.model(id, { retry: { attempts: 2 } }), tools: [],
  input: z.object({ question: z.string() }), output: z.object({ answer: z.string() }),
});

const runtime = createRuntime({
  profile: 'ephemeral',
  permissions: { allow: [`model:${id}`] },
  limits: { maxCostMicros: 500_000 }, // at most $0.50 per run
});
try {
  const outcome = await runtime.submit(agent, { input: { question: 'Where is my order?' } }).result();
  console.log(outcome.status === 'succeeded' ? outcome.output.answer : outcome.error);
} finally {
  await runtime.close();
}

The adapter's id is the model id, so the run needs model:bedrock/global.anthropic.claude-sonnet-5-5, and that grant admits no other model or profile. A run without it ends blocked with PERMISSION_DENIED before any request is sent. See Permissions.

For short-lived credentials, pass a function. It is asked for credentials as the SDK needs them:

ts
const provider = bedrock({ region: 'eu-west-1', credentials: async () => assumeRole() });

Model ids

A model id is bedrock/<name>, where <name> is a Bedrock model id or inference profile id as Bedrock takes it: up to 120 letters, digits and ., _, :, / or -, such as bedrock/global.anthropic.claude-sonnet-5-5 or bedrock/amazon.nova-pro-v1:0. Inference profiles that start with global. route anywhere; those that start with us. stay in the US, at a higher price. Any name works once it has a price; the catalog prices the ones below.

Catalog prices

prices: 'catalog' uses Bedrock's on-demand list prices in US East (N. Virginia) as of 2026-09-29, from the Bedrock pricing page. Other regions can cost more, so the catalog is offered only by a provider whose region is us-east-1; elsewhere, give every model's price yourself. In US dollars per million tokens:

Model or inference profile Input Output Context Max output
global.anthropic.claude-opus-5-5 $4 $20 1,000,000 128,000
us.anthropic.claude-opus-5-5 $4.40 $22 1,000,000 128,000
global.anthropic.claude-sonnet-5-5 $2 $10 1,000,000 128,000
us.anthropic.claude-fable-5-1 $11 $55 1,000,000 128,000
global.anthropic.claude-haiku-4-5-20251001-v1:0 $1 $5 200,000 64,000
us.anthropic.claude-haiku-4-5-20251001-v1:0 $1.10 $5.50 200,000 64,000
global.amazon.nova-2-lite-v1:0 $0.30 $2.50 1,000,000 64,000
us.amazon.nova-2-lite-v1:0 $0.33 $2.75 1,000,000 64,000
amazon.nova-premier-v1:0 $2.50 $12.50 1,000,000 25,000
amazon.nova-pro-v1:0 $0.80 $3.20 300,000 5,000
amazon.nova-lite-v1:0 $0.06 $0.24 300,000 5,000
amazon.nova-micro-v1:0 $0.035 $0.14 128,000 5,000
us.meta.llama4-maverick-17b-instruct-v1:0 $0.24 $0.97 1,000,000 8,000
us.meta.llama4-scout-17b-instruct-v1:0 $0.17 $0.66 10,000,000 8,000
us.meta.llama3-3-70b-instruct-v1:0 $0.72 $0.72 128,000 4,000
mistral.mistral-large-3-675b-instruct $0.50 $1.50 256,000 32,000
mistral.ministral-3-8b-instruct $0.15 $0.15 128,000 8,000
mistral.devstral-2-123b $0.40 $2 256,000 32,000

Prices change: models.list() shows each model's catalogAsOf, context and output limits, and the catalog is exported as catalog. A price you give, in prices or as pricing on one model, always wins, and is the only way to price a model outside us-east-1:

ts
const models = createModels({
  providers: [bedrock({ region: 'eu-west-1', credentials: async () => assumeRole() })],
  // Check the price in your region on the Bedrock pricing page.
  prices: { 'bedrock/global.anthropic.claude-sonnet-5-5': { inputMicrosPerMillionTokens: 2_000_000, outputMicrosPerMillionTokens: 10_000_000 } },
  maxCallCostMicros: 100_000,
});

Options

Option Default Meaning
region required The AWS region, such as us-east-1.
credentials none AWS credentials, { accessKeyId, secretAccessKey, sessionToken? }, or a function returning them (with an optional expiration). Give this or apiKey.
apiKey none A Bedrock API key, sent as a bearer token. Give this or credentials.
baseURL https://bedrock-runtime.<region>.amazonaws.com Where requests go instead, such as a VPC endpoint. https only.
media PNG, JPEG, WebP, GIF and PDF, as bytes What the models can see, { types, urls: false }; false for none. URLs are not accepted.
maxRequestBytes 1 MiB Largest request JSON, not counting media bytes (the run's maxMediaBytes bounds those).
maxResponseBytes 1 MiB Largest response body; four times that for a stream. A larger one fails without being read into memory.
timeoutMs 60,000 How long one call may take, unless the registry or the model sets timeoutMs.
fetch globalThis.fetch The transport, for tests and proxies. Redirects are never followed.

The registry's timeoutMs (on createModels or on one model, 100 to 3,600,000 ms) wins over the provider's.

What it sends and supports

  • Structured output. Every call asks for the agent's output as JSON Schema (outputConfig.textFormat of type json_schema), and tools are sent with strict: true and an auto tool choice. The schemas must follow the strict rules; defineAgent checks them when the agent is defined. Use models that Bedrock offers structured output and tool use for.
  • Streaming. With a stream policy on the agent, the package calls ConverseStream and reports output text as the model writes it.
  • Reasoning. Reasoning a model returns with a tool call, its signature and redacted reasoning included, is kept in the run's private state and sent back on the next call. It is never released as output or put in events. That state names the provider and model, so it never moves to another provider or model.
  • Narration. Text a model writes before a tool call is not an answer and is dropped.
  • Images and PDFs. By default the models see PNG, JPEG, WebP, GIF and PDF, sent as bytes. Images a tool returns go inside its tool result, PDFs right after it. Media given as a URL fails the call with configuration. See Vision.
  • Output tokens. inferenceConfig.maxTokens is the run's limits.maxOutputTokens (4,096 unless you set it).

Costs

Each call's cost is Bedrock's reported usage at your prices, rounded up to a whole micro:

  • input tokens at the input rate;
  • cache-write tokens at twice the input rate and cache-read tokens at the full input rate, so a budget never undercounts;
  • output tokens at the output rate.

The tokens reported to events and traces count cache writes and reads as input.

maxCallCostMicros (or a model's maxCostMicros) is reserved before every call, and a call that doesn't fit in the run's budget never starts. Choose it to cover your largest prompt plus maxOutputTokens: on global.anthropic.claude-sonnet-5-5, 20,000 input tokens and 4,096 output tokens cost at most 40,000 + 40,960 = 80,960 micros. A call whose cost is unknown, such as one that timed out after it was sent, is charged its full bound. See Costs and budgets.

Retries and fallback

The SDK makes one attempt per call (maxAttempts: 1). Retries belong to the registry:

ts
const model = models.model('bedrock/global.anthropic.claude-sonnet-5-5', { retry: { attempts: 3, backoffMs: 500 } });
  • retry calls the model again after rate_limited (Bedrock's throttling), unavailable or timeout; never after the caller cancels, a failure that would repeat, or once streamed text was released.
  • attempts is 1 to 5, and the model's bound becomes attempts times its bound. Every attempt is charged.
  • Waits double from backoffMs (default 500 ms).

To fall back to another model or region, use a chain. It is a model router granted by the name you choose, and granting it grants every model in it:

ts
const support = models.chain('support', ['bedrock/global.anthropic.claude-sonnet-5-5', 'bedrock/global.amazon.nova-2-lite-v1:0']);
// Grant model:support.

A second provider in another region is a route too, but the registry takes each provider id once, so register it in a second registry and combine the adapters with createModelRouter.

Errors

A failed call ends the run with MODEL_FAILED and a reason (see Errors for the messages):

reason When
authentication HTTP 401 or 403: credentials Bedrock refuses, or no access to the model.
rate_limited HTTP 429 (throttling), 402, or a throttling event inside a stream.
unavailable HTTP 408 or 5xx, no connection, or a service, internal, model-stream or model-timeout error inside a stream.
timeout No answer within timeoutMs.
rejected Any other HTTP error, such as a 400 validation error, a validation error inside a stream, or the prompt exceeding the model's context window.
refused The model stopped at the output-token limit, or a content filter or guardrail intervened.
invalid_response An answer that is not the required JSON, a response without usage, or one larger than maxResponseBytes.
configuration A schema that breaks the strict rules, or media given as a URL (code INVALID_CONFIG).

Bedrock's error text and your credentials never appear in outcomes or events. Options the package cannot use, such as a malformed region, both or neither of credentials and apiKey, credentials without both keys, an http:// baseURL, or media with URLs, throw INVALID_CONFIG when you call bedrock(); a malformed model id throws it when you call models.model().

How it is tested

  • Unit tests run the package through the AWS SDK against a fake Converse API, given through fetch, including AWS's event-stream framing for streams. It passes the model adapter conformance suite from mayura/testing: response shapes, costs, tool calls, streaming, the reason for each failure, no leaked provider text, cancellation, timeouts and strict schemas.
  • They also check that requests are signed with the given credentials in the given region, once, with nothing from the environment or AWS config; that an API key is sent as a bearer token; the cache-token charges; that reasoning is sent back and never released; and that the catalog is offered only in us-east-1.
  • It has not been run against a real AWS account yet.