Traces
DriftWise records traces of every LLM call made during plan analysis, drift narratives, and noise fix generation. Traces help you understand how the AI reached its conclusions and debug unexpected results. For endpoint shapes, see the scans tag of the API reference — trace endpoints live there alongside scan lifecycle.
Viewing traces
List traces for a scan via GET /orgs/:id/scans/:scan_id/traces. The
list returns summary metadata — ID, kind, token counts, latency,
cache status. To fetch the full trace body (prompt, response,
structured parsed output), call GET /orgs/:id/traces/:trace_id.
Trace IDs are prefixed trc-.
The full-fetch endpoint returns different status codes for different trace states:
200 OK— trace is ready (or failed); body contains the details202 Accepted— trace upload is still in progress. The backend inserts the trace row and uploads the body asynchronously after the LLM call returns, so there's a brief window where the DB row exists but the body doesn't.410 Gone— the trace body has been deleted (the retention window elapsed or the underlying object was removed). The metadata row is still returned so clients can keep rendering a timeline entry.
Trace fields
| Field | Description |
|---|---|
id | Trace ID (trc- prefix + 24 hex chars) |
kind | Operation type — see Trace Kinds below |
model | LLM model used |
input_tokens | Token count for the input prompt |
output_tokens | Token count for the response |
latency_ms | End-to-end LLM call time in milliseconds |
cached | true when the result was served from the in-memory classifier LRU instead of calling the LLM. Only classify traces ever set this flag — other kinds always emit false. |
fallback | Whether fallback (non-LLM) generation was used |
error | Error message if the LLM call failed |
inputs | The data sent to the LLM (plan JSON, resource state, etc.) |
parsed | Structured output extracted from the LLM response |
Admin vs. regular view
Traces contain sensitive data (full prompts and raw LLM responses). Access is tiered:
| Field | Regular user | Platform admin |
|---|---|---|
| ID, kind, model, tokens, latency | Yes | Yes |
| Inputs and parsed output | Yes | Yes |
| System prompt | - | Yes |
| User prompt | - | Yes |
| Raw LLM response | - | Yes |
Regular users see enough to understand what data was analyzed and what the LLM concluded. Admins see the full prompts for debugging prompt engineering and injection issues. The server applies the redaction before the response is written — the wire format is the same shape for both tiers, just with fields omitted for non-admins.
Trace kinds
| Kind | When generated |
|---|---|
narrative | Plain-English narrative for plan analysis |
drift-narrative | Narrative for cloud drift vs. Terraform state |
classify | Risk classification for a single change |
plan-noise-fix | AI-generated fix for a noisy plan pattern |
iac-gen | Terraform code generated from live resources |
Retention
Trace bodies live in object storage (GCS in production) and are
deleted by a bucket lifecycle rule 90 days after upload. Once the
body is gone, GET /traces/:trace_id returns 410 Gone with the
metadata row; the prompts, raw response, inputs, and parsed output are
unrecoverable. Download traces you need to retain longer.
Use cases
- Debugging unexpected risk scores — check what data the LLM received and how it reasoned.
- Monitoring LLM costs — track token usage across scans.
- Classifier cache efficiency — for
classifytraces, thecachedflag shows when the in-memory classifier LRU satisfied the request instead of calling the LLM. - Fallback detection —
fallback: truemeans the LLM was unavailable and a deterministic fallback was used instead.