> ## Documentation Index
> Fetch the complete documentation index at: https://glassray.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Privacy & redaction

> What @glassray/tracing sends, what it never sends, and the four layers of content control - in the order they apply.

Glassray traces carry **content by default** - inputs, outputs, and LLM messages - because discovery judges traces on evidence, and a trace without content can't be judged. That makes the controls first-class: four layers, applied in a fixed order at serialize time, each able to remove content the layer below would have sent.

## What leaves the process

* Span structure: names, kinds, nesting, timing.
* LLM metadata: model, provider, token usage.
* Content attributes: trace/span inputs and outputs, LLM messages - **after** the controls below run.
* [Metadata](/sdk-metadata): customer, environment, agent, flow, session ID.

## What never leaves the process

* Anything a control below removed - hidden, scrubbed, or redacted values are replaced **before** serialization; the raw value is never queued or sent.
* Any telemetry about you or your code. The SDK has **zero phone-home** beyond the traces themselves - no usage pings, no error reporting, no fetch to anywhere but your configured endpoint.

## The controls, in precedence order

Each applies to content attributes only - structure, names, timing, and tokens always flow, so flows and shape detection keep working even for a maximum-privacy setup.

### 1. Hide switches

`GLASSRAY_HIDE_INPUTS` / `GLASSRAY_HIDE_OUTPUTS` (or `hideInputs` / `hideOutputs` on the constructor) replace the corresponding content wholesale with `[hidden]`. This is the max-privacy mode: Glassray still sees what your agent *did*, never what it said.

### 2. Scrub-by-default

On unless you turn it off (`scrubbing: false`): secret-shaped keys inside structured I/O - `password`, `api_key`, `secret`, `token`, `authorization`, `cookie`, `jwt`, `ssn`, credit-card-shaped keys, and `sk_…`-shaped values - are replaced with a placeholder that says why:

```
[scrubbed: matched 'api_key']
```

### 3. Your `redact` hook

A `redact(key, value)` function on the constructor sees every content attribute and returns what to send. It is **fail-closed**: if your hook throws, the value becomes `[redaction hook failed - value withheld]` - a buggy hook can never leak the raw data.

```ts theme={null}
const glassray = new Glassray({
  redact: (key, value) => (key.includes("email") ? "[pii]" : value),
});
```

### 4. Per-call capture flags

Switch capture off for a single sensitive step without touching anything else:

```ts theme={null}
await t.tool("lookup-patient", { captureInput: false, captureOutput: false }, () =>
  lookupPatient(id),
);
```

<Note>
  The ingest key itself is **write-only** (`traces:write`): even if it leaks from your environment, it cannot read back any trace - yours or anyone else's.
</Note>
