Skip to content

Anthropic /v1/messages rejects cache_control.scope that Anthropic direct accepts #1589

@camwest

Description

@camwest

What Happened?

Portkey's Anthropic-compatible /v1/messages endpoint rejects a request body that Anthropic direct accepts.

The incompatibility appears to be cache_control.scope = "global" on a system content block when using Claude Code / Claude Agent SDK prompt caching scope betas.

Observed behavior:

  • Direct Anthropic: 200 OK
  • Portkey /v1/messages: 400 invalid_request_error
  • Error: anthropic error: system.1.cache_control.ephemeral.scope: Extra inputs are not permitted

This is breaking Claude Code / Claude Agent SDK traffic routed through Portkey for us.

What Should Have Happened?

Portkey should accept and forward the same Anthropic-compatible request body that Anthropic direct accepts, including cache_control.scope = "global" when the request uses Anthropic's prompt-caching-scope beta.

Relevant Code Snippet

Minimal raw repro:

const body = {
  model: 'claude-opus-4-6',
  max_tokens: 32,
  system: [
    {
      type: 'text',
      text: "You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK.",
    },
    {
      type: 'text',
      text: 'Session-specific guidance. Reply with ok.',
      cache_control: { type: 'ephemeral', scope: 'global' },
    },
  ],
  messages: [
    { role: 'user', content: [{ type: 'text', text: 'Reply with ok.' }] },
  ],
  stream: false,
};

const anthropicBeta =
  'claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,effort-2025-11-24';

Direct Anthropic request:

curl https://api.anthropic.com/v1/messages \
  -H 'content-type: application/json' \
  -H 'anthropic-version: 2023-06-01' \
  -H "anthropic-beta: $ANTHROPIC_BETA" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -d "$BODY"

Result:

{
  "status": 200,
  "content": [{ "type": "text", "text": "ok" }]
}

Portkey request with a single Anthropic target:

curl https://api.portkey.ai/v1/messages \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer dummy' \
  -H 'anthropic-version: 2023-06-01' \
  -H "anthropic-beta: $ANTHROPIC_BETA" \
  -H "x-portkey-api-key: $PORTKEY_API_KEY" \
  -H 'x-portkey-config: {"strategy":{"mode":"fallback","on_status_codes":[429,500,502,503,529]},"targets":[{"virtual_key":"anthropic-default-prod","override_params":{"model":"claude-opus-4-6"}}]}' \
  -d "$BODY"

Result:

{
  "error": {
    "message": "anthropic error: system.1.cache_control.ephemeral.scope: Extra inputs are not permitted",
    "type": "invalid_request_error"
  },
  "provider": "anthropic"
}

Additional context:

  • @anthropic-ai/claude-agent-sdk@0.2.89
  • claude-cli/2.1.89
  • This field is emitted by Claude Code / Agent SDK request construction, not by our application prompt builder.
  • Portkey docs appear to document cache_control.type and ttl, but I could not find mention of cache_control.scope.

If helpful, I can provide a fully self-contained Node repro as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions