Skip to content

fix: preserve unknown fields in Anthropic schemas (restores prompt caching)#74

Merged
sgasser merged 3 commits intosgasser:mainfrom
raseidl:fix/anthropic-passthrough-cache-control-clean
Feb 27, 2026
Merged

fix: preserve unknown fields in Anthropic schemas (restores prompt caching)#74
sgasser merged 3 commits intosgasser:mainfrom
raseidl:fix/anthropic-passthrough-cache-control-clean

Conversation

@raseidl
Copy link
Contributor

@raseidl raseidl commented Feb 27, 2026

Problem

Clients that rely on prompt caching experienced dramatically higher token usage when routing through PasteGuard. Every request was billed as if the full system prompt and tool definitions were new input, rather than being served from cache.

Root Cause

PasteGuard validates incoming requests using Zod schemas. Only the top-level AnthropicRequestSchema used .passthrough(), but all nested schemas — TextBlockSchema, AnthropicMessageSchema, ToolSchema, and others — did not.

Zod strips unknown fields by default. This silently removed cache_control: { "type": "ephemeral" } from content blocks, system prompt blocks, tool definitions, and messages before they were forwarded upstream. Without these fields, the API receives no cache breakpoints and prompt caching is disabled entirely.

The OpenAI schemas already handled this correctly via OpenAIMessageSchema.passthrough().

Fix

Add .passthrough() to all nested z.object() schemas in src/providers/anthropic/types.ts, matching the OpenAI implementation. This ensures any fields PasteGuard does not explicitly declare are passed through unchanged.

Tests

Added regression tests covering:

  • cache_control preservation through Zod parsing on text blocks, system blocks, tools, and messages
  • cache_control survival through the full applyMasked round-trip in the extractor

@raseidl raseidl marked this pull request as ready for review February 27, 2026 09:44
Copy link
Owner

@sgasser sgasser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this @raseidl!

Clean fix, good test coverage, and the root cause analysis in the PR description is really helpful.

- Add biome-ignore comments to suppress noExplicitAny in tests
  (required for testing unknown field preservation)
- Add .passthrough() to OpenAI schemas for consistency
  (OpenAIMessageSchema, OpenAIContentPartSchema)
- Format Anthropic schemas to match project style
- Schema tests for name, tool_calls, audio content, unknown fields
- Extractor tests for field preservation through applyMasked
@sgasser sgasser merged commit 9e8006a into sgasser:main Feb 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants