Skip to main content
ChatCLI supports AWS Bedrock as a native provider (BEDROCK) with three dispatch paths that cover the entire AWS-hosted catalog:
  • Anthropic Messagesanthropic.* and inference profiles (global./us./eu./apac.anthropic.*). Preserves cache markers and extended-thinking budget.
  • OpenAI Chat Completionsopenai.gpt-oss-* (OpenAI’s open-weights on Bedrock).
  • Converse API (default) — AWS’s unified schema covering everything else: Llama, Amazon Nova, Mistral, Cohere, AI21 Jamba, DeepSeek, Stability, Writer Palmyra, Moonshot Kimi, MiniMax, Qwen, Z.AI/GLM, Google Gemma, NVIDIA Nemotron, TwelveLabs Pegasus, and any provider AWS onboards next.
The /switch --model listing trusts AWS-side responses from ListFoundationModels + ListInferenceProfiles 100% — there is no hardcoded allowlist. A new model on AWS shows up on the next /switch --model without a ChatCLI release. Ideal for corporate environments that already manage billing, compliance, and access control through AWS — no need for API keys from the original providers.

Why AWS Bedrock?

No per-provider API key

Uses existing AWS credentials (IAM role, ~/.aws/credentials, AWS_PROFILE). Single identity across every model.

AWS billing and compliance

Costs appear on your AWS bill. CloudTrail logs, native Bedrock guardrails.

Full catalog

Anthropic, OpenAI, Llama, Nova, Mistral, Cohere, AI21, DeepSeek, Moonshot Kimi, MiniMax, Qwen, Z.AI/GLM, Gemma, Nemotron, TwelveLabs — all under one account.

VPC endpoints

Works in private environments via BEDROCK_BASE_URL (or the AWS-native AWS_ENDPOINT_URL_BEDROCK_RUNTIME).

Auto-detected family

Anthropic and OpenAI use dedicated paths (cache, thinking); the rest goes through Converse — one call covers all.

Native embeddings

Embeddings provider reuses the same AWS credential chain. Titan v1/v2 + Cohere v3. See RAG + HyDE.

Configuration

The provider is auto-detected when ChatCLI finds valid AWS credentials (not just file existence):
  • Static creds in env: AWS_ACCESS_KEY_ID
  • Profile selection: AWS_PROFILE (via env var or .env file)
  • ~/.aws/credentials file with at least one non-empty aws_access_key_id
  • AWS SSO: SSO profile in ~/.aws/config (detects sso_session, sso_start_url, sso_account_id)
  • Assume-role / credential_process: profiles with role_arn or credential_process in ~/.aws/config
  • SSO token cache: presence of files in ~/.aws/sso/cache/ (indicating a prior aws sso login)
  • Web Identity Token (EKS IRSA): AWS_WEB_IDENTITY_TOKEN_FILE
  • Container Credentials (ECS): AWS_CONTAINER_CREDENTIALS_RELATIVE_URI / _FULL_URI
The mere existence of ~/.aws/config with only region or output does not activate Bedrock. The file must contain credential configuration (SSO, assume-role, credential_process), or credentials must exist in another source.

Option 1: ~/.aws/credentials (static credentials)

If you already use AWS CLI, just have a profile configured:
Inside ChatCLI:
You can also set AWS_PROFILE in your .env file instead of exporting in the shell:
ChatCLI reads the .env via godotenv and resolves the profile correctly.

Option 2: AWS SSO (IAM Identity Center)

If your company uses AWS SSO, configure the profile in ~/.aws/config:
ChatCLI automatically detects SSO profiles in ~/.aws/config (via sso_session, sso_start_url, sso_account_id keys). If the SSO token expires, the error will be clear (SSOTokenProviderError) — just run aws sso login again.Important: the AWS SDK does not know which profile is “logged in”. You must indicate the profile via AWS_PROFILE (env, .env, or flag). If your SSO profile is named default, it is used automatically without AWS_PROFILE.

Option 3: Environment variables (static credentials)

Option 4: IAM Role (EC2/ECS/EKS)

On AWS-native environments, nothing to configure — the SDK picks up the role automatically through IMDSv2 / webidentity. Just make sure the role has the IAM permissions below.
ChatCLI disables the IMDS probe (169.254.169.254) by default on machines that are not EC2/ECS/EKS, to avoid unnecessary timeouts. IMDS is automatically enabled when container/EKS env vars are detected (AWS_CONTAINER_CREDENTIALS_*, AWS_WEB_IDENTITY_TOKEN_FILE, ECS_CONTAINER_METADATA_URI*).To force behavior, use:
  • AWS_EC2_METADATA_DISABLED=true — explicitly disable IMDS
  • CHATCLI_BEDROCK_ENABLE_IMDS=1 — force enable IMDS (useful on EC2 without standard env vars)

IAM Permissions

Minimum permissions to invoke and list models. The bedrock:InvokeModel action covers both InvokeModel (Anthropic/OpenAI) and Converse (everything else):
To restrict to specific providers, swap the Resource ARNs for a list (e.g. arn:aws:bedrock:*::foundation-model/anthropic.*, arn:aws:bedrock:*::foundation-model/moonshotai.*). Remember to include the matching inference profile ARNs (*:inference-profile/*anthropic.* etc.) — otherwise Claude 3.7+ and equivalents from other providers stop working.
ListFoundationModels and ListInferenceProfiles are used by /switch --model to dynamically discover what your account can invoke. Without them, ChatCLI falls back to the static catalog (still functional but can’t reflect account-specific access).
Also, in the Bedrock console you must enable model access for each provider you want to use (one-time per account + region): Bedrock Console → Model access → Request access.

Model families and schema selection

Bedrock uses different schemas depending on the model. ChatCLI has three dispatch paths and auto-detects which one to use from the model-id prefix:

Manual override

To force a family regardless of the prefix (e.g. test Converse on an Anthropic model), use the env var:
Accepted values: anthropic / claude, openai / gpt, converse / auto (case-insensitive). The env var takes precedence over prefix detection.
Why do Anthropic and OpenAI stay out of Converse? Anthropic’s cache_control breakpoints and extended-thinking knobs map onto Converse with a different shape — we deliberately don’t disturb the production-proven cache planner. OpenAI gpt-oss runs stable on direct InvokeModel and Converse coverage for those IDs varies by region. Set BEDROCK_PROVIDER=converse if you want to experiment with everything on Converse.
No hardcoded allowlist. /switch --model lists every text-output model with on-demand inference your account has access to — Kimi K2.6, GLM 4.7, Qwen3 Coder Next, Nemotron Nano 3, anything new AWS adds — without a release on our side. If a rare ID doesn’t fit Converse, ChatCLI returns a friendly error pointing the way.

New-generation Claude and the Messages endpoint (bedrock-mantle)

The newest Claude generation on Bedrock (Fable 5, Opus 5, Sonnet 5, Opus 4.8, Opus 4.7) uses dateless IDsanthropic.claude-fable-5, anthropic.claude-opus-5, anthropic.claude-sonnet-5, anthropic.claude-opus-4-8, anthropic.claude-opus-4-7 — with no ARN-versioned IDs (...-v1:0). On the InvokeModel path (Opus 4.8/4.7) the bare dateless ID is not on-demand invokable — AWS answers “retry with the ID or ARN of an inference profile” — so ChatCLI invokes them through the global. inference profile (global.anthropic.claude-opus-4-8); the Messages-endpoint models (Opus 5, Sonnet 5, Fable 5) use the bare dateless ID. Claude Opus 5, Claude Sonnet 5 and Claude Fable 5 have one particularity: they are served exclusively by the Claude in Amazon Bedrock endpoint — the Messages API at https://bedrock-mantle.{region}.api.aws/anthropic/v1/messages. Opus 5 and Sonnet 5 do not exist on legacy InvokeModel, and Fable 5 rejects it with 400 ValidationException: data retention mode 'default' is not available for this model (it requires 30-day data retention, available only under the Claude in Amazon Bedrock agreement). ChatCLI handles this on its own:
  • The catalog flags these models with the bedrock_mantle_only capability and the client routes the request through the Messages endpoint automatically — /switch --model claude-opus-5 (or claude-sonnet-5 / claude-fable-5) just works.
  • Inference-profile IDs are canonicalized on the wire: the Messages endpoint only knows the dateless anthropic.* IDs — sending us.anthropic.claude-sonnet-5 or global.anthropic.claude-fable-5 verbatim returns 404 not_found_error (“model does not exist”). If you pick one of those profiles in /switch (that’s what your account’s ListInferenceProfiles lists), ChatCLI converts it to the canonical ID (anthropic.claude-sonnet-5) before building the request.
  • Auth: SigV4 with the bedrock-mantle service name over the same credentials chain (IAM, profile, SSO), or a short-lived bearer token via AWS_BEARER_TOKEN_BEDROCK (x-api-key header) for corporate environments without IAM.
  • Body: same shape as the first-party Messages API — the version travels in the anthropic-version header (the anthropic_version body field is InvokeModel-only). cache_control markers reach the wire unchanged, exactly as on the InvokeModel path.
  • Operational overrides: BEDROCK_ANTHROPIC_ENDPOINT=mantle|invoke forces every Claude model onto either wire (gradual migration/rollback) and BEDROCK_MANTLE_BASE_URL points at VPC endpoints or proxies. Corporate TLS (CHATCLI_BEDROCK_CA_BUNDLE etc.) is honored.
Opus 4.8 and Opus 4.7 stay on InvokeModel by default (served by the same infrastructure as the Messages endpoint); set BEDROCK_ANTHROPIC_ENDPOINT=mantle to move them to the new endpoint too. Prerequisite for Opus 5/Sonnet 5/Fable 5: enable the model under Model access in the Bedrock console with a data retention mode selected.

Inference Profiles vs. Model IDs

This is the most important detail when using Claude on Bedrock. Anthropic models from the 3.7–4.6 era (3.7, 4.x, 4.5, 4.6) do NOT accept direct on-demand invocation by base model ID (the dateless new generation — Fable 5, Opus 5, Sonnet 5, Opus 4.8/4.7 — needs no profile; see the section above). Attempting this with an older-era model returns:
The fix is to use an inference profile ID — a logical ARN that routes the call to a region with available capacity. It carries a geography prefix: Example:
ChatCLI already uses a global inference profile as the default model (global.anthropic.claude-sonnet-4-5-20250929-v1:0). Claude 3 and 3.5 models still accept direct base-ID invocation and are also in the catalog.

Model Listing

/switch --model queries two live sources and merges them with the static catalog:
  1. bedrock:ListFoundationModels with ByOutputModality: TEXT — text-output models available in the region.
  2. bedrock:ListInferenceProfiles — regional/global profiles (paginated).
Two AWS-side filters guarantee that only invokable IDs appear:
  • Modality TEXT (server-side) — drops embedding-only and image-only models.
  • InferenceTypesSupported contains ON_DEMAND — drops base IDs that are only invokable via inference profile (Claude 3.7+/4.x and cross-region-only IDs from other providers). Those models still appear via ListInferenceProfiles with global./us./eu./apac. prefix.
Example output (depends on your account’s permissions):
Models with [api] are the ones your account actually can invoke in that region. [catalog] entries are static registrations that may or may not be enabled.
You still need to enable Model Access in the Bedrock console for each provider you intend to use. AWS gates this per account + region. If a model appears in ListFoundationModels but throws AccessDeniedException on invoke, model access is missing — usually a one-click fix in the console.

Corporate Proxy and Private TLS

In corporate environments with a proxy intercepting TLS using a private CA, you may see:
ChatCLI provides two Bedrock-specific env vars:
If the proxy intercepts TLS for all providers (not just Bedrock), prefer the global variables CHATCLI_CA_BUNDLE / CHATCLI_TLS_INSECURE_SKIP_VERIFY — they apply to every outbound connection (LLM providers, web tools, gateway, MCP), and Bedrock inherits them as fallback. The Bedrock-specific ones take precedence when both are set. See Global TLS Trust.
CHATCLI_BEDROCK_INSECURE_SKIP_VERIFY=true logs a warning and accepts any certificate. Use only for troubleshooting — never in production.
HTTP(S) proxy is honored automatically through Go’s standard env vars:

VPC endpoints / private endpoints / custom DNS

If your company routes Bedrock through a VPC interface endpoint, an API gateway or custom DNS, point the runtime (data plane) at it with BEDROCK_BASE_URL — the same role ANTHROPIC_BEDROCK_BASE_URL plays in Claude Code:
One variable covers the whole Bedrock surface — chat (InvokeModel/Converse), embeddings, image generation and model listing in /switch. If your control plane genuinely lives on another host — AWS VPC interface endpoints are created per service (bedrock vs bedrock-runtime), each with its own DNS name — the optional BEDROCK_CONTROL_BASE_URL overrides just the control plane (ListFoundationModels/ListInferenceProfiles). URLs must be absolute http(s) (validated at startup, fail-fast). The AWS-standard variables also work, read natively by SDK v2:
Precedence — data plane: BEDROCK_BASE_URL > AWS_ENDPOINT_URL_BEDROCK_RUNTIME > AWS_ENDPOINT_URL > regional default; control plane: BEDROCK_CONTROL_BASE_URL > BEDROCK_BASE_URL > AWS_ENDPOINT_URL_BEDROCK. AWS_IGNORE_CONFIGURED_ENDPOINT_URLS=true disables the AWS-standard ones but never the BEDROCK_*_BASE_URL pair. For the new-generation Claude Messages endpoint (bedrock-mantle), use BEDROCK_MANTLE_BASE_URL — it is a different host and service.

Environment Variables

Default model: global.anthropic.claude-sonnet-4-5-20250929-v1:0 Default region: us-east-1 All these vars surface in /config providers (chat) and /config quality (embeddings). See Environment Variables for the full reference.

Observability — endpoint URL in logs

Bedrock now logs its endpoint URL on every request — parity with Anthropic, OpenAI, and Copilot. Useful for debugging credential / region / VPC endpoint / proxy issues. On init (once per session):
On each request (chat):
On embeddings init:
The URL is derived from the SDK-resolved region (https://bedrock-runtime.<region>.amazonaws.com). If you set AWS_ENDPOINT_URL_BEDROCK_RUNTIME (VPC endpoint), the SDK uses your override — the log shows the canonical URL but the actual request goes to your custom endpoint.

Architecture

The bedrockruntime.Client construction lives in an exported helper (bedrock.LoadBedrockRuntime) shared between the chat client and the embeddings provider — single source of truth for AWS config. Authentication is SigV4, handled transparently by the SDK. The HTTP client can be overridden by ChatCLI when CHATCLI_BEDROCK_CA_BUNDLE or CHATCLI_BEDROCK_INSECURE_SKIP_VERIFY is set (via awshttp.BuildableClient).

Bedrock vs. Direct Anthropic

If your company already runs everything on AWS with managed compliance, BEDROCK is the way. If you’re an individual developer wanting the newest Claude features (1M context, OAuth via Claude Code plan), use CLAUDEAI direct.

Troubleshooting

ChatCLI message when you select a base ID that requires an inference profile (Claude 3.7+/4.x/4.5/4.6/4.7 and equivalents from other providers). The message already suggests the fix:
/switch --model automatically filters out base IDs that require profiles, so this only shows up if you typed an ID manually. The filter uses the InferenceTypesSupported field of ListFoundationModels: a model without ON_DEMAND is suppressed from the listing.
Go to the Bedrock console for that region and enable Model Access for the provider. Takes a few minutes. Also check the IAM role has bedrock:InvokeModel on the model ARN + the inference profile ARN.
The SDK didn’t find credentials. Check:
If nothing returns credentials, set them up via aws configure, aws sso login, or export env vars.
This error occurs when the AWS SDK tries to reach the EC2 Instance Metadata Service (IMDS) on a machine that is not EC2 (e.g., your laptop). ChatCLI disables the IMDS probe by default on non-EC2, but if the error persists:
If you are actually on EC2 and need IMDS:
Your SSO token has expired (default validity ~8h). Log in again:
Remember to have AWS_PROFILE set (env, .env, or name your profile default).
Corporate proxy doing TLS interception. Configure CHATCLI_BEDROCK_CA_BUNDLE with the PEM of the corp CA. For quick troubleshooting, set CHATCLI_BEDROCK_INSECURE_SKIP_VERIFY=true (insecure, temporary only).
You’ve hit on-demand quota for that region. Options:
  • Use a global.* inference profile (routes to any available region)
  • Use Provisioned Throughput (configure in the Bedrock console)
  • Raise quotas via AWS Service Quotas

Embeddings via Bedrock

ChatCLI also uses Bedrock as an embeddings provider (HyDE phase 3b, vector retrieval). Activation:
Supported families: Reuses the same credentials chain as the chat client — BEDROCK_REGION / AWS_REGION / AWS_PROFILE / ~/.aws/credentials etc. See RAG + HyDE for the retrieval architecture.
Titan and Cohere use different schemas but ChatCLI auto-detects from the model id prefix. If you need a large batch with Titan (which only accepts 1 text per call), the provider parallelizes with an 8-worker pool transparently.

Next Steps

Provider Fallback

Configure automatic failover between Bedrock and other providers

RAG + HyDE

Embeddings via Bedrock Titan/Cohere for semantic retrieval

Supported Models

Full list of models per provider

Environment Variables

Complete configuration reference