# Privacy

> The two privacy profiles, what a metadata_only document may hold, and how the promise is kept.

Agent runs are full of private text: prompts, code, tool output, customer data. Most of what a consumer needs to compare runs is not that text but its shape: which agents ran, with which models, for how many tokens, and whether the result was accepted. OCP makes the difference explicit. Every document MUST declare a privacy profile, so a reader knows what it is holding before it opens a single field.

```json
"privacy": { "profile": "metadata_only" }
```

- `profile` (enum, required): metadata_only: no prompt, completion, or transcript text anywhere in the document; free-text fields hold only short producer-authored labels. full: text may appear in ext namespaces (never in core fields).

  One of: `metadata_only`, `full`.

- `note` ([ShortText](https://orchestrationcontextprotocol.io/specification/0.3/schema#shorttext))

- `ext` ([Ext](https://orchestrationcontextprotocol.io/specification/0.3/schema#ext))

## Profiles

| Profile | What it promises |
|---|---|
| `metadata_only` | No prompt, completion or transcript text anywhere in the document. Free-text fields hold only short labels the producer wrote. |
| `full` | Text MAY appear inside `ext` namespaces. Core fields still hold only labels, never text. |

`metadata_only` is a first-class profile, not a reduced one: every field this specification defines is available under it.

## What a metadata_only document holds

| Kept | Left out |
|---|---|
| The run graph: nodes, edges, groups | Prompts and system prompts |
| Harness, model and reasoning effort of every attempt | Completions and reasoning text |
| Token counts per stream, dollars and the price table | Transcripts and tool output |
| Status, outcome, verdicts and evidence tiers | Artifact contents: an artifact is recorded by path, never by content |
| Task type, features and ids; configuration and signals | Anything a user typed, beyond a short label the producer chose |
| Short labels: titles, reasons, receipts, details | |

## Requirements

- The schema caps the designated label fields (titles, reasons, receipts, details, evidence notes and `labels` values) at 500 characters. Other strings, such as `task.features` values, setting `options` and `ext` payloads, are not capped.
- Under `metadata_only`, a field MUST NOT contain prompt, completion or transcript text, whether capped or not. A title such as "fix flaky retry test" is a label; the issue body it came from is text.
- Under `full`, text MUST stay inside `ext` namespaces; core fields hold labels under either profile.
- Locators such as `artifact.path`, `attempt.cwd` and `task.repo` are not text, but they can still be sensitive. A producer MAY write them as opaque ids.

## How the promise is kept

The schema checks the length cap on the label fields that carry it, and nothing else. The rule that no field holds transcript text cannot be checked mechanically: no checker can tell a 400-character label from 400 characters of prompt. It is a promise the producer makes by declaring the profile, and it is part of what a conforming producer does ([Conformance](https://orchestrationcontextprotocol.io/specification/0.3/conformance#not-checked-mechanically)). A consumer that takes documents from producers it does not control is relying on that declaration, and can spot-check it.

A tool that shares documents further can reduce them more. loopmath's `share` command, for example, hashes repository names and removes titles, paths, commands, session ids and commit hashes before anything leaves the machine.
