Last reviewed: October 9, 2026
DeepSeek Context Caching is DeepSeek’s automatic API-side caching system for repeated prompt prefixes. When later requests reuse context that DeepSeek has already persisted, those input tokens can be billed as cache hits instead of cache misses, which can reduce cost and improve latency for long, repetitive workloads.
You do not need to enable DeepSeek Context Caching manually. DeepSeek documents automatic caching without code changes. Your application still needs stable reusable prefixes and a way to measure actual cache hits. The separate user_id field controls isolation; it is not a cache activation switch. Context Caching guide; Rate Limit & Isolation.
This guide explains how cache hits work, how to read prompt_cache_hit_tokens and prompt_cache_miss_tokens, how V4.1 Flash pricing treats cached input, and how to structure repeated workloads. It also shows how to pass user_id correctly through the OpenAI Python SDK without confusing isolation with cache setup.
Quick answer: does DeepSeek Context Caching need setup?
No. DeepSeek Context Caching runs automatically on the API side. You do not need to call a separate cache endpoint, add a cache-control parameter, or change your interface to turn it on.
However, automatic does not mean every repeated phrase becomes a cache hit. DeepSeek’s cache is prefix-based. Current documentation explains that each request can create persisted cache prefix units, and a later request can hit the cache only when it fully matches a persisted prefix unit. Repeated text that appears only in the middle of a different prompt should not be treated as a guaranteed cache hit.
| Question | Answer |
|---|---|
| Do I need to enable it? | No. DeepSeek says Context Caching is enabled by default. |
| Do I need different code? | No for basic usage. You use the normal API request path. |
| How do I know it worked? | Read usage.prompt_cache_hit_tokens and usage.prompt_cache_miss_tokens. |
| Does it reduce output cost? | No. It affects cached input tokens. Output tokens are still billed as output. |
| Are cache hits guaranteed? | No. DeepSeek describes the cache as best-effort. |
| What matters most? | Stable reusable prefixes, repeated workloads, and measuring actual hit/miss tokens. |
What DeepSeek Context Caching actually does
DeepSeek Context Caching stores reusable prompt prefixes on disk so later requests can reuse previously processed context instead of recomputing everything from scratch. The original DeepSeek announcement called this “Context Caching on Disk” and described it as a way to reduce latency and cost for repetitive API usage. DeepSeek Context Caching announcement
In practical terms, this is useful when your application repeatedly sends the same long instructions, same document, same repository context, same few-shot examples, or same conversation history before asking a new question.
The Context Caching guide describes persisted prefix units created at request boundaries, when common prefixes are detected, and at fixed token intervals for long inputs or outputs. This is not a cache of complete answers: the model still generates a response after reusing available input processing. Cache persistence and hit rules.
How cache hits work: the prefix rule
The most important rule is simple: design your prompts so the repeated material appears before the changing material.
DeepSeek’s guide gives a multi-turn conversation example where the second request can reuse the prefix created by the first request. It also gives a long-text Q&A example where the first two requests over the same document may not hit immediately, but after DeepSeek detects and persists the common prefix, a third request can reuse that shared prefix. DeepSeek Context Caching guide
A good mental model:
Stable reusable prefix
+ changing task
= better chance of cache reuse
Changing metadata first
+ stable content later
= lower chance of useful cache hitsKeep repeated system instructions, examples, document text, and repository context stable, and place the changing question after that material. Keep tool definitions and their ordering consistent where the API requires them. These are prompt-design practices, not instructions to move API fields into message text or remove authorization information.
How to read cache-hit and cache-miss tokens
DeepSeek reports cache behavior in the usage object of API responses. The key fields are documented in the Chat Completions API reference. DeepSeek Chat Completions API reference
| Usage field | Meaning |
|---|---|
prompt_cache_hit_tokens | Input tokens that hit the context cache. |
prompt_cache_miss_tokens | Input tokens that did not hit the context cache. |
prompt_tokens | Total input tokens. DeepSeek documents this as prompt_cache_hit_tokens + prompt_cache_miss_tokens. |
prompt_tokens_details.cached_tokens | Number of prompt tokens that hit the context cache. DeepSeek says this is the same as prompt_cache_hit_tokens. |
completion_tokens | Generated output tokens. |
total_tokens | Total request tokens: prompt plus completion. |
A simple cache hit rate formula is:
cache_hit_rate = prompt_cache_hit_tokens / (prompt_cache_hit_tokens + prompt_cache_miss_tokens)
Use the hit rate as a diagnostic, not a target in isolation. When total input is zero, report the ratio as unavailable rather than dividing by zero. If usage fields are missing, do not silently record them as zero: missing telemetry is different from a measured cache miss.
Current pricing: cache hit vs cache miss vs output
Use the current DeepSeek Models & Pricing page for billing. The 2024 caching announcement contains historical prices and points readers to the updated table. The rates below are for deepseek-flash, serving DeepSeek-V4.1-Flash, in USD per one million tokens. They are not V4 Pro prices.
| V4.1 Flash pricing | Input: cache hit | Input: cache miss | Output |
|---|---|---|---|
| Off-peak | $0.003 / 1M tokens | $0.15 / 1M tokens | $0.60 / 1M tokens |
| Peak hours | $0.006 / 1M tokens | $0.30 / 1M tokens | $1.20 / 1M tokens |
Peak hours are 01:00–04:00 and 06:00–10:00 UTC, Monday through Friday, excluding Chinese public holidays. All other hours are off-peak. U.S. public holidays do not define this schedule. Convert from UTC when planning a workload, and use the rates applicable when requests are billed. Official pricing schedule.
Cost calculation should separate cached input, uncached input, and output:
input_cost = (cache_hit_tokens / 1,000,000 × cache_hit_price) + (cache_miss_tokens / 1,000,000 × cache_miss_price) total_request_cost = input_cost + (output_tokens / 1,000,000 × output_price)
Sample cost calculation
This is an illustrative calculation, not a measured API result. Suppose one off-peak deepseek-flash request uses:
prompt_cache_hit_tokens = 80,000prompt_cache_miss_tokens = 20,000completion_tokens = 2,000
Using the V4.1 Flash off-peak prices:
cached input cost: 80,000 / 1,000,000 × $0.003 = $0.00024 uncached input cost: 20,000 / 1,000,000 × $0.15 = $0.003 output cost: 2,000 / 1,000,000 × $0.60 = $0.0012 estimated total: $0.00024 + $0.003 + $0.0012 = $0.00444
If the same 100,000 input tokens were all cache misses, with the same 2,000 output tokens, the off-peak input cost would be:
100,000 / 1,000,000 × $0.15 = $0.015
The all-miss total would be $0.0162 after adding the same $0.0012 output cost, compared with $0.00444 in the cache-hit scenario. This comparison keeps output fixed. Actual savings depend on prefix reuse, billable output, timing, and the model used; an input-only saving is not the saving on the entire request.
Python example: log cache hit and miss tokens
The following example uses the OpenAI Python SDK configured for DeepSeek. It sends a request and a follow-up that preserves the conversation prefix. A stable demonstration user_id is passed in both calls for consistent isolation; it is optional for basic caching, not an enablement parameter. Running the example makes billable API requests.
First, install the SDK and store your API key safely:
pip install openaiOn macOS or Linux:
export DEEPSEEK_API_KEY="your-api-key"On Windows PowerShell:
$env:DEEPSEEK_API_KEY="your-api-key"Then log cache usage. The short support-bot context is demonstration data, not a benchmark. The helper distinguishes missing usage fields from zero cache-hit tokens, and both calls put user_id and thinking inside one extra_body dictionary.
import os
import time
from openai import OpenAI
api_key = os.environ.get("DEEPSEEK_API_KEY")
if not api_key:
raise RuntimeError("Set DEEPSEEK_API_KEY before running this example.")
client = OpenAI(
api_key=api_key,
base_url="https://api.deepseek.com",
)
# Demonstration ID only. In production, derive this from trusted backend state.
user_id = "tenant_8f1a2c7e"
def print_cache_usage(label: str, usage) -> None:
print(f"\n{label}")
if usage is None:
print("Token usage was not returned.")
return
hit = getattr(usage, "prompt_cache_hit_tokens", None)
miss = getattr(usage, "prompt_cache_miss_tokens", None)
total_prompt = getattr(usage, "prompt_tokens", None)
if any(value is None for value in (hit, miss, total_prompt)):
print("Cache metrics are missing; inspect the usage object or wrapper.")
return
if any(type(value) is not int or value < 0
for value in (hit, miss, total_prompt)):
raise ValueError("Unexpected token usage values.")
if hit + miss != total_prompt:
raise ValueError("Cache hit/miss counts do not match prompt_tokens.")
hit_rate = f"{hit / total_prompt:.2%}" if total_prompt else "N/A"
print(f"cache hit tokens: {hit}")
print(f"cache miss tokens: {miss}")
print(f"prompt tokens: {total_prompt}")
print(f"cache hit rate: {hit_rate}")
messages = [
{
"role": "system",
"content": (
"You are a concise technical assistant. "
"Answer with practical engineering guidance."
),
},
{
"role": "user",
"content": (
"Context:\n"
"We are building an AI support bot for a SaaS product. "
"It uses long internal policy notes, repeated support flows, "
"and the same troubleshooting rubric on many requests.\n\n"
"Task: Summarize the main engineering risks."
),
},
]
first = client.chat.completions.create(
model="deepseek-flash",
messages=messages,
max_tokens=512,
extra_body={
"user_id": user_id,
"thinking": {"type": "disabled"},
},
)
print_cache_usage("First request", first.usage)
# Preserve the earlier conversation and the same isolation ID.
messages.append(first.choices[0].message)
messages.append({
"role": "user",
"content": "Now turn those risks into a short implementation checklist.",
})
# Optional demo pause; three seconds is not a cache-readiness guarantee.
time.sleep(3)
second = client.chat.completions.create(
model="deepseek-flash",
messages=messages,
max_tokens=512,
extra_body={
"user_id": user_id,
"thinking": {"type": "disabled"},
},
)
print_cache_usage("Second request", second.usage)A positive hit count shows that part of the input reused the cache; do not expect a particular number from this small example. Cache construction is best-effort and may take time. The pause is only a demonstration choice, not a requirement to sleep between production requests. Disabling Thinking Mode simplifies the example; it does not activate caching. Thinking Mode controls.
Streaming responses and usage fields
If you stream responses, DeepSeek’s Chat Completions reference says token usage appears on the last stream chunk. If stream_options.include_usage is set to true, every chunk includes a usage field, but it is null except on the final chunk. If it is omitted or false, the usage field is absent until the last chunk. DeepSeek Chat Completions API reference
# Reuse client, messages, user_id, and print_cache_usage from the example above.
stream = client.chat.completions.create(
model="deepseek-flash",
messages=messages,
max_tokens=512,
stream=True,
stream_options={"include_usage": True},
extra_body={
"user_id": user_id,
"thinking": {"type": "disabled"},
},
)
final_usage = None
try:
for chunk in stream:
if chunk.choices:
text = chunk.choices[0].delta.content
if text:
print(text, end="", flush=True)
usage = getattr(chunk, "usage", None)
if usage is not None:
final_usage = usage
finally:
stream.close()
print()
if final_usage is None:
print("Final usage was not received; cache metrics are unavailable.")
else:
print_cache_usage("Streamed request", final_usage)Read usage from the final chunk of a completed stream. An interrupted stream may never deliver that object; record unavailable metrics rather than zero tokens. This snippet reuses the client, conversation, isolation ID, and logging helper from the preceding example and makes another billable request.
How to improve DeepSeek cache hit rate
Improve prompt layout within the correct privacy boundary. Keep reusable content stable, but do not move mandatory instructions, weaken authorization, or reuse private data across tenants just to increase a cache-hit metric.
| Prompt design | Effect on caching | Better approach |
|---|---|---|
| Timestamp or request ID before long reusable context | Can change the prefix on every request. | Move changing metadata after the reusable context or omit it from the prompt if not needed. |
| Stable system prompt and document first, question last | Improves chance of matching a reusable prefix. | Keep long instructions and repeated documents before the changing task. |
| Random formatting changes between requests | Can reduce prefix reuse. | Use consistent separators, headings, and serialization. |
| Tool definitions reordered every request | Can break stable prefix matching. | Keep tool definitions stable and in the same order when possible. |
| Few-shot examples rewritten or shuffled | Reduces reuse of the examples. | Keep examples stable and append the new user input after them. |
| RAG chunks inserted in different order | May reduce hits for repeated documents. | Use deterministic ordering for repeated documents when appropriate. |
| Assuming hits without checking usage | Can hide cost regressions. | Log hit and miss tokens per request type. |
For cost-sensitive systems, log cache metrics by workflow: chat, RAG, code review, support bot, evaluation batch, and agent run. For an overall token-weighted hit rate, divide the sum of hit tokens by the sum of prompt tokens; simply averaging per-request percentages can overrepresent small requests.
Best use cases for DeepSeek Context Caching
Multi-turn chat applications
Multi-turn conversations reuse earlier turns. Keep history ordered and preserve the same legitimate isolation ID across related requests. In Thinking Mode workflows that send tools, retain the required assistant reasoning_content as well; do not shorten history solely to manipulate caching. Thinking Mode history rules.
Support bots with long system prompts
If every request includes the same support policy, escalation rules, tone guide, and tool-use rules, place that stable context before the user’s specific support ticket. Monitor cache hits on the repeated policy block.
RAG over repeated documents
When a user repeatedly asks questions about the same document, keep authorized document text and instructions in a stable order, then append the specific question. Reuse applies within the selected isolation scope. Do not send irrelevant or unauthorized documents merely to lengthen the cached prefix.
Code analysis and repository context
Code review, debugging, and agent workflows often resend the same repository summary, file tree, coding rules, or tool instructions. Stable repository context can benefit from caching, while the specific bug report or requested change can remain at the end.
Few-shot classification or extraction
Few-shot prompts often include repeated examples. Keep those examples stable and append each new item after the examples. Track whether the example block becomes cached rather than assuming it is automatically saving money.
Evaluation pipelines
If you repeatedly grade outputs with the same rubric, policy, or benchmark instructions, put the stable rubric first and the candidate output last. This is a strong fit for monitoring cache hit rate and cost per evaluated item.
Common mistakes that prevent cache hits
| Mistake | Why it hurts | Fix |
|---|---|---|
| Putting changing content first | The prefix changes before the reusable context appears. | Move changing instructions after the stable context. |
| Adding timestamps before long context | Every request starts differently. | Remove timestamps or place them after the reusable prefix. |
| Reordering retrieved chunks | The document prefix no longer matches previous requests. | Use deterministic ordering for repeated documents. |
| Expecting a hit on the second request in every pattern | Some common prefixes may need detection and persistence first. | Look at the third and later requests for document Q&A patterns. |
| Ignoring output cost | Caching affects input tokens, not generated output tokens. | Track input hit/miss cost and output cost separately. |
| Using wrappers that hide DeepSeek-specific fields | You may miss prompt_cache_hit_tokens. | Inspect the raw response or SDK model for DeepSeek usage fields. |
| Mixing unrelated users to chase hits | Can create privacy and product-boundary problems. | Respect user/session boundaries and use user_id where appropriate. |
DeepSeek Context Caching vs other caching types
DeepSeek Context Caching is easy to confuse with other caching concepts. The differences matter.
| Caching type | What it caches | Who controls it? | When to use it |
|---|---|---|---|
| DeepSeek Context Caching | Reusable prompt prefix processing inside DeepSeek’s API infrastructure. | DeepSeek runs it automatically; developers influence it through prompt structure. | Repeated long prompts, conversations, documents, agents, and few-shot examples. |
| Application response cache | Complete responses for identical requests. | Your application. | Deterministic lookups where the same input should return the same saved output. |
| Anthropic prompt caching | Prompt prefixes with cache-control configuration and TTL behavior. | The developer explicitly enables it or uses Anthropic’s automatic cache-control option. | Claude workflows with repeated context and provider-specific cache controls. Anthropic prompt caching docs |
| OpenAI cached input | Cached input tokens as part of OpenAI’s billing model. | OpenAI handles provider-side caching behavior. | OpenAI API workloads with repeated prefixes, under OpenAI’s own model and retention rules. OpenAI prompt caching documentation. |
| Self-hosted KV cache | Runtime attention key/value tensors inside your own inference server. | Your serving stack. | Self-hosted inference optimization, not DeepSeek hosted API billing. |
DeepSeek Context Caching does not replace RAG, summarization, conversation storage, or application-level caching. You still send the required context in the request. Reused processing can reduce input cost and latency, but it does not make the model remember omitted documents or return a guaranteed identical answer.
Privacy, user_id, and KVCache isolation
DeepSeek documents user_id for content-safety handling, KVCache isolation, and scheduling isolation among users of the same business account. It is not required to activate Context Caching. Use it when your application needs the documented isolation controls. Rate Limit & Isolation.
Pass user_id through extra_body in Python
With the OpenAI Python SDK, put user_id inside extra_body, not directly beside model. The following call reuses client and messages from the earlier example:
response = client.chat.completions.create(
model="deepseek-flash",
messages=messages,
extra_body={
"user_id": "tenant_8f1a2c7e",
"thinking": {"type": "disabled"},
},
)Use one extra_body dictionary for both fields. The Python SDK merges its contents into the outgoing JSON body, so user_id and thinking reach DeepSeek at the top level. extra_body itself is a Python client option, not a JSON wrapper required by DeepSeek. DeepSeek’s Python example; OpenAI Python SDK options.
Do not copy this SDK wrapper into a raw HTTP body. Conversely, do not remove extra_body from Python merely because a raw HTTP example shows user_id at the top level. Also, do not substitute a differently named OpenAI parameter and assume it provides DeepSeek’s isolation behavior.
Choose a stable identifier without personal information
The Chat Completions reference limits user_id to letters, digits, underscores, and hyphens, with a maximum of 512 characters. For a nonempty ID, the documented pattern is [a-zA-Z0-9\-_]+. Do not include names, email addresses, phone numbers, credentials, or other private information.
As an application-design practice, derive an opaque ID from trusted backend state for the intended user or tenant boundary. The demonstration value is not a production-wide shared ID. Keep its mapping private, and use the same ID for related requests within that authorized scope. Do not let clients choose another tenant’s identifier.
Changing the identifier changes the requested isolation scope, so do not expect the previous scope’s cache to remain reusable. Never combine unrelated users under one ID merely to improve hits. The field is not authentication, an authorization check, or a complete privacy guarantee.
user_id does not increase account-wide concurrency
For regular API users, DeepSeek combines all user_id values when applying account concurrency limits. Accounts with increased quotas can also have per-ID limits. Generating more IDs does not multiply the account’s capacity. See the current scheduling rules for your account type.
Monitor aggregate token counts, model, workflow, and appropriately protected pseudonymous identifiers rather than logging complete prompts or secrets. Reducing a cache bill must not weaken the application’s privacy boundaries.
Troubleshooting low cache hit rates
Python rejects user_id before sending the request
A TypeError about an unexpected user_id keyword points to the SDK call shape, not a cache failure. Move the field into extra_body as shown above. The SDK method signature does not declare a direct user_id argument. Retrying the same invalid Python call will not populate the cache.
Cache reuse changes after adding or changing user_id
Compare requests within the same legitimate isolation scope. Introducing an ID after earlier calls without one, changing it on every request, or testing with different tenant IDs is not an equivalent reuse test. Keep the identifier stable where appropriate rather than removing required isolation to chase hits.
Cache hits are always zero
Check whether the repeated material is actually at the beginning of the prompt. If a timestamp, request ID, user message, or changing metadata appears before the long reusable block, your reusable content may not be part of a stable prefix.
The second document question does not hit the cache
This can be normal. DeepSeek’s long-text Q&A example shows that the first two requests may allow the system to detect and persist a shared prefix, while the third request can then hit that persisted prefix. Do not evaluate a document-Q&A cache strategy from one retry only.
Streaming responses do not show usage until the end
On a completed stream, DeepSeek documents usage on the last content chunk before data: [DONE]. Capture that object before calculating a hit rate. If the connection is interrupted first, report the metrics as unavailable. Streaming reference.
Your SDK or wrapper does not expose cache fields
Inspect the response’s usage object or the wrapper’s documented access to raw fields. The OpenAI Python SDK allows access to additional response properties, including through model_extra. A wrapper may omit provider-specific metrics; missing data must remain unavailable, not become a reported 0% hit rate. SDK response-field documentation.
Costs are still high despite cache hits
Check output tokens. Context caching lowers the cost of cached input tokens, but long generated answers are still billed as output. Also check whether your workload runs during peak hours, where V4.1 Flash input and output prices are higher than off-peak prices.
Production checklist
- Keep stable instructions, examples, documents, and tool definitions before changing task instructions.
- Remove changing timestamps, request IDs, and random metadata from the prompt prefix.
- Log
prompt_cache_hit_tokensandprompt_cache_miss_tokensper request type. - Calculate cache hit rate from hit and miss tokens, not from assumptions.
- Track output tokens separately because caching does not reduce output pricing.
- Compare peak and off-peak costs if your workload can be scheduled.
- Use deterministic formatting and ordering for repeated documents or retrieved chunks.
- Respect tenant and user isolation; do not mix unrelated users to chase cache hits.
- Derive a stable, non-personal
user_idfrom trusted backend state when isolation is required; do not share it across unrelated users. - Verify current DeepSeek pricing before publishing cost estimates or budgeting production workloads.
- Test with your real prompts, not only toy examples.
- Keep a fallback strategy for low hit rates, such as summarization, better retrieval, or application-level caching.
- In Python, place
user_idand other DeepSeek-specific fields inside oneextra_bodydictionary. - Keep missing or interrupted usage records separate from measured zero cache hits.
- Do not treat
user_idas a cache switch or a way around account concurrency limits.
Frequently asked questions
What is DeepSeek Context Caching?
DeepSeek Context Caching is an API-side system that stores reusable prompt prefixes so later requests can reuse cached context instead of recomputing the full input. It is especially useful for long, repetitive prompts.
Do I need to enable DeepSeek Context Caching?
No. DeepSeek’s current Context Caching guide says the feature is enabled by default for all users and does not require code changes.
How do I know if DeepSeek cache was used?
Read the response usage object. prompt_cache_hit_tokens shows how many input tokens hit the cache, while prompt_cache_miss_tokens shows how many input tokens missed the cache.
What is prompt_cache_hit_tokens?
prompt_cache_hit_tokens is the number of input tokens served from DeepSeek’s context cache. DeepSeek also reports prompt_tokens_details.cached_tokens, which the API reference says is the same value.
What is prompt_cache_miss_tokens?
prompt_cache_miss_tokens is the number of input tokens that did not hit the context cache. Those tokens are billed as uncached input rather than cached input.
Why are my cache hits zero?
Common reasons include unstable prompt prefixes, changing metadata before reusable context, too little repeated content, cache construction not being complete yet, or using a request pattern that requires multiple calls before a common prefix is persisted.
Does DeepSeek Context Caching reduce output cost?
No. It affects cached input tokens. Output tokens are still billed as output according to the current pricing for the model and time period.
Does DeepSeek Context Caching work with streaming?
Yes, but usage statistics are available only at the end of the streamed response. DeepSeek’s API reference says the final chunk carries token usage for the entire streamed request.
Is DeepSeek Context Caching the same as prompt caching?
It is similar in goal but not identical to every provider’s prompt caching feature. DeepSeek Context Caching is automatic and prefix-based, while some providers require explicit cache-control markers or different TTL settings.
Does user_id affect KVCache isolation?
Yes. DeepSeek documents the field for KVCache isolation. Use an appropriately scoped, non-personal identifier, and do not treat it as a replacement for application authorization. In the OpenAI Python SDK, send it inside extra_body.
Do I need user_id to enable caching?
No. Caching is automatic. The field is for isolation and related handling, not cache activation.
How do I send user_id and thinking together in Python?
Use one dictionary: extra_body={"user_id": "tenant_8f1a2c7e", "thinking": {"type": "disabled"}}. This sends both as top-level HTTP body fields.
Can different user_id values bypass account limits?
No. Account-wide concurrency still applies. Additional per-ID limits may apply to expanded-quota accounts; they do not remove the overall account cap.
Bottom line
DeepSeek Context Caching is automatic, but good results are not automatic. The strongest savings usually come from workloads that repeat long stable prefixes: multi-turn conversations, repeated documents, RAG pipelines, code analysis, few-shot prompts, and agent workflows.
To use it well, keep reusable context stable, place changing instructions afterward where appropriate, and calculate costs from actual cached input, uncached input, and output. Preserve the intended isolation boundaries. In Python, pass user_id through extra_body without mistaking that field for cache enablement or additional account capacity.
Official references
- DeepSeek Context Caching guide
- DeepSeek Chat Completions API reference
- DeepSeek Rate Limit & Isolation
- DeepSeek Models & Pricing
- DeepSeek Thinking Mode guide
- DeepSeek’s original Context Caching announcement — historical context
- OpenAI Python SDK reference
- OpenAI Python SDK Chat Completions implementation
- Claude prompt caching documentation
- OpenAI prompt caching documentation
