Skip to main content

Overview

A trace is the complete record of a single agent run - the task it was given, the full message trajectory (every user message, assistant response, and tool call), which memories were retrieved, and which model was used. Think of it as a structured log entry that Reflect can learn from. A review is a pass/fail judgment on a trace. When you review a trace, Reflect:
  1. Reads the trajectory, the outcome, and your feedback
  2. Generates a concise reflection (an LLM-produced summary of what worked or went wrong)
  3. Embeds the reflection and stores it as a new memory with an initial utility of 0.5
  4. Updates the utility scores of the memories that were retrieved during that run (up for pass, down for fail)
Without reviews, Reflect is just a trace logger. Reviews are what close the learning loop - they’re the training signal that makes memory retrieval improve over time.
Reviewing a trace is one of two ways to create a memory. If your agent already knows the lesson, it can author the reflection itself and skip the trajectory entirely - see agent-authored reflections and the MCP create_memory tool.

Why traces capture the full trajectory

Reflect stores the entire conversation, not just the final answer, because the reflection LLM needs context to generate useful advice. A reflection like “always verify the order exists before processing a return” can only be generated if the trajectory shows that the agent didn’t verify the order. The final answer alone wouldn’t reveal that. The trajectory also enables the dashboard to show step-by-step replays, which is useful for debugging and manual review.

Why reviews are separate from traces

Reviews can be submitted inline (at trace creation time) or deferred (later, via the API or dashboard). This separation exists because:
  • Automated pipelines know the answer immediately (e.g., comparing against a gold answer) and can submit inline reviews
  • Human review workflows need to collect the trace first and review asynchronously
  • Batch evaluation collects many traces and reviews them all at once
Both paths produce the same result: a reflection is generated, a memory is created, and utility scores are updated.

Three ways to record traces

The SDK provides three patterns for recording traces. They all produce the same result - a trace stored in Reflect - but differ in how much boilerplate they handle for you.

Pattern 1: Context manager

The context manager retrieves memories on entry and auto-submits the trace on exit. It tracks retrieved_memory_ids for you, so the utility learning loop works automatically. Best for: multi-step workflows, streaming, cases where you need to inspect output before deciding the review result.

Context manager parameters

ctx.trace_id

After the with block exits, ctx.trace_id contains the ID of the submitted trace. This is useful for deferred reviews — pass it to client.review_trace() later in your application. Inside the with block (before submission), trace_id is None.

set_output parameters

Blocking mode

Pass blocking=True to wait for the reflection and memory to be created before the with block exits. Useful in evaluation loops where the next task needs to retrieve the memory from the previous one.

Exception handling

If an unhandled exception occurs after set_output was called, the trace is auto-submitted with result="fail" and the exception message as feedback. This prevents losing trace data on crashes. Disable with auto_fail_on_exception=False.

Async variant

Pattern 2: @reflect_trace decorator

The decorator wraps a function so that memory retrieval, trace submission, and retrieved_memory_ids tracking happen automatically. You just write the agent logic. Best for: single-function agents, clean integration with existing function signatures, when you want the least boilerplate.

Decorator parameters

Two return types

Return a TraceResult when you need to provide the full trajectory, review result, feedback, model, or metadata. Return a plain string for quick prototyping - the string is used as both the trajectory and the final response.

Async support

Async functions are detected automatically:

Pattern 3: Explicit API calls

Call augment_with_memories and create_trace directly. This gives you full control over every step but requires you to pass retrieved_memory_ids manually. Best for: existing codebases where you can’t wrap the agent function, batch pipelines, cases where traces are created far from where memories are retrieved.
When using create_trace directly, you must pass retrieved_memory_ids manually. If you forget, the utility learning loop breaks silently - memories won’t be reinforced or penalized based on outcomes. The context manager and decorator handle this automatically.

create_trace vs create_trace_and_wait

Reviews

Inline reviews

Include the review when creating the trace. This is the simplest path - one call does everything.
The SDK accepts "success" / "failure" as aliases for "pass" / "fail".

Deferred reviews

Create the trace without a review, then submit one later. This is useful when:
  • A human needs to evaluate the answer
  • You’re running a batch and want to review traces in one go afterwards
  • The review depends on external feedback that isn’t available yet
Deferred reviews are processed synchronously - the returned Trace includes the review and the created memory ID. You can also review traces from the Reflect Console.

What makes good feedback

When a trace fails, feedback_text is included in the reflection prompt. Specific feedback produces better reflections: For passing traces, feedback is optional. The trajectory itself provides enough context for the reflection.

Listing and fetching traces

Each Trace object includes:

Choosing a pattern

Context manager

client.trace() — Auto-tracks retrieved_memory_ids. Flexible - inspect output before deciding the review. Supports blocking mode for eval loops. Best for multi-step agents, streaming, conditional review logic.

Decorator

@reflect_trace — Least boilerplate. Wraps a single function. Supports sync and async. Return TraceResult for full control or a string for quick prototyping. Best for single-function agents and clean codebases.

Explicit calls

create_trace / create_trace_and_wait — Full control over every step. Must pass retrieved_memory_ids manually. Best for existing codebases, batch pipelines, and cases where traces are created separately from memory retrieval.