Skip to content

Context & caching

Long-context and agent workloads live or die on three things: knowing the limit, knowing where you stand against it, and getting cache pricing without doing anything special. This page covers all three — plus one promise: we never rewrite or truncate your messages.

Context windows

Every model has a fixed context window covering input tokens plus your max_tokens budget — the provider counts both when deciding whether a request fits, so a prompt that is technically under the window can still be rejected if max_tokens pushes the total over.

ModelContext windowNotes
deepseek-v4-flash · deepseek-v4-pro1,048,576 tokens1M-class
kimi-k2.6 · kimi-k2.7-code · glm-5.2 · qwen3.8-27b262,144 tokens256K-class
glm-4.7-flash131,072 tokens128K-class

Working near 1M tokens

On the 1M-class models, prefill is real work: we measured roughly 45 ms per 1,000 input tokens on deepseek-v4-flash (a 600K-token prompt takes over a minute to first token), and deepseek-v4-pro can queue for longer under load. Use streaming for anything large, and expect 429 no_capacity at peak times on very large requests — it is retryable.

The live list is on the models page and in GET /v1/models. Output length is separately capped by max_tokens (16,384 per request by default for an organization).

When a request is too large

Oversized requests fail fast with 400 context_length_exceeded — rejected before any generation starts, so nothing is billed. The message carries the estimated total and the limit:

error
# 400 context_length_exceeded
{
  "error": {
    "message": "Estimated 332876 tokens (input + max_tokens) exceeds the model context window of 262144 tokens. Reduce message length or max_tokens.",
    "type": "invalid_request_error",
    "code": "context_length_exceeded",
    "param": null
  }
}
  • Do not retry as-is. The same payload gets the same rejection on every attempt. Shorten the conversation or lower max_tokens, then retry.
  • The gate is an estimate. The rejection threshold is computed from an approximation, not an exact tokenizer pass — treat the numbers as a firm boundary with a little fuzz, and keep headroom instead of engineering to the exact token.

Counting tokens before you send

POST /v1/count_tokens returns an estimate for your messages without touching the model — free, no rate-limit charge, nothing billed:

curl
curl https://api.clfaigateway.dev/v1/count_tokens \
  -H "Authorization: Bearer sk-gw-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kimi-k2.6",
    "messages": [{"role": "user", "content": "Summarize this repository..."}]
  }'

# 200
{
  "object": "token_count",
  "model": "kimi-k2.6",
  "estimated": true,
  "method": "chars-per-model",
  "estimated_input_tokens": 1210,
  "context_window": 262144
}

The estimate is ceil(total content characters / 4) — the same family of approximation the provider uses at its gate, which is why we mirror it instead of shipping a tokenizer that would disagree with the gatekeeper. It is labeled "estimated": true and the honest error bars, measured against real usage, are:

Content typeEstimate vs real
English prose+22% to +28% (over-estimates — safe)
Vietnamese on GLM modelswithin ±2%
Source code−3% to −7% (Kimi/GLM) · −18% to −35% (DeepSeek)
JSON / numeric data−16% to −23% (Kimi/GLM) · −26% to −40% (DeepSeek)
Vietnamese on Kimi modelswithin a few % — the estimator uses each model’s own ratio
Vietnamese on DeepSeek modelswithin a few % — same

Vietnamese prompts cost more on some models — the estimate already knows

Kimi tokenizes Vietnamese at roughly 1.8 characters per token and DeepSeek at roughly 2.4, against about 4.1 on GLM and 4.5 on Qwen. The same paragraph therefore costs about 2.2× more input tokens on Kimi than on GLM — that is a real price difference, not an estimation artefact. Since 2026-08-18 the estimator applies each model’s measured ratio to Vietnamese text, so you no longer need to double anything by hand; if input cost matters on Vietnamese workloads, the routing choice is what to think about.

Context headers on every response

HeaderWhen presentMeaning
x-gw-context-windowEvery response once the model is resolved, including streams and errorsThe context window of the model that served (or rejected) the request
x-gw-prompt-tokens / x-gw-cached-tokens / x-gw-completion-tokensNon-streaming responses and cache hitsUsage of this request, matching the usage object token-for-token. Streams send headers before usage exists — read the final chunk instead.

Automatic prefix caching

Prompt caching is automatic. There is no field to set and no header to send — repeated prompt prefixes are served from the provider cache and billed at the cheaper cached_input rate (see live pricing) wherever your requests land.

Coming from Anthropic or OpenAI?

There is no cache_control block and no cache TTL to manage. Send plain OpenAI-format messages; caching happens on its own. Unknown top-level request fields are rejected with unknown_parameter rather than silently ignored.

qwen3.8-27b: no cached-input discount today

Prefix caching is not active for this model in our measurements (repeating an identical 150K-token prompt after 60 s returned zero cached tokens), and no separate cached rate is published upstream. So we price cached input the same as regular input rather than advertising a saving that would not arrive. Prefill is also slower here — roughly 165–195 ms per 1,000 input tokens — so a very large prompt takes real time before the answer starts. We re-check regularly; if a cache rate becomes real, the models page shows it the moment it applies.

DeepSeek V4: cached pricing listed, cache not active yet

The cached_input price for the DeepSeek V4 models is published and wired up, but as of 2026-08-16 our measurements show the upstream prefix cache is not serving hits for them yet (repeating an identical 300K-token prompt after 60 s returned zero cached tokens). You are never charged the cached rate incorrectly — it simply applies automatically the moment the upstream cache goes live. We re-check regularly; this note will be removed when it lands.

  • Cache granularity is 64-token blocks — very short prompts do not cache; the win starts at a few hundred tokens of stable prefix.
  • Cached prefixes stay warm for at least an hour of reuse, which covers chat sessions and agent loops comfortably.
  • Keep your prefix byte-stable to earn it: fixed system prompt first, append-only history, and no timestamps, request ids, or random values near the top of the conversation. One changed byte early in the prompt invalidates every block after it.
  • Tool definitions are serialized deterministically by the gateway (stable key order), so identical tool sets never break your cache by accident.

We never modify your messages

The gateway forwards messages exactly as you sent them — no truncation, no summarization, no middle-out compression, ever, not even as an opt-in. A request that does not fit fails loudly with the error above instead of being silently trimmed into a different question. Context management strategies (sliding windows, summarizing old turns) belong in your application, where you know what matters; this API guarantees the model sees exactly what you sent.