Core Concepts¶
This page covers the small set of concepts you need to integrate Tuor cleanly: traces, review outcomes, payload shapes, and how reviewed data gets back to your system.
Trace¶
A trace is one ordered model trajectory that can be reviewed by a human. It has three payloads you control:
| Field | Required | Purpose |
|---|---|---|
spans |
yes | What happened in order: system notes, user and assistant messages, reasoning, tool requests and responses, and unknown provider data. |
model_output |
yes | What your model produced. |
trace_config |
no | Metadata for traceback: model name, prompt version, run ID, customer/account ID, experiment ID. |
Tuor adds review fields:
| Field | Meaning |
|---|---|
status |
pending, approved, rejected, or corrected. |
corrected_output |
Human-edited output, present after a correction. |
final_output |
The output to trust downstream. It equals model_output when approved, corrected_output when corrected, and null when pending or rejected. |
tags |
Optional labels for routing, filtering, and export cohorts. |
Each JSON payload field is capped at 5 MB and 10 nesting levels.
Review outcomes¶
Every trace starts as pending. Reviewers then choose one of three outcomes:
| Outcome | Meaning | final_output |
|---|---|---|
approved |
The model output is correct as-is. | model_output |
corrected |
A reviewer fixed the output. | corrected_output |
rejected |
The output is not usable. | null |
For most integrations, this is the state machine that matters: send traces while they are pending, then consume approved and corrected traces through webhooks or export.
Span taxonomy¶
spans is a flat array. Its order is the trace order; Tuor does not sort, group, or infer model-call boundaries. Every returned span receives a Tuor-generated id.
| Span | Purpose |
|---|---|
message |
A system, user, or assistant message containing ordered content blocks. |
reasoning |
The assistant's reasoning, as ordered content blocks. |
tool_request |
A tool request from the assistant. It requires a name; an optional call_id connects it to a response. |
tool_response |
A tool response from the system. Its optional call_id connects it to a request. |
event |
A system event with category state, metadata, or error. |
unknown |
Unsupported or malformed span data preserved in JSON content blocks. |
Event categories describe the record's purpose: state for explicit lifecycle changes, metadata for measurements and descriptive attributes, and error for explicit non-tool failures. Usage, model, timestamps, and completion reasons stay together as metadata. Events have no name field; provider-specific labels stay in their content. The viewer initially collapses event content.
Canonical spans have no extra field. Unread attributes of recognized provider objects become adjacent metadata events; unsupported records remain unknown. Details and exports retain all events, while prompt refinement excludes them. These span events are separate from the trace's review-history events.
Codex guardian transcript inputs become system messages only when session metadata identifies a guardian subagent and the response item matches a recognized transcript wrapper. The original user role and the classification basis remain in an adjacent metadata event. This is a format-based inference, not proof of authorship or instruction priority. Ordinary user messages, unknown wrappers, and event-only conversations retain their existing classification.
Every span supports ordered text, json, encrypted, refusal, image, and document blocks. Media blocks describe their base64 source. A document looks like:
{
"type": "message",
"role": "user",
"content": [
{"type": "text", "value": "Extract the invoice total."},
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"filename": "invoice.pdf",
"value": "JVBERi0xLjQK..."
}
}
]
}
Unknown and malformed spans are preserved as unknown spans. Unknown or malformed content becomes a json block at the smallest valid boundary. Tool requests and responses may be orphaned, duplicated, ambiguous, or out of order; Tuor renders the supplied trajectory without inventing status.
Tuor calls these ordered units spans, but they are not full OpenTelemetry spans and are not OTLP-compatible.
Output shapes¶
Outputs
model_output is structured JSON — the reviewer edits nested object leaves as dot-path form rows. Values can be strings, numbers, booleans, arrays, or nested objects. Each form row gets a sensible control inferred from the value's type, but you can pin a path to a specific typed control by describing its dot path in the trace's output_schema. Three field types are available:
type |
Reviewer control | Extra keys |
|---|---|---|
enum |
Fixed-choice label picker, pre-selected to the model's value. | options, multi, open |
boolean |
A true/false toggle. | none |
json |
The value's whole subtree stays one editable JSON block instead of expanding into child rows. | none |
model_output |
output_schema (optional) |
|---|---|
{"invoice": {"vendor": "Acme", "total": 1250.45}} |
omitted — controls inferred per field |
{"review": {"sentiment": "positive", "confidence": 0.97}} |
{"review.sentiment": {"type": "enum", "options": ["positive", "neutral", "negative"]}} |
{"is_compliant": true, "raw": {"a": 1}} |
{"is_compliant": {"type": "boolean"}, "raw": {"type": "json"}} |
Paths absent from output_schema are unconstrained JSON and fall back to inferred controls. For enum fields, add "multi": true for multi-label fields and "open": false to reject write-in values at ingest and correction time; boolean rejects non-boolean values, and json accepts any JSON. See Reviewer Blueprints for practical recipes.
Getting results back¶
There are three common patterns:
| Pattern | Best for |
|---|---|
trace_config IDs |
Tying every Tuor trace back to your own run, user, ticket, or database row. |
| Webhooks | Reacting as soon as a reviewer approves, rejects, or corrects a trace. |
| JSONL export | Batch evals, dashboards, analytics, training-data jobs, or prompt-improvement workflows. |
Use trace_config aggressively. For example, include internal_run_id, prompt_version_id, and customer_id when you create a trace. Tuor echoes those values in exports and on the trace object returned by GET /v1/traces/{trace_id}, so most downstream systems do not need a separate mapping table.