Skip to content

[V2] Bedrock application inference profile ARN gets Nova-format effort variants for Claude models #53756

Open

Description

@gillespied

Description

When a Bedrock model's API id is an application inference profile ARN, the generated effort variants are built in Amazon Nova format even though the profile is backed by a Claude model. Bedrock returns a 400 for reasoningConfig on a Claude model.

This is the v2 counterpart of #53751, which was closed as won't-fix for v1 (v1 only gets critical fixes) with a request to check v2.

An ARN looks like arn:aws:bedrock:<region>:<account>:application-inference-profile/<id>. It contains no model name, so any check that reads the model name from the id will misidentify it.

Cause

Read from the v2 branch at 119cb15d1d (2.0.24). I have not yet run @opencode/cli against a real profile, so this comes from reading the code.

  • packages/core/src/variant.ts:410-412: bedrockConverse sets claude = modelID(model).includes("anthropic"). For an ARN this is false, so the Claude shape (thinking + output_config: { effort }) is replaced by reasoningConfig: { type: "enabled", maxReasoningEffort }.
  • packages/core/src/variant.ts (claudeInfo): reads the Claude family and version from the id. For an ARN the version is NaN, so the model is treated as a new one (adaptive thinking). That is wrong for Claude 4.5 and older, which need a token budget.
  • packages/core/src/config/plugin/provider.ts:151: variants are only auto-generated when none are configured. That is why declaring variants by hand avoids the problem.
  • packages/ai/src/protocols/utils/claude-model.ts: claudeVersion also reads the id. The compatibility.supportsThinkingBlockBinding override covers this one.

The model already has a family field, and the config accepts it, but the Bedrock variant generator never reads it.

Expected behaviour

Claude behaviour whenever the model is known to be Claude, for example when family is set to a Claude family, whatever the API id looks like.

Suggested fix

Treat the model as Claude when model.family contains "claude", in bedrockConverse and claudeInfo. Add a test in the variant tests using an ARN id with family set. Happy to send a PR if that direction is fine.

Workaround

Declare variants on the model with body.additionalModelRequestFields = { thinking: { type: "adaptive" }, output_config: { effort } }.

Why it matters

Application inference profiles are the supported way to get per-team Bedrock cost and usage tracking, so this blocks that setup.

Related

OpenCode version

2.0.24 (@opencode/cli, source read from the v2 branch)

Steps to reproduce

  1. Configure a Bedrock model whose API id is an application inference profile ARN backed by a Claude model, with family set to a Claude family.
  2. Let variants auto-generate (do not set variants).
  3. Select any effort variant, such as high, and send a message.
  4. Expected: the request carries thinking and output_config. Actual (from reading the code): it carries reasoningConfig, which Bedrock rejects with a 400.

Activity

  1. github-actions commented on Oct 7, 2026

    @github-actions
    Contributor

    This issue appears to overlap with existing Bedrock Claude inference-profile reasoning reports. Please check:

    • #53751: closely related v1 report covering the same ARN-based reasoning-variant failure, plus incorrect system-prompt selection; this issue tracks v2.
    • #31749: earlier report of Claude application inference profile reasoning variants being rejected due to an invalid payload.
    • #10611: earlier report of the same Bedrock Claude inference-profile extended-thinking format mismatch.
  2. opencode-agent commented on Oct 7, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report. I could reproduce this on @opencode/cli 2.0.24.

    Setup: an amazon-bedrock model whose modelID is an application inference profile ARN (arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123), with family: "claude-sonnet" and no variants. I pointed baseURL at a local server that records requests, then ran opencode2 run -m 'amazon-bedrock/team-sonnet#high' "hello".

    The Converse request for the ARN carried additionalModelRequestFields: { reasoningConfig: { type: "enabled", maxReasoningEffort: "high" } }, not the Claude thinking/output_config shape. A regular us.anthropic.claude-sonnet-4-5… id gets the Claude shape, so the configured family is not taken into account. The variant code is unchanged on the current v2 branch. Until this is addressed, declaring variants by hand, as you describe, avoids it.

  3. gillespied commented on Oct 7, 2026

    @gillespied
    Author

    Thanks for reproducing this.

    I have a one-line fix with a test on a fork branch: bedrockConverse in packages/core/src/variant.ts also treats the model as Claude when family contains "claude". The branch is https://github.com/gillespied/opencode/tree/fix/bedrock-arn-claude-variants, based on v2 at 119cb15. The new test in variant.test.ts fails without the change (Nova spelling for an ARN id) and passes with it. I have only checked the variant generator, not a real profile, so your end-to-end repro above is the better check. Happy to open a PR if that's useful, or you can take it from the branch.

    Correction to the issue text: I suggested changing claudeInfo too, but a family name carries no version, so that wouldn't help. Claude 4.5 and older behind an ARN still need explicit variants.

  4. opencode-agent commented on Oct 7, 2026

    @opencode-agent
    Contributor

    You can fix this in config today, without a code change. Use the Bedrock catalog id of the model your profile wraps as the model key, and put the ARN in modelID:

    {
      "providers": {
        "amazon-bedrock": {
          "models": {
            "us.anthropic.claude-sonnet-4-5-20250929-v1:0": {
              "modelID": "arn:aws:bedrock:<region>:<account>:application-inference-profile/<id>"
            }
          }
        }
      }
    }

    Then select it as amazon-bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0#high.

    Why this works: if a configured model's key (or modelID) matches a catalog model, it inherits that catalog entry, including the variants already generated from the real Claude id. Variants are only regenerated from modelID when nothing in the catalog matches. That is the case you hit, where the ARN gets misread as a non-Claude model. modelID still decides what gets sent, so requests go to your profile.

    I checked this on 2.0.24 against a real application inference profile backed by Sonnet 4.5:

    • Custom key, ARN in modelID, family: "claude-sonnet", #high: fails with reasoningConfig: Extra inputs are not permitted. This reproduces your report.
    • Catalog id as the key, same ARN in modelID, #high: works, and reasoning comes back.
    • Catalog id as the key with a bogus ARN: fails with The provided model identifier is invalid. So the profile ARN is what actually gets called.

    If you'd rather keep your own key, declaring variants yourself, as in your workaround, also works.

  5. rekram1-node commented on Oct 8, 2026

    @rekram1-node
    Contributor

    recommend u solve it this way^ for now. I'll look at bedrock im less familiar with these unknown deployments.

  6. andrewcarson commented on Oct 8, 2026

    @andrewcarson

    Keying the model by its exact catalog ID and putting the ARN in modelID fixes the reasoning variants and inherits the right limits. It has one downside with application inference profiles on v2: prompt caching turns off.

    Bedrock Converse decides whether to emit cachePoint blocks from the model ID. BedrockCache.breakpoints(request.model.id) sets supported only when the ID includes anthropic.claude- (packages/ai/src/protocols/utils/bedrock-cache.ts). The same string is also sent to the API as modelId.

    An application inference profile ARN is opaque (…:application-inference-profile/abc123) and has no Claude name in it, so no checkpoints are added.

    The model and reasoning work, but every request is uncached. That costs more and is slower.

    I have a fix on a branch. It adds an arn setting to the Bedrock Converse provider. The model keeps its real ID, and the ARN goes in settings:

    "us.anthropic.claude-sonnet-4-6": {
      "settings": { "arn": "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123" }
    }

    Here the property name is the real model ID. With a custom name, set modelID to the real ID as well:

    "my-sonnet": {
      "modelID": "us.anthropic.claude-sonnet-4-6",
      "settings": { "arn": "arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/abc123" }
    }

    Catalog inheritance, variants and cache detection all use the real ID. opencode sends the ARN to Bedrock as the request's modelId.

  7. florislw commented on Oct 15, 2026

    @florislw

    We hit this too. Caching is off for our Claude application inference profiles on v2, so we're sticking with v1 for now.

    Looks like a regression: v1 fixed the same thing in #9838.

    @andrewcarson, any chance you could open a PR for the settings.arn change? Would be great to have.

  8. florislw commented on Oct 15, 2026

    @florislw

    Another option, possibly smaller than settings.arn: a model compatibility flag for Bedrock cache points, like the ones supportsThinkingBlockBinding and supportsEffortUpdates already have for their checks. The TODO in anthropic-messages.ts about moving capability heuristics into compatibility seems to point the same way.

    Happy to open a PR if that sounds right to you.

  9. rekram1-node commented on Oct 15, 2026

    @rekram1-node
    Contributor

    I'll take a look sorry about that yall

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions