# Context Attribution

After every assistant turn, Anteroom records a bounded, safety-scanned summary of what fed into that turn: recent chat turns, recalled memories, retrieved RAG sources, executed tool calls, attached packs, and loaded project instruction files. This summary is called **runtime context attribution**, and it makes the invisible parts of the context window visible.

## Why It Exists

LLM responses are the product of their context. When you ask *"why did the assistant bring up `README.md`?"* or *"did that memory about timezone preferences actually get loaded?"* you are really asking **what was in the context window for that turn**. Attribution answers that question without having to dig through logs or inspect the database by hand.

It also provides a privacy audit trail: the snapshot records only **IDs and labels**, never raw memory bodies or source chunks. Every user-derived label flows through the same DLP scanner and output filter that protect streamed responses, so whatever redaction policy your installation has for model output applies identically here.

## What's In the Snapshot

Each turn's snapshot has six sections, capped at 20 entries each:

| Section | One line per | What it tells you |
|---|---|---|
| **Recent turns** | Chat turn fed into the prompt | Context carried forward from the conversation |
| **Recalled memories** | Durable memory retrieved | Which of your user/project/local memories were surfaced |
| **RAG sources** | Knowledge chunk retrieved | Which documents / past conversations the retriever pulled |
| **Tool calls** | Tool the assistant actually invoked | Which operations ran during the turn |
| **Attached packs** | Pack in force for the turn | Which artifact bundles shaped the system prompt |
| **Project instructions** | Instruction file loaded into the system prompt | Which `ANTEROOM.md` / `CLAUDE.md` / global instruction file actually landed. Records `path`, `scope` (`global`/`project`), and `estimated_tokens`. A file that was skipped by `--no-project-context` or a denied trust prompt does NOT appear here. |

Plus two counters that sit on the summary line:

- `DLP:N` — how many labels were redacted or warned on by the DLP scanner.
- `OF:N` — how many labels triggered the output filter.

If a section had more than 20 entries, the last row is a `+N more` marker.

## Where You See It

### CLI

Each turn ends with a single muted line:

```
[ctx] 3 turns · 2 memories · 1 sources · 2 tools · 1 packs · 1 instruction file — /attribution for detail
```

The `N instruction file(s)` segment is hidden when no instruction file is loaded, so the default zero-context footer stays compact.

Type `/attribution` to expand the six tables for the most recent turn.

You can quiet the footer with:

```yaml
cli:
  show_attribution_footer: false
```

### Web UI

The assistant message grows a collapsed **"Why this context? — …"** disclosure. Click to expand; it renders the same six sections inline under the message. All values are drawn with `textContent`, so hostile payloads render as literal text and never as markup.

### Persisted Metadata

The snapshot is stored under `messages.metadata["attribution"]` on the assistant message, so it survives reloads and resumes. Reloading a conversation reconstructs the same footer without re-running the turn.

## Safety and Bounds

- **IDs and labels only.** The builder never includes content, raw memory bodies, or source text.
- **Every label is scanned.** DLP runs first, then the output filter. `redact` replaces the label with the scanner's output; `block` substitutes `[DLP blocked]` or `[output filter blocked]`; `warn` keeps the label and bumps a counter.
- **Per-request instances.** The scanners used are the live `_dlp_scanner` and `_output_filter` already attached to the turn, not separately instantiated — so they honour any per-request or per-space policy.
- **Hard cap.** Twenty entries per section, no exceptions. A serialised snapshot fits comfortably under 8 KB.

## Related

- [How memory recall works](how-memory-recall-works.md) — where the *memory* section comes from.
- [How RAG works](how-rag-works.md) — where the *sources* section comes from.
- [CLI commands](../cli/commands.md#attribution) — `/attribution` reference.
- [Web UI overview](../web-ui/index.md) — "Why this context?" footer reference.
- [Config file](../configuration/config-file.md) — `cli.show_attribution_footer`.
