Rekalldocs
Guides

The reasoning trace

Why did it find that? Walk a real multi-hop query hop by hop — the trace is the proof that Rekall reasons, and explainability vector search structurally cannot offer.

The trace is the product. It's not debug output — it's the receipt that shows Rekall followed a chain of reasoning to its answer. Turn it on with return_trace: true (--trace on the CLI); it costs almost nothing.

A real multi-hop query

Over the demo corpus (contracts + policies), ask a question that cannot be answered by similarity — it requires reading one document, then finding the conflicting clause in another:

rekall search "which supplier contract conflicts with the 2026 policy?" \
  --store demo --trace
Output
● 2 passages · 2 hops · confidence 0.87 · 4.2 ms

  1. supplier_a.pdf     score 0.92   hop 1
     "…Supplier A payment terms are net-90 as amended in §4.2…"
  2. policy_2026.md     score 0.81   hop 2
     "…all supplier payment terms must not exceed net-60…"

  reasoning trace
  hop 1 → supplier_a.pdf   (matches query)
  hop 2 → policy_2026.md   (conflict found, given hop 1)
  ✓ sufficient — stopped after 2 of 4 max hops
const r = await store.search(
  "which supplier contract conflicts with the 2026 policy?",
  { trace: true },
);
console.log(r.trace);
Output
[
  { hop: 1, docId: 'supplier_a',  why: 'matches query' },
  { hop: 2, docId: 'policy_2026', why: 'conflict found, given hop 1' }
]
r = store.search(
    "which supplier contract conflicts with the 2026 policy?",
    trace=True,
)
print(r.trace)
Output
[TraceStep(hop=1, doc_id='supplier_a',  why='matches query'),
 TraceStep(hop=2, doc_id='policy_2026', why='conflict found, given hop 1')]

Hop by hop

Hop 1 — address the query

The engine encodes the query into the store's address space and reads the most relevant passage: supplier_a.pdf"Supplier A payment terms are net-90…". The why is "matches query": this passage looks like the question. A vector search would also find this. The interesting part is what happens next.

Absorb

A small controller absorbs what hop 1 read. The engine now "knows" that Supplier A's terms are net-90 — this fact becomes part of the query state for the next hop.

Hop 2 — re-address, given what it knows

The engine re-addresses the store conditioned on hop 1. It retrieves policy_2026.md"all supplier payment terms must not exceed net-60" — with the why "conflict found, given hop 1".

This is the key move: policy_2026.md shares no keywords with the original query ("which supplier contract conflicts…"). Similarity search cannot reach it. Rekall reaches it because the reasoning state — net-90 terms that need checking against policy — points there.

Sufficiency stop

A learned sufficiency head decides it has enough to answer and stops after 2 of a possible 4 hops. You never told it a contradiction takes two hops — it decided. That's what hops_used: 2 and confidence: 0.87 report.

The trace schema

Each TraceStep has three fields:

Prop

Type

Adaptive effort — a longer chain

Not every question takes two hops. Evidence-aggregation questions fan out across more documents, and the engine spends more hops before its sufficiency head is satisfied:

rekall search "what evidence supports ending the legacy billing contract?" \
  --store demo --trace
Output
● 4 passages · 4 hops · confidence 0.79 · 8.1 ms

  reasoning trace
  hop 1 → billing_legacy.pdf   (matches query)
  hop 2 → incident_2025.md     (outage evidence, given hop 1)
  hop 3 → sla_addendum.pdf     (breached SLA terms, given hop 2)
  hop 4 → finance_review.md    (cost overrun, aggregates prior hops)
  ✓ sufficient — stopped after 4 of 4 max hops
const r = await store.search(
  "what evidence supports ending the legacy billing contract?",
  { trace: true },
);
console.log(r.hopsUsed, r.confidence);  // 4 0.79
console.log(r.trace);

The same engine, same defaults — it simply worked harder because the question demanded it. hops_used is your window into that.

Why vector search can't do this

A vector database does one lookup: it returns the passages most similar to your query embedding. It has no notion of "given what I just read, what matters next," so it cannot produce a policy_2026.md that shares no words with the query — and it has nothing to put in a why. The trace is a structural consequence of reasoning at retrieval time, which is exactly what similarity search lacks.

Turn it on everywhere

return_trace is near-zero cost. Enable it in production for explainability and audit — a reviewer, an auditor, or a user can see why each document was retrieved.

Next steps

On this page