AWS Bedrock

Hankweave runs models hosted on AWS Bedrock under the operator's own AWS credentials and billing, for both codons (sealed agent tasks in a sequence) and sentinels (parallel observers). This page is the lookup reference for that support: how to spell Bedrock model ids, which harness each spelling lands on, where codons and sentinels get AWS credentials, what the AWS account needs, and how Bedrock failures are classified. Each section ends with pointers to the broader pages it depends on, so a reader can start anywhere and follow the links outward.

When to run on Bedrock#

Bedrock is a fit when consolidated billing, private networking, or AWS compliance controls matter, because requests stay inside the AWS account and its guardrails. When those constraints do not apply, a direct provider API is simpler to set up and debug; see authentication and models.

[since 0.9.0] Bedrock support is available.

Spelling Bedrock models#

Every place Hankweave accepts a model also accepts a Bedrock spelling: amazon-bedrock/<model-id-or-inference-profile-id>. That covers a codon's model, a sentinel's model, and global overrides such as HANKWEAVE_RUNTIME_MODEL. The provider id amazon-bedrock comes from the models.dev registry, and the override is a free-form string validated at runtime by Hankweave's model registry (LLMRegistry).

Anthropic-family ids use anthropic.claude-… for on-demand models and <geo>.anthropic.claude-… for cross-region inference profiles. The supported geography prefixes are us., eu., jp., au., global., and us-gov.. The prefix matters in practice: AWS rejects a bare on-demand id for newer Anthropic models when on-demand throughput is unsupported, so use the serving geography or a global. profile where available.

The Bedrock catalog ships inside the runtime from a static JSON import of the models.dev snapshot. The pinned release snapshot contains 153 Amazon Bedrock models out of 7,436 total. Pinned ids can be re-checked against the amazon-bedrock provider's models array in the shipped model data, or by running bunx hankweave@0.11.0 --validate, which runs the same per-model harness self-test as startup.

The two fragments below are valid one-line codon model settings in a hank (a run configuration). The first uses a cross-region inference profile for an Anthropic model; the second uses a non-Anthropic Bedrock model. Their enclosing codon shape is defined by hank.schema.json, the configuration schema.

JSON
{"model": "amazon-bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0"}
JSON
{"model": "amazon-bedrock/deepseek.v3.2"}

See model resolution for the broader spelling and resolution rules.

Which harness a Bedrock model lands on#

The routing predicate sends a model to the Claude Agent SDK harness when its provider is anthropic or when it is an Anthropic-family id on amazon-bedrock. Non-Anthropic Bedrock models use the embedded Pi harness. The table summarizes the three spellings:

Scroll to explore the table →
Model spellingHarness
amazon-bedrock/<anthropic-family-id>Claude Agent SDK harness
pi/amazon-bedrock/<anthropic-family-id>embedded Pi harness
amazon-bedrock/<non-Anthropic-id>embedded Pi harness

The pi/ prefix is the explicit override. Selection is late-bound at dispatch from the model's real identity. "Claude Code (Bedrock mode)" is an allowed alias for the Claude Agent SDK harness; the canonical name is Claude Agent SDK harness. For example, pi/amazon-bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0 selects the embedded Pi harness even though the underlying model is Anthropic-family.

On the Claude Agent SDK route, the runtime sets CLAUDE_CODE_USE_BEDROCK=1 and passes an enumerated list of AWS environment variables to the Agent SDK subprocess. The list below is the complete set of ambient AWS variables forwarded in Bedrock mode; HANKWEAVE_AWS_* aliases are dropped. Bedrock mode also forwards HTTPS_PROXY, HTTP_PROXY, ALL_PROXY, NO_PROXY and NODE_EXTRA_CA_CERTS and sets CLAUDE_CODE_USE_BEDROCK=1; a non-Bedrock codon receives a byte-identical environment to the one it received before Bedrock support.

TS
const BEDROCK_AWS_ENV_VARS = [
  "AWS_REGION",
  "AWS_DEFAULT_REGION",
  "AWS_BEARER_TOKEN_BEDROCK",
  "AWS_ACCESS_KEY_ID",
  "AWS_SECRET_ACCESS_KEY",
  "AWS_SESSION_TOKEN",
  "AWS_PROFILE",
  "AWS_SHARED_CREDENTIALS_FILE",
  "AWS_CONFIG_FILE",
  "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
  "AWS_CONTAINER_CREDENTIALS_FULL_URI",
  // EKS Pod Identity (and any token-protected full-URI endpoint) needs the
  // authorization token alongside the URI, or the subprocess can't fetch creds.
  "AWS_CONTAINER_AUTHORIZATION_TOKEN",
  "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE",
  "AWS_WEB_IDENTITY_TOKEN_FILE",
  "AWS_ROLE_ARN",
  "AWS_ROLE_SESSION_NAME",
  "AWS_EC2_METADATA_DISABLED",
  // Custom/IPv6 IMDS endpoints: the child's SDK chain must target the same
  // metadata endpoint the preflight probe resolved.
  "AWS_EC2_METADATA_SERVICE_ENDPOINT",
  "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE",
  "AWS_CA_BUNDLE",
] as const;

See model resolution and runtime architecture for routing and harness boundaries.

Where codons get AWS credentials#

Codons use the ambient AWS credential chain: sources visible to the Hankweave process, not credentials stored in a hank. On the Claude Agent SDK route, the quickest source is AWS_BEARER_TOKEN_BEDROCK. Other sources are AWS_ACCESS_KEY_ID plus AWS_SECRET_ACCESS_KEY and optional AWS_SESSION_TOKEN, AWS_PROFILE with single sign-on (SSO), ECS container credentials including EKS Pod Identity authorization tokens, IRSA web identity, and EC2 instance roles through the Instance Metadata Service (IMDS). A minimal bearer-token setup looks like this:

⌁ Terminal
export AWS_BEARER_TOKEN_BEDROCK="..."
export AWS_REGION="us-east-1"

Before a run starts, Bedrock preflight checks these sources in order: gateway-managed authentication through CLAUDE_CODE_SKIP_BEDROCK_AUTH, ambient source detection, Claude settings helpers (awsAuthRefresh and awsCredentialExport), and then an IMDS probe. The probe requests an IMDSv2 token and requires a non-empty iam/security-credentials/ listing within 500 ms. It honors AWS_EC2_METADATA_SERVICE_ENDPOINT and AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE, and is skipped when AWS_EC2_METADATA_DISABLED=true.

Two interactions in that chain trip people up. With AWS_PROFILE set, an environment key pair does not satisfy preflight because the AWS SDK skips its environment-key provider; the selected profile must provide usable credentials, and profile sections are inspected for actual credential keys, not merely for the section's presence. And EC2/IMDS instance roles authenticate only the Claude Agent SDK route: the embedded Pi route does not probe on-disk config files or IMDS, so Pi-routed Bedrock models need an explicit environment credential source.

Region resolution follows the same ambient rule. AWS_REGION or AWS_DEFAULT_REGION wins. If neither is set and AWS_PROFILE or the default profile defines a region, the Agent SDK CLI resolves it from that profile while the runtime leaves the variable unset. Otherwise the runtime sets AWS_REGION=us-east-1 and writes "AWS_REGION not set — defaulting to us-east-1…" to the server log at info level only. Nothing reaches the console, so a run that went to the wrong region shows no console warning; the self-test records its "(AWS_REGION not set — defaulting)" note only alongside its passed results.

Short-term Bedrock API keys expire. An expired or invalid bearer token is a permanent failure, so the request is not retried; generate a long-term key in AWS Console → Bedrock → API keys.

See environment variables for process variable names and scopes.

Why sentinel credentials are narrower#

Sentinels do not share the codon credential chain. A Bedrock-modeled sentinel accepts explicit environment credentials only: AWS_BEARER_TOKEN_BEDROCK, or AWS_ACCESS_KEY_ID plus AWS_SECRET_ACCESS_KEY with optional AWS_SESSION_TOKEN. The sentinel-scoped HANKWEAVE_SENTINEL_AWS_BEARER_TOKEN_BEDROCK override is checked before the process-wide bearer token.

Profile/SSO, container credentials, IRSA, and IMDS are not sentinel sources. The sentinel provider signs requests through its built-in aws4fetch path instead of the ambient chain; including the omitted credential-provider package would add a transitive tree of about 6 MB to the binary.

The practical consequence: without an explicit source, the amazon-bedrock sentinel provider is marked not-configured with an error naming the accepted sources. Bedrock-modeled sentinels are skipped, while Bedrock codons on the same machine can run normally.

The sentinel health check follows the configured region's geographic profile for the Anthropic Haiku model: us-gov. for GovCloud, us., eu., jp., or au. where served, and global. otherwise. A geographic profile routes only within its own geography.

A sentinel configuration selects its model with the same amazon-bedrock/… spelling used for codons:

JSON
{
  "model": "amazon-bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0"
}

See sentinel configuration.

Setting up the AWS account#

Model access in commercial AWS Regions is enabled by default once the account holds the AWS Marketplace permissions (aws-marketplace:Subscribe, aws-marketplace:Unsubscribe, aws-marketplace:ViewSubscriptions) and a valid payment method is configured for AWS Marketplace purchases. First-time Anthropic use needs a one-time use-case form, submitted once per account or organization across all commercial Regions; opt-in Regions require the form again, and models accessed through the bedrock-mantle endpoint are exempt. The documented console route is the model catalog: select an Anthropic model and submit use-case details (or call PutUseCaseForModelAccess). After a model is enabled, the Marketplace subscription permissions are no longer needed to invoke it. Marketplace-served models need one first invoke by a Marketplace-permissioned user.

Invocation permission maps by operation: bedrock:InvokeModel covers Converse (non-streaming) and bedrock:InvokeModelWithResponseStream covers ConverseStream (streaming). The AWS CLI supports no Bedrock streaming operation, so the verification recipe below exercises the non-streaming action only. An invoke-only policy allowing both actions on Resource: "*" is an illustrative broad-resource permission, not a least-privilege recommendation: Resource: "*" avoids enumerating resources but grants broadly, and operators designing least privilege scope their resources and conditions instead. The runtime's own AccessDenied remedy still suggests Resource: "*" for a simple invoke-only principal. A cross-region us.* inference profile needs invoke permission on both the profile and its associated foundation models in every Region.

Once the account is enabled and permissioned, the following AWS-side command verifies a non-streaming Converse request for the selected model before pointing Hankweave at it. Replace the region and model id with a supported target and serving region before running it; the recipe sends a billable model request and may incur charges.

Output
aws bedrock-runtime converse \
  --region '<serving-region>' \
  --model-id '<model-id-or-inference-profile-id-or-arn>' \
  --messages '[{"role":"user","content":[{"text":"Say OK"}]}]'

An invoke-only policy can use these actions:

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream"
      ],
      "Resource": "*"
    }
  ]
}

These are AWS-side procedures grounded in AWS's public documentation, not a live-account test; entitlement, effective IAM or SCP permissions, and regional availability remain account-specific. See authentication and models for the provider setup boundary.

How Bedrock failures classify#

Bedrock authentication and access failures are permanent (retriable: false) and carry a remediation hint. They do not enter the retry path because the surfaced text has no HTTP status; the default would otherwise retry a failure that only the operator can fix.

Ten Bedrock matchers run in declaration order, and the first matching row wins. The table below is the Bedrock slice of the classifier, rendered sorted by id for lookup; use matchOrder, not row order, to follow declaration precedence. matchOrder preserves each matcher's position in the complete classifier, so this slice starts at 3 rather than being renumbered. In the pattern column, AND and OR describe compound conditions, and /…/ marks the regular expression used for the on-demand-throughput pattern.

Scroll to explore the table →
idpatternclassificationretriablematchOrderreceipts
bedrock-access-deniedaccessdeniedexceptionapi-errorfalse4error-classification.ts:178-184, error-classification.ts:350-358
bedrock-expired-tokenexpiredtokenexceptionapi-errorfalse7error-classification.ts:209-213, error-classification.ts:350-358
bedrock-invalid-credentialsunrecognizedclientexception OR security token included in the request is invalidapi-errorfalse5error-classification.ts:188-195, error-classification.ts:350-358
bedrock-model-not-foundresourcenotfoundexception OR the provided model identifier is invalidapi-errorfalse12error-classification.ts:257-263, error-classification.ts:350-358
bedrock-no-credentialscould not load credentials OR unable to locate credentialsapi-errorfalse9error-classification.ts:226-233, error-classification.ts:350-358
bedrock-on-demand-throughput/on-demand throughput isn.t supported/api-errorfalse11error-classification.ts:245-251, error-classification.ts:350-358
bedrock-pi-not-configuredprovider is not configured: amazon-bedrockapi-errorfalse10error-classification.ts:237-243, error-classification.ts:350-358
bedrock-signatureinvalidsignatureexception OR signaturedoesnotmatch OR signature we calculated does not matchapi-errorfalse6error-classification.ts:199-207, error-classification.ts:350-358
bedrock-sso-sessionsso session AND (not found OR invalid OR expired)api-errorfalse8error-classification.ts:218-224, error-classification.ts:350-358
bedrock-sts-assume-rolests:assumerole AND (accessdenied OR not authorized)api-errorfalse3error-classification.ts:171-176, error-classification.ts:350-358

Reading the rows in precedence order explains the remedies. The role-assumption matcher precedes generic AccessDeniedException, so a role denial gets the role remedy: check the role ARN, trust policy, and external-id or MFA requirements. Generic access denials point to IAM/SCP restrictions, cross-region permissions, first-time Anthropic access, or Marketplace first invoke. Invalid credentials point to the bearer token or key pair; expired short-term keys need a long-term key. Signature failures point to the access-key secret, expired or invalid SSO sessions to refreshed profile credentials, and missing credentials to an explicit bearer token, key pair, or profile plus region. The Pi-not-configured row requires an explicit environment source; the on-demand-throughput row requires a geography prefix or available global. profile. Signature matching runs before the timeout branch because AWS signature-error dumps contain x-stainless-timeout header lines; otherwise a broken credential chain could become retriable.

One failure looks like a model problem but is a region problem: a wrong-region model appears as ResourceNotFoundException or Pi's "The provided model identifier is invalid." Both are permanent; set AWS_REGION to a serving region or use the global. inference profile id. The complete failure taxonomy and exit-code contract live in errors and exit codes; this page embeds only the Bedrock slice.

When Bedrock features are unavailable#

Two route constraints limit which models and credential sources work:

  • A codon model must accept tool definitions in Converse requests. A model that rejects them cannot drive codons; DeepSeek-R1 surfaces "This model doesn't support tool use" as a permanent invalid request, while the shipped catalog carries deepseek.v3.2 as the working alternative.
  • EC2 instance roles through IMDS authenticate only the Claude Agent SDK route. The embedded Pi route does not probe on-disk config files or IMDS; its checkAuth covers only Pi's credential store and ambient environment markers. Pi-routed Bedrock models, and all sentinels, need an explicit environment credential source.

Where to continue from Bedrock#