> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opper.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompt caching

> Reuse a large, stable prompt prefix across calls to cut cost and latency on Anthropic models. Opt-in, one field.

When you send the same long prefix — a big system prompt, a document, a tool catalog — on call after call, prompt caching lets the provider store that prefix and skip re-processing it next time. On Anthropic (Claude) models this is a real, billable feature: a **cache read costs 0.1×** the normal input price, so a reused prefix gets \~90% cheaper and comes back faster.

It isn't free, though. Writing the cache costs **1.25×** input, and Anthropic's cache entries expire after **5 minutes** (extendable to 1 hour). So caching only pays off when the same prefix comes back **within the cache lifetime**. If your calls are minutes apart with no reuse, you'd pay the 1.25× write premium every time and never collect the discount.

Because of that trade-off, **Opper leaves prompt caching off by default** and lets you turn it on per request. You decide, because only you know whether your prefix repeats.

<Note>
  This page is about **Anthropic** prompt caching. **OpenAI** and **Gemini** cache automatically, server-side, at no extra cost and with no flag — there's nothing to enable. The `cache_control` field below is a no-op on those providers, so the same request stays portable across models.
</Note>

## Enable it: top-level `cache_control`

Add a top-level `cache_control` to the request body. Opper places a single **moving breakpoint** on the largest cacheable prefix and advances it as the conversation grows — the "automatic" mode, best for multi-turn chats and agent loops.

<CodeGroup>
  ```python OpenAI SDK theme={null}
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.opper.ai/v3/compat",
      api_key=os.environ["OPPER_API_KEY"],
  )

  resp = client.chat.completions.create(
      model="anthropic/claude-sonnet-4-6",
      messages=[
          {"role": "system", "content": LONG_STABLE_SYSTEM_PROMPT},
          {"role": "user", "content": "What changed in the latest revision?"},
      ],
      extra_body={"cache_control": {"type": "ephemeral"}},
  )
  ```

  ```typescript OpenAI SDK theme={null}
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.opper.ai/v3/compat",
    apiKey: process.env.OPPER_API_KEY,
  });

  const resp = await client.chat.completions.create({
    model: "anthropic/claude-sonnet-4-6",
    messages: [
      { role: "system", content: LONG_STABLE_SYSTEM_PROMPT },
      { role: "user", content: "What changed in the latest revision?" },
    ],
    // @ts-expect-error — Opper extension, passed through to the model
    cache_control: { type: "ephemeral" },
  });
  ```

  ```bash cURL theme={null}
  curl https://api.opper.ai/v3/compat/chat/completions \
    -H "Authorization: Bearer $OPPER_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "anthropic/claude-sonnet-4-6",
      "cache_control": { "type": "ephemeral" },
      "messages": [
        { "role": "system", "content": "…long stable system prompt…" },
        { "role": "user", "content": "What changed in the latest revision?" }
      ]
    }'
  ```
</CodeGroup>

The top-level field works on every Anthropic-routable compat endpoint: `chat/completions`, `v1/messages`, `responses`, `openresponses`, and the Google-shape `interactions` / `generateContent`.

### Extend the lifetime to 1 hour

Add a `ttl`. Useful when your prefix is reused over minutes rather than seconds (a long research session, a slow agent).

```json theme={null}
{ "cache_control": { "type": "ephemeral", "ttl": "1h" } }
```

## Precise placement: per-block `cache_control`

For fine control over exactly where the cached prefix ends, put `cache_control` directly on a content block instead of the top level. Anthropic allows up to **four** such breakpoints. This is the same syntax the Anthropic API uses natively, so existing code works unchanged.

Per-block placement is supported on **`chat/completions`** (OpenAI shape) and **`v1/messages`** (Anthropic shape):

<CodeGroup>
  ```python OpenAI SDK theme={null}
  resp = client.chat.completions.create(
      model="anthropic/claude-sonnet-4-6",
      messages=[
          {
              "role": "user",
              "content": [
                  {
                      "type": "text",
                      "text": BIG_DOCUMENT,               # cache everything up to here
                      "cache_control": {"type": "ephemeral"},
                  },
                  {"type": "text", "text": "Summarize the section on billing."},
              ],
          }
      ],
  )
  ```

  ```python Anthropic SDK theme={null}
  from anthropic import Anthropic

  client = Anthropic(
      base_url="https://api.opper.ai/v3/compat",
      api_key=os.environ["OPPER_API_KEY"],
  )

  message = client.messages.create(
      model="anthropic/claude-sonnet-4-6",
      max_tokens=1024,
      system=[
          {
              "type": "text",
              "text": LONG_STABLE_SYSTEM_PROMPT,
              "cache_control": {"type": "ephemeral"},   # cache the system prompt
          }
      ],
      messages=[{"role": "user", "content": "What changed in the latest revision?"}],
  )
  ```
</CodeGroup>

If you set both a top-level `cache_control` and explicit per-block breakpoints, the **per-block breakpoints win** — Opper won't add its automatic one on top.

## When it's worth it

<CardGroup cols={2}>
  <Card title="Turn it on" icon="circle-check">
    A large, stable prefix (system prompt, document, tool catalog) reused across back-to-back calls — agent loops, multi-turn chat, batch jobs over one context.
  </Card>

  <Card title="Leave it off" icon="circle-xmark">
    One-shot calls, or calls spaced further apart than the cache lifetime. You'd pay the 1.25× write premium with no read to recoup it.
  </Card>
</CardGroup>

Every response reports what actually happened via its usage: `cache_creation_input_tokens` (written at 1.25×) and `cache_read_input_tokens` (read at 0.1×). Watch those to confirm caching is paying off — reads should dominate writes once your prefix starts repeating.

## Reference

* **Field:** `cache_control` — top-level (automatic) or on a content block (explicit).
* **Value:** `{ "type": "ephemeral" }`, optionally `"ttl": "1h"` (default is 5 minutes).
* **Activates on:** Anthropic-family models. No-op on OpenAI / Gemini (they cache automatically).
* **Pricing:** cache write 1.25× input, cache read 0.1× input.
* **Breakpoints:** up to 4 explicit per-block; or 1 automatic top-level.
