Skip to main content

Read a run

Every run keeps its evidence. By the end of this page you will have read one back step by step with get_trajectory, read a run that paused for a person as one story with get_run_trajectory, found a sub-agent’s run nested under the call that started it, and seen exactly what the record does not hold.
Every output on this page is what the code printed when it was run with gpt-5.4-mini. The model’s wording, the token counts, the prices and the IDs will differ on your run.
Two words first. A trace is the record of one uninterrupted stretch of a run. A run that never paused is one trace; a run that paused for an approval or a budget and was resumed is several, one per segment. A trajectory is a trace read in order, from the request to the answer.

One run, step by step

Read top to bottom, that is the whole run:
  • The harness is what the model ran with: the model, the 15 tools it was offered (get_weather and the built-in workspace file tools, on by default), governance on, and privacy saying the trace is redacted for credit cards, emails, phone numbers and SSNs.
  • Step 1: the model asked for get_weather; the default policy allowed it by its rule allow_local_tools; the observation is the exact text the model got back.
  • Step 2: the model answered, and the run ended with final_answer.
  • Totals add it up. evidence_status is complete and capture_gaps is empty: nothing in this record is missing, redacted, or cut short.

A run that paused: one story

A run that waited for an approval or a budget top-up, or was recovered after a crash, continues in a new trace segment. get_run_trajectory reads every segment in order. Here a refund waits for a person:
  • The first segment ended suspended, with the call awaiting_approval and the rule that asked.
  • The second segment picks up at the same step number, marked resumed=True: the call is asked again, and allowed because alice approved it.
  • The story’s totals are summed over the segments, with each step and each tool call counted once, by how it finally ended. approvals and tool_calls come from the run’s record (Durable runs).
get_trajectory(run_id=...) would have returned only the second segment; it lists the others in other_trace_ids_for_run.

A sub-agent’s run, nested

A delegated run has its own trace. The lead’s trajectory nests it under the tool call that started it, in call["subagent"]["child_trajectory"], down to max_depth=5 levels:
A trajectory’s own totals are its own run’s; including_subagents adds its children’s tokens and cost. Pass include_children=False to leave the children out; get_trace_family(trace_id=...) lists the raw traces of the lead and every child (Sub-agents).

What the record does not hold

A trace records the full trajectory by default (capture: "full"). A deployment that must not keep prompts sets capture: "default", and the trajectory says exactly what is missing:
  • The prompts and responses were not recorded, but the facts were: tokens, cost, finish reason and latency are metadata, kept under every capture setting.
  • Under governance, with a capture that records neither prompts nor responses, tool arguments are recorded as [REDACTED]: the record shows which arguments a call used, not their values. With capture: "full" the model’s own call already holds them, so they are recorded as written, through the privacy filter and redact_keys.
  • Every payload has a capture state: available, redacted, truncated, offloaded, not_recorded, missing or inferred. capture_gaps lists every record whose payload is not all there, and any gap makes evidence_status partial.
What is recorded, and how to change it, is on Telemetry and exporters; what is redacted is on Privacy.

Over HTTP

OmniServe serves the same structures. A server on port 8123:
Run once, then read the run and its segment, with the run_id and trace_id the run returned:
An unknown run is a 404 with {"detail":"No run nope"}; an unknown or pruned trace, {"detail":"Trajectory not found"}.

How it works

1

Every run records typed events and spans

As the run goes, the runtime records a span for each piece of work (the run, each step, each model call, each tool call) and an event for each thing that happened in it, into the trace store.
2

Facts are metadata; payloads follow the capture policy

IDs, links between records, tokens, cost, outcomes and policy decisions are event metadata, kept under every setting. Prompts, responses, tool arguments and results are payloads, recorded as capture and the record_* settings say, redacted, and truncated or offloaded when large.
3

The trajectory is built from the stored trace

get_trajectory reads the trace and places every event exactly once: in the request, a step, a model call, a tool call, the final section, or an other_events list where it occurred. Nothing is hidden, and nothing is stored twice: the trajectory is computed when you ask for it.
4

A run is its segments

The run’s record keeps the IDs of its traces. get_run_trajectory reads each one and sums them.

The shape at a glance

A trajectory (omnicoreagent.trajectory/v1) is a plain dict. Every entry of a list has every field, None when it does not apply.

The harness

The run’s run_configuration event, recorded before the first step under every capture setting. Never credentials.

Each step

Each model call

facts holds tokens (input, output, total, and cached_input and reasoning when the provider reports them), estimated_cost_usd with cost_source (provider_response when the response came with its cost, as LiteLLM attaches for models it knows, or price_table when it was computed from LiteLLM’s prices afterwards; either way an estimate, not an invoice), latency_ms, time_to_first_delta_ms for streamed text, finish_reason, refused, provider_model and provider_response_id, request_settings, policy_version (the model the provider served, with its fingerprint when reported), attempts and retries (each failed attempt, its message redacted), and, for a thinking model, continuation (counts and a digest; signatures and encrypted values are never recorded).

Each tool call

Each governance entry has effect (allow, ask, deny), capability, reason_code (matched_allow, matched_ask, approved, denied, expired_policy, …), matched_rule_ids, and for a person’s decision approval_id and approved_by or denied_by (system when nobody decided in time; Approvals).

Totals

steps; model_calls (total, agent_turn, context_summary, failed); tokens; estimated_cost_usd and cost_complete (False when any call had no known price); model_latency_ms; model_retries; tool_calls (total and by_outcome); compressions; runtime_messages by kind; subagents (count, child_trace_ids); executions (sandbox sessions, commands, failed, timed_out); workspace_changes, each via a tool or the sandbox; offloaded_results; duration_ms; and including_subagents (tokens, cost, cost_complete with the children).

A whole run

get_run_trajectory(run_id) returns run_id, session_id, agent_name, status (the run’s), attempt and previous_attempts, segments (each with trace_id, status, trajectory and trace_kept), traces_missing, totals, tool_calls and approvals (from the run’s record), and usage. The run’s saved conversation is not included. Traces are kept 7 days by default and run records 30. After a segment’s trace is pruned, it stays in the story with trace_kept: False and trajectory: None; traces_missing counts them, and totals cover only the traces still kept (empty, not zero, when none is). The record’s usage remains. See how long a run’s evidence is kept.

Options

What is recorded is set by telemetry_config: capture ("full" by default, or "default"), the record_* switches, and retention_days (telemetry settings). Every method is in the OmniCoreAgent reference.

When things go wrong

No stored trace has that ID: a typo, a trace from another store (another workspace, or storage: "memory" in another process), or one pruned after retention_days (7 by default). get_run_trajectory returns None when no run record has that ID; a record whose traces are gone has trace_kept: False segments instead.
Pass one of them:
The second is a positional ID together with run_id=.
The run paused and resumed: get_trajectory(run_id=...) is its latest segment only (the others are in other_trace_ids_for_run). Read the whole run with get_run_trajectory(run_id).
The agent records with capture: "default", or a record_* switch is off. Check request_capture and response_capture: not_recorded says why. Tokens, cost and outcomes are still there.
None: nothing was priced, because no model call answered (a run cut off by its deadline before the first answer) or the model has no published price (a model behind base_url, for example). cost_complete: False: some calls could not be priced, so the figure is a lower bound. The tokens are right either way. including_subagents follows the same rule. Guard for None before rounding or adding.

Next

Telemetry and exporters

What is recorded, where it is kept, the live stream, and exporting to OTLP, LangSmith, Opik and JSONL.

Outcomes and training

Attach what a run turned out to be worth, and read runs back as training records.

Headless runs

Run from the command line and keep the evidence.

Harbor

Run the agent on benchmarks, with each trial’s trajectory.