Capabilities

Prompt caching

Use provider-supported prompt caching and read cache usage without assuming a universal cache control.

Caching depends on the model and provider route. Some providers cache repeated prefixes implicitly; others take explicit cache points. The response's cache read and write usage shows what a request hit.

Explicit cache points

json
{"type":"text","text":"Reusable instructions for this task.","cache_control":{"type":"ephemeral"}}

Use an eligible native route and its supported content form. The Anthropic and Converse adapters support ephemeral five-minute caching; one-hour cache TTL is refused. Do not add cache controls to every route indiscriminately.

Usage and cost

Read the provider-reported cache read and write usage and the model's cache prices. Cache writes can be priced differently from ordinary input. An inbound Responses prompt_cache_key is ignored and listed in the ignored-fields header.

Keep the same provider route when comparing repeat requests. See Cost and Provider routing.

Compare a cold and warm prefix

Choose a ready provider route and keep it fixed. This example makes exactly two paid calls when run; use it only within your authorized allowance. The first request may create cache entries; read the repeat's cache counters to confirm a hit. Preserve errors instead of automatically retrying them.

python
import json, os, urllib.request

prefix = "\n".join(
    f"Reference item {i}: code ITEM-{i:04d}; stock {i % 31}."
    for i in range(300)
)
body = {
    "model": "deepseek/deepseek-v4-pro",
    "provider": {"only": ["alibaba-model-studio"], "allow_fallbacks": False},
    "messages": [{"role": "user", "content": prefix + "\nReturn only the stock of item 299."}],
    "max_tokens": 4000,
}
for label in ("cold", "warm"):
    request = urllib.request.Request(
        "https://tokenhub-api.belive.sg/api/v1/chat/completions",
        data=json.dumps(body).encode(),
        headers={"Authorization": "Bearer " + os.environ["TOKENHUB_API_KEY"],
                 "Content-Type": "application/json"},
    )
    with urllib.request.urlopen(request, timeout=120) as response:
        result = json.load(response)
        generation_id = response.headers.get("X-Generation-Id")
    usage = result.get("usage", {})
    details = usage.get("prompt_tokens_details", {})
    print(label, generation_id, "read", details.get("cached_tokens"),
          "write", details.get("cache_write_tokens"))

The named provider must be ready in your catalogue; select a compatible ready route before running, not as a fallback after a failed request. The counters are what the provider reports for your request; they are not minimum cache thresholds or promised savings.

Read each request's generation receipt for settled cost. Cache reads and writes can have different prices; do not multiply all prompt tokens by the uncached rate and then add the cached portion again. Missing cache counters mean unavailable evidence, not a proven miss or free usage.