Implementation:BerriAI Litellm Redact Messages
| Knowledge Sources | Domains | Last Updated |
|---|---|---|
| [[1]] | Observability, Privacy, Compliance | 2026-02-15 |
Overview
Concrete tool for redacting sensitive content from LLM request/response payloads before they reach logging backends provided by the redact_messages module in LiteLLM.
Description
The redact_messages.py module provides functions that strip message content from logging payloads while preserving operational metadata. It supports two entry points:
redact_message_input_output_from_logging()-- Used by the coreLoggingclass to apply global and per-request redaction before dispatching to all callbacks.redact_message_input_output_from_custom_logger()-- Used to apply per-logger redaction when a specificCustomLoggerinstance hasmessage_logging=False.
The module also includes should_redact_message_logging(), which implements the priority resolution logic (dynamic params > headers > global setting), and perform_redaction(), which performs the actual content replacement on both the model_call_details dict and the response object.
Additionally, redact_user_api_key_info() strips user API key metadata from the logging payload when litellm.redact_user_api_key_info is enabled.
Usage
Use this module's functions when:
- You need to programmatically check whether redaction should be applied for a given request.
- You are building a custom integration that needs to apply the same redaction logic LiteLLM uses internally.
- You want to strip API key metadata from logging payloads.
Code Reference
Source Location
litellm/litellm_core_utils/redact_messages.py (lines 1-245)
Signature
def redact_message_input_output_from_logging(
model_call_details: dict,
result,
input: Optional[Any] = None,
) -> Any:
"""
Removes messages, prompts, input, response from logging.
Modifies model_call_details in-place.
Only redacts when litellm.turn_off_message_logging == True
or when per-request/header settings indicate redaction.
"""
...
def redact_message_input_output_from_custom_logger(
litellm_logging_obj: LiteLLMLoggingObject,
result,
custom_logger: CustomLogger,
) -> Any:
"""
Redacts if the custom_logger instance has message_logging set to False.
"""
...
def should_redact_message_logging(model_call_details: dict) -> bool:
"""
Determine if message logging should be redacted.
Priority: dynamic param > headers > global setting.
"""
...
def perform_redaction(model_call_details: dict, result) -> Any:
"""
Performs the actual redaction on the logging object and result.
Replaces messages with 'redacted-by-litellm' placeholder.
"""
...
def redact_user_api_key_info(metadata: dict) -> dict:
"""
Removes user_api_key_* fields from metadata when
litellm.redact_user_api_key_info is True.
"""
...
Import
from litellm.litellm_core_utils.redact_messages import (
redact_message_input_output_from_logging,
redact_message_input_output_from_custom_logger,
should_redact_message_logging,
perform_redaction,
redact_user_api_key_info,
)
I/O Contract
Inputs (redact_message_input_output_from_logging)
| Parameter | Type | Required | Description |
|---|---|---|---|
| model_call_details | dict |
Yes | The call metadata dictionary containing messages, prompt, input, litellm_params, stream, and optionally complete_streaming_response. Modified in-place.
|
| result | Any |
Yes | The LLM response object (ModelResponse, EmbeddingResponse, ResponsesAPIResponse, or other). A deep copy is made before redaction.
|
| input | Optional[Any] |
No | Optional additional input data to redact. |
Outputs (redact_message_input_output_from_logging)
| Output | Type | Description |
|---|---|---|
| result | Any |
If redaction is applied: a deep-copied response with content replaced by "redacted-by-litellm". If not: the original result unchanged.
|
| (side effect) | mutation of model_call_details |
When redaction is applied, model_call_details["messages"] is set to [{"role": "user", "content": "redacted-by-litellm"}], prompt and input are set to empty strings, and streaming responses are redacted in-place.
|
Inputs (should_redact_message_logging)
| Parameter | Type | Required | Description |
|---|---|---|---|
| model_call_details | dict |
Yes | Call metadata dict. Checks litellm_params.metadata.headers for redaction headers and standard_callback_dynamic_params.turn_off_message_logging for dynamic overrides.
|
Outputs (should_redact_message_logging)
| Output | Type | Description |
|---|---|---|
| should_redact | bool |
True if message content should be redacted, False otherwise.
|
Usage Examples
Global Redaction via Module Flag
import litellm
# Enable global message redaction
litellm.turn_off_message_logging = True
# All subsequent calls will have messages/responses redacted in logs
response = litellm.completion(
model="gpt-4",
messages=[{"role": "user", "content": "My SSN is 123-45-6789"}],
)
# Callbacks receive: messages=[{"role": "user", "content": "redacted-by-litellm"}]
Per-Request Redaction via Headers
import litellm
# Global redaction is OFF
litellm.turn_off_message_logging = False
# But this specific request enables redaction via header
response = litellm.completion(
model="gpt-4",
messages=[{"role": "user", "content": "Confidential data"}],
metadata={
"headers": {
"x-litellm-enable-message-redaction": True,
}
},
)
# Only this request's messages are redacted in logs
Per-Request Dynamic Parameter
import litellm
# Per-request override via dynamic callback params
response = litellm.completion(
model="gpt-4",
messages=[{"role": "user", "content": "Sensitive info"}],
turn_off_message_logging=True, # highest priority
)
Programmatic Redaction Check
from litellm.litellm_core_utils.redact_messages import should_redact_message_logging
model_call_details = {
"litellm_params": {
"metadata": {
"headers": {"x-litellm-enable-message-redaction": True}
}
}
}
if should_redact_message_logging(model_call_details):
print("Messages will be redacted")
else:
print("Messages will be logged as-is")
Redacting API Key Info
import litellm
from litellm.litellm_core_utils.redact_messages import redact_user_api_key_info
litellm.redact_user_api_key_info = True
metadata = {
"user_api_key": "sk-1234...",
"user_api_key_alias": "production-key",
"team_id": "team-abc",
}
clean_metadata = redact_user_api_key_info(metadata)
# Returns: {"team_id": "team-abc"}
# All user_api_key* fields are stripped