Skip to content

Multi-Turn Conversation Support

By default each Redact request is independent. If "John Smith" appears in message 1 it gets a pseudonym, but if it appears again in message 7 a fresh pseudonym might be generated, breaking the LLM's context and making responses incoherent.

Multi-turn support solves this by scoping the entity map to a conversation thread. Pass a thread_id on every request in the same conversation and Redact reuses the same pseudonyms for the lifetime of that thread.


How to use it

Add thread_id to any proxy request body. It can be any string that uniquely identifies the conversation in your system, a session ID, a database primary key, or a UUID you generate.

{
  "thread_id": "conv_abc123",
  "model": "gpt-4o",
  "messages": [
    { "role": "user", "content": "My name is John Smith, my email is john@acme.com" }
  ]
}

On the next message in the same conversation:

{
  "thread_id": "conv_abc123",
  "model": "gpt-4o",
  "messages": [
    { "role": "user", "content": "As I mentioned, John Smith will be joining the call" }
  ]
}

"John Smith" resolves to the same pseudonym in both messages. The LLM sees a consistent identity throughout the conversation.


What changes with a thread_id

  • Entity mappings are stored and looked up by (workspace_id, thread_id) instead of workspace_id alone
  • A real value seen for the first time in a thread gets a new pseudonym scoped to that thread
  • The same real value in a different thread gets its own independent pseudonym
  • Workspace-level mappings (requests without a thread_id) are unaffected

What stays the same

  • Requests without a thread_id behave exactly as before, no changes needed for existing integrations
  • All other request fields work as normal, model, policy, doc_class, stream
  • TTL and entity map expiry apply to thread-scoped entries the same way they apply to workspace-level ones
  • Vault records are written per request as usual, with no change to the audit trail

Clearing a thread

When a conversation ends, delete the thread to free up entity map storage and ensure the pseudonyms cannot be reused in a future conversation with the same ID.

DELETE /api/redact/{workspace_id}/threads/{thread_id}

Response

{
  "ok": true,
  "deleted": 12
}

deleted is the number of entity map entries removed.


Listing active threads

GET /api/redact/{workspace_id}/threads

Returns all thread IDs that have entity map entries in the workspace, with a count of entries per thread.

Response

{
  "ok": true,
  "threads": [
    { "thread_id": "conv_abc123", "entries": 12 },
    { "thread_id": "conv_def456", "entries": 4 }
  ]
}

Thread ID guidelines

  • Use an ID that is stable for the lifetime of the conversation and unique across conversations
  • Keep thread IDs under 120 characters
  • Do not reuse a thread ID for a new conversation without deleting the old one first, otherwise old pseudonym mappings carry over
  • Thread IDs are internal to your system and are not exposed in vault records or to the LLM