# Traces and memory evolution

Graph-resident traces, reflection, elaboration, consolidation, and semantic response reuse.

## Tracing as graph-resident memory

SurrealDB Agent Memory stores three trace kinds as **first-class nodes** in the substrate, linked by real edges to entities, attributes, passages, and model calls. Traces are **inputs** to future ranking and consolidation - not only external telemetry.

| Trace | Emitted by | Holds (conceptually) | Typical edges |
| --- | --- | --- | --- |
| **`retrieval_trace`** | Every `/query` and ranked read | Query text, candidate sets per index, fused scores, returned subset, model metadata | `considered`, `returned`, `parent_trace` |
| **`decision_trace`** | Every reconciliation | Input extraction, confidence, trust, per-record outcome (created, updated, superseded, flagged), plus the acting principal, any **on-behalf-of** delegation target, and the session scope under which the write ran | `considered`, `created`, `superseded`, `flagged`, `parent_trace` |
| **`response_trace`** | `/chat` and `/reflect` | User message, assembled prompt, model response, tokens, cost, latency | `used_retrieval`, `produced_decision`, `wrote`, `parent_session` (session id for `/chat`; also populated on the unified query path) |

Traces are queryable (for example `GET /api/v1/{ctx}/traces` and `GET /api/v1/{ctx}/traces/{id}`) and inspectable from the CLI (`spectron inspect trace:…`). Trace listing respects the same access model as memory: principals with **`grant:manage`** or appropriate **`memory:read`** grants see traces in their region; others see only traces whose session scope falls within their read grant. See [Surface, models, and security](/docs/agent-memory/architecture/surface-security-and-models.md) for HTTP and CLI detail.

**Feedback loops** (examples):

- The ranker uses aggregated `retrieval_trace.returned` similarity - entities that helped similar queries get boosted; records tied to corrections get demoted. **Trace-feedback signals are scope-gated** - only traces visible under the caller’s read grant contribute to ranking for that query.
- Elaboration uses `decision_trace.considered` co-occurrence to propose links between entities that were examined together but never connected.
- Consolidation reinforces facts that `response_trace` shows were **actually used** in successful answers; untouched records can age out.
- Calibration uses repeated `decision_trace.superseded` lineage as a negative trust signal on the original source.

That is the difference between “we logged what happened” and “we **remember** what happened - and it changes what we do next.”

## Reflection, elaboration, and consolidation

Three mechanisms create new memory; they answer different questions and run at different times.

| Mechanism | Trigger | When | Output |
| --- | --- | --- | --- |
| **Reflection** | Caller asks a synthesis question | On-demand (`POST /reflect`) | Answer plus optional new facts (`source.kind = "reflect"`) |
| **Elaboration** | Background sweep (default); also ingest-time or targeted | Async / periodic | New relations and attributes (`source.kind = "elaboration"`) linking previously disconnected material |
| **Consolidation** | Async job; on-demand via `POST /consolidate` | Cron-style, triggered, or caller-initiated | Observation records (`source.kind = "consolidation"`) with cumulative `history`, `derived_from`, and `proof_count` across updates |

On-demand **`POST /consolidate`** is **caller-scoped** (pools only within the caller's `memory:read` region; persists only where `memory:write` applies). The background scheduler pass pools every scope and owns the consolidation watermark.

- **Reflection** is the *active* path: it runs when something **asks**.
- **Elaboration** and **consolidation** are *passive*: they evolve memory **between** user interactions.

All write through the **same reconciler** as turns and documents, so supersession and uncertainty rules stay identical.

## Semantic response reuse (tier 2)

Prior **`response_trace`** records can answer new questions when:

- The new question is the same or very similar (embedding similarity) **within** the same Context and scope, and
- Every entity and attribute cited via `used_retrieval → retrieval_trace.returned` is still **current** (no superseding writes, no new contradicting `uncertainty`).

Then SurrealDB Agent Memory can return the stored answer and link a fresh `response_trace` with **`reused_from`** pointing at the original trace.

This is **semantic response caching with entity-aware invalidation** - the cache key is not a raw string hash; it is the query plus the **set of facts** the prior answer depended on. When any cited fact moves, dependent responses invalidate automatically.

Operational notes:

- Reuse is **conservative** by default; similarity, freshness, and trust thresholds are tuneable per Context.
- A reuse still emits a **new** `response_trace` so the graph distinguishes “answered from cache” from “fresh LLM call”, and reinforcement continues to attribute to the original.

The [REST API](/docs/agent-memory/reference/rest-api.md) and [MCP tools reference](/docs/agent-memory/integrations/mcp-server/tools-reference.md) exercise these paths.
