Skip to content
Blog

Privacy

Logging LLM applications without creating a privacy problem

How to log prompts, completions, and tool calls well enough for incident response, while keeping personal data and secrets out of long-lived storage.

Published
Reading time
3 min read
Diagram of a request passing through a redaction step that replaces email, card number, and API key values with placeholders before splitting into a one-year audit log and a fourteen-day debug log

Key takeaways

  • Split LLM logs by purpose: a long-lived audit log of metadata and decisions, and a short-lived debug log of redacted content.
  • Redact personal data and secrets before content reaches any log sink, not in a downstream pipeline.
  • Never store credentials or full retrieved documents in logs; log document identifiers instead.
  • Correlation IDs, model versions, and authorization decisions make LLM incidents reconstructable.
On this page

When an LLM feature misbehaves, the first thing anyone asks for is the prompt. What did the user send, what did the retrieval step add, what did the model return, and which tools did it call? Without those records, investigating a bad answer or a suspected injection is guesswork.

The same records are a privacy liability. Users paste in names, account numbers, medical details, and occasionally credentials. Retrieval pulls internal documents into the context. Store all of it indefinitely in a general-purpose logging platform and you have built a sensitive data store that nobody designed, reviewed, or scoped.

The way out is to stop treating "the logs" as one thing.

Separate logs by purpose

Most LLM logging serves two distinct purposes with different requirements.

Audit logDebug log
Question it answersWhat happened, and was it allowed?Why did the model produce this output?
ContentMetadata, decisions, hashesFull redacted prompt and completion
RetentionLong, set by your security policyShort, often days to weeks
AccessSecurity and incident responseThe owning engineering team

The audit log records events: who made a request, which model and version answered, which tools were proposed, what the authorization decision was, and a hash of the prompt and completion. It is small, low-sensitivity, and kept for as long as your incident response process needs.

The debug log holds the content itself, after redaction. It is the higher-risk store, so it gets short retention and narrow access.

Redact at the edge

Redaction should happen before content reaches any log sink, not in a downstream pipeline. Once raw text has been written to a shared logging platform, it has usually been replicated, indexed, and backed up.

A pragmatic redaction step combines pattern matching for well-structured values with your existing data classification where you have it:

python
import re

PATTERNS = {
    "EMAIL": re.compile(r"[\w.+-]+@[\w-]+\.[\w.-]+"),
    "PAN": re.compile(r"\b(?:\d[ -]?){13,19}\b"),
    "SECRET": re.compile(r"\b(?:sk|pk|api)[_-][A-Za-z0-9]{16,}\b"),
}

def redact(text: str) -> str:
    for label, pattern in PATTERNS.items():
        text = pattern.sub(f"[{label}]", text)
    return text

Pattern-based redaction will miss things, especially free-text personal details. That is acceptable as long as you design for it: short retention and restricted access on the debug log are what protect you from the misses.

Decide what never gets logged

Some content should not be stored even in redacted form. Make the list explicit and enforce it in code.

  • Credentials and session tokens passed through tool calls or headers.
  • Full retrieved documents. Log document identifiers and versions instead; the source system already holds the content under its own access controls.
  • Special-category data in regulated workflows, where your privacy team has decided the risk outweighs the debugging value.

Make the records useful for incident response

When something goes wrong, responders need to reconstruct a session quickly. A few fields make that possible:

  1. A correlation ID that ties together the user request, retrieval calls, model calls, and tool calls.
  2. Model and prompt template versions, so you can tell whether behaviour changed because of a deploy.
  3. Authorization decisions for every tool call, including denials. A spike in denied calls is often the first visible sign of an injection attempt; see why authorization is the real control.
  4. The principal, taken from the authenticated session rather than from anything the model produced.

Write it down

Logging choices are governance decisions. Record the retention periods, redaction approach, and access rules alongside each system in your AI model inventory, so reviewers can see them and so they change deliberately rather than by drift.

None of this requires specialised tooling. It requires deciding, before the first incident, which questions your logs must answer and which data they must never hold.

Follow via RSS

New research, in the reader you already use.

No account, no email, no tracking. Add the feed to Feedly, Inoreader, NetNewsWire, or Slack and get every new article. How RSS works

Open RSS feed