Skip to content

setCacheKey sends promptCacheKey (wrong) instead of cache_control on content blocks for openai-compatible Bedrock proxies (Bifrost, LiteLLM) #25984

@KTS-o7

Description

@KTS-o7

Description

When setCacheKey: true is configured on an @ai-sdk/openai-compatible provider that routes to AWS Bedrock Claude models (via proxies like Bifrost or LiteLLM), OpenCode sends a promptCacheKey request option — which these proxies ignore entirely. No prompt caching occurs.

Root cause in transform.tsoptions() (~line 1008):

if (input.model.providerID === "openai" || input.providerOptions?.setCacheKey) {
  result["promptCacheKey"] = input.sessionID
}

promptCacheKey is an OpenAI-native caching hint. Bifrost and LiteLLM (when routing to Bedrock/Anthropic) require cache_control: { type: "ephemeral" } injected as a property on message content blocks — the Anthropic-style caching format that both proxies accept and translate to the native backend format.

applyCaching() already knows how to inject openaiCompatible: { cache_control: { type: "ephemeral" } } onto content blocks, but message() never calls it for @ai-sdk/openai-compatible providers. Additionally, string system messages fall through to message-level providerOptions injection (not content-block level), which the @ai-sdk/openai-compatible SDK spreads as a top-level message field rather than a content block property — Bifrost ignores this for caching.

Correct wire format (required by Bifrost and LiteLLM for Bedrock/Anthropic routing):

{
  "messages": [
    {
      "role": "system",
      "content": [
        { "type": "text", "text": "...", "cache_control": { "type": "ephemeral" } }
      ]
    },
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "...", "cache_control": { "type": "ephemeral" } }
      ]
    }
  ]
}

Plugins

None

OpenCode version

Latest (dev branch)

Steps to reproduce

  1. Configure an @ai-sdk/openai-compatible provider pointing to Bifrost or LiteLLM routing to Bedrock Claude:
{
  "provider": {
    "bifrost": {
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "baseURL": "http://localhost:24242/v1",
        "setCacheKey": true
      },
      "models": {
        "claude-sonnet-4-6": {
          "id": "bedrock/global.anthropic.claude-sonnet-4-6"
        }
      }
    }
  }
}
  1. Start a session and send a message with a large system prompt.
  2. Inspect the outgoing request body (e.g., via Bifrost debug logs or a proxy like Wireshark/mitmproxy).
  3. Observe: request contains promptCacheKey at top level — no cache_control on content blocks.
  4. Expected: cache_control: { type: "ephemeral" } on the last content block of the system message and targeted user messages.

Screenshot and/or share link

PR with fix: #25985

Operating System

macOS 15.4 (Darwin arm64)

Terminal

Ghostty

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions