Context system — architecture-review checklist
Published
Architecture-review checklist — the ten questions for any AI design
- What’s the context strategy? pre-index · read-on-demand · none — predicts cost shape & failure mode.
- Recall and precision as separate stages — retrieve wide, then rerank? Is it hybrid (lexical + semantic)?
- Chunking strategy — split on meaning, overlap, per-chunk contextual prefix so a chunk stands alone?
- Index freshness / invalidation — invalidate on write, or stale-by-default? Fetch live for volatile data?
- Is retrieval evaluated — recall@k / hit-rate on a labeled set — not just final answers (“vibes”)?
- Token budget + compression for long sessions — summarize, prune, prioritize within the window?
- Observe the assembled context per call — log exactly what was sent, so a wrong answer is debuggable & auditable?
- Are all five failure modes covered? missing · wrong · outdated · conflicting · excessive
- PII / compliance in retrieval — redaction, access control at the retrieve stage, injection defense (OWASP LLM)?
- Deterministic vs semantic retrieval matched to the data type — exact → structured query, fuzzy → hybrid + rerank?
Product teardown — name the strategy, the failure falls out
| Product | Context strategy | Strengths | Weaknesses | Signature failure |
|---|---|---|---|---|
| Cursor | Pre-indexed repo embeddings + semantic retrieval (+ open files) | Fast recall across huge repos; finds code before you know the filename | Index staleness; embeddings miss exact identifiers | Retrieves a topically-similar but wrong file |
| Claude Code | Agentic read-on-demand via tools (grep / glob / read); no persistent index | Always fresh; precise; transparent about what it read | More tool round-trips → latency & token cost; depends on good searches | Misses a file it never thought to grep |
| ChatGPT | Conversation history + optional retrieval / uploads / connectors / memory | Broad general capability; cross-session memory | Weak grounding in your live systems without connectors | Hallucinates when nothing was retrieved |
| GitHub Copilot | Open files + nearby code + (newer) repo / workspace indexing for chat | Low-latency inline local context | Limited surrounding window; weaker whole-repo reasoning | Suggests plausible code that ignores a distant constraint |
Product specifics are version-dependent / at time of writing — review the architecture, not the version.
Production design — match retrieval to the data type
| Agent | Context strategy (matched to data) | Scalability | Cost | Reliability | Observability |
|---|---|---|---|---|---|
| Billing | MATCH Deterministic structured query / SQL keyed by account_id — never fuzzy embeddings | Cheap point lookups | Low tokens | No hallucinated numbers; quote only what was pulled, never synthesize | Log every assembled context + tool call for audit / disputes |
| Support | Hybrid over help-center KB + customer history (memory); rerank | KB grows; cache hot articles | Moderate | KB freshness; PII handling / compliance | Retrieval hit-rate; deflection/escalation; cite sources to user |
| Engineering | Codebase hybrid + structural retrieval and/or read-on-demand; tests as a grounding signal | Large repos; token-heavy | Token cost dominates | Ground in real code; run tests | Log which files / symbols loaded per task |
| Research | Multi-source web/doc retrieval, multi-step; compress intermediate findings; keep citations | Many calls / sources | High (fan-out) | Adversarial verification; dedupe conflicting sources | Source provenance per claim |
The senior reflex: exact & financial → structured query; fuzzy & textual → hybrid + rerank; volatile → fetch live; long-running → compress + remember.
The five failure modes — symptom → cause → fix
| Mode | Symptom | Root cause | Fix |
|---|---|---|---|
| Missing | ”I don’t have info on that” / vague answer | Relevant doc never retrieved (recall gap) | Improve recall: hybrid retrieval, better chunking, raise k |
| Wrong | Confident answer about the wrong thing | Topically-similar but incorrect chunk ranked top | Add rerank; lexical signal for exact identifiers |
| Outdated | Answer reflects an old state of the world | Stale index / cached doc | Invalidate on write; or fetch live for volatile data |
| Conflicting | Inconsistent answers; arbitrary choice | Sources disagree; no resolution policy | Dedupe, prefer authoritative source, surface the conflict |
| Excessive | Slow, costly, “lost in the middle” | Too much low-signal context packed in | Tighten selection; rerank; compress; trim history |
Where the failure enters the pipeline
ingest -> chunk -> index -> retrieve
-> rerank -> assemble -> LLM -> log
MISSING at retrieve (recall gap)
WRONG at rerank (bad ranking)
OUTDATED at index (freshness)
CONFLICTING at assemble (no policy)
EXCESSIVE at assemble (over budget)
Each stage gets its own metric.
A wrong answer with the RIGHT context
= a reasoning bug.
With the WRONG context
= a retrieval bug. Separate them.RED FLAGS in a context architecture
”Just use vector search for everything” · semantic search over exact/financial data (returns most-similar, i.e. confidently wrong) · pure embeddings with no lexical / rerank stage · an index with no invalidation (stale-by-default) · “we evaluate by trying it” — no labeled set, no recall@k · no compression plan for long sessions · the assembled context is not logged (“the wrong answer is undebuggable”) · no PII redaction / access control at retrieve · tool/retrieved content trusted as instructions (injection) · “we’ll add observability later.”
Evaluation & observability — what to probe L6
- Is retrieval measured on its own? recall@k / hit-rate (did the right doc make the top-k at all) — not just end-answer quality. A high end-to-end score masks low recall on the hard slice; the model bluffs from parametric memory on easy queries.
- Reranker / order graded? precision@k, MRR, nDCG judge the final order on top of high recall — separate metric, separate stage.
- Answer half graded against the context? faithfulness / groundedness (every claim supported → catches hallucination), answer relevance, context precision/recall. A grounded answer over bad context is a retrieval bug; a hallucination over good context is a generation bug — don’t fix the wrong half.
- Versioned golden set + offline regression in CI? query · relevant doc IDs · ideal answer, replayed pre-deploy to catch regressions before users do — not “we evaluate by trying it.”
- Online signals tracked? thumbs up/down, deflection / escalation, citation-clicks, follow-up / rephrase rate — curated back into the golden set so the next offline run catches them.
- Is the assembled context logged & traceable per call? query (+ any rewrite), retrieved IDs+scores, packed chunks, final answer — so “the bot was wrong” becomes “doc X wasn’t retrieved.” A wrong answer with the RIGHT context is a reasoning bug; with the WRONG context it’s a retrieval bug.
- LLM-as-judge calibrated? if used to scale faithfulness/relevance grading — anchored to human labels on a sample, watched for judge bias (verbosity, position, self-preference). Use it to scale, not to define truth.
Pre-retrieval & advanced RAG — decision points L7
| Probe | Reach for… | When it justifies the cost |
|---|---|---|
| Recall is low — is the raw query transformed before retrieval? | rewrite · multi-query · HyDE · decomposition · step-back · routing | The query is the worst search query you have; recall lost at retrieve can’t be recovered by any reranker or bigger model. Cheapest place to fix recall. |
| Does the retrieval structure match the question shape? | local fact → small-to-big / parent-doc; large doc → hierarchical; ambiguous chunk → contextual; global theme → GraphRAG | Flat top-k is a floor, not a ceiling. GraphRAG earns its keep only on theme-spanning questions; it’s wasted complexity (build + keep-fresh) on “what is X?”. |
| Multi-part question (e.g. “EU vs US refund policy”)? | decomposition (split → retrieve each → combine) | One embedding averages two facts and matches neither; verify both regions’ chunks appear in the assembled context. |
| Is an agentic / corrective loop used? | grade docs · re-retrieve / web fallback · critique the draft | ONLY where correctness justifies the extra latency & cost — retrieval becomes an action in a loop, not a one-shot step. |
Red flag: “a better reranker will fix our low recall” — reranking only reorders what was already retrieved; a doc never in the candidate set can’t be surfaced. That’s a pre-retrieval problem.
Embeddings, indexing & cost — what to probe L8
- Is the ANN index choice justified?
HNSW(graph — fast, high recall, memory-heavy) vsIVF(cluster — tune speed via #probes) vsPQ(compress — big memory savings, lossy → lower recall; oftenIVF+PQ) — picked against the recall ↔ latency ↔ memory triangle, not by default. Don’t reach for a vector DB before you need one. - Is index freshness / invalidation handled? incremental upserts / CDC on edit, deletes on removal, invalidation on source change. A stale index is the outdated-context failure (L4), just upstream — monitor oldest-chunk age as an SLO so staleness is observable, not silent.
- Is volatile data fetched live, not embedded? prices / availability change constantly → TTL or fetch via a structured tool at query time; never bake fast-changing fields into the index.
- Is a re-embedding plan in place? changing the embedding model = re-embed the whole corpus behind a shadow index + cutover (old and new vectors are incomparable) — quantify tokens-per-chunk × chunk count × price, validate the win on an eval set first.
- Cost levers identified & measured? input tokens usually dominate → fewer-but-better chunks (also more accurate), trim the prompt, rerank only the top-n, cheaper / Matryoshka-truncated embedding model, batch corpus embedding, prompt caching of the stable prefix. Validate each cut against an eval set so you don’t trade accuracy for dollars.
Caching, ordering & security — what to probe L9
Cost & ordering
- Prompt structured stable-first / volatile-last? system + tools + few-shots + static docs in one byte-stable prefix at the top (the prefix is the cache key); query, retrieved docs, timestamps, session IDs strictly after it. Any edit above a token busts the cache from there down.
- Ordering managed for lost-in-the-middle? attention is U-shaped — edges get read, the deep middle gets skimmed. Put the query last, the best retrieved doc at an edge, cap history / tool-output bloat. Caching and recency agree: the volatile query last satisfies both.
- Explicit delimiters? XML tags / headers so the model separates instructions from data from query — also shrinks the injection surface.
Security & multi-tenancy
- Retrieved content treated as untrusted? it is data the model reads, never instructions it follows — indirect prompt injection rides in through your own KB (even internal docs: pasted emails, scraped pages, uploads). Delimit it; filter output.
- ACL IN THE QUERY Multi-tenant access control enforced in the RETRIEVAL QUERY (pre-filter by
tenant_id/ ACL at the index), NOT via a prompt instruction. The prompt is not a security boundary — like SQL row-level security, authorization belongs in the WHERE clause, not a comment asking the query to behave. If another tenant’s docs were retrieved, they’re already in context. - PII & OWASP LLM Top 10 covered? injection (#1) · sensitive-info disclosure (redaction, retention/residency limits, least-privilege retrieval) · data exfiltration (constrain tool egress, least privilege).
VP / leadership review questions
- Build vs buy? Buy when the data is generic and the vendor’s strategy fits; build when our differentiation is retrieval over proprietary data. The model is a commodity; the pipeline is the moat. grounding in live systems
- Retrieval investment vs a model upgrade? Retrieval fixes compound across every feature; a model upgrade is a flat tax on every call. Better retrieval lifts accuracy, cuts cost, and reduces hallucination at once.
- How do we measure retrieval quality? recall@k + rerank precision on a labeled set; production hit-rate; deflection/escalation for support, audit-pass for billing — tracked separately from end-answer accuracy.
- Cost levers? Cost scales with tokens sent — tighter selection + rerank, compress long sessions, trim history, cache hot retrievals. Right context on a cheaper model often beats wrong context on the flagship.
- Risk & compliance? PII in retrieved context → redaction + access control at retrieve; injection via poisoned content → guardrails before the model; auditability → log assembled context per call; finance → deterministic retrieval + no-synthesis rule.
- Upgrade the model, or fix retrieval? Instrument first — was the right context retrieved for the failing cases? If no → fix retrieval (cheaper, compounds). If yes and multi-step reasoning is the bottleneck → pay for model capability. Never upgrade to paper over a retrieval gap.
- How do we measure retrieval quality? recall@k / hit-rate on a versioned golden set, graded separately from the answer; reranker order via nDCG; production signals (deflection, citation-clicks, rephrase rate). If the only answer is “we try it,” there is no measurement. L6
- What’s our eval / observability maturity? Is there an offline regression gate in CI, online signals fed back into the golden set, and a per-call trace of the assembled context — so any wrong answer is debuggable to a stage (retrieval vs generation)? “We’ll add observability later” is the red flag.
- What’s our multi-tenant data-isolation guarantee? Access control enforced in the retrieval query (scoped by
tenant_id/ ACL at the index), never via a prompt instruction — the prompt is not a security boundary. Plus injection defense on untrusted retrieved content and PII handling per OWASP LLM Top 10. ACL in the query