MarkDB

Chat continuity

How the proxy groups requests into chats and sessions, and the headers to control it.

MarkDB stitches a stream of proxy requests into chats, sessions, and turns. Most clients need nothing to make this work, but you can control it with headers when you want explicit threading.

How grouping is derived

Clients like Cursor replay the whole conversation on every request and rotate their session id each time. To keep that from fragmenting into one session per request, the proxy derives a stable chat key by hashing the first couple of messages of the conversation (it reads both the Chat Completions messages[] and the Responses input[] shapes). Same opening, same chat key -- so the thread stays one chat even as the client's ids churn.

Request headers

Send these to override the derived behavior:

HeaderEffect
X-MarkDB-Chat-KeyForce the conversation thread id. Use this when you manage threading yourself and don't want the derived key.
X-MarkDB-External-Session-IDYour client's session id for this bout of work.

Response headers

Every proxied response tells you where it landed:

HeaderMeaning
X-MarkDB-Session-IDThe MarkDB session this exchange was recorded under.
X-MarkDB-External-Session-IDThe external session id in effect.
X-MarkDB-Chat-KeyThe chat key this exchange grouped into.

Idle rollover

Within a chat, MarkDB keeps appending to the active session while the conversation is live. After an idle gap it rolls the next request into a new session under the same chat key -- marking the natural break between sittings. The gap is MARKDB_PROXY_CHAT_IDLE_TIMEOUT, default 3h.

Deduplication

Because clients replay history, the proxy de-duplicates by content hash, scoped to the chat key, so a message is stored once no matter how many requests replay it. The dedup set is kept in Redis with a rolling ~24h TTL, so an active chat never loses its dedup state mid-flight.

When you need the headers

If your client already has stable conversation and session ids -- or doesn't replay history -- set X-MarkDB-Chat-Key (and optionally X-MarkDB-External-Session-ID) so grouping matches your model exactly instead of relying on the derived key.