MMSP-RFC-0014 Prompt Cache Sessions
Abstract
UniConfig gains session_id, an optional string naming the conversation a request belongs to. A client whose provider takes a prompt cache routing key sends it as prompt_cache_key, unchanged up to 64 characters and as its SHA-256 hex digest beyond; every other client ignores it.
1. Introduction
A provider keeps a prompt's cached prefix on the machine that served it, so a later request reuses the prefix only if it is routed there. OpenAI routes by a hash of the prefix and, above about 15 requests per minute on one prefix, overflows to machines that hold no entry; its prompt_cache_key groups the requests that share a prefix so they reach the same cache (llmsdk_docs/gpt6/docs/prompt-caching.md). Kimi asks multi-turn agents to send one prompt_cache_key per session (llmsdk_docs/kimi_k3_1/docs/chat-api.md: 对于其他多轮对话 Agent,也建议使用此字段), and MiniMax's Responses API takes it as a "prompt cache routing identifier" (llmsdk_docs/minimax_m3/docs/responses-create.md).
A caller had no way to say which conversation a request belongs to. MMSP sent a key only on Kimi K2, taken from trace_id (#81); #163 dropped it on Kimi K3, whose documentation then described its cache as fully automatic, and the key has since returned to the K3 documentation. The owner's words: 支持prompt cache key的端点,我们要在UniConfig里面加一个session id的可选字段,允许用户来通过指定Session id来设置prompt cache key, and 告诉用户推荐设置Session id,这样能增加命中率.
Probes of 2026-11-02 sent prompt_cache_key to OpenAI, Moonshot, MiniMax, DeepSeek, Z.AI, OpenRouter, SiliconFlow and TokenDance, on Responses, Chat Completions and embeddings: every endpoint answered 200. OpenAI's Responses API refuses a key longer than 64 characters (400, string_above_max_length), counting code points: 64 emoji pass and 65 CJK characters fail. OpenRouter relays the same refusal from OpenAI models on Chat Completions too, while OpenAI's own Chat Completions takes 2000 characters and Moonshot, MiniMax and Z.AI take 300.
2. Conventions and Terminology
The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY in this document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals.
- Session id: the value of
UniConfig.session_id. - Prompt cache key: the string a client sends as
prompt_cache_key. - Character: a Unicode code point, as Python's
lencounts it and asArray.fromsplits a JavaScript string.
3. The session_id Key
UniConfigand the TypeScriptUniConfiginterface MUST definesession_id, an optional string. It names the conversation or agent task a request belongs to and means the same on every client (MMSP-RFC-0002 §3.1).- An empty string MUST be treated as unset.
- A caller SHOULD set one session id per conversation, keep it across the conversation's turns and a resumed session, and SHOULD NOT share it with an unrelated conversation. A UUID fits every endpoint as it is.
session_idandtrace_idare independent:trace_idnames where a turn is saved (MMSP-RFC-0010) and sets no prompt cache key.
4. The Prompt Cache Key
4.1 From a session id
The prompt cache key MUST be the session id when it has at most 64 characters, and otherwise the lowercase hexadecimal SHA-256 digest of its UTF-8 bytes, which has 64. prompt_cache_key in utils.py and promptCacheKey in utils.ts compute it, and every client that sends a key MUST use them, so one session id gives one key in both packages (MMSP-RFC-0002 §6).
4.2 Per client
| Client | Sends |
|---|---|
openai-official, openai-responses |
prompt_cache_key on the Responses request |
openai-chat, openai-chat-vllm-adapter |
prompt_cache_key on the Chat Completions request |
moonshot-official |
prompt_cache_key, on every generation |
minimax-official |
prompt_cache_key on the Responses request |
anthropic-official, ant-messages, google-official, google-genai, openai-embedding, deepseek-official, zai-official |
nothing: the key is ignored |
mmsp |
the configuration as given; the server's client applies this table |
prompt_cache_keyis a typed parameter ofresponses.createandchat.completions.createin both OpenAI SDKs, so both packages MUST send it as one, not throughextra_body.- A client MUST NOT raise for
session_id: a client whose provider takes no key ignores it (MMSP-RFC-0003 §6.2). - A client MUST NOT send a gateway's own session field or header for it, such as OpenRouter's
session_idandx-session-id, OpenCode Go'sx-opencode-sessionor Fireworks'x-session-affinity. A caller reaches those headers throughdefault_headers. moonshot-officialMUST NOT sendtrace_idasprompt_cache_keyon Kimi K2 any more; onlysession_idsets the key, on every Kimi generation.
5. The Playground
The playground page MUST send its per-conversation id as session_id and generate it with crypto.randomUUID(), or from crypto.getRandomValues where the page runs outside a secure context and randomUUID is missing. A new conversation takes a new id. The playground server MUST NOT send the id it falls back to when a request names none.
6. Drawbacks
- An endpoint that ignores the key gains nothing from it, and a caller cannot tell from the response whether the key was used.
- A session id longer than 64 characters reaches the provider as a digest, so a provider's dashboard shows the digest rather than the caller's id.
- A Kimi K2 caller who relied on
trace_idfor the key gets none until it setssession_id.
7. Rationale and Alternatives
- The key is named for the caller's concept, the conversation, not for one provider's field: OpenAI calls it
prompt_cache_key, OpenRoutersession_id, OpenCode Gox-opencode-session, Fireworksx-session-affinity. - Over 64 characters, refusing with
UnsupportedParameterErrorwould make a long id fail on the clients that send a key and pass on the rest; passing it through would fail at OpenAI and at OpenRouter's OpenAI models. The digest keeps one session on one key everywhere, and 64 characters is OpenAI's limit, the strictest probed. deepseek-officialandzai-officialsend nothing although their endpoints accept the field: DeepSeek documentsprompt_cache_keyas not supported and silently ignored, and Z.AI documents no such field. The owner chose not to send it there, though OpenRouter, which serves models of both clients, routes byprompt_cache_keywhen nosession_idis set.- Gateway fields stay out because a compatible client carries no vendor's quirks, and
default_headersalready reaches them. session_idis ignored rather than refused where no key exists, so a caller can set it on every request whatever the model, which is what raises the hit rate where it counts.
8. Prior Art
OpenAI's prompt_cache_key on Responses and Chat Completions; Kimi's prompt_cache_key, required for Kimi Code Plan; MiniMax's prompt_cache_key; OpenRouter's session_id body field and x-session-id header, at most 256 characters, its sticky routing key; OpenCode Go's x-opencode-session header; Fireworks' user field and x-session-affinity header; vLLM's session_id request field.
9. Future Possibilities
- Sending the key on
deepseek-officialandzai-officialfor their OpenRouter rows, or OpenRouter's ownsession_id. - vLLM's
session_idonopenai-chat-vllm-adapter, once vLLM documents what it does.