Skip to navigation

Trace ingestion

Sikaru stores trajectories in Harbor's ATIF format. Convert and submit traces from LangSmith, Braintrust, Raindrop, or your own agent, and read managed run trajectories.
View as Markdown

Sikaru has two ways to get execution evidence. Submitted traces come from an agent you run elsewhere. Managed run trajectories come from runs Sikaru executes. They are separate entry points and separate views.

submit traces retained automatically Agent you run elsewhere Submitted traces view Managed run in Sikaru Managed run history Trajectory and measured usage

In short: submit traces from your own agent; managed runs need no upload and appear in their own history.

These examples use the authenticated client and project from the Quickstart.

Trajectory format: Harbor ATIF

Sikaru records every trajectory in the Agent Trajectory Interchange Format (ATIF) from Harbor. An ATIF document is one JSON object holding an agent’s full interaction: user and system messages, agent replies, reasoning, tool calls, tool results, and metrics. One open format means the same trajectory works for inspection, evaluation, and improvement, wherever it came from.

FieldPurpose
schema_versionATIF-v1.7 or ATIF-v1.8. Managed run trajectories are exported as ATIF-v1.8.
agentAgent name and version (both required), plus optional model_name
stepsOrdered user, agent, and system steps, numbered from 1
session_idOptional ID shared by trajectories from one conversation
final_metricsOptional token, cost, and step totals

Read the ATIF specification for every field.

Bring traces from LangSmith, Braintrust, Raindrop, and others

Historical traces become trajectories once they are in ATIF. Export them from your current tool, convert each trace to one ATIF document, and submit it.

export convert harbor.atif.v1 LangSmith, Braintrust, Raindrop,Langfuse, ... Exported traces ATIF documents Sikaru trajectories
What you haveWhat to do
ATIF files, such as Harbor’s trajectory.jsonSubmit them as they are.
Traces in LangSmith, Braintrust, Raindrop, Langfuse, or another toolExport them, convert to ATIF, then submit.
OpenInference or OpenTelemetry spansSubmit them directly. They are stored as spans, not trajectories, so convert to ATIF if you want to evaluate them as conversations.
1

Export your traces

Use your tool’s export feature or API. For each trace, build one list of OpenAI-style chat messages (role, content, tool_calls, tool_call_id). In most exports, the last model call’s input messages plus its output message hold the whole conversation.

2

Convert each trace to ATIF

This function turns one message list into an ATIF document that passes Sikaru’s validation:

import json
def to_atif(messages, *, session_id, agent_name, agent_version, model_name=None):
"""Convert OpenAI-style chat messages from an exported trace into an ATIF document."""
steps = []
for msg in messages:
role = msg["role"]
if role == "tool":
# A tool result belongs to the agent step that made the call.
observation = steps[-1].setdefault("observation", {"results": []})
observation["results"].append(
{"source_call_id": msg["tool_call_id"], "content": msg.get("content") or ""}
)
continue
step = {
"step_id": len(steps) + 1,
"source": {"user": "user", "system": "system"}.get(role, "agent"),
"message": msg.get("content") or "",
}
if role == "assistant":
if model_name:
step["model_name"] = model_name
calls = msg.get("tool_calls") or []
if calls:
step["tool_calls"] = [
{
"tool_call_id": call["id"],
"function_name": call["function"]["name"],
"arguments": json.loads(call["function"]["arguments"] or "{}"),
}
for call in calls
]
steps.append(step)
return {
"schema_version": "ATIF-v1.7",
"session_id": session_id,
"agent": {"name": agent_name, "version": agent_version},
"steps": steps,
}

Adapt the field names if your export uses a different message shape. Harbor also publishes Pydantic models for building ATIF in harbor.models.trajectories.

3

Submit the trajectories

Send each document with the harbor.atif.v1 format. Use the source trace ID in the idempotency key so a retry never creates a duplicate:

from sikaru_api import TraceMetadata
for trace in exported_traces:
receipt = client.trace_streams.stream_openinference_spans(
format="harbor.atif.v1",
trajectory=to_atif(
trace["messages"],
session_id=trace["id"],
agent_name="support-agent",
agent_version="2026-10-01",
),
dataset="historical",
metadata=TraceMetadata(account_id="customer-42", project_id=project, source="langsmith-export"),
idempotency_key=f"historical-{trace['id']}",
)

The service validates each document and rejects invalid ones. Fix the converter, then resubmit with the same idempotency key.

Submit traces

The generated trace method accepts declared wire formats directly. It does not provide a local Experience builder, vendor converter, trajectory class, or agent facade. Normalize source data in your application before you send it. Server-side normalization stays part of the private service.

import json
from pathlib import Path
from sikaru_api import TraceMetadata
trajectory = json.loads(Path("trajectory.json").read_text())
receipt = client.trace_streams.stream_openinference_spans(
format="harbor.atif.v1", trajectory=trajectory, dataset="baseline",
metadata=TraceMetadata(account_id="customer-42", project_id=project, source="my-agent"),
idempotency_key="baseline-trace-001",
)
FormatPayload field
harbor.atif.v1trajectory (ATIF documents, validated by the service)
openinference.v1spans, using generated OpenInferenceSpan values
opentelemetry.otlp.v1resource_spans

Reuse trace idempotency keys only for identical batches.

A trace ingest acknowledgement does not prove that downstream evaluation or improvement completed.

Read a managed run’s trajectory

Use a project API key with runs:read to read retained execution structure and measured token usage:

evidence = client.runs.get_trajectory(project, run_id)
trajectory = evidence["trajectory"]

The response includes runId, harnessVersionId, status, and an ATIF 1.8 trajectory.

  • Private messages, reasoning, tool payloads, and provider metadata are omitted and marked in trajectory.extra.
  • Embedded subagent trajectories keep their own token totals. Root totals exclude those children.
  • Missing metrics mean unknown usage, not zero.
  • This export does not include model pricing.

The endpoint reads a committed snapshot. Active or interrupted runs may have partial evidence.

ResponseMeaningWhat to do
404 for an authorized, existing runNo retained trajectory is availableTreat evidence as unavailable, not empty.
404 otherwiseThe run may be missing or inaccessibleCheck the run ID and project.
Service errorThe read failed; the trajectory is not necessarily absentRetry the read. Do not submit the run again.

The Python method requires a client generated from the updated API contract and a service that supports this endpoint.

Find runs in the platform

Open your project and go to Conversations. Managed runs appear in their own history. Open a run to inspect its retained trajectory and measured usage. Use Show older managed runs to continue through earlier runs. Agent pages also scope managed history to that agent.

Managed history and submitted traces are separate views:

  • A managed run does not need to be uploaded again to appear in managed history.
  • Submitted-trace counts can be zero while managed runs exist.
  • Do not add their totals together as a unique-run count.

A visible run confirms that work was admitted, not that a complete trajectory was retained. Run status, trajectory availability, and measurement completeness are separate. Refresh active runs to read newer retained evidence. Never read an unavailable trajectory or failed read as zero steps or zero usage.

Next steps