Design notes One X-ray. Every recall. Every surface.
Debugging an agent-memory recall used to mean stitching three
separate outputs together: the tier-explain block, the audit log,
and the MMR diversification trace. Remnic now emits a single
RecallXraySnapshot that fuses all three. The same
snapshot is available from the CLI, HTTP, and MCP — CLI, HTTP,
and MCP all flow through one shared renderer, so the three
surfaces never drift.
Shipping slice-by-slice under
issue #570
. This page updates as each slice lands.
TL;DR. Opt-in via xrayCapture: true
on any recall call, or use the new remnic xray CLI.
The captured snapshot includes the served-by tier, a filter
trace with considered/admitted counts per gate, the score
decomposition (vector + bm25 + importance + tier prior + MMR
penalty) per result, the graph path (when applicable), and the
audit entry id.
What the X-ray answers
Which tier served this?
Each result is tagged with servedBy:
direct-answer, hybrid,
graph, recent-scan,
procedural, or review-context.
No more guessing whether QMD or the fallback path
materialized a given memory.
What dropped candidates?
The filter trace records every gate the recall
walked — namespace, trust zone, confidence, result limit —
with the candidate pool it saw and the number it admitted.
considered − admitted tells you exactly where
the dropped candidates went.
Why this score?
Every result carries a score decomposition:
final, vector,
bm25, importance,
mmrPenalty, tierPrior. You can
see the MMR penalty applied for diversity, the importance
prior applied by the tier, and the raw ranking signals.
Which audit entry?
Each result is cross-linked to its recall-audit entry id,
so you can jump from the X-ray back to the durable audit
ledger for forensic inspection or regression bisect.
Three surfaces, one renderer
CLI, HTTP, and MCP all call the same
recall-xray-renderer.ts module. The surfaces
cannot drift — a fix to the renderer fixes all three
simultaneously.
CLI
remnic xray "what editor do I use" \
--format markdown \
--namespace workspace-a \
--out ./xray.md
Flags: --format
(text|markdown|json), --budget,
--namespace, --out. Invalid
flag values throw listed-options errors rather than
silently defaulting.
HTTP
GET /engram/v1/recall/xray?q=…
Authorization: Bearer <token>
Returns the snapshot as JSON. Namespace scope is enforced
against the authenticated principal before the recall
fires; a mismatch returns
{snapshotFound: false} so
cross-tenant data cannot leak.
MCP
tools/call
name: "remnic.recall_xray"
arguments: { query, namespace?, budget? }
Available under both the canonical
remnic.* and the legacy
engram.* name (dual-naming invariant).
Returns identical JSON to the HTTP surface.
Renderer
renderXray(snapshot, "markdown")
renderXray(snapshot, "text")
renderXray(snapshot, "json")
Pure function in
packages/remnic-core/src/recall-xray-renderer.ts.
Golden-file tests guard the output shape on every commit.
Opt-in, zero overhead by default
Capture is gated on xrayCapture: true. Without
the flag, recall is byte-for-byte identical to the non-X-ray
path. There is no additional retrieval cost when a snapshot
is captured — the data is composed from values the
orchestrator has already computed. Capture failures are
caught and logged; they never propagate into the primary
recall path.
What's in the snapshot
{
"schemaVersion": "1",
"snapshotFound": true,
"query": "what editor do I use",
"snapshotId": "…uuid…",
"capturedAt": 1700000000000,
"sessionKey": "sess-42",
"namespace": "workspace-a",
"traceId": "trace-xyz",
"tierExplain": { "tier": "direct-answer", … },
"filters": [
{ "name": "namespace", "considered": 120, "admitted": 30 },
{ "name": "recall-result-limit",
"considered": 30, "admitted": 5, "reason": "cap=5" }
],
"results": [
{
"memoryId": "mem-1",
"path": "facts/tools/editor.md",
"servedBy": "direct-answer",
"scoreDecomposition": {
"final": 0.87, "vector": 0.81, "bm25": 0.42,
"importance": 0.9, "mmrPenalty": 0.05, "tierPrior": 0.2
},
"admittedBy": ["namespace", "trustZone", "importance"],
"graphPath": ["mem-root", "mem-1"],
"auditEntryId": "audit-2026-04-20-abc"
}
],
"budget": { "chars": 4096, "used": 1234 }
}
The schemaVersion field is version-gated so
downstream consumers can pin their parsers. The renderer
handles missing / out-of-range fields (including non-finite
capturedAt) gracefully rather than crashing.
Honest status
- Shipped Schema +
in-process capture (
xrayCapture: true) —
PR #578. - Shipped Shared renderer
(
renderXray) with text / markdown / JSON
formats and golden-file tests. - Shipped
remnic xray CLI command. - Shipped
GET /engram/v1/recall/xray HTTP route (bearer
auth + namespace scope). - Shipped
engram.recall_xray / remnic.recall_xray
MCP tool. - In flight Legacy
/recall/explain delegates to the xray renderer
in markdown mode for backwards-compatible output.
Status reflects the merge state of issue #570's 7 slices. A
slice flips from "In flight" to "Shipped" the moment its PR
merges into main.