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

# Client

> [tab] TypeScript
>
> LaminarClient
>
> HTTP client for Tracevell API operations.
>
> ```typescript theme={null}
> import { LaminarClient } from '@lmnr-ai/lmnr';
>
> const client = new LaminarClient({
>   projectApiKey: process.env.LMNR_PROJECT_API_KEY,
> });
>
> // Tag a completed trace
> await client.tags.tag(traceId, ['user-feedback-positive']);
> ```
>
> **Constructor parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `projectApiKey` | `string` | `LMNR_PROJECT_API_KEY` env | API key |
> | `baseUrl` | `string` | `https://api.lmnr.ai` | API base URL |
> | `port` | `number` | `443` | API port |
>
> **Resources:**
>
> client.tags.tag(traceId, tags)
>
> Add tags to a completed trace.
>
> ```typescript theme={null}
> await client.tags.tag('trace-uuid', ['positive-feedback', 'resolved']);
> ```
>
> **Example: Capture a trace ID and tag later**
>
> ```typescript theme={null}
> import { Tracevell, LaminarClient, observe } from '@lmnr-ai/lmnr';
>
> Laminar.initialize();
> const client = new LaminarClient();
>
> const traceId = await observe({ name: 'chat_completion' }, async () => {
>   // ... your work ...
>   return Laminar.getTraceId();
> });
>
> await Laminar.flush();
>
> if (traceId) {
>   await client.tags.tag(traceId, 'good');
> }
> ```
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `traceId` | `string` | — | Trace UUID |
> | `tags` | `string[]` \| `string` | — | Tag(s) to add |
>
> **Returns:** `Promise<any>`
>
> **Note:** Call after `Laminar.flush()` to ensure trace exists.
>
> ***
>
> client.traces.pushMetadata(traceId, metadata)
>
> Push a metadata patch to a finished trace. The patch is shallow-merged into the trace's existing metadata server-side. Use it for post-hoc signals (quality scores, reviewer notes, edit counts) you compute after the trace ends.
>
> ```typescript theme={null}
> import { Tracevell, LaminarClient, observe } from '@lmnr-ai/lmnr';
>
> Laminar.initialize();
> const client = new LaminarClient();
>
> const traceId = await observe({ name: 'chat_completion' }, async () => {
>   // ... your work ...
>   return Laminar.getTraceId();
> });
>
> await Laminar.flush();
>
> if (traceId) {
>   await client.traces.pushMetadata(traceId, {
>     score: 0.85,
>     reviewer: 'alice',
>     editsMade: 2,
>   });
> }
> ```
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `traceId` | `string` | — | Trace UUID, or a 32-char OTel hex trace id |
> | `metadata` | `Record<string, unknown>` | — | Patch merged into existing trace metadata. Must be non-empty |
>
> **Returns:** `Promise<void>`
>
> **Note:** Call after `Laminar.flush()` to ensure the trace exists. If the trace can't be found at processing time, the call logs a warning and returns without raising. The patch increments the trace's `numSpans` by 1 (the virtual span that carried the patch) but does not change `endTime`, tokens, cost, top span, tags, or span names.
>
> ***
>
> client.rolloutSessions
>
> Debugger session management. The SDK and `lmnr-cli` call these for you during a [debugger](https://tracevell.com/docs/debugger/introduction.md) run; reach for them directly only when you script against a debug session yourself. The resource keeps its `rollout` name for backward compatibility, and it is the same session you see in the debugger UI.
>
> ```typescript theme={null}
> const projectId = await client.rolloutSessions.register({
>   sessionId: 'session-uuid',
>   name: 'checkout-agent',
> });
>
> await client.rolloutSessions.addBlock({
>   sessionId: 'session-uuid',
>   type: 'text',
>   content: { text: 'Planner skipped the inventory check.' },
> });
> ```
>
> client.rolloutSessions.register(options)
>
> Idempotently create (upsert) a debug session so it shows up in the UI. Omitting `name` never overwrites a name set elsewhere.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.sessionId` | `string` | — | Debug session id (UUID) |
> | `options.name` | `string` | — | Optional session name |
>
> **Returns:** `Promise<string | null>`: the project id resolved from the API key, or `null` if the response can't be parsed.
>
> ***
>
> client.rolloutSessions.addBlock(options)
>
> Append a block to a debug session. `trace` and `evaluation` blocks are written by the backend at ingest, so the usual use is a `text` block: a standalone note tied to the session, the same thing `lmnr-cli debug session add-note` posts.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.sessionId` | `string` | — | Debug session id (UUID) |
> | `options.type` | `SessionBlockType` | — | Block type, see [SessionBlock](https://tracevell.com/docs/sdk/typescript/types.md#sessionblock) |
> | `options.content` | `SessionBlockContent` | — | Type-specific payload, e.g. `{ text }` for a `text` block |
> | `options.failOnNotFound` | `boolean` | `false` | Throw on an unknown session instead of logging a warning |
> | `options.signal` | `AbortSignal` | — | Abort signal for the request |
>
> **Returns:** `Promise<string | null>`: the created block id, or `null` if the session was not found or the response can't be parsed.
>
> ***
>
> client.rolloutSessions.listBlocks(options)
>
> List a debug session's blocks in creation order, the same data the debugger UI renders.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.sessionId` | `string` | — | Debug session id (UUID) |
>
> **Returns:** `Promise<SessionBlock[]>`
>
> ***
>
> client.rolloutSessions.delete(options)
>
> Delete a debug session.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.sessionId` | `string` | — | Debug session id (UUID) |
>
> **Returns:** `Promise<void>`
>
> **Note:** `client.rolloutSessions.cache(...)` also exists. It is the replay cache lookup the instrumentations call during a [cached replay](https://tracevell.com/docs/debugger/caching.md) and is not meant to be called directly.
>
> `client.rolloutSessions.setName(...)` only works with `lmnr-cli` user authentication and returns a 404 for a client created with a project API key. To name or rename a session with a project API key, call `register` with a `name`.
>
> ***
>
> client.datasets
>
> Dataset operations.
>
> ```typescript theme={null}
> // List datasets
> const datasets = await client.datasets.listDatasets();
>
> // Get by name
> const dataset = await client.datasets.getDatasetByName('my-dataset');
>
> // Push datapoints
> await client.datasets.push({
>   name: 'my-dataset',
>   points: [{ data: { query: 'test' }, target: { answer: '42' } }],
>   createDataset: true,
> });
>
> // Pull datapoints
> const points = await client.datasets.pull({
>   name: 'my-dataset',
>   limit: 100,
> });
> ```
>
> client.datasets.listDatasets()
>
> **Returns:** `Promise<Dataset[]>`
>
> ***
>
> client.datasets.getDatasetByName(name)
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `name` | `string` | — | Dataset name |
>
> **Returns:** `Promise<Dataset[]>`
>
> ***
>
> client.datasets.pull(options)
>
> Pull datapoints from a dataset.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.name` | `string` | — | Dataset name |
> | `options.id` | `string` | — | Dataset ID |
> | `options.limit` | `number` | `100` | Max datapoints |
> | `options.offset` | `number` | `0` | Pagination offset |
>
> **Returns:** `Promise<GetDatapointsResponse<D, T>>`
>
> ***
>
> client.datasets.push(options)
>
> Push datapoints to a dataset.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.points` | `Datapoint<D, T>[]` | — | Datapoints to push |
> | `options.name` | `string` | — | Dataset name |
> | `options.id` | `string` | — | Dataset ID |
> | `options.batchSize` | `number` | `100` | Batch size |
> | `options.createDataset` | `boolean` | `false` | Create dataset if missing |
>
> Each point may set `taskId`. Without one, the datapoint's task id defaults to its id; a task id already used by another datapoint in the dataset is renamed `<taskId>#2`, `#3`, and so on.
>
> **Returns:** `Promise<PushDatapointsResponse | undefined>`
>
> ***
>
> client.evals
>
> Evaluation operations.
>
> ```typescript theme={null}
> // Initialize evaluation
> const eval = await client.evals.init('my-eval', 'default-group');
>
> // Create datapoint
> await client.evals.createDatapoint({
>   evalId: eval.id,
>   data: { query: 'test' },
>   target: { answer: '42' },
> });
> ```
>
> client.evals.init(name?, groupName?, metadata?)
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `name` | `string` | — | Evaluation name |
> | `groupName` | `string` | — | Group name |
> | `metadata` | `Record<string, any>` | — | Evaluation metadata |
>
> **Returns:** `Promise<InitEvaluationResponse>`
>
> ***
>
> client.evals.createDatapoint(options)
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.evalId` | `string` | — | Evaluation UUID |
> | `options.data` | `any` | — | Input data |
> | `options.target` | `any` | — | Target/expected output |
> | `options.metadata` | `Record<string, any>` | — | Datapoint metadata |
> | `options.index` | `number` | — | Dataset index |
> | `options.traceId` | `string` | — | Trace UUID |
> | `options.taskId` | `string` | — | Task id shared by every Trial of the Task (server defaults to `index`) |
>
> **Returns:** `Promise<string>`
>
> ***
>
> client.evaluators.score(options)
>
> Attach evaluator score to a trace or span.
>
> ```typescript theme={null}
> await client.evaluators.score({
>   name: 'quality',
>   score: 0.95,
>   traceId: 'trace-uuid',
> });
> ```
>
> **Parameters:**
>
> Pass exactly one of `traceId` or `spanId`.
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `options.name` | `string` | — | Evaluator name |
> | `options.score` | `number` | — | Score value |
> | `options.metadata` | `Record<string, any>` | — | Score metadata |
> | `options.traceId` | `string` | — | Trace UUID |
> | `options.spanId` | `string` | — | Span UUID |
>
> **Returns:** `Promise<void>`

> [tab] Python
>
> LaminarClient
>
> Synchronous HTTP client for Tracevell API operations.
>
> ```python theme={null}
> from lmnr import LaminarClient
>
> client = LaminarClient()
>
> # Tag a completed trace
> client.tags.tag(trace_id, ["user-feedback-positive"])
> ```
>
> **Constructor parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `project_api_key` | `str` | `LMNR_PROJECT_API_KEY` env | API key |
> | `base_url` | `str` | `https://api.lmnr.ai` | API base URL |
> | `port` | `int` | From URL | API port |
> | `timeout` | `int` | `3600` | Request timeout (seconds) |
>
> **Resources:**
>
> client.tags.tag(trace\_id, tags)
>
> Add tags to a completed trace.
>
> ```python theme={null}
> from lmnr import Tracevell, LaminarClient, observe
>
> Laminar.initialize()
> client = LaminarClient()
>
> @observe()
> def my_trace():
>     return Laminar.get_trace_id()
>
> trace_id = my_trace()
> Laminar.flush()
>
> if trace_id:
>     client.tags.tag(trace_id, ["user-feedback-positive"])
> ```
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `trace_id` | `str` \| `int` \| `uuid.UUID` | — | Trace identifier |
> | `tags` | `list[str]` \| `str` | — | Tag(s) to add |
>
> **Returns:** `list[dict]` (returns `[]` on 404)
>
> **Note:** Call after the trace has ended (use `Laminar.flush()` for short-lived scripts).
>
> ***
>
> client.traces.push\_metadata(trace\_id, metadata)
>
> Push a metadata patch to a finished trace. The patch is shallow-merged into the trace's existing metadata server-side. Use it for post-hoc signals (quality scores, reviewer notes, edit counts) you compute after the trace ends.
>
> ```python theme={null}
> from lmnr import Tracevell, LaminarClient, observe
>
> Laminar.initialize()
> client = LaminarClient()
>
> @observe(name="chat_completion")
> def chat_completion():
>     # ... your work ...
>     return Laminar.get_trace_id()
>
> trace_id = chat_completion()
> Laminar.flush()
>
> if trace_id:
>     client.traces.push_metadata(
>         trace_id,
>         {"score": 0.85, "reviewer": "alice", "edits_made": 2},
>     )
> ```
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `trace_id` | `str` \| `int` \| `uuid.UUID` | — | Trace identifier |
> | `metadata` | `dict[str, Any]` | — | Patch merged into existing trace metadata. Must be non-empty |
>
> **Returns:** `None`
>
> **Note:** Call after the trace has ended (use `Laminar.flush()` for short-lived scripts). If the trace can't be found at processing time, the call logs a warning and returns without raising. The patch increments the trace's `num_spans` by 1 (the virtual span that carried the patch) but does not change `end_time`, tokens, cost, top span, tags, or span names. The async client exposes the same method as `await client.traces.push_metadata(...)`.
>
> ***
>
> client.rollout\_sessions
>
> Debugger session management. The SDK and `lmnr-cli` call these for you during a [debugger](https://tracevell.com/docs/debugger/introduction.md) run; reach for them directly only when you script against a debug session yourself. The resource keeps its `rollout` name for backward compatibility, and it is the same session you see in the debugger UI.
>
> ```python theme={null}
> project_id = client.rollout_sessions.register("session-uuid", name="checkout-agent")
>
> client.rollout_sessions.add_block(
>     "session-uuid",
>     type="text",
>     content={"text": "Planner skipped the inventory check."},
> )
> ```
>
> client.rollout\_sessions.register(session\_id, name=None)
>
> Idempotently create (upsert) a debug session so it shows up in the UI. Omitting `name` never overwrites a name set elsewhere.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `session_id` | `uuid.UUID` \| `str` | — | Debug session id (UUID) |
> | `name` | `str` \| `None` | `None` | Optional session name |
>
> **Returns:** `str | None`: the project id resolved from the API key, or `None` if the response can't be parsed.
>
> ***
>
> client.rollout\_sessions.add\_block(session\_id, type, content, fail\_on\_not\_found=False)
>
> Append a block to a debug session. `trace` and `evaluation` blocks are written by the backend at ingest, so the usual use is a `text` block: a standalone note tied to the session, the same thing `lmnr-cli debug session add-note` posts.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `session_id` | `uuid.UUID` \| `str` | — | Debug session id (UUID) |
> | `type` | `SessionBlockType` | — | Block type, see [SessionBlock](https://tracevell.com/docs/sdk/python/types.md#sessionblock) |
> | `content` | `SessionBlockContent` | — | Type-specific payload, e.g. `{"text": ...}` for a `text` block |
> | `fail_on_not_found` | `bool` | `False` | Raise on an unknown session instead of logging a warning |
>
> **Returns:** `str | None`: the created block id, or `None` if the session was not found or the response can't be parsed.
>
> ***
>
> client.rollout\_sessions.list\_blocks(session\_id)
>
> List a debug session's blocks in creation order, the same data the debugger UI renders.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `session_id` | `uuid.UUID` \| `str` | — | Debug session id (UUID) |
>
> **Returns:** `list[SessionBlock]`
>
> ***
>
> client.rollout\_sessions.delete(session\_id)
>
> Delete a debug session.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `session_id` | `uuid.UUID` \| `str` | — | Debug session id (UUID) |
>
> **Returns:** `None`
>
> **Note:** `AsyncLaminarClient.rollout_sessions` exposes the same methods as awaitables. `rollout_sessions.cache(...)` also exists. It is the replay cache lookup the instrumentations call during a [cached replay](https://tracevell.com/docs/debugger/caching.md) and is not meant to be called directly.
>
> ***
>
> client.close()
>
> Close the underlying HTTP client.
>
> **Returns:** `None`
>
> ***
>
> client.datasets.pull(name=None, id=None, limit=100, offset=0)
>
> Pull datapoints from a dataset.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `name` | `str` | `None` | Dataset name |
> | `id` | `uuid.UUID` | `None` | Dataset ID |
> | `limit` | `int` | `100` | Max datapoints |
> | `offset` | `int` | `0` | Pagination offset |
>
> **Returns:** `GetDatapointsResponse`
>
> ***
>
> client.datasets.push(points, name=None, id=None, batch\_size=100, create\_dataset=False)
>
> Push datapoints to a dataset.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `points` | `list[Datapoint]` | — | Datapoints to push |
> | `name` | `str` | `None` | Dataset name |
> | `id` | `uuid.UUID` | `None` | Dataset ID |
> | `batch_size` | `int` | `100` | Batch size |
> | `create_dataset` | `bool` | `False` | Create dataset if missing |
>
> Each point may set `task_id` (or `taskId`). Without one, the datapoint's task id defaults to its id; a task id already used by another datapoint in the dataset is renamed `<task_id>#2`, `#3`, and so on.
>
> **Returns:** `PushDatapointsResponse | None`
>
> ***
>
> client.evals.init(name=None, group\_name=None, metadata=None)
>
> Initialize an evaluation.
>
> **Parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `name` | `str` | `None` | Evaluation name |
> | `group_name` | `str` | `None` | Group name |
> | `metadata` | `dict` | `None` | Evaluation metadata |
>
> **Returns:** `InitEvaluationResponse`
>
> ***
>
> client.evaluators.score(...)
>
> Create a score for a trace or span.
>
> **Parameters:**
>
> Pass exactly one of `trace_id` or `span_id`.
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `name` | `str` | — | Evaluator name |
> | `score` | `float` | — | Score value |
> | `trace_id` | `str` \| `int` \| `uuid.UUID` | `None` | Trace identifier |
> | `span_id` | `str` \| `int` \| `uuid.UUID` | `None` | Span identifier |
> | `metadata` | `dict` | `None` | Score metadata |
>
> **Returns:** `None`
>
> ***
>
> AsyncLaminarClient
>
> Async variant of `LaminarClient`.
>
> ```python theme={null}
> from lmnr import AsyncLaminarClient
>
> client = AsyncLaminarClient()
> await client.tags.tag(trace_id, ["feedback"])
> await client.close()
> ```
>
> **Constructor parameters:**
>
> | Name | Type | Default | Description |
> | - | - | - | - |
> | `project_api_key` | `str` | `None` | API key (defaults to `LMNR_PROJECT_API_KEY`) |
> | `base_url` | `str` | `None` | API base URL (defaults to `LMNR_BASE_URL` or `https://api.lmnr.ai`) |
> | `port` | `int` | `None` | API port (defaults to `443`) |
> | `timeout` | `int` | `3600` | Request timeout (seconds) |
>
> await client.close()
>
> **Returns:** `None`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.