Skip to main content
A trace records the full trajectory of an agent run. A review marks the outcome and triggers memory creation. Together they form the learning loop that makes future memory queries more useful.

Create a trace

submission = client.create_trace(
    task="Parse the CSV and return the top 5 rows",
    trajectory=[
        {"role": "user", "content": "Parse the CSV..."},
        {"role": "assistant", "content": "Here are the top 5 rows: ..."},
    ],
    retrieved_memory_ids=["mem-abc", "mem-def"],
    model="gpt-5.4-mini",
    metadata={"source": "cli", "run_id": "run-123"},
    # final_response is optional — auto-extracted from the last assistant message
)

print(submission.id)              # trace UUID
print(submission.ingest_status)   # "completed" (no review) or "queued" (with review)
ParameterTypeDefaultDescription
taskstrrequiredThe task given to the agent
trajectorylist[dict] | strrequiredThe conversation between user and agent — role/content message dicts or a JSON string
final_responsestr | NoneNoneThe agent’s final answer. When omitted, extracted from the last assistant message in the trajectory.
retrieved_memory_idsSequence[str]()IDs of memories used during this run (Q-values will be updated on review)
modelstr | NoneNoneModel identifier
metadatadict | NoneNoneArbitrary key-value pairs
review_resultstr | NoneNoneInline review result: "pass", "fail", "success", or "failure"
feedback_textstr | NoneNoneOptional feedback text (typically added by judge/platform workflows)
create_trace returns a TraceSubmission (not a full Trace). Use wait_for_trace or get_trace to fetch the complete object.

Inline review

Include the review when creating the trace. The review is processed asynchronously:
submission = client.create_trace(
    task="...",
    trajectory=[...],
    retrieved_memory_ids=["mem-abc"],
    review_result="success",
)
# submission.ingest_status == "queued"
The SDK accepts "success" / "failure" as aliases for the API’s "pass" / "fail".

Deferred review

Create the trace without a review, then submit one later when feedback is available:
submission = client.create_trace(
    task="...",
    trajectory=[...],
)

# Later, after human evaluation:
trace = client.review_trace(
    trace_id=submission.id,
    result="failure",
)
# trace.review_status == "reviewed"
# trace.created_memory_id is set
Deferred reviews are processed synchronously — the returned Trace includes the review and created memory ID.

Waiting for ingestion

Inline reviews are processed in the background. Poll until the trace is fully ingested:
trace = client.wait_for_trace(
    submission.id,
    require_reviewed=True,
    poll_interval=0.25,
    wait_timeout=60.0,
)
ParameterTypeDefaultDescription
trace_idstrrequiredTrace to wait for
require_reviewedboolFalseIf True, wait until review_status == "reviewed"
poll_intervalfloat0.25Seconds between polls
wait_timeoutfloat60.0Maximum seconds to wait before raising TimeoutError
Raises RuntimeError if ingestion fails, TimeoutError if the deadline is exceeded.

Create and wait

Combine trace creation and polling in one call:
trace = client.create_trace_and_wait(
    task="...",
    trajectory=[...],
    review_result="pass",
    poll_interval=0.5,
    wait_timeout=30.0,
)
# Returns the fully processed Trace

List and fetch traces

pending = client.list_traces(review_status="pending")
reviewed = client.list_traces(review_status="reviewed")
all_traces = client.list_traces()

trace = client.get_trace(trace_id="abc-123")
Each returned Trace includes the attached Review (if reviewed), the created_memory_id, and ingestion status.
In production flows, feedback text is generally generated by an LLM judge pipeline or entered in the platform UI. SDK/API usage usually submits just the pass/fail result.