Content is stripped at the source
Redaction runs inside your process, as a gate in front of the exporter, before any byte leaves it:- Allowlist first. Metadata that’s explicitly safe passes: token counts, model names, request parameters, tool names, timing.
- Content vocabulary stripped. Every known content-bearing attribute — prompts, completions, message bodies, retrieved documents, embedding text, exception messages and stack traces — is removed by exact match.
- Heuristic backstop. Anything whose name merely looks like content
(
.text,.body,.query, …) is stripped too.
Events are metadata only
Every LLM call is recorded as an event containing hashes, token counts, costs, model names, tool names, and timing. Events never contain prompt or response text, and never contain PII. The read APIs — stats, traces, events — serve this metadata and nothing else.Your provider keys stay yours
Your LLM-provider API keys (OpenAI, Anthropic, and so on) live in your own environment or secrets manager. Visceral never stores them. Your Visceral key is stored as a SHA-256 hash — the full key exists in exactly one response, at mint time.Isolation and encryption
Per-workspace isolation
Customer data is isolated per workspace with database-enforced row-level
security — every query runs inside your workspace’s boundary, so one
workspace can never read another’s.
Encrypted end to end
Where payloads are handled at all, they are encrypted in the SDK with
AES-256-GCM under a key unique to your workspace, derived from a
server-side master secret that is never stored alongside your data.
If you ever need Visceral to see less, the safe default is already the one in
place: metadata, hashed, isolated, encrypted.