> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trajectory.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API Reference

> Complete reference for all Trajectory SDK functions, primitives, and helpers.

## 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`.

```python theme={null}
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
```

| Parameter            | Type                          | Default  | Description                                                                                                |
| -------------------- | ----------------------------- | -------- | ---------------------------------------------------------------------------------------------------------- |
| `project_id`         | `str`                         | required | Your project ID.                                                                                           |
| `provider`           | `str \| None`                 | `None`   | Trace provider (e.g. `"langsmith"`). Omit for telemetry-only / BYO-data usage.                             |
| `api_key`            | `str \| None`                 | `None`   | Provider API key. Falls back to `LANGSMITH_API_KEY` / `LANGCHAIN_API_KEY` env vars when `provider` is set. |
| `workspace_id`       | `str \| None`                 | `None`   | LangSmith workspace/tenant ID. Required for [bulk export](/sdk/bulk-import).                               |
| `destination_id`     | `str \| None`                 | `None`   | Bulk export destination ID. Required for live bulk export.                                                 |
| `trajectory_api_key` | `str \| None`                 | `None`   | API key for `upload`, `upload_trace`, `push_events`. Falls back to `TRAJECTORY_API_KEY` env var.           |
| `transforms`         | `list[BaseTransform] \| None` | `None`   | Transforms applied after building (e.g. [PII redaction](/sdk/pii-redaction)).                              |
| `debug`              | `bool`                        | `False`  | Enable debug logging.                                                                                      |

***

## Trace Import

### `tj.list_conversations()`

List available conversations from the configured provider.

```python theme={null}
tj.list_conversations(*, limit: int = 50) -> list[ConversationSummary]
```

### `tj.import_conversations()`

Import conversations and return one `Trajectory` per conversation.

```python theme={null}
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]
```

| Parameter       | Type                            | Default | Description                                                                                        |
| --------------- | ------------------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `conversations` | `list`                          | `None`  | Conversation IDs or `ConversationSummary` objects.                                                 |
| `bulk`          | `bool`                          | `False` | Use bulk export instead of individual API calls.                                                   |
| `runs_query`    | `bool`                          | `False` | Use the runs-query path (mutually exclusive with `bulk`).                                          |
| `source`        | `str \| None`                   | `None`  | Local parquet file path. When `bulk=True` and `source` is omitted, the SDK triggers a live export. |
| `limit`         | `int \| None`                   | `None`  | Max conversations (bulk mode only).                                                                |
| `since`         | `timedelta \| datetime \| None` | `None`  | Time 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.

```python theme={null}
tj.transform(raw_data: dict, *, provider: str = "langsmith", api_key: str = "", project_id: str = "") -> Trajectory
```

***

## Building Trajectories

See [Bring Your Own Data](/sdk/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.

```python theme={null}
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.

```python theme={null}
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`.

```python theme={null}
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](/sdk/bring-your-own-data) for examples.

| Function                                                             | Source 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

| Function                           | Purpose                                                                                                         |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `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](/sdk/linking-events-to-trajectories) for the workflow.

### `tj.start_trace()`

Create a `TraceContext` for buffering correlated telemetry and trajectory data.

```python theme={null}
tj.start_trace(trace_id: str | None = None) -> TraceContext
```

If `trace_id` is omitted, the SDK generates a UUID4 hex string.

### `TraceContext`

| Attribute  | Type                   | Description                                                                          |
| ---------- | ---------------------- | ------------------------------------------------------------------------------------ |
| `trace_id` | `str`                  | Correlation key shared by all events and trajectories produced through this context. |
| `events`   | `list[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.

```python theme={null}
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.

```python theme={null}
tj.upload(
    trajectories: Trajectory | list[Trajectory],
    dataset: str,
) -> dict[str, Any]
```

Returns a dict:

| Key               | Type         | Description                                                                                                                      |
| ----------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| `uploaded`        | `int`        | Trajectories accepted by the backend.                                                                                            |
| `skipped`         | `int`        | Total skipped (client + backend).                                                                                                |
| `client_skipped`  | `int`        | Empty trajectories filtered before upload.                                                                                       |
| `backend_skipped` | `int`        | Trajectories rejected by the backend.                                                                                            |
| `errors`          | `list[str]`  | Backend error messages.                                                                                                          |
| `trajectories`    | `list[dict]` | Per-trajectory items with `request_index`, `trace_id`, `trajectory_id`, `status`, etc. — used to map `trace_id → trajectory_id`. |
| `batches`         | `int`        | Number of HTTP batches.                                                                                                          |
| `elapsed_s`       | `float`      | Wall-clock upload time.                                                                                                          |

### `tj.push_events()`

Push telemetry events to the Trajectory API. Invalid events are dropped with logged warnings.

```python theme={null}
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`.

```python theme={null}
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 / Function                                   | Description                                                            |
| ----------------------------------------------------- | ---------------------------------------------------------------------- |
| `tj.TRAJECTORY_MODEL_ID_HEADER`                       | Header 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

| Field                  | Type                        | Description                          |
| ---------------------- | --------------------------- | ------------------------------------ |
| `task`                 | `Task`                      | Conversation metadata.               |
| `steps`                | `list[Step]`                | Cumulative decision-point snapshots. |
| `reward`               | `Reward \| None`            | Aggregate reward signal.             |
| `metrics`              | `TrajectoryMetrics \| None` | Content metrics.                     |
| `execution_metrics`    | `ExecutionMetrics \| None`  | Timing data.                         |
| `reference_trajectory` | `dict \| None`              | Optional reference for comparison.   |
| `telemetry`            | `Telemetry \| None`         | Source telemetry metadata.           |
| `idx`                  | `int \| None`               | Index within a batch.                |
| `error`                | `str \| None`               | Error if the conversation failed.    |
| `trace_id`             | `str \| None`               | Caller-owned correlation key.        |
| `model_id`             | `str \| None`               | Trajectory model identifier.         |

### Task

| Field             | Type            | Description                                                             |
| ----------------- | --------------- | ----------------------------------------------------------------------- |
| `id`              | `str \| None`   | Task identifier (`{data_source}:{conversation_id}` when built locally). |
| `data_source`     | `str \| None`   | Provider name (e.g. `"langsmith"`) or your own source label.            |
| `conversation_id` | `str \| None`   | Unique conversation identifier.                                         |
| `num_turns`       | `int \| None`   | Number of user-agent turns.                                             |
| `num_steps`       | `int \| None`   | Number of steps.                                                        |
| `total_tokens`    | `int \| None`   | Total tokens consumed.                                                  |
| `total_cost`      | `float \| None` | Estimated cost in USD.                                                  |

### Step

| Field              | Type              | Description                           |
| ------------------ | ----------------- | ------------------------------------- |
| `messages`         | `list[Message]`   | Cumulative messages up to this point. |
| `reward`           | `Reward \| None`  | Per-step reward.                      |
| `info`             | `dict \| None`    | Provider-specific metadata.           |
| `trainable_status` | `TrainableStatus` | Training-suitability flag.            |

### Message

| Field              | Type                           | Description                                       |
| ------------------ | ------------------------------ | ------------------------------------------------- |
| `role`             | `Role`                         | `"system"`, `"user"`, `"assistant"`, or `"tool"`. |
| `content`          | `str \| None`                  | Text content.                                     |
| `tool_calls`       | `list[ToolCall] \| None`       | Tool invocations by the assistant.                |
| `tool_response`    | `ToolResponse \| None`         | Tool execution result.                            |
| `tool_definitions` | `list[ToolDefinition] \| None` | Tools available to the model at this point.       |
| `usage`            | `dict \| None`                 | Token usage stats.                                |
| `finish_reason`    | `str \| None`                  | `"stop"`, `"tool_calls"`, etc.                    |
| `metadata`         | `dict \| None`                 | Provider-specific message metadata.               |
| `reasoning`        | `str \| None`                  | Chain-of-thought content.                         |
| `trainable_status` | `TrainableStatus`              | Training-suitability flag.                        |

### ToolCall

| Field       | Type          | Description                             |
| ----------- | ------------- | --------------------------------------- |
| `name`      | `str`         | Tool name.                              |
| `arguments` | `dict`        | Arguments passed to the tool.           |
| `id`        | `str \| None` | Identifier matching the `ToolResponse`. |

### ToolResponse

| Field       | Type           | Description                 |
| ----------- | -------------- | --------------------------- |
| `id`        | `str`          | Matches the `ToolCall` id.  |
| `name`      | `str`          | Tool name.                  |
| `arguments` | `dict`         | Arguments passed.           |
| `response`  | `Any \| None`  | Return value.               |
| `error`     | `str \| None`  | Error if the call failed.   |
| `metadata`  | `dict \| None` | Provider-specific metadata. |

### ToolDefinition

| Field         | Type   | Description                     |
| ------------- | ------ | ------------------------------- |
| `name`        | `str`  | Tool name.                      |
| `description` | `str`  | What the tool does.             |
| `parameters`  | `dict` | JSON Schema for tool arguments. |

### Reward & RewardComponent

| Field (Reward)       | Type                            | Description                        |
| -------------------- | ------------------------------- | ---------------------------------- |
| `aggregated_value`   | `float \| None`                 | Top-level reward score.            |
| `aggregation_method` | `str \| None`                   | How components were combined.      |
| `components`         | `list[RewardComponent] \| None` | Per-rubric / per-judge components. |

| Field (RewardComponent) | Type                          | Description                             |
| ----------------------- | ----------------------------- | --------------------------------------- |
| `name`                  | `str`                         | Component label.                        |
| `value`                 | `float`                       | Raw value.                              |
| `scaled_value`          | `float \| None`               | Normalized to `[0, 1]`.                 |
| `explanation`           | `str \| None`                 | Free-form notes (e.g. judge rationale). |
| `weight`                | `float`                       | Weight in the aggregate.                |
| `range`                 | `tuple[float, float] \| None` | Original score range.                   |
| `metadata`              | `dict \| None`                | Provider-specific context.              |

### TelemetryEvent

See [Telemetry Events](/sdk/telemetry-events) for the full guide.

| Field           | Type           | Default       | Description                       |
| --------------- | -------------- | ------------- | --------------------------------- |
| `event_type`    | `str`          | required      | Dotted event name.                |
| `session_id`    | `str`          | required      | Session grouping.                 |
| `properties`    | `dict`         | `{}`          | Free-form payload.                |
| `event_id`      | `str`          | new UUID4 hex | Idempotency key.                  |
| `timestamp`     | `str`          | now (UTC ISO) | Event time.                       |
| `user_id`       | `str \| None`  | `None`        | End-user identifier.              |
| `trajectory_id` | `str \| None`  | `None`        | Backend trajectory ID once known. |
| `trace_id`      | `str \| None`  | `None`        | Caller-owned correlation key.     |
| `source`        | `str`          | `"sdk"`       | Where the event originated.       |
| `metadata`      | `dict \| None` | `None`        | Additional context.               |

### PushResult

| Field     | Type        | Description                            |
| --------- | ----------- | -------------------------------------- |
| `pushed`  | `int`       | Events accepted by the backend.        |
| `skipped` | `int`       | Events dropped client-side as invalid. |
| `errors`  | `list[str]` | One message per invalid event.         |

### Telemetry

| Field    | Type   | Description                                                                           |
| -------- | ------ | ------------------------------------------------------------------------------------- |
| `source` | `str`  | Telemetry source identifier.                                                          |
| `data`   | `dict` | Raw telemetry data (includes `trace_id`, `content_hash`, `idempotency_key` when set). |

### TrajectoryMetrics & ExecutionMetrics

| Field                    | Type                        | Description                       |
| ------------------------ | --------------------------- | --------------------------------- |
| `steps`                  | `int \| None`               | Total steps.                      |
| `tokens_generated`       | `int \| None`               | Total completion tokens.          |
| `aggregated_reward`      | `float \| None`             | Aggregate reward value.           |
| `num_tool_calls`         | `int \| None`               | Total tool invocations.           |
| `num_tool_failures`      | `int \| None`               | Failed tool calls.                |
| `num_tool_response_none` | `int \| None`               | Tool calls with no response.      |
| `tool_error_rate`        | `float \| None`             | Failure ratio.                    |
| `env_time`               | `float \| None`             | Time in tool execution (seconds). |
| `llm_time`               | `float \| None`             | Time waiting for LLM (seconds).   |
| `total_time`             | `float \| None`             | Wall-clock time (seconds).        |
| `termination_reason`     | `TerminationReason \| None` | Why the conversation ended.       |

### ConversationSummary

| Field             | Type          | Description                         |
| ----------------- | ------------- | ----------------------------------- |
| `conversation_id` | `str`         | Unique conversation identifier.     |
| `num_turns`       | `int`         | Number of turns.                    |
| `first_seen`      | `str \| None` | ISO timestamp of earliest trace.    |
| `last_seen`       | `str \| None` | ISO timestamp of most recent trace. |
| `root_run_names`  | `list[str]`   | Names of top-level runs.            |

***

## Type Aliases

```python theme={null}
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"]
```
