RAG Observability: Which Events and Contexts to Log
Trace a decision receipt without turning every conversation into telemetry
Versioned evidence, bounded event fields, redaction, terminal routes and reviewable ownership
Original OBSERVE-8 public synthetic workflow with explicit limits, not an observability guarantee
RAG observability, RAG telemetry, RAG tracing, AI system logs, RAG evaluation and safe event design

$ observe rag --contract OBSERVE-8
> bind: receipt / policy / index / route
> retrieve: eligible counts / permitted locators
> redact: payload fields / trace dimensions / retention
> inspect: versions / reason codes / terminal event
> route: answer / clarify / no-answer / deny / reviewRAG observability is not a request to store every prompt, passage and completion forever. Its job is to let an owner answer a bounded engineering question: what route did this request take, what versioned evidence was eligible, and where did the result become unsafe, unavailable or unhelpful?
That question needs a receipt, not a surveillance archive. The receipt must preserve enough linked events to reproduce a failure class while minimizing sensitive content. The wider product and delivery conversation belongs on RAG systems and AI specialist Armenia. This guide supports those pages with implementation criteria; it does not replace their commercial intent or promise compliance.
Define an observable decision before choosing a tracing tool
Start from routes a real system is allowed to take. A request can return a cited answer, request clarification, return no-answer, deny access or wait for review. For each route, identify the owner who must decide whether it was expected. Then record a stable requestReceiptId, configuration versions and safe references to the relevant inputs.
OBSERVE-8 uses four linked records:
| Record | Minimum fields | Why it exists |
|---|---|---|
| Request receipt | opaque ID, authenticated scope reference, declared purpose, locale, received time | connects events without copying identity payloads |
| Retrieval receipt | corpus/index version, policy version, eligible count, selected source locators | explains what evidence could influence the answer |
| Generation receipt | model and prompt-template version, bounded token/count signals, output route | distinguishes an answer path from a blocked or unavailable path |
| Review receipt | reason code, severity, decision owner, follow-up locator | keeps a human decision inspectable without embedding the whole incident |
An identifier is not automatically harmless. Keep cross-system IDs opaque, restrict raw-event access and define retention with the data owner. Do not log a prompt or document excerpt merely because a field is convenient to search later.
OBSERVE-8: an event flow with a redaction boundary
The workflow separates product behavior from telemetry behavior. Authorization decides whether retrieval may start. Retrieval emits counts and permitted locators, not the entire candidate payload. A redaction step removes or hashes fields that do not belong in operational telemetry. Routing stores why the system answered, clarified, denied, stopped or sent a case for review.
request -> authorize -> retrieve eligible evidence -> compose bounded proposal
-> redact telemetry fields -> evaluate route -> answer | clarify | deny | review
-> link receipt IDs, versions and reason codesThe source locator needs an independent access rule: a reviewer who can inspect a trace may still be unable to open the underlying customer document. Likewise, a support dashboard must not be able to reassemble a secret from event fragments. The related access-control guide covers upstream eligibility; retrieval metrics covers what to measure in a declared evaluation set.
Choose events that can explain a failure without capturing the conversation
Useful events are narrow and typed. They capture a transition, a version or a reason code—not an unbounded prose blob. An implementation can start with this event family:
| Event | Safe example signals | Do not treat as a default field |
|---|---|---|
request.accepted | receipt ID, policy version, locale, declared route class | raw user prompt, email, account name |
retrieval.completed | eligible count, latency band, index revision, permitted locator IDs | full chunks, titles from restricted documents |
evidence.selected | claim-to-locator count, freshness state, no-evidence reason | hidden ACL values or document text |
route.decided | answer / clarify / no-answer / deny / review, reason code | generated answer body |
tool.proposed | action type, allowlist decision, approval state | arguments containing customer data |
review.closed | resolution category, owner reference, corrected config version | incident narrative copied into broad analytics |
Retain bounded samples only when an approved incident process needs them. Store the sample separately, encrypt and access-control it, attach an expiry and make the decision visible in the receipt. That is different from quietly adding complete content to every trace.
Inspect one synthetic run from input to route
Use harmless fixture documents so the team can validate correlation before involving customer records. In this synthetic example, a user asks a support question. The trusted scope permits one current help collection; the expected answer depends on two known locators.
{
"requestReceiptId": "obs_demo_017",
"policyVersion": "rag-policy-2026-09",
"indexVersion": "help-current-42",
"events": [
{ "name": "request.accepted", "purpose": "support" },
{ "name": "retrieval.completed", "eligibleCount": 12, "selectedLocators": ["help:returns#v4", "help:delivery#v7"] },
{ "name": "evidence.selected", "coverage": "sufficient" },
{ "name": "route.decided", "route": "cited-answer", "reason": "permitted-current-evidence" }
]
}The point is not the number 12. It is the relationship: a reviewer can find the policy and index version, see that the chosen locators were permitted, and distinguish an evidence problem from a routing problem. If a locator becomes stale, the synthetic test should expect review or no-answer rather than a confident stale response.
Test the telemetry contract alongside the RAG contract
Observability itself can fail. Add checks to the normal evaluation set and release process:
- Correlation. Every terminal route has a receipt ID, required version fields and a bounded reason code.
- Minimization. A deliberately sensitive fixture does not appear in permitted event fields, queryable dimensions or exported dashboards.
- Authorization. A user with trace access cannot open a source locator unless their separate document policy permits it.
- Completeness. A simulated timeout, empty retrieval, denied scope and review route emit the expected terminal event once.
- Change detection. A prompt, policy, index or tool change produces a distinguishable version receipt; an unknown version holds the release for review.
- Operational use. An owner can follow one synthetic receipt from a symptom to a route and decide the next action without reading a customer conversation.
Keep evaluation results segmented by route and risk class. One average latency or answer score cannot show whether denied retrieval was correctly denied, whether no-answer was honest or whether a new index version removed evidence. A route distribution may signal a change worth investigating, but it is not proof of product quality on its own.
Make review and retention part of the production boundary
Before enabling a new trace field, name its purpose, audience, retention period, storage boundary and removal path. Recheck the field when a prompt template, tool call, collection or downstream analytics destination changes. If the team cannot state why a field is needed, do not collect it by default.
OBSERVE-8 is an original public engineering pattern, not an observability product specification, legal advice or a claim that a RAG system is safe. Use it to conduct a controlled architecture review: define the terminal routes, prove telemetry minimization with synthetic fixtures, and assign owners for redaction, access, retention and release decisions. For a scoped implementation discussion, start with RAG systems or AI specialist Armenia.
require(receipt.id && receipt.policyVersion && receipt.indexVersion);
require(event.route && event.reasonCode && event.occurredAt);
require(telemetry.excludesSensitiveFixture && telemetry.locatorsAreAccessControlled);
require(testSet.timeout && testSet.empty && testSet.denied && testSet.review);
if (event.versionUnknown) route = "hold-for-review";
if (scope.denied) route = "deny-before-retrieval";
if (evidence.missing) route = "clarify-or-no-answer";
if (telemetry.redactionFailed) route = "stop-and-investigate";