Skip to content

feat(ai): default claude-* models to automatic Anthropic prompt caching - #3923

Merged
Yeachan-Heo merged 12 commits into
devfrom
feat/automatic-caching-default-for-anthropic-models
Aug 6, 2026
Merged

feat(ai): default claude-* models to automatic Anthropic prompt caching#3923
Yeachan-Heo merged 12 commits into
devfrom
feat/automatic-caching-default-for-anthropic-models

Conversation

@Yeachan-Heo

@Yeachan-Heo Yeachan-Heo commented Aug 6, 2026

Copy link
Copy Markdown
Owner

What

Claude-family models routed through non-canonical Anthropic-compatible gateways (Cloudflare AI Gateway, GitHub Copilot, GitLab Duo, Vercel AI Gateway, zenmux, ...) previously received no generated prompt-cache markers, so long agentic sessions paid full input cost on every turn. This PR makes the anthropic-messages provider emit Anthropic's automatic caching (cache_control: { type: "ephemeral" } at the request top level, per platform.claude.com prompt-caching docs) for every claude-* model id — the same default canonical api.anthropic.com already had.

Behavior

Model / endpoint Before After
claude-* on api.anthropic.com automatic, ttl: "1h" unchanged
claude-* on non-canonical gateway no caching automatic {type:"ephemeral"} (default ~5m)
claude-* gateway + compat.supportsLongCacheRetention: true no caching automatic {type:"ephemeral", ttl:"1h"}
non-claude-* on unknown endpoint no caching unchanged

Escape hatches preserved: compat.promptCacheMode: "none" | "explicit" and per-request cacheRetention: "none" still win. Classification keys off the dispatched model.id (last path segment, case-insensitive claude- prefix) — wireModelId is inert for this transport, so the cache decision always describes the model actually posted.

Changes

  • packages/ai/src/providers/anthropic.tsisClaudeFamilyModel helper; getCacheControl mode is now automatic for isCanonicalApi || isClaudeFamilyModel(model)
  • packages/ai/src/types.tspromptCacheMode JSDoc updated
  • packages/ai/test/anthropic-cache.test.ts — defaults test extended + new table-driven mode/identifier matrix (prefixed/uppercase ids, long-retention opt-in, both opt-outs, -claude- false positive, wire-id inertness)
  • packages/ai/test/anthropic-stream-envelope.test.ts — cache TTL cases extended
  • packages/ai/CHANGELOG.md — Unreleased entry
  • artifacts/issue-3670-anthropic-cache-eval.json — regenerated source-identity pins

Verification

  • bun test targeted suites: cache 10, stream-envelope 26, alignment 47, issue-814 2, cache-eval write+validate 2+2 — 89 pass / 0 fail; 11/11 adversarial payload probes
  • bun --cwd=packages/ai run check (biome + tsc) clean
  • Ultragoal boundary cohort (generation 2, frozen sha256:f92bc40c…): cleaner PASS, architect CLEAR/APPROVE, executor QA passed, terminal critic OKAY
  • Note: repo-wide check:ts has one pre-existing failure in verify-gjc-sdk-canonicalization.ts --self-test (stale fixture expects exit 1 where verification now passes); reproduces on the base commit and in the parent checkout, unrelated to this diff (verified: no non-packages/ai/artifacts files changed)

Review follow-up

  • Addressed Codex P1 in 9dc8a8d9c: custom anthropic-messages endpoints can configure compat.promptCacheMode (none, explicit, automatic) and compat.supportsLongCacheRetention at provider, model, and model-override levels. Generated schema + focused validation and registry propagation tests included.

  • Synced the branch with current dev in merge commit b3f7ba2a3; GitHub now reports the PR mergeable.

  • Final independent review found and fixed GitLab Duo retention precedence in 4c71ba5db: Anthropic cache resolution now falls back to model.cacheRetention at the provider boundary, so special dispatch wrappers preserve configured none and explicit request options still win. Added a GitLab Duo payload regression; eval identity refreshed in 9c8cc8328.

Yeachan-Heo added 4 commits August 6, 2026 15:08
Claude-family models routed through non-canonical Anthropic-compatible
gateways (Cloudflare AI Gateway, GitHub Copilot, GitLab Duo, Vercel AI
Gateway, zenmux, ...) previously received no generated cache markers, so
long agentic sessions paid full input cost on every turn. The provider now
emits top-level `cache_control: { type: "ephemeral" }` (automatic caching
per platform.claude.com prompt-caching docs) for any claude-* model id,
matching the canonical-API default. Non-Claude models on unknown compatible
endpoints keep the no-cache default; `promptCacheMode: none|explicit` and
per-request `cacheRetention: none` still opt out. Non-canonical endpoints
keep the default ~5m cache lifetime unless they opt into
`supportsLongCacheRetention`.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
Tested: anthropic-cache, anthropic-stream-envelope, anthropic-alignment, issue-814 repro, biome, ai typecheck
Regenerate artifacts/issue-3670-anthropic-cache-eval.json so the pinned
providerSourceBlobOid/providerSourceSha256 match the committed
anthropic.ts after the automatic-caching default change.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
The automatic-caching classifier previously read `wireModelId ?? id`
while the Anthropic transport serializes `params.model = model.id`, so a
custom model with a differing wire id could get a cache decision for a
different model than the one dispatched. Classify `model.id` only and add
a table-driven matrix covering prefixed/uppercase claude ids, non-canonical
long-retention opt-in, promptCacheMode none, cacheRetention none,
`-claude-` false positives, and wire-id override inertness.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
Tested: anthropic-cache suite (10 tests), packages/ai check (biome + tsc)
Regenerate artifacts/issue-3670-anthropic-cache-eval.json so the pinned
provider source identity matches the classifier change in 483ba5f.

Confidence: high
Scope-risk: narrow
Reversibility: trivial

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 00d32034bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/ai/src/providers/anthropic.ts Outdated
Comment on lines 474 to 475
: isCanonicalApi || isClaudeFamilyModel(model)
? "automatic"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Gate automatic caching on endpoint capability

When a user-defined anthropic-messages endpoint exposes a claude-* model but rejects top-level cache_control and requires block-level markers, this identifier-only default now makes every request fail upstream. The updated AnthropicCompat documentation explicitly recognizes such endpoints and recommends promptCacheMode: "explicit", but the coding-agent models configuration still validates compat with OpenAICompatSchema, which does not admit promptCacheMode, so CLI users cannot select that advertised mode (short of disabling caching entirely with cacheRetention: "none"). Restrict this default to known-capable endpoints or expose the Anthropic compatibility setting through the configuration schema.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 9dc8a8d. The shared models compatibility schema now admits compat.promptCacheMode (none, explicit, automatic) and compat.supportsLongCacheRetention at provider, model, and model-override levels; the generated schemas/models.schema.json is updated. Focused schema validation and ModelRegistry propagation/precedence tests cover all three configuration levels. The branch is also merged with current dev, and Anthropic/config/package checks are clean.

Yeachan-Heo added 2 commits August 6, 2026 16:02
Automatic caching for claude-* models must remain configurable on custom
Anthropic-compatible endpoints that reject top-level cache_control or lack
one-hour retention. The models config schema previously admitted only the
OpenAI compatibility fields, making the documented promptCacheMode escape
hatch unavailable to CLI users.

Expose promptCacheMode and supportsLongCacheRetention through the shared
model compatibility schema at provider, model, and model-override levels,
regenerate models.schema.json, and lock propagation/validation with focused
tests.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
Tested: models config Anthropic cache compat, focused model registry propagation, coding-agent biome + tsc
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b3f7ba2a36

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

});

test("generated JSON schema exposes Anthropic prompt-cache compatibility", async () => {
const schema = (await import("../../../schemas/models.schema.json")) as Record<string, unknown>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Move the generated-schema import to the top level

This new test uses await import() even though the repository contract explicitly prohibits inline imports and requires top-level imports; import the JSON schema statically instead.

AGENTS.md reference: AGENTS.md:L101-L105

Useful? React with 👍 / 👎.

Comment thread packages/ai/src/providers/anthropic.ts Outdated
Comment on lines 474 to 476
: isCanonicalApi || isClaudeFamilyModel(model)
? "automatic"
: "none";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor the explicit automatic cache mode

When a non-Claude model on a noncanonical Anthropic-compatible endpoint sets the newly accepted compat.promptCacheMode: "automatic", this ternary ignores that value and falls through to the model-name classifier, selecting "none" and emitting no cache marker. This makes the only meaningful opt-in use of automatic ineffective for custom identifiers; handle promptCacheMode === "automatic" before applying the endpoint/model defaults.

Useful? React with 👍 / 👎.

Yeachan-Heo added 2 commits August 6, 2026 16:11
The compatibility schema now exposes promptCacheMode to custom endpoints,
so the automatic enum value must actively opt a non-Claude, non-canonical
Anthropic-compatible model into top-level caching instead of falling through
to the conservative none default.

Honor the explicit automatic mode, lock it with a payload test, and update
the models configuration guidance and generated docs index.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
Tested: focused Anthropic/config/registry tests, packages/ai biome + tsc
Regenerate the Anthropic cache-eval source identity after the explicit
automatic prompt-cache mode change.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: de8d673a4c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Keep the Anthropic cache-compat schema regression test within the repo's
top-level-import contract while preserving the generated-schema assertions.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
Tested: focused schema test, Biome, coding-agent typecheck
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 95713183bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Yeachan-Heo added 2 commits August 6, 2026 16:48
GitLab Duo dispatches before the shared option mapper, so a configured
model.cacheRetention value was not forwarded to Anthropic. With automatic
Claude-family caching, that could silently turn cacheRetention:none into an
ephemeral cache marker.

Resolve request-over-model retention at the Anthropic cache-control boundary
and cover GitLab Duo's special dispatch for both configured none and an
explicit request override.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
Tested: 86 Anthropic/GitLab tests, packages/ai biome + tsc
Regenerate the Anthropic cache-eval source identity after moving model cache
retention fallback to the provider boundary.

Confidence: high
Scope-risk: narrow
Reversibility: trivial
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 9c8cc83284

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…-default-for-anthropic-models

# Conflicts:
#	packages/coding-agent/src/internal-urls/docs-index.generated.ts
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.

1 participant