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:- Reads the trajectory, the outcome, and your feedback
- Generates a concise reflection (an LLM-produced summary of what worked or went wrong)
- Embeds the reflection and stores it as a new memory with an initial utility of 0.5
- Updates the utility scores of the memories that were retrieved during that run (up for pass, down for fail)
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
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 tracksretrieved_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
Passblocking=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 afterset_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
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
Callaugment_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.
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."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
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
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.