Skip to main content
Traces can contain personal information, credentials, and other sensitive data. Braintrust supports three approaches to protecting that data in your logs, which you can use separately or together:
  • Redact during ingestion: Braintrust receives your logs and sends unredacted text from selected fields to a detection model hosted on Baseten. Braintrust replaces detected sensitive text before storing the logs.
  • Redact before upload: An SDK masking function, span customizers, or bt span plugins remove sensitive values within your application or on your machine. Values they remove are not sent to Braintrust.
  • Hide fields when read: Braintrust stores your logs unchanged and hides selected fields from some or all members when they view or query the logs.
Redaction removes sensitive values from stored logs. Hiding controls who can see values that Braintrust stores. If a value must never leave your application, remove it before upload.

Redact during ingestion

Ingestion redaction detects sensitive text, such as names, email addresses, and credentials, in incoming project logs and replaces it before storage. You define protected fields: named rules that each choose which log fields to scan and which types of sensitive information to redact. Create them for one project or your entire organization without changing your application code.
Ingestion redaction is in private preview, available to a limited set of customers. Behavior can change during the preview. To request access, contact Braintrust.

How redaction works

Redaction runs on incoming project logs before storage:
  1. Select text: Braintrust applies the protected fields from your project and organization to identify which fields and entity types to scan. Each rule redacts only its own entity types in its own fields. Selected fields include strings nested in objects and arrays.
  2. Detect sensitive information: Braintrust sends unredacted text from the selected fields to a Braintrust-managed detection model hosted on Baseten, a subprocessor. The model identifies text matching the rule’s entity types.
  3. Replace and store: Braintrust replaces the text identified by the model with category markers such as [REDACTED_EMAIL], then stores the records. Text outside the detected spans and the object and array structure are preserved.
Only incoming project logs are scanned. Object keys, non-string values, existing records, direct writes to datasets or experiments, and image, audio, or file attachment contents are excluded.
For organizations on the EU data plane, unredacted text selected for detection is sent to a Baseten-hosted model endpoint outside the EU. Using the EU data plane does not keep ingestion redaction processing within the EU.

Create a protected field

To view or configure protected fields, you need the Update permission on the organization or project. Braintrust recommends creating protected fields at the project level during private preview.
Redaction permanently replaces detected sensitive text in stored logs. You cannot recover the original text from those logs, even after you delete the rule. Queries, exports, and scorers receive only the replacement text.
1

Choose the scope

Go to Settings > PII redaction, then select a tab:
  • Project: Redact logs in the selected project. Requires the Update permission on the project. The tab also lists rules inherited from your organization, labeled Inherited from organization, which you can’t edit or delete here.
  • Organization: Redact logs in every existing and new project. Requires the Update permission on the organization.
If you can update only one scope, the page opens that scope without tabs.
2

Define the rule

Click Create protected field, then:
  1. Enter a Name for the rule.
  2. Set Stage to Ingest. The Action is Redact.
  3. Under Entity types to redact, search or browse the types (categories of sensitive text) and select at least one.
  4. Under Fields to redact, click Field, then select a top-level field or enter a nested path such as input.messages[0].content. On the Project tab, the list also suggests nested paths from the project’s logs, such as metadata.user.email. Paths must start with input, output, expected, error, metadata, comments, or context. Fields don’t need to exist in your logs yet.
  5. Optionally, under Fields to pass through, click Field and add paths that this rule never redacts, such as input.messages[0].role. The rule skips each pass-through field and everything nested under it, so passing through a parent field also skips any redacted fields below it. Paths match exactly, so input.messages[0].role covers only the first message. Other rules, including rules inherited from your organization, still redact the field if they include it.
  6. Optionally, expand Preview rule to see example text redacted with the selected entity types.
  7. Click Create.
New rules start with no fields or entity types selected. The rule applies to logs ingested after you create it.
3

Verify the results

Send representative test logs, then go to Logs and inspect the covered fields.In LLM message views, rendered Markdown text, and the data editor, category markers appear as labeled pills. For example, [REDACTED_EMAIL] displays as Redacted email address. Exports, API queries, and scorers receive the category marker text.Detection is model-based and can miss sensitive values or treat identical inputs differently. Check for missed values and incorrect redactions before relying on the results. Missed values are stored unredacted. For values you can match reliably, such as known credential formats, also redact before upload.

Edit, disable, or delete a protected field

The rule table on the PII redaction page lists each rule with a Status of Enabled or Disabled. New rules start enabled.
Removing fields or entity types from a rule, adding fields to Fields to pass through, and disabling or deleting a rule all stop redacting the affected fields in new logs. Removing a field from Fields to pass through redacts it again in new logs. Data already redacted during ingestion can’t be restored. Other rules, including rules inherited from your organization, still apply.
  • Edit: Click a rule or its edit icon, change its settings, and click Save. You can’t change a rule’s Stage after you create it.
  • Disable: Open the rule, turn off the Enabled switch, and click Save. The rule stops applying but keeps its configuration. Turn the switch back on to apply it again. Disabled organization rules don’t appear on the Project tab.
  • Delete: Click the rule’s delete icon, or open the rule and click Delete, then confirm with Delete.
Saved changes apply to new logs and queries without waiting for cached rules to expire. Changes to permission group membership can take about a minute to affect read rules.

Failure behavior

Ingestion redaction fails open:
  • If redaction fails for a log record, Braintrust stores that record without ingestion redaction. Successfully redacted records in the same batch retain their redactions.
  • If policy lookup or evaluation fails, Braintrust can store the entire batch without ingestion redaction.
  • Ingestion redaction has a time budget of 45 seconds per batch by default, including policy lookup and redaction. If that budget expires, Braintrust stores unfinished records without ingestion redaction.
Sensitive content can be stored when ingestion redaction fails. To prevent specific values from reaching Braintrust, redact them before upload.

Hide fields when read

Read rules hide selected project-log fields from every member except those you exempt, or from only the members and groups you choose. Braintrust stores the logs unchanged, so other members still see the full values, and disabling or deleting a rule makes its fields visible again. Read rules don’t apply to experiments or datasets.
Read rules are in private preview, available to a limited set of customers. Behavior can change during the preview. To request access, contact Braintrust.

Create a read rule

Read rules are created on the same PII redaction page as ingestion redaction. To create one, you need the Update permission on the organization or project.
1

Choose the scope

Go to Settings > PII redaction, then select a tab:
  • Project: Hide fields in the selected project. Requires the Update permission on the project. The tab also lists rules inherited from your organization, labeled Inherited from organization, which you can’t edit or delete here.
  • Organization: Hide fields in every existing and new project. Requires the Update permission on the organization.
If you can update only one scope, the page opens that scope without tabs.
2

Define the rule

Click Create protected field, then:
  1. Enter a Name for the rule.
  2. Set Stage to Read. The Action changes to Hide.
  3. Under Fields to hide, click Field, then select a top-level field or enter a nested path such as metadata.user. On the Project tab, the list also suggests nested paths from the project’s logs, such as metadata.user.email. Paths must start with input, output, expected, error, metadata, comments, or context. Fields don’t need to exist in your logs yet.
  4. Under Hide from, select an option:
    • Everyone except specific members or groups: Hides the fields from every member, including members who join later, except the members and permission groups you select. To hide the fields from everyone, leave the selection at No one.
    • Specific members and groups: Hides the fields only from the members and groups you select. Choose at least one member or group.
  5. Click Create.
A read rule hides each selected field and everything nested under it. Read rules don’t use entity types, pass-through fields, or the rule preview. With Everyone except specific members or groups, the rule also hides the fields from you unless you select yourself or one of your groups. If a read rule was created with a condition that the Hide from options can’t represent, the dialog shows the condition as read-only and keeps it unchanged when you save.
A read rule controls what members see. It doesn’t remove data from storage, so it isn’t a substitute for redaction. To keep a value out of stored logs, redact it during ingestion or before upload.

Recognize hidden fields

When a field is hidden from you, Braintrust omits it from the logs you read, so a hidden field looks the same as a field that was never logged. In trace and log views:
  • A hidden field shows Hidden field in place of its value.
  • An object with some hidden fields inside it shows Some fields hidden above the remaining content.
  • A span’s raw data lists the hidden paths, labeled Hidden by protected-field rules.

Query limitations

When you query project logs that have fields hidden from you, Braintrust returns rows with those fields removed. If a query reads logs from several projects, a field hidden from you in one of those projects is hidden in every row the query returns. A query’s outermost select can return a hidden field, a field nested inside it, or a field that contains it, under its own name or a new one, such as metadata, metadata.model, or metadata AS m. Braintrust removes the hidden parts from the returned column, or omits the column if the selected value is itself hidden. On self-hosted deployments, selecting a nested or renamed field requires data plane v2.21.0 or later. Earlier versions allow only a whole top-level field. Custom columns on the Logs page follow the same rules, so a custom column that reads a hidden field doesn’t block the page. How the column appears depends on what it does:
  • Returns a hidden field, or a field nested inside or containing one, such as input.input.command or metadata: Shows only the parts that aren’t hidden, or no value if the returned value is itself hidden.
  • Computes on a hidden field, such as len(input.input.command) or lower(input): Shows no value.
  • Has the same name as a built-in field, such as project_id: Takes the place of that field and follows the rules above.
  • Is named input: Causes the query to be rejected. A custom column named input that doesn’t read a hidden field works as usual.
On self-hosted deployments, this custom column behavior requires data plane v2.22.0 or later (not yet released). On earlier versions, any query that includes a custom column that reads a hidden field is rejected. Some queries are rejected because they could reveal hidden values:
  • Queries that filter, sort, group, aggregate, or compute on a hidden field, or on a field nested inside or containing it, including through a renamed column, such as ORDER BY m, or a custom column. A custom column that computes on a hidden field shows no value instead.
  • Queries that rename one of these fields in a subquery. An outer query can rename a field that the subquery returns whole.
  • Some selects of nested paths through arrays.
  • Audit log queries.
  • Async queries.
Full-text search skips any top-level field that contains a hidden field. For example, if metadata.user is hidden from you, search skips all of metadata. Facets and classifications, which Topics builds on, are also hidden from you.

Redact before upload

To remove sensitive values before they reach Braintrust, change data before it leaves your application or machine. Braintrust SDKs provide masking functions and span customizers for data logged by your application, and the bt CLI provides span plugins for coding-agent traces:
  • Masking functions: Functions that replace sensitive parts of field values, one value at a time, in a fixed set of fields: input, output, expected, metadata, context, scores, and metrics. The SDK runs your function on every record it logs. If it fails, the SDK uploads an error message in place of the affected field instead of the unmasked value.
  • Span customizers: Code that changes, adds, or removes fields on a span, including tags and error. The SDK runs your customizers before it uploads each span. Which spans they cover, and what happens when one fails, depends on the SDK.
  • Span plugins: JavaScript modules that change coding-agent traces, which don’t pass through an SDK. The bt CLI runs your plugins on your machine before it uploads the traces. See Transform spans with JavaScript.
Support for masking functions and span customizers varies by SDK. See the Redact sensitive data page for TypeScript, Python, Go, Java, or Ruby.
The C# SDK doesn’t support masking functions or span customizers. To remove sensitive data from its traces, use ingestion redaction, or remove it before you log it.

Next steps