Skip to content

[Bug]: Bedrock cacheRetention: "long" sends unsupported ttl: "1h" to models that only support 5-min TTL #21986

@snese

Description

@snese

Related Issues

Problem

When cacheRetention: "long" is configured for a Bedrock Claude model, the pi-ai provider unconditionally injects ttl: { ttl: "1h" } into cache points. However, only a subset of Claude models on Bedrock support 1-hour TTL. All others reject the request with an API error, breaking the agent turn entirely.

Additionally, the config auto-injection logic (which sets cacheRetention: "short" as default) only runs for provider === "anthropic", skipping amazon-bedrock. Users running Claude on Bedrock don't get prompt caching defaults unless they manually configure it.

PR #20866 correctly disables caching for non-Anthropic Bedrock models but doesn't address either of these issues.

Reproduction

  1. Set config:
{
  "amazon-bedrock/us.anthropic.claude-opus-4-1-v1": {
    "params": { "cacheRetention": "long" }
  }
}
  1. Send any message → API error:
"Extra inputs are not permitted"

Same error for Claude Opus 4.0, Sonnet 4.0, 3.7 Sonnet, 3.5 Haiku, 3.5 Sonnet v2.

For Nova models with cacheRetention: "long":

"Extended TTL prompt caching is only supported for Anthropic models"

Expected Behavior

cacheRetention: "long" should gracefully degrade to "short" (5-min TTL) for models that don't support 1-hour TTL, instead of causing an API error.

Models Supporting 1-Hour TTL (per AWS docs)

Only these Bedrock models accept ttl: "1h":

  • Claude Opus 4.5+
  • Claude Sonnet 4.5
  • Claude Haiku 4.5

All other Claude models (Opus 4.0/4.1, Sonnet 4.0, 3.7 Sonnet, 3.5 Haiku/Sonnet) support only 5-min TTL.

Proposed Fix

These two issues belong in different layers:

1. supportsExtendedTTL guard → upstream pi-ai (amazon-bedrock.ts)

TTL support is a Bedrock API constraint, not openclaw business logic. pi-ai's streamBedrock already has supportsPromptCaching() as a model-level gate — supportsExtendedTTL is the same category of concern. Placing it in pi-ai means all consumers get the fix, rather than each one needing to wrap around the provider (as PR #20866 does for the Nova case).

function supportsExtendedTTL(modelId: string): boolean {
  const id = modelId.toLowerCase();
  if (!id.includes("anthropic") || !id.includes("claude")) return false;
  const m = id.match(/claude-(?:opus|sonnet|haiku)-4-(\d{1,2})(?:-\d{8}|-v)/);
  return m ? parseInt(m[1], 10) >= 5 : false;
}

In streamBedrock, downgrade "long""short" when !supportsExtendedTTL(model).

2. Config auto-injection → openclaw (config-*.ts)

This is openclaw's own config migration logic. The provider gate just needs to also accept "amazon-bedrock" (filtered to Anthropic Claude models via isAnthropicBedrockModel from PR #20866):

// Current:
if (!parsed || parsed.provider !== "anthropic") continue;

// Fix:
if (!parsed || (parsed.provider !== "anthropic" && parsed.provider !== "amazon-bedrock")) continue;

Environment

  • OpenClaw: 2026.2.19-2
  • Provider: amazon-bedrock
  • Model: us.anthropic.claude-opus-4-6-v1 (and tested against Opus 4.1, Nova Micro)

Workaround

Local patch to amazon-bedrock.js adding supportsExtendedTTL() and effectiveCacheRetention() that downgrades "long""short" for unsupported models. Manual params.cacheRetention in config.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleMarked as stale due to inactivity

    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