---
title: Sensitive data
description: How Prefactor stores, redacts, and discards sensitive values in
  span payloads, and how your integration marks them.
editUrl: true
head: []
template: doc
sidebar:
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

A faithful record of what an agent did will sooner or later contain things you do not want every reviewer to read: email addresses, account numbers, medical details, credentials. Dropping those values from the record weakens the audit trail; keeping them in plain view turns the audit trail itself into an exposure. Prefactor resolves this by letting your integration mark the sensitive values in a [span](/platform/concepts/span)'s payload, and then handling those values differently from the rest of the record — stored separately, redacted by default, revealed on demand, and removable for good.

Prefactor does not detect sensitive data for you. The team building the agent knows which fields carry a customer's email and which carry a search query, so marking is done in your integration, at the point where the payload is built. Once markers arrive, Prefactor stores those values separately, redacts them by default, reveals them on demand, and lets you discard them for good.

## Marking values

When your integration sends a span with `sensitive_encoding: true`, Prefactor parses the payload for `$sensitive` markers. A marker wraps a single value and says what type it is, which categories of sensitive data it contains, and the value itself:

```json
{
  "email": {
    "$sensitive": "string",
    "labels": ["personal_identifiers", "contact_information"],
    "value": "ada@example.com"
  }
}
```

The `$sensitive` type is `"string"`, `"number"`, or `"boolean"`. The `labels` list uses the same data-category vocabulary as [risk profiles](/platform/concepts/risk-profile) — `personal_identifiers`, `contact_information`, `financial_information`, `health_and_medical`, `authentication_and_secrets`, and the rest, including the GDPR special categories. The labels travel with the value wherever it appears, so a reviewer always knows what kind of data was redacted even when they cannot see it.

Both the span's input payload and its result payload can carry markers — set `sensitive_encoding: true` on create for the input, and on finish for the result. Without the flag (the default), nothing is parsed: the payload is stored as-is, and a literal `$sensitive` key in your data is just a key.

In the TypeScript SDK, pass `sensitiveEncoding: true` in the span options and build the marker objects in your payload; the SDK sends them through unchanged. The Python SDK does not support sensitive encoding yet.

## What Prefactor does with marked values

Marked values never sit in the main span record. On write, Prefactor splits them out: the span's payload keeps a redacted marker — the type and labels, no value — and the values move to a separate secure store attached to the span. The API always accepts and returns the combined payload, so your integration reads back exactly what it sent; the split is a storage arrangement, not something you manage.

In the web app, sensitive values are redacted by default. Span summaries and conversation views render with the values hidden, and the span detail panel shows each marked value as a labelled placeholder. A **Show sensitive information** toggle in the panel reveals the values for that viewing; it is off again the next time you look.

## Discarding values

Some values should not be retrievable at all once a run has been reviewed — or should never have been captured in the first place. The **Discard sensitive** action on a span permanently deletes its stored sensitive values. The span keeps its redacted markers, so the record still shows that sensitive data of those categories was present; only the values are gone, and there is no way to recover them. Discard is also available through the API, span by span.

## Sensitive markers and risk

Markers and [risk scoring](/platform/concepts/risk-profile#how-risk-is-scored) share a vocabulary but do different jobs. Risk is scored from the activity schema's declarations — which data categories each span type can touch — because risk is about what the agent is capable of handling, assessed before and across runs. Markers annotate the actual values in an actual run, so they drive redaction and discard, not the risk score. An agent whose schema declares `personal_identifiers` scores for it whether or not a given run marked any values; a marked value in a run does not add to the score.

## Further reading

- [Span](/platform/concepts/span) — the record that carries payloads, results, and sensitive markers.
- [Risk](/platform/risk) — what data sensitivity means for scoring and classification.
- [Agent › Instance › Activity tab](/admin-ui/agent-instance/activity) — where redacted values, the reveal toggle, and the discard action appear.