Skip to main content

Session Management

tj.init()

Configure the SDK. Call once before other functions. For telemetry-only usage, only project_id and trajectory_api_key are required; for trace import, also pass provider and api_key.
tj.init(
    *,
    project_id: str,
    provider: str | None = None,
    api_key: str | None = None,
    workspace_id: str | None = None,
    destination_id: str | None = None,
    trajectory_api_key: str | None = None,
    transforms: list[BaseTransform] | None = None,
    debug: bool = False,
) -> None
ParameterTypeDefaultDescription
project_idstrrequiredYour project ID.
providerstr | NoneNoneTrace provider (e.g. "langsmith"). Omit for telemetry-only / BYO-data usage.
api_keystr | NoneNoneProvider API key. Falls back to LANGSMITH_API_KEY / LANGCHAIN_API_KEY env vars when provider is set.
workspace_idstr | NoneNoneLangSmith workspace/tenant ID. Required for bulk export.
destination_idstr | NoneNoneBulk export destination ID. Required for live bulk export.
trajectory_api_keystr | NoneNoneAPI key for upload, upload_trace, push_events. Falls back to TRAJECTORY_API_KEY env var.
transformslist[BaseTransform] | NoneNoneTransforms applied after building (e.g. PII redaction).
debugboolFalseEnable debug logging.

Trace Import

tj.list_conversations()

List available conversations from the configured provider.
tj.list_conversations(*, limit: int = 50) -> list[ConversationSummary]

tj.import_conversations()

Import conversations and return one Trajectory per conversation.
tj.import_conversations(
    conversations: list[str] | list[ConversationSummary] | None = None,
    *,
    bulk: bool = False,
    runs_query: bool = False,
    source: str | None = None,
    limit: int | None = None,
    since: timedelta | datetime | None = None,
) -> list[Trajectory]
ParameterTypeDefaultDescription
conversationslistNoneConversation IDs or ConversationSummary objects.
bulkboolFalseUse bulk export instead of individual API calls.
runs_queryboolFalseUse the runs-query path (mutually exclusive with bulk).
sourcestr | NoneNoneLocal parquet file path. When bulk=True and source is omitted, the SDK triggers a live export.
limitint | NoneNoneMax conversations (bulk mode only).
sincetimedelta | datetime | NoneNoneTime window for bulk export.

tj.transform()

Transform raw provider data into a Trajectory without fetching. Useful for custom pipelines that already have the source payload.
tj.transform(raw_data: dict, *, provider: str = "langsmith", api_key: str = "", project_id: str = "") -> Trajectory

Building Trajectories

See Bring Your Own Data for the full walkthrough.

tj.build_trajectory_from_messages()

Build a Trajectory from a flat list of Message objects. Cumulative steps, tool-call metrics, and telemetry fields (content hash, idempotency key) are computed automatically.
tj.build_trajectory_from_messages(
    messages: list[Message],
    *,
    conversation_id: str,
    data_source: str,
    reward: Reward | None = None,
    task_metadata: dict | None = None,
    error: str | None = None,
    start_time: str | None = None,
    end_time: str | None = None,
    termination_reason: TerminationReason | None = None,
    extra_telemetry: dict | None = None,
    trace_id: str | None = None,
    model_id: str | None = None,
) -> Trajectory
task_metadata recognizes num_turns, total_tokens, total_cost, and completion_tokens; other keys are ignored.

tj.build_trajectory_from_parsed()

Build a Trajectory from a ParsedConversation. Provider subclasses delegate to this so the ParsedConversation → Trajectory logic has a single implementation.
tj.build_trajectory_from_parsed(parsed: ParsedConversation) -> Trajectory

tj.build_reward_from_scalar()

Build a single-component Reward from a numeric score. scaled_value is normalized to [0, 1] using score_range.
tj.build_reward_from_scalar(
    value: float,
    *,
    name: str = "score",
    score_range: tuple[float, float] = (0.0, 1.0),
    weight: float = 1.0,
) -> Reward

Message Recipes

Adapters from common third-party message formats into Message objects. All recipes fail loud on unexpected input — see Bring Your Own Data for examples.
FunctionSource format
tj.messages_from_openai_chat(raw)OpenAI ChatCompletion
tj.messages_from_anthropic_messages(raw)Anthropic Messages API
tj.messages_from_vercel_ai_sdk(raw)Vercel AI SDK (UIMessage / CoreMessage)
tj.messages_from_prompt_response(prompt, response, *, system=None)Flat prompt/response strings
tj.messages_from_role_content_pairs(pairs)[(role, content), ...] tuples

Helpers

FunctionPurpose
tj.normalize_role(role_str)Canonicalize to system / user / assistant / tool. Recognizes aliases (human, ai, function, etc.).
tj.flatten_text_content(content)Collapse multi-modal content (string, list of blocks, or dict) to plain text.
tj.parse_tool_arguments(raw)Normalize tool-call arguments (dict, JSON string, or None) into a dict.

Trace Workflow

See Linking Events to Trajectories for the workflow.

tj.start_trace()

Create a TraceContext for buffering correlated telemetry and trajectory data.
tj.start_trace(trace_id: str | None = None) -> TraceContext
If trace_id is omitted, the SDK generates a UUID4 hex string.

TraceContext

AttributeTypeDescription
trace_idstrCorrelation key shared by all events and trajectories produced through this context.
eventslist[TelemetryEvent]Buffered events produced via .event(...).
trace.event(event_type, properties=None, *, user_id=None, trajectory_id=None, source="sdk", metadata=None) -> TelemetryEvent Append a TelemetryEvent to trace.events with trace_id and session_id set to trace.trace_id. trace.build_trajectory(messages, *, data_source, conversation_id=None, ...) -> Trajectory Convenience wrapper around build_trajectory_from_messages that injects trace_id and defaults conversation_id to trace_id. Accepts the same kwargs as build_trajectory_from_messages (minus trace_id).

tj.upload_trace()

Upload trajectories, stamp matching events with their returned trajectory_id, then push events — atomically.
tj.upload_trace(
    trajectories: Trajectory | list[Trajectory],
    events: list[TelemetryEvent],
    dataset: str,
    organization_id: str | None = None,
    chunk_size: int = 1000,
    max_retries: int = 3,
) -> dict[str, Any]
Each input trajectory must carry a trace_id. Returns a dict with upload, push, events (as actually sent), and unstamped_events (events pushed without a trajectory_id because no match was found). Raises RuntimeError if any trajectory’s upload failed and there are unstamped events tied to its trace_id — no events are pushed in that case.

Upload & Push

tj.upload()

Upload trajectories via the Trajectory API.
tj.upload(
    trajectories: Trajectory | list[Trajectory],
    dataset: str,
) -> dict[str, Any]
Returns a dict:
KeyTypeDescription
uploadedintTrajectories accepted by the backend.
skippedintTotal skipped (client + backend).
client_skippedintEmpty trajectories filtered before upload.
backend_skippedintTrajectories rejected by the backend.
errorslist[str]Backend error messages.
trajectorieslist[dict]Per-trajectory items with request_index, trace_id, trajectory_id, status, etc. — used to map trace_id → trajectory_id.
batchesintNumber of HTTP batches.
elapsed_sfloatWall-clock upload time.

tj.push_events()

Push telemetry events to the Trajectory API. Invalid events are dropped with logged warnings.
tj.push_events(
    events: list[TelemetryEvent],
    *,
    organization_id: str | None = None,
    chunk_size: int = 1000,
    max_retries: int = 3,
) -> PushResult

tj.save()

Save trajectories to JSON files on disk. Each file is named {output_dir}/{conversation_id}.json.
tj.save(
    trajectories: Trajectory | list[Trajectory],
    output_dir: str,
) -> None

Model ID Helpers

For chaining a Trajectory-served chat completion back to its trajectory id, the backend returns the model id on the response headers.
Constant / FunctionDescription
tj.TRAJECTORY_MODEL_ID_HEADERHeader name: "x-trajectory-model-id".
tj.model_id_from_chat_completion_headers(headers)Extract the model id from a headers mapping. Returns None if absent.
tj.model_id_from_chat_completion_response(response)Extract from a response object with a .headers attribute.

Primitives

All primitives are frozen dataclasses unless noted.

Trajectory

FieldTypeDescription
taskTaskConversation metadata.
stepslist[Step]Cumulative decision-point snapshots.
rewardReward | NoneAggregate reward signal.
metricsTrajectoryMetrics | NoneContent metrics.
execution_metricsExecutionMetrics | NoneTiming data.
reference_trajectorydict | NoneOptional reference for comparison.
telemetryTelemetry | NoneSource telemetry metadata.
idxint | NoneIndex within a batch.
errorstr | NoneError if the conversation failed.
trace_idstr | NoneCaller-owned correlation key.
model_idstr | NoneTrajectory model identifier.

Task

FieldTypeDescription
idstr | NoneTask identifier ({data_source}:{conversation_id} when built locally).
data_sourcestr | NoneProvider name (e.g. "langsmith") or your own source label.
conversation_idstr | NoneUnique conversation identifier.
num_turnsint | NoneNumber of user-agent turns.
num_stepsint | NoneNumber of steps.
total_tokensint | NoneTotal tokens consumed.
total_costfloat | NoneEstimated cost in USD.

Step

FieldTypeDescription
messageslist[Message]Cumulative messages up to this point.
rewardReward | NonePer-step reward.
infodict | NoneProvider-specific metadata.
trainable_statusTrainableStatusTraining-suitability flag.

Message

FieldTypeDescription
roleRole"system", "user", "assistant", or "tool".
contentstr | NoneText content.
tool_callslist[ToolCall] | NoneTool invocations by the assistant.
tool_responseToolResponse | NoneTool execution result.
tool_definitionslist[ToolDefinition] | NoneTools available to the model at this point.
usagedict | NoneToken usage stats.
finish_reasonstr | None"stop", "tool_calls", etc.
metadatadict | NoneProvider-specific message metadata.
reasoningstr | NoneChain-of-thought content.
trainable_statusTrainableStatusTraining-suitability flag.

ToolCall

FieldTypeDescription
namestrTool name.
argumentsdictArguments passed to the tool.
idstr | NoneIdentifier matching the ToolResponse.

ToolResponse

FieldTypeDescription
idstrMatches the ToolCall id.
namestrTool name.
argumentsdictArguments passed.
responseAny | NoneReturn value.
errorstr | NoneError if the call failed.
metadatadict | NoneProvider-specific metadata.

ToolDefinition

FieldTypeDescription
namestrTool name.
descriptionstrWhat the tool does.
parametersdictJSON Schema for tool arguments.

Reward & RewardComponent

Field (Reward)TypeDescription
aggregated_valuefloat | NoneTop-level reward score.
aggregation_methodstr | NoneHow components were combined.
componentslist[RewardComponent] | NonePer-rubric / per-judge components.
Field (RewardComponent)TypeDescription
namestrComponent label.
valuefloatRaw value.
scaled_valuefloat | NoneNormalized to [0, 1].
explanationstr | NoneFree-form notes (e.g. judge rationale).
weightfloatWeight in the aggregate.
rangetuple[float, float] | NoneOriginal score range.
metadatadict | NoneProvider-specific context.

TelemetryEvent

See Telemetry Events for the full guide.
FieldTypeDefaultDescription
event_typestrrequiredDotted event name.
session_idstrrequiredSession grouping.
propertiesdict{}Free-form payload.
event_idstrnew UUID4 hexIdempotency key.
timestampstrnow (UTC ISO)Event time.
user_idstr | NoneNoneEnd-user identifier.
trajectory_idstr | NoneNoneBackend trajectory ID once known.
trace_idstr | NoneNoneCaller-owned correlation key.
sourcestr"sdk"Where the event originated.
metadatadict | NoneNoneAdditional context.

PushResult

FieldTypeDescription
pushedintEvents accepted by the backend.
skippedintEvents dropped client-side as invalid.
errorslist[str]One message per invalid event.

Telemetry

FieldTypeDescription
sourcestrTelemetry source identifier.
datadictRaw telemetry data (includes trace_id, content_hash, idempotency_key when set).

TrajectoryMetrics & ExecutionMetrics

FieldTypeDescription
stepsint | NoneTotal steps.
tokens_generatedint | NoneTotal completion tokens.
aggregated_rewardfloat | NoneAggregate reward value.
num_tool_callsint | NoneTotal tool invocations.
num_tool_failuresint | NoneFailed tool calls.
num_tool_response_noneint | NoneTool calls with no response.
tool_error_ratefloat | NoneFailure ratio.
env_timefloat | NoneTime in tool execution (seconds).
llm_timefloat | NoneTime waiting for LLM (seconds).
total_timefloat | NoneWall-clock time (seconds).
termination_reasonTerminationReason | NoneWhy the conversation ended.

ConversationSummary

FieldTypeDescription
conversation_idstrUnique conversation identifier.
num_turnsintNumber of turns.
first_seenstr | NoneISO timestamp of earliest trace.
last_seenstr | NoneISO timestamp of most recent trace.
root_run_nameslist[str]Names of top-level runs.

Type Aliases

Role = Literal["system", "user", "assistant", "tool"]

TrainableStatus = Literal[
    "trainable", "not_trainable", "superseded", "summarization_boundary"
]

TerminationReason = Literal[
    "TIMEOUT", "ENV_DONE", "MAX_STEPS", "TRUNCATION", "STALE", "ERROR", "NONE"
]

PiiRule = Literal["EMAIL", "PHONE", "CREDIT_CARD", "SSN"]