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

# Migrate to SmithDB-backed SDK methods

> Migrate your existing LangSmith SDK methods to their SmithDB-backed equivalents for faster agent observability.

## Context

In May 2026, we released [SmithDB](https://www.langchain.com/blog/introducing-smithdb?utm_source=docs), a new observability database built for modern AI agents. SmithDB delivers industry-leading performance across every key observability workload, making core LangSmith experiences dramatically faster.

SmithDB-powered methods are now available to SDK users in eligible regions.

## Deployment support

| Deployment                | Status                                               |
| ------------------------- | ---------------------------------------------------- |
| US SaaS                   | Available. Methods are fully SmithDB-backed.         |
| EU and other SaaS regions | Methods are available but not yet backed by SmithDB. |
| Self-hosted               | Supported starting with self-hosted version 0.16.0.  |

## Minimum SDK version

The SmithDB-backed methods require a minimum SDK version:

| Language   | Package          | Minimum version |
| ---------- | ---------------- | --------------- |
| Python     | `langsmith`      | `>=0.9.8`       |
| TypeScript | `langsmith`      | `>=0.7.15`      |
| Java       | `langsmith-java` | `0.1.0-beta.11` |
| Go         | `langsmith-go`   | `v0.17.0`       |

## Migrate with an AI agent

This guide is written to be fetched and applied directly by an AI coding agent. Copy the following prompt into your agent to migrate your codebase to the SmithDB-backed methods.

```text theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
Migrate this codebase's LangSmith SDK usage to the new SmithDB-backed methods.

Fetch https://docs.langchain.com/langsmith/smithdb-sdk-migration.md and treat it
as the source of truth for what changed, including which methods and
parameters are affected, what replaces them, and deployment support.

1. Check the installed LangSmith SDK version against the minimum version
   required for the SmithDB-backed methods per the guide, and upgrade the
   dependency if it does not meet that minimum.
2. Identify every call site in this codebase that uses a method the guide
   marks as migrated, in whichever language(s) this codebase uses.
3. For each call site, apply the corresponding before/after change from the
   guide, including any added, removed, or renamed parameters.

If a call site or parameter is not covered by the guide, stop and ask rather
than guessing.
```

## Runs: query

Query runs from a project with optional filtering and field projection. Returns a paginated result set.

### Main changes

#### Method name

<Tabs>
  <Tab title="Python">
    | Before               | After                 |
    | -------------------- | --------------------- |
    | `client.list_runs()` | `client.runs.query()` |
  </Tab>

  <Tab title="TypeScript">
    | Before              | After                 |
    | ------------------- | --------------------- |
    | `client.listRuns()` | `client.runs.query()` |
  </Tab>

  <Tab title="Java">
    | Before                  | After                     |
    | ----------------------- | ------------------------- |
    | `client.runs().query()` | `client.runs().queryV2()` |
  </Tab>

  <Tab title="Go">
    | Before                | After                   |
    | --------------------- | ----------------------- |
    | `client.Runs.Query()` | `client.Runs.QueryV2()` |
  </Tab>

  <Tab title="cURL">
    | Before                    | After                 |
    | ------------------------- | --------------------- |
    | `POST /api/v1/runs/query` | `POST /v2/runs/query` |
  </Tab>
</Tabs>

#### Query parameters

<Tabs>
  <Tab title="Python">
    <Warning>
      `project_name` is not supported in `runs.query`. Pass `project_ids` with the project UUID instead. To look up a UUID by name, use `client.read_project(project_name="my-project")`, or `await client.aread_project(project_name="my-project")` in async code.
    </Warning>

    <Warning>
      `min_start_time` defaults to **1 day ago** when omitted. `list_runs` with no `start_time` returned all historical runs; `runs.query` without `min_start_time` silently scopes the query to the last 24 hours. Pass an explicit `min_start_time` if you need a wider window.
    </Warning>

    | Before (`list_runs`)   | After (`runs.query`)   | Notes                                                                                                            |
    | ---------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
    | `project_name`         | *(removed)*            | Use `project_ids` with UUID(s)—see warning above                                                                 |
    | `project_id`           | `project_ids`          | Now takes a list; mutually exclusive with `reference_dataset_id`                                                 |
    | `run_type`             | `run_type`             | Values must now be uppercase: `"LLM"`, `"CHAIN"`, `"TOOL"`, `"RETRIEVER"`, `"EMBEDDING"`, `"PROMPT"`, `"PARSER"` |
    | `trace_id`             | `trace_id`             | Unchanged                                                                                                        |
    | `reference_example_id` | `reference_examples`   | Now takes a list of UUIDs                                                                                        |
    | `query`                | *(removed)*            | No equivalent                                                                                                    |
    | `filter`               | `filter`               | Syntax unchanged                                                                                                 |
    | `trace_filter`         | `trace_filter`         | Unchanged                                                                                                        |
    | `tree_filter`          | `tree_filter`          | Unchanged                                                                                                        |
    | `is_root`              | `is_root`              | Unchanged                                                                                                        |
    | `parent_run_id`        | *(removed)*            | No equivalent                                                                                                    |
    | `start_time`           | `min_start_time`       | Renamed; defaults to 1 day ago—see warning above                                                                 |
    | `error`                | `has_error`            | Renamed                                                                                                          |
    | `run_ids`              | `ids`                  | Renamed                                                                                                          |
    | `select`               | `selects`              | Field names are now uppercase (`"NAME"`, `"STATUS"`, etc.)                                                       |
    | `limit`                | *(removed)*            | Use `page_size` for per-request batch size                                                                       |
    | *(not available)*      | `max_start_time`       | Upper bound for `start_time`; defaults to now                                                                    |
    | *(not available)*      | `page_size`            | Per-request result count (default 100, max 1000)                                                                 |
    | *(not available)*      | `reference_dataset_id` | Alternative to `project_ids`; mutually exclusive                                                                 |
    | *(not available)*      | `cursor`               | Pass `next_cursor` from previous response to fetch next page                                                     |
  </Tab>

  <Tab title="TypeScript">
    <Warning>
      `projectName` is not supported in `client.runs.query`. Pass `project_ids` with the project UUID instead. To look up a UUID by name, use `client.readProject({ projectName: "my-project" })`.
    </Warning>

    <Warning>
      `min_start_time` defaults to **1 day ago** when omitted. `listRuns` with no `startTime` returned all historical runs; `client.runs.query` without `min_start_time` silently scopes the query to the last 24 hours. Pass an explicit `min_start_time` if you need a wider window.
    </Warning>

    | Before (`listRuns`)  | After (`client.runs.query`) | Notes                                                                                                                                     |
    | -------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
    | `projectName`        | *(removed)*                 | Use `project_ids` with UUID(s)—see warning above                                                                                          |
    | `projectId`          | `project_ids`               | Renamed to `snake_case`; now takes a list; mutually exclusive with `reference_dataset_id`                                                 |
    | `runType`            | `run_type`                  | Renamed to `snake_case`; values must now be uppercase: `"LLM"`, `"CHAIN"`, `"TOOL"`, `"RETRIEVER"`, `"EMBEDDING"`, `"PROMPT"`, `"PARSER"` |
    | `traceId`            | `trace_id`                  | Renamed to `snake_case`                                                                                                                   |
    | `referenceExampleId` | `reference_examples`        | Renamed to `snake_case`; now takes a list of UUIDs                                                                                        |
    | `query`              | *(removed)*                 | No equivalent                                                                                                                             |
    | `filter`             | `filter`                    | Syntax unchanged                                                                                                                          |
    | `traceFilter`        | `trace_filter`              | Renamed to `snake_case`                                                                                                                   |
    | `treeFilter`         | `tree_filter`               | Renamed to `snake_case`                                                                                                                   |
    | `isRoot`             | `is_root`                   | Renamed to `snake_case`                                                                                                                   |
    | `parentRunId`        | *(removed)*                 | No equivalent                                                                                                                             |
    | `startTime`          | `min_start_time`            | Renamed to `snake_case`; defaults to 1 day ago—see warning above                                                                          |
    | `error`              | `has_error`                 | Renamed                                                                                                                                   |
    | `id`                 | `ids`                       | Renamed                                                                                                                                   |
    | `select`             | `selects`                   | Field names are now uppercase (`"NAME"`, `"STATUS"`, etc.)                                                                                |
    | `limit`              | *(removed)*                 | Use `page_size` for per-request batch size                                                                                                |
    | `order`              | *(removed)*                 | No equivalent                                                                                                                             |
    | `executionOrder`     | *(removed)*                 | No equivalent                                                                                                                             |
    | *(not available)*    | `max_start_time`            | Upper bound for `start_time`; defaults to now                                                                                             |
    | *(not available)*    | `page_size`                 | Per-request result count (default 100, max 1000)                                                                                          |
    | *(not available)*    | `reference_dataset_id`      | Alternative to `project_ids`; mutually exclusive                                                                                          |
    | *(not available)*    | `cursor`                    | Pass `next_cursor` from previous response to fetch next page                                                                              |
  </Tab>

  <Tab title="Java">
    <Warning>
      `minStartTime()` defaults to **1 day ago** when omitted. `query()` with no `startTime()` returned all historical runs; `queryV2()` without `minStartTime()` silently scopes the query to the last 24 hours. Pass an explicit `minStartTime()` if you need a wider window.
    </Warning>

    | Before (`RunQueryParams`) | After (`RunQueryV2Params`) | Notes                                            |
    | ------------------------- | -------------------------- | ------------------------------------------------ |
    | `session()`               | `projectIds()`             | Renamed; now takes explicit project UUIDs        |
    | `runType()`               | `runType()`                | Values must now be uppercase                     |
    | `trace()`                 | `traceId()`                | Renamed                                          |
    | `referenceExample()`      | `referenceExamples()`      | Renamed to plural                                |
    | `query()`                 | *(removed)*                | No equivalent                                    |
    | `filter()`                | `filter()`                 | Syntax unchanged                                 |
    | `traceFilter()`           | `traceFilter()`            | Unchanged                                        |
    | `treeFilter()`            | `treeFilter()`             | Unchanged                                        |
    | `isRoot()`                | `isRoot()`                 | Unchanged                                        |
    | `parentRun()`             | *(removed)*                | No equivalent                                    |
    | `startTime()`             | `minStartTime()`           | Renamed; defaults to 1 day ago—see warning above |
    | `error()`                 | `hasError()`               | Renamed                                          |
    | `id()`                    | `ids()`                    | Renamed                                          |
    | `select()`                | `selects()`                | Field names are now uppercase                    |
    | `limit()`                 | *(removed)*                | Use `pageSize()`                                 |
    | `order()`                 | *(removed)*                | No equivalent                                    |
    | `executionOrder()`        | *(removed)*                | No equivalent                                    |
    | `cursor()`                | `cursor()`                 | Unchanged                                        |
    | *(not available)*         | `maxStartTime()`           | Upper bound for start time; defaults to now      |
    | *(not available)*         | `pageSize()`               | Per-request result count (default 100, max 1000) |
    | *(not available)*         | `referenceDatasetId()`     | Alternative to `projectIds()`                    |
  </Tab>

  <Tab title="Go">
    <Warning>
      `MinStartTime` defaults to **1 day ago** when omitted. `Query()` with no `StartTime` returned all historical runs; `QueryV2()` without `MinStartTime` silently scopes the query to the last 24 hours. Pass an explicit `MinStartTime` if you need a wider window.
    </Warning>

    | Before (`RunQueryParams`) | After (`RunQueryV2Params`) | Notes                                                                                            |
    | ------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------ |
    | `Session`                 | `ProjectIDs`               | Renamed; now takes explicit project UUIDs                                                        |
    | `RunType`                 | `RunType`                  | Values must now be uppercase: `RunQueryV2ParamsRunTypeLLM`, `RunQueryV2ParamsRunTypeChain`, etc. |
    | `Trace`                   | `TraceID`                  | Renamed                                                                                          |
    | `ReferenceExample`        | `ReferenceExamples`        | Renamed to plural                                                                                |
    | `Query`                   | *(removed)*                | No equivalent                                                                                    |
    | `Filter`                  | `Filter`                   | Unchanged                                                                                        |
    | `TraceFilter`             | `TraceFilter`              | Unchanged                                                                                        |
    | `TreeFilter`              | `TreeFilter`               | Unchanged                                                                                        |
    | `IsRoot`                  | `IsRoot`                   | Unchanged                                                                                        |
    | `ParentRun`               | *(removed)*                | No equivalent                                                                                    |
    | `StartTime`               | `MinStartTime`             | Renamed; defaults to 1 day ago—see warning above                                                 |
    | `Error`                   | `HasError`                 | Renamed                                                                                          |
    | `ID`                      | `IDs`                      | Renamed                                                                                          |
    | `Select`                  | `Selects`                  | Field name constants are now uppercase (e.g., `RunQueryV2ParamsSelectName`)                      |
    | `Limit`                   | *(removed)*                | Use `PageSize`                                                                                   |
    | `Order`                   | *(removed)*                | No equivalent                                                                                    |
    | `ExecutionOrder`          | *(removed)*                | No equivalent                                                                                    |
    | `Cursor`                  | `Cursor`                   | Unchanged                                                                                        |
    | *(not available)*         | `MaxStartTime`             | Upper bound for start time; defaults to now                                                      |
    | *(not available)*         | `PageSize`                 | Per-request result count (default 100, max 1000)                                                 |
    | *(not available)*         | `ReferenceDatasetID`       | Alternative to `ProjectIDs`                                                                      |
  </Tab>

  <Tab title="cURL">
    <Warning>
      `min_start_time` defaults to **1 day ago** when omitted. `POST /api/v1/runs/query` with no `start_time` returned all historical runs; `POST /v2/runs/query` without `min_start_time` silently scopes the query to the last 24 hours. Pass an explicit `min_start_time` if you need a wider window.
    </Warning>

    | Before (v1 `POST /api/v1/runs/query` body field) | After (v2 `POST /v2/runs/query` body field) | Notes                                                                                                            |
    | ------------------------------------------------ | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
    | `session`                                        | `project_ids`                               | Renamed; both take an array of project UUIDs. `project_ids` is mutually exclusive with `reference_dataset_id`    |
    | `run_type`                                       | `run_type`                                  | Values must now be uppercase: `"LLM"`, `"CHAIN"`, `"TOOL"`, `"RETRIEVER"`, `"EMBEDDING"`, `"PROMPT"`, `"PARSER"` |
    | `trace`                                          | `trace_id`                                  | Renamed                                                                                                          |
    | `reference_example`                              | `reference_examples`                        | Renamed to plural; now takes an array of UUIDs                                                                   |
    | `query`                                          | *(removed)*                                 | No equivalent                                                                                                    |
    | `filter`                                         | `filter`                                    | Syntax unchanged                                                                                                 |
    | `trace_filter`                                   | `trace_filter`                              | Unchanged                                                                                                        |
    | `tree_filter`                                    | `tree_filter`                               | Unchanged                                                                                                        |
    | `is_root`                                        | `is_root`                                   | Unchanged                                                                                                        |
    | `parent_run`                                     | *(removed)*                                 | No equivalent                                                                                                    |
    | `start_time`                                     | `min_start_time`                            | Renamed; defaults to 1 day ago—see warning above                                                                 |
    | `error`                                          | `has_error`                                 | Renamed                                                                                                          |
    | `id`                                             | `ids`                                       | Renamed to plural                                                                                                |
    | `select`                                         | `selects`                                   | Field names are now uppercase (`"NAME"`, `"STATUS"`, etc.)                                                       |
    | `limit`                                          | *(removed)*                                 | Use `page_size` for per-request batch size                                                                       |
    | *(not available)*                                | `max_start_time`                            | Upper bound for `start_time`; defaults to now                                                                    |
    | *(not available)*                                | `page_size`                                 | Per-request result count (default 100, max 1000)                                                                 |
    | *(not available)*                                | `reference_dataset_id`                      | Alternative to `project_ids`; mutually exclusive                                                                 |
    | *(not available)*                                | `cursor`                                    | Pass `next_cursor` from previous response to fetch next page                                                     |
  </Tab>
</Tabs>

#### Response fields

<Tabs>
  <Tab title="Python">
    Pass SCREAMING\_SNAKE\_CASE strings to `selects` (eg. `"ID"`, `"NAME"`, `"STATUS"`) to control which fields are populated on each `Run`; only selected fields are non-`None`. Default `selects` contains only `"ID"`.

    | Before (v1 `Run` attribute)    | After (v2 `Run` attribute)         | Notes                                                                                        |
    | ------------------------------ | ---------------------------------- | -------------------------------------------------------------------------------------------- |
    | `run.id`                       | `run.id`                           | Unchanged; returned by default when `selects` is omitted                                     |
    | `run.name`                     | `run.name`                         | Unchanged                                                                                    |
    | `run.run_type`                 | `run.run_type`                     | Values are now uppercase Literals: `"LLM"`, `"CHAIN"`, etc.                                  |
    | `run.status`                   | `run.status`                       | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                  |
    | `run.start_time`               | `run.start_time`                   | Unchanged                                                                                    |
    | `run.end_time`                 | `run.end_time`                     | Unchanged                                                                                    |
    | `run.error`                    | `run.error`                        | Unchanged                                                                                    |
    | `run.inputs`                   | `run.inputs`                       | Unchanged                                                                                    |
    | `run.outputs`                  | `run.outputs`                      | Unchanged                                                                                    |
    | `run.tags`                     | `run.tags`                         | Unchanged                                                                                    |
    | `run.extra`                    | `run.extra`                        | Unchanged                                                                                    |
    | `run.metadata`                 | `run.metadata`                     | Unchanged                                                                                    |
    | `run.events`                   | `run.events`                       | Unchanged                                                                                    |
    | `run.reference_example_id`     | `run.reference_example_id`         | Unchanged                                                                                    |
    | `run.trace_id`                 | `run.trace_id`                     | Unchanged                                                                                    |
    | `run.dotted_order`             | `run.dotted_order`                 | Unchanged                                                                                    |
    | `run.parent_run_id`            | *(removed)*                        | Use `run.parent_run_ids` (list of all ancestor UUIDs, root first)                            |
    | `run.parent_run_ids`           | `run.parent_run_ids`               | Unchanged                                                                                    |
    | `run.session_id`               | `run.project_id`                   | Renamed; `session_id` was the project UUID                                                   |
    | `run.feedback_stats`           | `run.feedback_stats`               | Unchanged                                                                                    |
    | `run.app_path`                 | `run.app_path`                     | Unchanged                                                                                    |
    | `run.attachments`              | `run.attachments`                  | v2 returns pre-signed download URLs instead of raw bytes                                     |
    | `run.total_tokens`             | `run.total_tokens`                 | Unchanged                                                                                    |
    | `run.prompt_tokens`            | `run.prompt_tokens`                | Unchanged                                                                                    |
    | `run.completion_tokens`        | `run.completion_tokens`            | Unchanged                                                                                    |
    | `run.total_cost`               | `run.total_cost`                   | Unchanged                                                                                    |
    | `run.prompt_cost`              | `run.prompt_cost`                  | Unchanged                                                                                    |
    | `run.completion_cost`          | `run.completion_cost`              | Unchanged                                                                                    |
    | `run.first_token_time`         | `run.first_token_time`             | Unchanged                                                                                    |
    | `run.latency` (property)       | `run.latency_seconds`              | Renamed; was a computed `timedelta` property, now a native `float` field                     |
    | `run.in_dataset`               | `run.is_in_dataset`                | Renamed                                                                                      |
    | `run.child_run_ids`            | *(removed)*                        | No equivalent                                                                                |
    | `run.child_runs`               | *(removed)*                        | No equivalent                                                                                |
    | `run.serialized`               | *(removed)*                        | Use `run.manifest`                                                                           |
    | `run.manifest_id`              | *(removed)*                        | Use `run.manifest`                                                                           |
    | *(not available)*              | `run.is_root`                      | New                                                                                          |
    | *(not available)*              | `run.manifest`                     | New: full manifest object (replaces `serialized` and `manifest_id`)                          |
    | *(not available)*              | `run.error_preview`                | New: truncated error snippet                                                                 |
    | *(not available)*              | `run.inputs_preview`               | New: truncated inputs preview                                                                |
    | *(not available)*              | `run.outputs_preview`              | New: truncated outputs preview                                                               |
    | *(not available)*              | `run.thread_id`                    | New: conversation thread UUID                                                                |
    | *(not available)*              | `run.reference_dataset_id`         | New: dataset UUID for the reference example                                                  |
    | *(not available)*              | `run.share_url`                    | New: public share URL (only set when the run has been shared)                                |
    | `run.prompt_token_details`     | `run.prompt_token_details.raw`     | Field now wraps the dict; access `.raw` to get `dict[str, int]` (element type unchanged)     |
    | `run.completion_token_details` | `run.completion_token_details.raw` | Field now wraps the dict; access `.raw` to get `dict[str, int]` (element type unchanged)     |
    | `run.prompt_cost_details`      | `run.prompt_cost_details.raw`      | Field now wraps the dict; access `.raw` to get `dict[str, float]` (was `dict[str, Decimal]`) |
    | `run.completion_cost_details`  | `run.completion_cost_details.raw`  | Field now wraps the dict; access `.raw` to get `dict[str, float]` (was `dict[str, Decimal]`) |
  </Tab>

  <Tab title="TypeScript">
    Pass SCREAMING\_SNAKE\_CASE strings to `selects` (eg. `"ID"`, `"NAME"`, `"STATUS"`) to control which fields are populated on each `Run`. Default `selects` contains only `"ID"`.

    | Before (v1 `Run` property) | After (v2 `Run` property)      | Notes                                                                       |
    | -------------------------- | ------------------------------ | --------------------------------------------------------------------------- |
    | `run.id`                   | `run.id`                       | Unchanged                                                                   |
    | `run.name`                 | `run.name`                     | Unchanged                                                                   |
    | `run.runType`              | `run.run_type`                 | Renamed to `snake_case`; values are now uppercase: `"LLM"`, `"CHAIN"`, etc. |
    | `run.status`               | `run.status`                   | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                 |
    | `run.startTime`            | `run.start_time`               | Renamed to `snake_case`                                                     |
    | `run.endTime`              | `run.end_time`                 | Renamed to `snake_case`                                                     |
    | `run.error`                | `run.error`                    | Unchanged                                                                   |
    | `run.inputs`               | `run.inputs`                   | Unchanged                                                                   |
    | `run.outputs`              | `run.outputs`                  | Unchanged                                                                   |
    | `run.tags`                 | `run.tags`                     | Unchanged                                                                   |
    | `run.extra`                | `run.extra`                    | Unchanged                                                                   |
    | *(not available)*          | `run.metadata`                 | New: previously accessed via `run.extra.metadata`                           |
    | `run.events`               | `run.events`                   | Unchanged                                                                   |
    | `run.referenceExampleId`   | `run.reference_example_id`     | Renamed to `snake_case`                                                     |
    | `run.traceId`              | `run.trace_id`                 | Renamed to `snake_case`                                                     |
    | `run.dottedOrder`          | `run.dotted_order`             | Renamed to `snake_case`                                                     |
    | `run.parentRunId`          | *(removed)*                    | Use `run.parent_run_ids` (list of all ancestor UUIDs, root first)           |
    | `run.parentRunIds`         | `run.parent_run_ids`           | Renamed to `snake_case`                                                     |
    | `run.sessionId`            | `run.project_id`               | Renamed; `sessionId` was the project UUID                                   |
    | `run.feedbackStats`        | `run.feedback_stats`           | Renamed to `snake_case`                                                     |
    | `run.appPath`              | `run.app_path`                 | Renamed to `snake_case`                                                     |
    | `run.attachments`          | `run.attachments`              | v2 returns pre-signed download URLs instead of raw bytes                    |
    | `run.totalTokens`          | `run.total_tokens`             | Renamed to `snake_case`                                                     |
    | `run.promptTokens`         | `run.prompt_tokens`            | Renamed to `snake_case`                                                     |
    | `run.completionTokens`     | `run.completion_tokens`        | Renamed to `snake_case`                                                     |
    | `run.totalCost`            | `run.total_cost`               | Renamed to `snake_case`                                                     |
    | `run.promptCost`           | `run.prompt_cost`              | Renamed to `snake_case`                                                     |
    | `run.completionCost`       | `run.completion_cost`          | Renamed to `snake_case`                                                     |
    | `run.firstTokenTime`       | `run.first_token_time`         | Renamed to `snake_case`                                                     |
    | `run.latency`              | `run.latency_seconds`          | Renamed; was a computed property, now a native `number` field (seconds)     |
    | `run.inDataset`            | `run.is_in_dataset`            | Renamed                                                                     |
    | `run.childRunIds`          | *(removed)*                    | No equivalent                                                               |
    | `run.childRuns`            | *(removed)*                    | No equivalent                                                               |
    | `run.serialized`           | *(removed)*                    | Use `run.manifest`                                                          |
    | `run.manifestId`           | *(removed)*                    | Use `run.manifest`                                                          |
    | `run.shareToken`           | *(removed)*                    | Use `run.share_url` (full URL, only set when the run has been shared)       |
    | *(not available)*          | `run.is_root`                  | New                                                                         |
    | *(not available)*          | `run.manifest`                 | New: full manifest object (replaces `serialized` and `manifestId`)          |
    | *(not available)*          | `run.error_preview`            | New: truncated error snippet                                                |
    | *(not available)*          | `run.inputs_preview`           | New: truncated inputs preview                                               |
    | *(not available)*          | `run.outputs_preview`          | New: truncated outputs preview                                              |
    | *(not available)*          | `run.thread_id`                | New: conversation thread UUID                                               |
    | *(not available)*          | `run.reference_dataset_id`     | New: dataset UUID for the reference example                                 |
    | *(not available)*          | `run.share_url`                | New: public share URL (only set when the run has been shared)               |
    | *(not available)*          | `run.prompt_token_details`     | New: per-category prompt token breakdown                                    |
    | *(not available)*          | `run.completion_token_details` | New: per-category completion token breakdown                                |
    | *(not available)*          | `run.prompt_cost_details`      | New: per-category prompt cost breakdown                                     |
    | *(not available)*          | `run.completion_cost_details`  | New: per-category completion cost breakdown                                 |
  </Tab>

  <Tab title="Java">
    Add `RunQueryV2Params.Select` values (eg. `Select.NAME`, `Select.STATUS`) via `.addSelect(...)` to control which fields are populated; unselected fields return empty `Optional` values. `selects()` defaults to `ID` only.

    | Before (`RunSchema` method)    | After (`Run` method)           | Notes                                                                                          |
    | ------------------------------ | ------------------------------ | ---------------------------------------------------------------------------------------------- |
    | `run.id()`                     | `run.id()`                     | Unchanged                                                                                      |
    | `run.name()`                   | `run.name()`                   | Unchanged                                                                                      |
    | `run.runType()`                | `run.runType()`                | Values are now uppercase: `"LLM"`, `"CHAIN"`, etc.                                             |
    | `run.status()`                 | `run.status()`                 | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                    |
    | `run.startTime()`              | `run.startTime()`              | Unchanged                                                                                      |
    | `run.endTime()`                | `run.endTime()`                | Unchanged                                                                                      |
    | `run.error()`                  | `run.error()`                  | Unchanged                                                                                      |
    | `run.inputs()`                 | `run.inputs()`                 | Unchanged                                                                                      |
    | `run.outputs()`                | `run.outputs()`                | Unchanged                                                                                      |
    | `run.tags()`                   | `run.tags()`                   | Unchanged                                                                                      |
    | `run.extra()`                  | `run.extra()`                  | Unchanged                                                                                      |
    | `run.events()`                 | `run.events()`                 | Unchanged                                                                                      |
    | `run.feedbackStats()`          | `run.feedbackStats()`          | Unchanged                                                                                      |
    | `run.inputsPreview()`          | `run.inputsPreview()`          | Unchanged                                                                                      |
    | `run.outputsPreview()`         | `run.outputsPreview()`         | Unchanged                                                                                      |
    | `run.referenceExampleId()`     | `run.referenceExampleId()`     | Unchanged                                                                                      |
    | `run.traceId()`                | `run.traceId()`                | Unchanged                                                                                      |
    | `run.dottedOrder()`            | `run.dottedOrder()`            | Unchanged                                                                                      |
    | `run.parentRunId()`            | *(removed)*                    | Use `run.parentRunIds()` (list of all ancestor UUIDs, root first)                              |
    | `run.parentRunIds()`           | `run.parentRunIds()`           | Unchanged                                                                                      |
    | `run.sessionId()`              | `run.projectId()`              | Renamed; `sessionId()` returned the project UUID                                               |
    | `run.appPath()`                | `run.appPath()`                | Unchanged                                                                                      |
    | `run.firstTokenTime()`         | `run.firstTokenTime()`         | Unchanged                                                                                      |
    | `run.totalTokens()`            | `run.totalTokens()`            | Unchanged                                                                                      |
    | `run.promptTokens()`           | `run.promptTokens()`           | Unchanged                                                                                      |
    | `run.completionTokens()`       | `run.completionTokens()`       | Unchanged                                                                                      |
    | `run.totalCost()`              | `run.totalCost()`              | Return type changed from `Optional<String>` to `Optional<Double>`                              |
    | `run.promptCost()`             | `run.promptCost()`             | Return type changed from `Optional<String>` to `Optional<Double>`                              |
    | `run.completionCost()`         | `run.completionCost()`         | Return type changed from `Optional<String>` to `Optional<Double>`                              |
    | `run.promptTokenDetails()`     | `run.promptTokenDetails()`     | Unchanged                                                                                      |
    | `run.completionTokenDetails()` | `run.completionTokenDetails()` | Unchanged                                                                                      |
    | `run.promptCostDetails()`      | `run.promptCostDetails()`      | Unchanged                                                                                      |
    | `run.completionCostDetails()`  | `run.completionCostDetails()`  | Unchanged                                                                                      |
    | `run.priceModelId()`           | `run.priceModelId()`           | Unchanged                                                                                      |
    | `run.inDataset()`              | `run.isInDataset()`            | Renamed                                                                                        |
    | `run.referenceDatasetId()`     | `run.referenceDatasetId()`     | Unchanged                                                                                      |
    | `run.threadId()`               | `run.threadId()`               | Unchanged                                                                                      |
    | `run.shareToken()`             | *(removed)*                    | Use `run.shareUrl()` (full URL, only set when the run has been shared)                         |
    | `run.childRunIds()`            | *(removed)*                    | No equivalent                                                                                  |
    | `run.directChildRunIds()`      | *(removed)*                    | No equivalent                                                                                  |
    | `run.serialized()`             | *(removed)*                    | Use `run.manifest()`                                                                           |
    | `run.manifestId()`             | *(removed)*                    | Use `run.manifest()`                                                                           |
    | `run.messages()`               | *(removed)*                    | No equivalent                                                                                  |
    | `run.executionOrder()`         | *(removed)*                    | No equivalent                                                                                  |
    | `run.lastQueuedAt()`           | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceFirstReceivedAt()`   | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceMaxStartTime()`      | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceMinStartTime()`      | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceTier()`              | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceUpgrade()`           | *(removed)*                    | No equivalent                                                                                  |
    | `run.ttlSeconds()`             | *(removed)*                    | No equivalent                                                                                  |
    | *(not available)*              | `run.attachments()`            | New: pre-signed download URLs for attachments (replaces S3 URL fields)                         |
    | *(not available)*              | `run.latencySeconds()`         | New: wall-clock duration in seconds                                                            |
    | *(not available)*              | `run.isRoot()`                 | New                                                                                            |
    | *(not available)*              | `run.errorPreview()`           | New: truncated error snippet                                                                   |
    | *(not available)*              | `run.manifest()`               | New: full manifest, typed as `Optional<Manifest>` (replaces `serialized()` and `manifestId()`) |
    | *(not available)*              | `run.metadata()`               | New: metadata, typed as `Optional<Metadata>` (was derived from `extra.metadata`)               |
    | *(not available)*              | `run.shareUrl()`               | New: public share URL (only set when the run has been shared)                                  |
    | *(not available)*              | `run.threadEvaluationTime()`   | New                                                                                            |
  </Tab>

  <Tab title="Go">
    Pass `RunQueryV2ParamsSelect` constants (eg. `RunQueryV2ParamsSelectName`, `RunQueryV2ParamsSelectStatus`) to `Selects` to control which fields are populated; unselected fields are zero-valued on the returned struct. `Selects` defaults to `ID` only.

    | Before (`RunSchema` field)   | After (`Run` field)              | Notes                                                                                        |
    | ---------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------- |
    | `run.ID`                     | `run.ID`                         | Unchanged                                                                                    |
    | `run.Name`                   | `run.Name`                       | Unchanged                                                                                    |
    | `run.RunType`                | `run.RunType`                    | Values changed to uppercase: `"LLM"`, `"CHAIN"`, etc.                                        |
    | `run.Status`                 | `run.Status`                     | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                  |
    | `run.TraceID`                | `run.TraceID`                    | Unchanged                                                                                    |
    | `run.DottedOrder`            | `run.DottedOrder`                | Unchanged                                                                                    |
    | `run.AppPath`                | `run.AppPath`                    | Unchanged                                                                                    |
    | `run.StartTime`              | `run.StartTime`                  | Unchanged                                                                                    |
    | `run.EndTime`                | `run.EndTime`                    | Unchanged                                                                                    |
    | `run.Error`                  | `run.Error`                      | Unchanged                                                                                    |
    | `run.Events`                 | `run.Events`                     | Unchanged; element type is now `RunEvent` (was `map[string]interface{}`)                     |
    | `run.Extra`                  | `run.Extra`                      | Unchanged; type is now `interface{}` (was `map[string]interface{}`)                          |
    | `run.FeedbackStats`          | `run.FeedbackStats`              | Unchanged; element type is now `RunFeedbackStat`                                             |
    | `run.FirstTokenTime`         | `run.FirstTokenTime`             | Unchanged                                                                                    |
    | `run.Inputs`                 | `run.Inputs`                     | Unchanged; type is now `interface{}` (was `map[string]interface{}`)                          |
    | `run.InputsPreview`          | `run.InputsPreview`              | Unchanged                                                                                    |
    | `run.Outputs`                | `run.Outputs`                    | Unchanged; type is now `interface{}` (was `map[string]interface{}`)                          |
    | `run.OutputsPreview`         | `run.OutputsPreview`             | Unchanged                                                                                    |
    | `run.ParentRunIDs`           | `run.ParentRunIDs`               | Unchanged                                                                                    |
    | `run.PriceModelID`           | `run.PriceModelID`               | Unchanged                                                                                    |
    | `run.PromptCost`             | `run.PromptCost`                 | Unchanged                                                                                    |
    | `run.PromptCostDetails`      | `run.PromptCostDetails.Raw`      | Field now wraps the map; access `.Raw` to get `map[string]float64` (was `map[string]string`) |
    | `run.PromptTokenDetails`     | `run.PromptTokenDetails.Raw`     | Field now wraps the map; access `.Raw` to get `map[string]int64` (element type unchanged)    |
    | `run.PromptTokens`           | `run.PromptTokens`               | Unchanged                                                                                    |
    | `run.CompletionCost`         | `run.CompletionCost`             | Unchanged                                                                                    |
    | `run.CompletionCostDetails`  | `run.CompletionCostDetails.Raw`  | Field now wraps the map; access `.Raw` to get `map[string]float64` (was `map[string]string`) |
    | `run.CompletionTokenDetails` | `run.CompletionTokenDetails.Raw` | Field now wraps the map; access `.Raw` to get `map[string]int64` (element type unchanged)    |
    | `run.CompletionTokens`       | `run.CompletionTokens`           | Unchanged                                                                                    |
    | `run.TotalCost`              | `run.TotalCost`                  | Unchanged                                                                                    |
    | `run.TotalTokens`            | `run.TotalTokens`                | Unchanged                                                                                    |
    | `run.ReferenceDatasetID`     | `run.ReferenceDatasetID`         | Unchanged                                                                                    |
    | `run.ReferenceExampleID`     | `run.ReferenceExampleID`         | Unchanged                                                                                    |
    | `run.Tags`                   | `run.Tags`                       | Unchanged                                                                                    |
    | `run.ThreadID`               | `run.ThreadID`                   | Unchanged                                                                                    |
    | `run.SessionID`              | `run.ProjectID`                  | Renamed                                                                                      |
    | `run.InDataset`              | `run.IsInDataset`                | Renamed                                                                                      |
    | `run.ChildRunIDs`            | *(removed)*                      | No equivalent                                                                                |
    | `run.DirectChildRunIDs`      | *(removed)*                      | No equivalent                                                                                |
    | `run.ExecutionOrder`         | *(removed)*                      | No equivalent                                                                                |
    | `run.InputsS3URLs`           | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.LastQueuedAt`           | *(removed)*                      | No equivalent                                                                                |
    | `run.ManifestID`             | *(removed)*                      | Use `run.Manifest`                                                                           |
    | `run.ManifestS3ID`           | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.Messages`               | *(removed)*                      | No equivalent                                                                                |
    | `run.OutputsS3URLs`          | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.ParentRunID`            | *(removed)*                      | Use `run.ParentRunIDs`                                                                       |
    | `run.S3URLs`                 | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.Serialized`             | *(removed)*                      | Use `run.Manifest`                                                                           |
    | `run.ShareToken`             | *(removed)*                      | Use `run.ShareURL`                                                                           |
    | `run.TraceFirstReceivedAt`   | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceMaxStartTime`      | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceMinStartTime`      | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceTier`              | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceUpgrade`           | *(removed)*                      | No equivalent                                                                                |
    | `run.TtlSeconds`             | *(removed)*                      | No equivalent                                                                                |
    | *(not available)*            | `run.Attachments`                | New: maps attachment filename to pre-signed download URL                                     |
    | *(not available)*            | `run.ErrorPreview`               | New: truncated error snippet                                                                 |
    | *(not available)*            | `run.IsRoot`                     | New                                                                                          |
    | *(not available)*            | `run.LatencySeconds`             | New: wall-clock duration in seconds                                                          |
    | *(not available)*            | `run.Manifest`                   | New: full manifest object (replaces `Serialized` and `ManifestID`)                           |
    | *(not available)*            | `run.Metadata`                   | New: arbitrary user-defined JSON metadata                                                    |
    | *(not available)*            | `run.ShareURL`                   | New: public share URL (only set when the run has been shared)                                |
    | *(not available)*            | `run.ThreadEvaluationTime`       | New                                                                                          |
  </Tab>

  <Tab title="cURL">
    Field names in the JSON response match Python `snake_case`.

    Pass SCREAMING\_SNAKE\_CASE strings in the `selects` JSON array (eg. `"ID"`, `"NAME"`, `"STATUS"`) to control which fields are populated. Default `selects` contains only `"ID"`.

    | Before (v1 response field) | After (v2 response field)      | Notes                                                                                                                  |
    | -------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
    | `id`                       | `id`                           | Unchanged                                                                                                              |
    | `name`                     | `name`                         | Unchanged                                                                                                              |
    | `run_type`                 | `run_type`                     | Values changed to uppercase: `"LLM"`, `"CHAIN"`, etc.                                                                  |
    | `status`                   | `status`                       | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                                            |
    | `trace_id`                 | `trace_id`                     | Unchanged                                                                                                              |
    | `dotted_order`             | `dotted_order`                 | Unchanged                                                                                                              |
    | `app_path`                 | `app_path`                     | Unchanged                                                                                                              |
    | `start_time`               | `start_time`                   | Unchanged                                                                                                              |
    | `end_time`                 | `end_time`                     | Unchanged                                                                                                              |
    | `error`                    | `error`                        | Unchanged                                                                                                              |
    | `events`                   | `events`                       | Unchanged                                                                                                              |
    | `extra`                    | `extra`                        | Unchanged                                                                                                              |
    | `feedback_stats`           | `feedback_stats`               | Unchanged                                                                                                              |
    | `first_token_time`         | `first_token_time`             | Unchanged                                                                                                              |
    | `inputs`                   | `inputs`                       | Unchanged                                                                                                              |
    | `inputs_preview`           | `inputs_preview`               | Unchanged                                                                                                              |
    | `outputs`                  | `outputs`                      | Unchanged                                                                                                              |
    | `outputs_preview`          | `outputs_preview`              | Unchanged                                                                                                              |
    | `parent_run_ids`           | `parent_run_ids`               | Unchanged                                                                                                              |
    | `price_model_id`           | `price_model_id`               | Unchanged                                                                                                              |
    | `prompt_cost`              | `prompt_cost`                  | Unchanged                                                                                                              |
    | `prompt_cost_details`      | `prompt_cost_details.raw`      | Field now wraps the object; read `.raw` for the same `{category: cost}` mapping, now with numeric values (was strings) |
    | `prompt_token_details`     | `prompt_token_details.raw`     | Field now wraps the object; read `.raw` for the same `{category: count}` mapping (values unchanged)                    |
    | `prompt_tokens`            | `prompt_tokens`                | Unchanged                                                                                                              |
    | `completion_cost`          | `completion_cost`              | Unchanged                                                                                                              |
    | `completion_cost_details`  | `completion_cost_details.raw`  | Field now wraps the object; read `.raw` for the same `{category: cost}` mapping, now with numeric values (was strings) |
    | `completion_token_details` | `completion_token_details.raw` | Field now wraps the object; read `.raw` for the same `{category: count}` mapping (values unchanged)                    |
    | `completion_tokens`        | `completion_tokens`            | Unchanged                                                                                                              |
    | `total_cost`               | `total_cost`                   | Unchanged                                                                                                              |
    | `total_tokens`             | `total_tokens`                 | Unchanged                                                                                                              |
    | `reference_dataset_id`     | `reference_dataset_id`         | Unchanged                                                                                                              |
    | `reference_example_id`     | `reference_example_id`         | Unchanged                                                                                                              |
    | `tags`                     | `tags`                         | Unchanged                                                                                                              |
    | `thread_id`                | `thread_id`                    | Unchanged                                                                                                              |
    | `session_id`               | `project_id`                   | Renamed                                                                                                                |
    | `in_dataset`               | `is_in_dataset`                | Renamed                                                                                                                |
    | `child_run_ids`            | *(removed)*                    | No equivalent                                                                                                          |
    | `direct_child_run_ids`     | *(removed)*                    | No equivalent                                                                                                          |
    | `execution_order`          | *(removed)*                    | No equivalent                                                                                                          |
    | `inputs_s3_urls`           | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `last_queued_at`           | *(removed)*                    | No equivalent                                                                                                          |
    | `manifest_id`              | *(removed)*                    | Use `manifest`                                                                                                         |
    | `manifest_s3_id`           | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `messages`                 | *(removed)*                    | No equivalent                                                                                                          |
    | `outputs_s3_urls`          | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `parent_run_id`            | *(removed)*                    | Use `parent_run_ids`                                                                                                   |
    | `s3_urls`                  | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `serialized`               | *(removed)*                    | Use `manifest`                                                                                                         |
    | `share_token`              | *(removed)*                    | Use `share_url`                                                                                                        |
    | `trace_first_received_at`  | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_max_start_time`     | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_min_start_time`     | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_tier`               | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_upgrade`            | *(removed)*                    | No equivalent                                                                                                          |
    | `ttl_seconds`              | *(removed)*                    | No equivalent                                                                                                          |
    | *(not available)*          | `attachments`                  | New: maps attachment filename to pre-signed download URL                                                               |
    | *(not available)*          | `error_preview`                | New: truncated error snippet                                                                                           |
    | *(not available)*          | `is_root`                      | New                                                                                                                    |
    | *(not available)*          | `latency_seconds`              | New: wall-clock duration in seconds                                                                                    |
    | *(not available)*          | `manifest`                     | New: full manifest object (replaces `serialized` and `manifest_id`)                                                    |
    | *(not available)*          | `metadata`                     | New: previously nested under `extra.metadata`                                                                          |
    | *(not available)*          | `share_url`                    | New: public share URL (only set when the run has been shared)                                                          |
    | *(not available)*          | `thread_evaluation_time`       | New                                                                                                                    |
  </Tab>
</Tabs>

### Examples

#### List all runs in a project

<Tabs>
  <Tab title="Python">
    `runs.query` does not accept a project name directly. Resolve the project UUID with `client.aread_project()` first, then pass it as a string in `project_ids`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        runs = client.list_runs(project_name="default")
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(project_ids=[str(project.id)])


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `client.runs.query` does not accept a project name directly. Resolve the project UUID with `client.readProject()` first, then pass it as a string in `project_ids`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs = client.listRuns({ projectName: "default" });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({ project_ids: [project.id] });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `queryV2()` does not accept a project name directly. Resolve the project UUID with `client.sessions().list()` first, then pass it as a string in `projectIds()`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().query(
            RunQueryParams.builder().addSession(project.id()).build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder().addProjectId(project.id()).build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `QueryV2()` does not accept a project name directly. Resolve the project UUID with `client.Sessions.List()` first, then pass it as a string in `ProjectIDs`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `POST /v2/runs/query` does not accept a project name directly. Resolve the project UUID with a `GET /api/v1/sessions` request first, then pass it as a string in `project_ids`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid]}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"project_ids": [$pid]}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Selecting fields

<Tabs>
  <Tab title="Python">
    `list_runs` returns a default set of fields with no selection needed. `runs.query` returns only `id` by default—pass `selects=[...]` to request more. Field names are now uppercase (`"name"` → `"NAME"`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        # returns a default set of fields; no explicit selection needed
        runs = client.list_runs(project_name="default")
        for run in runs:
            print(run.id, run.name, run.run_type, run.status, run.start_time, run.inputs, run.error)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            # must explicitly list every field needed; default returns only id
            async for run in client.runs.query(
                project_ids=[str(project.id)],
                selects=["ID", "NAME", "RUN_TYPE", "STATUS", "START_TIME", "INPUTS", "ERROR"],
            ):
                print(run.id, run.name, run.run_type, run.status, run.start_time, run.inputs, run.error)


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `listRuns` returns a default set of fields with no selection needed. `client.runs.query` returns only `id` by default—pass `selects: [...]` to request more. Field names are now uppercase (`"name"` → `"NAME"`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        // returns a default set of fields; no explicit selection needed
        const runs = client.listRuns({ projectName: "default" });
        for await (const run of runs) {
          console.log(run.id, run.name, run.run_type, run.status, run.start_time, run.inputs, run.error);
        }
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        // must explicitly list every field needed; default returns only id
        for await (const run of client.runs.query({
          project_ids: [project.id],
          selects: ["ID", "NAME", "RUN_TYPE", "STATUS", "START_TIME", "INPUTS", "ERROR"],
        })) {
          console.log(run.id, run.name, run.run_type, run.status, run.start_time, run.inputs, run.error);
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `query()` returns a default set of fields with no selection needed. `queryV2()` returns only `id` by default—call `.addSelect(RunQueryV2Params.Select.X)` for each field you need.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        // returns a default set of fields; no explicit selection needed
        val runs = client.runs().query(
            RunQueryParams.builder().addSession(project.id()).build()
        ).items()
        for (run in runs) {
            println("${run.id()} ${run.name()} ${run.runType()} ${run.status()} ${run.startTime()} ${run.inputs()} ${run.error()}")
        }
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        // must explicitly list every field needed; default returns only id
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder()
                .addProjectId(project.id())
                .addSelect(RunQueryV2Params.Select.ID)
                .addSelect(RunQueryV2Params.Select.NAME)
                .addSelect(RunQueryV2Params.Select.RUN_TYPE)
                .addSelect(RunQueryV2Params.Select.STATUS)
                .addSelect(RunQueryV2Params.Select.START_TIME)
                .addSelect(RunQueryV2Params.Select.INPUTS)
                .addSelect(RunQueryV2Params.Select.ERROR)
                .build()
        ).items()
        for (run in runs) {
            println("${run.id()} ${run.name()} ${run.runType()} ${run.status()} ${run.startTime()} ${run.inputs()} ${run.error()}")
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `Query` returns a default set of fields with no selection needed. `QueryV2` returns only `ID` by default—pass `Selects` with the uppercase field constants you need (e.g. `RunQueryV2ParamsSelectName`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"fmt"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        // returns a default set of fields; no explicit selection needed
        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        })
        for _, run := range runs.Runs {
        	fmt.Println(run.ID, run.Name, run.RunType, run.Status, run.StartTime, run.Inputs, run.Error)
        }
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"fmt"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        // must explicitly list every field needed; default returns only id
        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        	Selects: langsmith.F([]langsmith.RunQueryV2ParamsSelect{
        		langsmith.RunQueryV2ParamsSelectID,
        		langsmith.RunQueryV2ParamsSelectName,
        		langsmith.RunQueryV2ParamsSelectRunType,
        		langsmith.RunQueryV2ParamsSelectStatus,
        		langsmith.RunQueryV2ParamsSelectStartTime,
        		langsmith.RunQueryV2ParamsSelectInputs,
        		langsmith.RunQueryV2ParamsSelectError,
        	}),
        })
        for _, run := range runs.Items {
        	fmt.Println(run.ID, run.Name, run.RunType, run.Status, run.StartTime, run.Inputs, run.Error)
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `POST /api/v1/runs/query` returns a default set of fields with no selection needed. `POST /v2/runs/query` returns only `id` by default—pass `selects` with the uppercase field names you need (e.g. `"NAME"`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid]}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"project_ids": [$pid], "selects": ["ID", "NAME", "RUN_TYPE", "STATUS", "START_TIME", "INPUTS", "ERROR"]}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Filter by run type and time range

<Tabs>
  <Tab title="Python">
    `start_time` is renamed to `min_start_time`, and `run_type` values are now uppercase (`"llm"` → `"LLM"`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from datetime import datetime, timedelta

        from langsmith import Client

        client = Client()
        runs = client.list_runs(
            project_name="default",
            start_time=datetime.now() - timedelta(days=1),
            run_type="llm",
        )
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio
        from datetime import datetime, timedelta

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(
                project_ids=[str(project.id)],
                min_start_time=datetime.now() - timedelta(days=1),
                run_type="LLM",
            )


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `startTime` (camelCase) becomes `min_start_time` (snake\_case, matching the v2 request body), and `runType` values are now uppercase (`"llm"` → `"LLM"`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs = client.listRuns({
          projectName: "default",
          startTime: new Date(Date.now() - 24 * 60 * 60 * 1000),
          runType: "llm",
        });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
        const runs = client.runs.query({
          project_ids: [project.id],
          min_start_time: oneDayAgo.toISOString(),
          run_type: "LLM",
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.startTime()` is renamed to `.minStartTime()`, and `.runType()` now takes the new `RunQueryV2Params.RunType` enum instead of `RunTypeEnum`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import java.time.OffsetDateTime

        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.runs.RunTypeEnum
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().query(
            RunQueryParams.builder()
                .addSession(project.id())
                .startTime(OffsetDateTime.now().minusDays(1))
                .runType(RunTypeEnum.LLM)
                .build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import java.time.OffsetDateTime

        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder()
                .addProjectId(project.id())
                .minStartTime(OffsetDateTime.now().minusDays(1))
                .runType(RunQueryV2Params.RunType.LLM)
                .build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `StartTime` is renamed to `MinStartTime`, and `RunType` now takes the new `RunQueryV2ParamsRunType` enum instead of `RunTypeEnum`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"time"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session:   langsmith.F([]string{project.ID}),
        	StartTime: langsmith.F(time.Now().Add(-24 * time.Hour)),
        	RunType:   langsmith.F(langsmith.RunTypeEnumLlm),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"time"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs:   langsmith.F([]string{project.ID}),
        	MinStartTime: langsmith.F(time.Now().Add(-24 * time.Hour)),
        	RunType:      langsmith.F(langsmith.RunQueryV2ParamsRunTypeLlm),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `start_time` is renamed to `min_start_time`, and `run_type` values are now uppercase (`"llm"` → `"LLM"`).

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "run_type": "llm", "start_time": "2025-01-01T00:00:00Z"}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"project_ids": [$pid], "run_type": "LLM", "min_start_time": "2025-01-01T00:00:00Z"}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Filter root runs only

<Tabs>
  <Tab title="Python">
    `is_root` is unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        runs = client.list_runs(project_name="default", is_root=True)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(project_ids=[str(project.id)], is_root=True)


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `isRoot` (camelCase) becomes `is_root` (snake\_case, matching the v2 request body).

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs = client.listRuns({ projectName: "default", isRoot: true });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({
          project_ids: [project.id],
          is_root: true,
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.isRoot()` is unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().query(
            RunQueryParams.builder().addSession(project.id()).isRoot(true).build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder().addProjectId(project.id()).isRoot(true).build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `IsRoot` is unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        	IsRoot:  langsmith.F(true),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        	IsRoot:     langsmith.F(true),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `is_root` is unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "is_root": true}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"project_ids": [$pid], "is_root": true}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Fetch runs by ID list

<Tabs>
  <Tab title="Python">
    `id=[...]` is renamed to `ids=[...]`. `project_ids` is now required even when filtering by run IDs—v1 allowed omitting the project context.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        runs = client.list_runs(id=["<run-id-1>", "<run-id-2>"])
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(
                project_ids=[str(project.id)],
                ids=["<run-id-1>", "<run-id-2>"],
            )


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `id: [...]` is renamed to `ids: [...]`. `project_ids` is now required even when filtering by run IDs—v1 allowed omitting the project context.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs = client.listRuns({ id: ["<run-id-1>", "<run-id-2>"] });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({
          project_ids: [project.id],
          ids: ["<run-id-1>", "<run-id-2>"],
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.addId(...)` is unchanged—call it once per run ID. `.addProjectId(...)` is now required even when filtering by run IDs—v1 allowed omitting the project context.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        var runId1 = "<run-id-1>"
        var runId2 = "<run-id-2>"
        val runs = client.runs().query(
            RunQueryParams.builder()
                .addSession(project.id())
                .addId(runId1)
                .addId(runId2)
                .build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder()
                .addProjectId(project.id())
                .addId("<run-id-1>")
                .addId("<run-id-2>")
                .build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `ID: [...]` is renamed to `IDs: [...]`. `ProjectIDs` is now required even when filtering by run IDs—v1 allowed omitting the project context.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runID1 := "<run-id-1>"
        runID2 := "<run-id-2>"
        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        	ID:      langsmith.F([]string{runID1, runID2}),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runID1 := "<run-id-1>"
        runID2 := "<run-id-2>"
        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        	IDs:        langsmith.F([]string{runID1, runID2}),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `id` is renamed to `ids`. `project_ids` is now required in the request body even when filtering by run IDs—v1 allowed omitting the project context.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        RUN_ID_1="<run-id-1>"
        RUN_ID_2="<run-id-2>"

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg r1 "$RUN_ID_1" --arg r2 "$RUN_ID_2" '{"id": [$r1, $r2]}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        RUN_ID_1="<run-id-1>"
        RUN_ID_2="<run-id-2>"

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" --arg r1 "$RUN_ID_1" --arg r2 "$RUN_ID_2" '{"project_ids": [$pid], "ids": [$r1, $r2]}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Iterate through runs

<Tabs>
  <Tab title="Python">
    `list_runs` auto-paginates transparently, fetching up to 100 runs per API call and stopping once `limit` results are returned. `runs.query` does not accept a total `limit`; iterate with `async for` and `break` once you have enough, or use the returned page's `has_next_page()`/`get_next_page()` for manual page-by-page control.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        runs = client.list_runs(project_name="default", limit=150)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = []
            async for run in client.runs.query(
                project_ids=[str(project.id)],
            ):
                runs.append(run)
                if len(runs) >= 150:
                    break


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `listRuns` auto-paginates transparently. `client.runs.query` returns an async iterable of individual runs—use `for await` and `break` once you have enough.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs: unknown[] = [];
        for await (const run of client.listRuns({ projectName: "default" })) {
          runs.push(run);
          if (runs.length >= 150) break;
        }
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const runs: unknown[] = [];
        for await (const run of client.runs.query({
          project_ids: [project.id],
        })) {
          runs.push(run);
          if (runs.length >= 150) break;
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.autoPager()` is used the same way on both `query()` and `queryV2()`—break out of the loop once you have enough runs.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = mutableListOf<Any>()
        for (run in client.runs().query(
            RunQueryParams.builder().addSession(project.id()).build()
        ).autoPager()) {
            runs.add(run)
            if (runs.size >= 150) break
        }
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = mutableListOf<Any>()
        for (run in client.runs().queryV2(
            RunQueryV2Params.builder().addProjectId(project.id()).build()
        ).autoPager()) {
            runs.add(run)
            if (runs.size >= 150) break
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `QueryAutoPaging` is renamed to `QueryV2AutoPaging`; both use the same `iter.Next()`/`iter.Current()` pattern—break out of the loop once you have enough runs.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs := []langsmith.RunSchema{}
        iter := client.Runs.QueryAutoPaging(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        })
        for iter.Next() {
        	runs = append(runs, iter.Current())
        	if len(runs) >= 150 {
        		break
        	}
        }
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs := []langsmith.Run{}
        iter := client.Runs.QueryV2AutoPaging(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        })
        for iter.Next() {
        	runs = append(runs, iter.Current())
        	if len(runs) >= 150 {
        		break
        	}
        }
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    The v1 API returns all matching runs in one response with no cursor. The v2 API paginates—pass the `cursor` from a response's `next_cursor` field to fetch the next page.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "limit": 150}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        # Fetch pages, passing the cursor from each response's next_cursor field
        # to fetch the next page, until 150 runs are collected or pages run out.
        TOTAL=0
        CURSOR=""
        while :; do
          BODY=$(jq -n --arg pid "$PROJECT_ID" --arg cursor "$CURSOR" \
            'if $cursor == "" then {"project_ids": [$pid]} else {"project_ids": [$pid], "cursor": $cursor} end')
          RESPONSE=$(curl -s -X POST "https://api.smith.langchain.com/v2/runs/query" \
            -H "x-api-key: $LANGSMITH_API_KEY" \
            -H "Content-Type: application/json" \
            -d "$BODY")
          TOTAL=$((TOTAL + $(echo "$RESPONSE" | jq '.items | length')))
          CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor // empty')
          [ "$TOTAL" -lt 150 ] && [ -n "$CURSOR" ] || break
        done
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Filter runs with errors

<Tabs>
  <Tab title="Python">
    `error=True/False` is renamed to `has_error=True/False`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        runs = client.list_runs(project_name="default", error=True)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(project_ids=[str(project.id)], has_error=True)


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `error: true/false` is renamed to `has_error: true/false`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs = client.listRuns({ projectName: "default", error: true });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({
          project_ids: [project.id],
          has_error: true,
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.error(true/false)` is renamed to `.hasError(true/false)`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().query(
            RunQueryParams.builder().addSession(project.id()).error(true).build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder().addProjectId(project.id()).hasError(true).build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `Error` is renamed to `HasError`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        	Error:   langsmith.F(true),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        	HasError:   langsmith.F(true),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `error` is renamed to `has_error`.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "error": true}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" '{"project_ids": [$pid], "has_error": true}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Filter by metadata

<Tabs>
  <Tab title="Python">
    The `filter` string syntax is unchanged: `eq(metadata_key, ...)` checks for key presence, combined with `eq(metadata_value, ...)` to match a specific value.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        filter_str = 'and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))'
        runs = client.list_runs(project_name="default", filter=filter_str)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            filter_str = 'and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))'
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(project_ids=[str(project.id)], filter=filter_str)


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    The `filter` string syntax is unchanged: `eq(metadata_key, ...)` checks for key presence, combined with `eq(metadata_value, ...)` to match a specific value.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const filterStr = 'and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))';
        const runs = client.listRuns({ projectName: "default", filter: filterStr });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const filterStr = 'and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))';
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({
          project_ids: [project.id],
          filter: filterStr,
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    The `.filter(...)` string syntax is unchanged: `eq(metadata_key, ...)` checks for key presence, combined with `eq(metadata_value, ...)` to match a specific value.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val filterStr = "and(eq(metadata_key, \"user_id\"), eq(metadata_value, \"u_123\"))"
        val runs = client.runs().query(
            RunQueryParams.builder().addSession(project.id()).filter(filterStr).build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val filterStr = "and(eq(metadata_key, \"user_id\"), eq(metadata_value, \"u_123\"))"
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder().addProjectId(project.id()).filter(filterStr).build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    The `Filter` string syntax is unchanged: `eq(metadata_key, ...)` checks for key presence, combined with `eq(metadata_value, ...)` to match a specific value.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        filterStr := `and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))`
        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        	Filter:  langsmith.F(filterStr),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        filterStr := `and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))`
        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        	Filter:     langsmith.F(filterStr),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    The `filter` string syntax is unchanged: `eq(metadata_key, ...)` checks for key presence, combined with `eq(metadata_value, ...)` to match a specific value.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        FILTER='and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))'

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" --arg f "$FILTER" '{"session": [$pid], "filter": $f}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        FILTER='and(eq(metadata_key, "user_id"), eq(metadata_value, "u_123"))'

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" --arg f "$FILTER" '{"project_ids": [$pid], "filter": $f}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Complex boolean filters

<Tabs>
  <Tab title="Python">
    Nested `and()` / `or()` filter expressions are unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        filter_str = (
            'and(gt(start_time, "2023-07-15T12:34:56Z"),'
            ' or(neq(status, "error"),'
            '    and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))'
        )
        runs = client.list_runs(project_name="default", filter=filter_str)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            filter_str = (
                'and(gt(start_time, "2023-07-15T12:34:56Z"),'
                ' or(neq(status, "error"),'
                '    and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))'
            )
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(project_ids=[str(project.id)], filter=filter_str)


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    Nested `and()` / `or()` filter expressions are unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const filterStr =
          'and(gt(start_time, "2023-07-15T12:34:56Z"),' +
          ' or(neq(status, "error"),' +
          '    and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))';
        const runs = client.listRuns({ projectName: "default", filter: filterStr });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const filterStr =
          'and(gt(start_time, "2023-07-15T12:34:56Z"),' +
          ' or(neq(status, "error"),' +
          '    and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))';
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({
          project_ids: [project.id],
          filter: filterStr,
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    Nested `and()` / `or()` filter expressions are unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val filterStr = "and(gt(start_time, \"2023-07-15T12:34:56Z\")," +
            " or(neq(status, \"error\")," +
            "    and(eq(feedback_key, \"Correctness\"), eq(feedback_score, 0.0))))"
        val runs = client.runs().query(
            RunQueryParams.builder().addSession(project.id()).filter(filterStr).build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val filterStr = "and(gt(start_time, \"2023-07-15T12:34:56Z\")," +
            " or(neq(status, \"error\")," +
            "    and(eq(feedback_key, \"Correctness\"), eq(feedback_score, 0.0))))"
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder().addProjectId(project.id()).filter(filterStr).build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    Nested `and()` / `or()` filter expressions are unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        filterStr := `and(gt(start_time, "2023-07-15T12:34:56Z"), or(neq(status, "error"), and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))`
        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session: langsmith.F([]string{project.ID}),
        	Filter:  langsmith.F(filterStr),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        filterStr := `and(gt(start_time, "2023-07-15T12:34:56Z"), or(neq(status, "error"), and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))`
        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs: langsmith.F([]string{project.ID}),
        	Filter:     langsmith.F(filterStr),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    Nested `and()` / `or()` filter expressions are unchanged.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        FILTER='and(gt(start_time, "2023-07-15T12:34:56Z"), or(neq(status, "error"), and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))'

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" --arg f "$FILTER" '{"session": [$pid], "filter": $f}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        FILTER='and(gt(start_time, "2023-07-15T12:34:56Z"), or(neq(status, "error"), and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))'

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n --arg pid "$PROJECT_ID" --arg f "$FILTER" '{"project_ids": [$pid], "filter": $f}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Scoped filters: filter, trace\_filter, tree\_filter

<Tabs>
  <Tab title="Python">
    `filter`, `trace_filter`, and `tree_filter` are unchanged. `filter` applies to the matched run, `trace_filter` to the root of its trace, and `tree_filter` to other runs in the trace tree (siblings and children).

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        runs = client.list_runs(
            project_name="default",
            filter='eq(name, "RetrieveDocs")',
            trace_filter='and(eq(feedback_key, "user_score"), eq(feedback_score, 1))',
            tree_filter='eq(name, "ExpandQuery")',
        )
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            runs = client.runs.query(
                project_ids=[str(project.id)],
                filter='eq(name, "RetrieveDocs")',
                trace_filter='and(eq(feedback_key, "user_score"), eq(feedback_score, 1))',
                tree_filter='eq(name, "ExpandQuery")',
            )


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `filter`, `trace_filter`, and `tree_filter` are unchanged. `filter` applies to the matched run, `trace_filter` to the root of its trace, and `tree_filter` to other runs in the trace tree (siblings and children).

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const runs = client.listRuns({
          projectName: "default",
          filter: 'eq(name, "RetrieveDocs")',
          traceFilter: 'and(eq(feedback_key, "user_score"), eq(feedback_score, 1))',
          treeFilter: 'eq(name, "ExpandQuery")',
        });
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        const runs = client.runs.query({
          project_ids: [project.id],
          filter: 'eq(name, "RetrieveDocs")',
          trace_filter: 'and(eq(feedback_key, "user_score"), eq(feedback_score, 1))',
          tree_filter: 'eq(name, "ExpandQuery")',
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.filter()`, `.traceFilter()`, and `.treeFilter()` are unchanged. `filter` applies to the matched run, `traceFilter` to the root of its trace, and `treeFilter` to other runs in the trace tree (siblings and children).

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryParams
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().query(
            RunQueryParams.builder()
                .addSession(project.id())
                .filter("eq(name, \"RetrieveDocs\")")
                .traceFilter("and(eq(feedback_key, \"user_score\"), eq(feedback_score, 1))")
                .treeFilter("eq(name, \"ExpandQuery\")")
                .build()
        ).items()
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunQueryV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()
        val runs = client.runs().queryV2(
            RunQueryV2Params.builder()
                .addProjectId(project.id())
                .filter("eq(name, \"RetrieveDocs\")")
                .traceFilter("and(eq(feedback_key, \"user_score\"), eq(feedback_score, 1))")
                .treeFilter("eq(name, \"ExpandQuery\")")
                .build()
        ).items()
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `Filter`, `TraceFilter`, and `TreeFilter` are unchanged. `Filter` applies to the matched run, `TraceFilter` to the root of its trace, and `TreeFilter` to other runs in the trace tree (siblings and children).

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
        	Session:     langsmith.F([]string{project.ID}),
        	Filter:      langsmith.F(`eq(name, "RetrieveDocs")`),
        	TraceFilter: langsmith.F(`and(eq(feedback_key, "user_score"), eq(feedback_score, 1))`),
        	TreeFilter:  langsmith.F(`eq(name, "ExpandQuery")`),
        })
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
        	Name:  langsmith.F("default"),
        	Limit: langsmith.F(int64(1)),
        })
        project := sessions.Items[0]

        runs, err := client.Runs.QueryV2(ctx, langsmith.RunQueryV2Params{
        	ProjectIDs:  langsmith.F([]string{project.ID}),
        	Filter:      langsmith.F(`eq(name, "RetrieveDocs")`),
        	TraceFilter: langsmith.F(`and(eq(feedback_key, "user_score"), eq(feedback_score, 1))`),
        	TreeFilter:  langsmith.F(`eq(name, "ExpandQuery")`),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `filter`, `trace_filter`, and `tree_filter` are unchanged. `filter` applies to the matched run, `trace_filter` to the root of its trace, and `tree_filter` to other runs in the trace tree (siblings and children).

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        FILTER='eq(name, "RetrieveDocs")'
        TRACE_FILTER='and(eq(feedback_key, "user_score"), eq(feedback_score, 1))'
        TREE_FILTER='eq(name, "ExpandQuery")'

        curl -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n \
            --arg pid "$PROJECT_ID" \
            --arg f "$FILTER" \
            --arg tf "$TRACE_FILTER" \
            --arg treef "$TREE_FILTER" \
            '{"session": [$pid], "filter": $f, "trace_filter": $tf, "tree_filter": $treef}')"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        FILTER='eq(name, "RetrieveDocs")'
        TRACE_FILTER='and(eq(feedback_key, "user_score"), eq(feedback_score, 1))'
        TREE_FILTER='eq(name, "ExpandQuery")'

        curl -X POST "https://api.smith.langchain.com/v2/runs/query" \
          -H "x-api-key: $LANGSMITH_API_KEY" \
          -H "Content-Type: application/json" \
          -d "$(jq -n \
            --arg pid "$PROJECT_ID" \
            --arg f "$FILTER" \
            --arg tf "$TRACE_FILTER" \
            --arg treef "$TREE_FILTER" \
            '{"project_ids": [$pid], "filter": $f, "trace_filter": $tf, "tree_filter": $treef}')"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

## Runs: retrieve

Fetch a single run by ID. Returns only the run ID by default—specify a field selection list to retrieve additional data.

### Main changes

#### Method name

<Tabs>
  <Tab title="Python">
    | Before              | After                    |
    | ------------------- | ------------------------ |
    | `client.read_run()` | `client.runs.retrieve()` |
  </Tab>

  <Tab title="TypeScript">
    | Before             | After                    |
    | ------------------ | ------------------------ |
    | `client.readRun()` | `client.runs.retrieve()` |
  </Tab>

  <Tab title="Java">
    | Before                     | After                        |
    | -------------------------- | ---------------------------- |
    | `client.runs().retrieve()` | `client.runs().retrieveV2()` |
  </Tab>

  <Tab title="Go">
    | Before              | After                 |
    | ------------------- | --------------------- |
    | `client.Runs.Get()` | `client.Runs.GetV2()` |
  </Tab>

  <Tab title="cURL">
    | Before                      | After                   |
    | --------------------------- | ----------------------- |
    | `GET /api/v1/runs/{run_id}` | `GET /v2/runs/{run_id}` |
  </Tab>
</Tabs>

#### Query parameters

<Tabs>
  <Tab title="Python">
    <Warning>
      `runs.retrieve` requires two new fields—`project_id` and `start_time`—that `read_run` did not need. Both are required to locate the run in SmithDB.
    </Warning>

    | Before (`read_run`)                | After (`runs.retrieve`) | Notes                                                                             |
    | ---------------------------------- | ----------------------- | --------------------------------------------------------------------------------- |
    | `run_id`                           | `run_id`                | Unchanged                                                                         |
    | `load_child_runs`                  | *(removed)*             | No equivalent                                                                     |
    | *(not available)*                  | `project_id`            | **Required**—UUID of the project that owns the run                                |
    | *(not available)*                  | `start_time`            | **Required**—run's start time (RFC3339), used with `project_id` to locate the run |
    | *(all fields returned by default)* | `selects`               | Field projection; defaults to `["ID"]` only; field names are uppercase            |
  </Tab>

  <Tab title="TypeScript">
    <Warning>
      `client.runs.retrieve` requires two new fields—`project_id` and `start_time`—that `readRun` did not need. Both are required to locate the run in SmithDB.
    </Warning>

    | Before (`readRun`)                 | After (`client.runs.retrieve`) | Notes                                                                         |
    | ---------------------------------- | ------------------------------ | ----------------------------------------------------------------------------- |
    | `runId`                            | `runId`                        | Unchanged (positional parameter)                                              |
    | `options.loadChildRuns`            | *(removed)*                    | No equivalent                                                                 |
    | *(not available)*                  | `project_id`                   | **Required**—`snake_case`; UUID of the project that owns the run              |
    | *(not available)*                  | `start_time`                   | **Required**—`snake_case`; run's start time (RFC3339), used to locate the run |
    | *(all fields returned by default)* | `selects`                      | Field projection; defaults to `["ID"]` only; field names are uppercase        |
  </Tab>

  <Tab title="Java">
    <Warning>
      `retrieveV2()` requires `projectId()`, which replaces the removed `sessionId()`, and makes `startTime()` required (previously optional). Both are needed to locate the run in SmithDB.
    </Warning>

    | Before (`RunRetrieveParams`)       | After (`RunRetrieveV2Params`) | Notes                                                                  |
    | ---------------------------------- | ----------------------------- | ---------------------------------------------------------------------- |
    | `runId()`                          | `runId()`                     | Unchanged                                                              |
    | `sessionId()`                      | *(removed)*                   | Replaced by `projectId()`                                              |
    | `startTime()`                      | `startTime()`                 | Now **required**; used with `projectId()` to locate the run in SmithDB |
    | `excludeS3StoredAttributes()`      | *(removed)*                   | No equivalent                                                          |
    | `excludeSerialized()`              | *(removed)*                   | No equivalent                                                          |
    | `includeMessages()`                | *(removed)*                   | No equivalent                                                          |
    | *(not available)*                  | `projectId()`                 | **Required**—UUID of the project that owns the run                     |
    | *(all fields returned by default)* | `selects()`                   | Field projection; defaults to `["ID"]` only; field names are uppercase |
  </Tab>

  <Tab title="Go">
    <Warning>
      `GetV2()` requires `ProjectID`, which replaces the removed `SessionID`, and makes `StartTime` required (previously optional). Both are needed to locate the run in SmithDB.
    </Warning>

    | Before (`RunGetParams`)            | After (`RunGetV2Params`) | Notes                                                                                                              |
    | ---------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
    | `runID` (positional)               | `runID` (positional)     | Unchanged                                                                                                          |
    | `ExcludeS3StoredAttributes`        | *(removed)*              | No equivalent                                                                                                      |
    | `ExcludeSerialized`                | *(removed)*              | No equivalent                                                                                                      |
    | `IncludeMessages`                  | *(removed)*              | No equivalent                                                                                                      |
    | `SessionID`                        | *(removed)*              | Replaced by `ProjectID`                                                                                            |
    | `StartTime`                        | `StartTime`              | Now **required**; used with `ProjectID` to locate the run in SmithDB                                               |
    | *(not available)*                  | `ProjectID`              | **Required**—UUID of the project that owns the run                                                                 |
    | *(all fields returned by default)* | `Selects`                | Field projection; defaults to `["ID"]` only; field name constants are uppercase (e.g., `RunGetV2ParamsSelectName`) |
  </Tab>

  <Tab title="cURL">
    `run_id` remains in the URL path. All other parameters are query string values with `snake_case` names.

    <Warning>
      `GET /v2/runs/{run_id}` requires a new `project_id` query param and makes `start_time` required (previously optional). Both are needed to locate the run in SmithDB.
    </Warning>

    | Before (`GET /api/v1/runs/{run_id}` param) | After (`GET /v2/runs/{run_id}` param) | Notes                                                                  |
    | ------------------------------------------ | ------------------------------------- | ---------------------------------------------------------------------- |
    | `run_id` (path)                            | `run_id` (path)                       | Unchanged                                                              |
    | `load_child_runs` (query)                  | *(removed)*                           | No equivalent                                                          |
    | *(not available)*                          | `project_id` (query)                  | **Required**—UUID of the project that owns the run                     |
    | `start_time` (query)                       | `start_time` (query)                  | Now **required**; used with `project_id` to locate the run in SmithDB  |
    | *(all fields returned by default)*         | `selects` (query, repeatable)         | Field projection; defaults to `["ID"]` only; field names are uppercase |
  </Tab>
</Tabs>

#### Response fields

<Tabs>
  <Tab title="Python">
    Pass SCREAMING\_SNAKE\_CASE strings to `selects` (eg. `"ID"`, `"NAME"`, `"STATUS"`) to control which fields are populated on the returned `Run`; only selected fields are non-`None`. Default `selects` contains only `"ID"`.

    | Before (v1 `Run` attribute)    | After (v2 `Run` attribute)         | Notes                                                                                        |
    | ------------------------------ | ---------------------------------- | -------------------------------------------------------------------------------------------- |
    | `run.id`                       | `run.id`                           | Unchanged; returned by default when `selects` is omitted                                     |
    | `run.name`                     | `run.name`                         | Unchanged                                                                                    |
    | `run.run_type`                 | `run.run_type`                     | Values are now uppercase Literals: `"LLM"`, `"CHAIN"`, etc.                                  |
    | `run.status`                   | `run.status`                       | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                  |
    | `run.start_time`               | `run.start_time`                   | Unchanged                                                                                    |
    | `run.end_time`                 | `run.end_time`                     | Unchanged                                                                                    |
    | `run.error`                    | `run.error`                        | Unchanged                                                                                    |
    | `run.inputs`                   | `run.inputs`                       | Unchanged                                                                                    |
    | `run.outputs`                  | `run.outputs`                      | Unchanged                                                                                    |
    | `run.tags`                     | `run.tags`                         | Unchanged                                                                                    |
    | `run.extra`                    | `run.extra`                        | Unchanged                                                                                    |
    | `run.metadata`                 | `run.metadata`                     | Unchanged                                                                                    |
    | `run.events`                   | `run.events`                       | Unchanged                                                                                    |
    | `run.reference_example_id`     | `run.reference_example_id`         | Unchanged                                                                                    |
    | `run.trace_id`                 | `run.trace_id`                     | Unchanged                                                                                    |
    | `run.dotted_order`             | `run.dotted_order`                 | Unchanged                                                                                    |
    | `run.parent_run_id`            | *(removed)*                        | Use `run.parent_run_ids` (list of all ancestor UUIDs, root first)                            |
    | `run.parent_run_ids`           | `run.parent_run_ids`               | Unchanged                                                                                    |
    | `run.session_id`               | `run.project_id`                   | Renamed; `session_id` was the project UUID                                                   |
    | `run.feedback_stats`           | `run.feedback_stats`               | Unchanged                                                                                    |
    | `run.app_path`                 | `run.app_path`                     | Unchanged                                                                                    |
    | `run.attachments`              | `run.attachments`                  | v2 returns pre-signed download URLs instead of raw bytes                                     |
    | `run.total_tokens`             | `run.total_tokens`                 | Unchanged                                                                                    |
    | `run.prompt_tokens`            | `run.prompt_tokens`                | Unchanged                                                                                    |
    | `run.completion_tokens`        | `run.completion_tokens`            | Unchanged                                                                                    |
    | `run.total_cost`               | `run.total_cost`                   | Unchanged                                                                                    |
    | `run.prompt_cost`              | `run.prompt_cost`                  | Unchanged                                                                                    |
    | `run.completion_cost`          | `run.completion_cost`              | Unchanged                                                                                    |
    | `run.first_token_time`         | `run.first_token_time`             | Unchanged                                                                                    |
    | `run.latency` (property)       | `run.latency_seconds`              | Renamed; was a computed `timedelta` property, now a native `float` field                     |
    | `run.in_dataset`               | `run.is_in_dataset`                | Renamed                                                                                      |
    | `run.child_run_ids`            | *(removed)*                        | No equivalent                                                                                |
    | `run.child_runs`               | *(removed)*                        | No equivalent                                                                                |
    | `run.serialized`               | *(removed)*                        | Use `run.manifest`                                                                           |
    | `run.manifest_id`              | *(removed)*                        | Use `run.manifest`                                                                           |
    | *(not available)*              | `run.is_root`                      | New                                                                                          |
    | *(not available)*              | `run.manifest`                     | New: full manifest object (replaces `serialized` and `manifest_id`)                          |
    | *(not available)*              | `run.error_preview`                | New: truncated error snippet                                                                 |
    | *(not available)*              | `run.inputs_preview`               | New: truncated inputs preview                                                                |
    | *(not available)*              | `run.outputs_preview`              | New: truncated outputs preview                                                               |
    | *(not available)*              | `run.thread_id`                    | New: conversation thread UUID                                                                |
    | *(not available)*              | `run.reference_dataset_id`         | New: dataset UUID for the reference example                                                  |
    | *(not available)*              | `run.share_url`                    | New: public share URL (only set when the run has been shared)                                |
    | `run.prompt_token_details`     | `run.prompt_token_details.raw`     | Field now wraps the dict; access `.raw` to get `dict[str, int]` (element type unchanged)     |
    | `run.completion_token_details` | `run.completion_token_details.raw` | Field now wraps the dict; access `.raw` to get `dict[str, int]` (element type unchanged)     |
    | `run.prompt_cost_details`      | `run.prompt_cost_details.raw`      | Field now wraps the dict; access `.raw` to get `dict[str, float]` (was `dict[str, Decimal]`) |
    | `run.completion_cost_details`  | `run.completion_cost_details.raw`  | Field now wraps the dict; access `.raw` to get `dict[str, float]` (was `dict[str, Decimal]`) |
  </Tab>

  <Tab title="TypeScript">
    Pass SCREAMING\_SNAKE\_CASE strings to `selects` (eg. `"ID"`, `"NAME"`, `"STATUS"`) to control which fields are populated on the returned `Run`. Default `selects` contains only `"ID"`.

    | Before (v1 `Run` property) | After (v2 `Run` property)      | Notes                                                                       |
    | -------------------------- | ------------------------------ | --------------------------------------------------------------------------- |
    | `run.id`                   | `run.id`                       | Unchanged                                                                   |
    | `run.name`                 | `run.name`                     | Unchanged                                                                   |
    | `run.runType`              | `run.run_type`                 | Renamed to `snake_case`; values are now uppercase: `"LLM"`, `"CHAIN"`, etc. |
    | `run.status`               | `run.status`                   | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                 |
    | `run.startTime`            | `run.start_time`               | Renamed to `snake_case`                                                     |
    | `run.endTime`              | `run.end_time`                 | Renamed to `snake_case`                                                     |
    | `run.error`                | `run.error`                    | Unchanged                                                                   |
    | `run.inputs`               | `run.inputs`                   | Unchanged                                                                   |
    | `run.outputs`              | `run.outputs`                  | Unchanged                                                                   |
    | `run.tags`                 | `run.tags`                     | Unchanged                                                                   |
    | `run.extra`                | `run.extra`                    | Unchanged                                                                   |
    | *(not available)*          | `run.metadata`                 | New: previously accessed via `run.extra.metadata`                           |
    | `run.events`               | `run.events`                   | Unchanged                                                                   |
    | `run.referenceExampleId`   | `run.reference_example_id`     | Renamed to `snake_case`                                                     |
    | `run.traceId`              | `run.trace_id`                 | Renamed to `snake_case`                                                     |
    | `run.dottedOrder`          | `run.dotted_order`             | Renamed to `snake_case`                                                     |
    | `run.parentRunId`          | *(removed)*                    | Use `run.parent_run_ids` (list of all ancestor UUIDs, root first)           |
    | `run.parentRunIds`         | `run.parent_run_ids`           | Renamed to `snake_case`                                                     |
    | `run.sessionId`            | `run.project_id`               | Renamed; `sessionId` was the project UUID                                   |
    | `run.feedbackStats`        | `run.feedback_stats`           | Renamed to `snake_case`                                                     |
    | `run.appPath`              | `run.app_path`                 | Renamed to `snake_case`                                                     |
    | `run.attachments`          | `run.attachments`              | v2 returns pre-signed download URLs instead of raw bytes                    |
    | `run.totalTokens`          | `run.total_tokens`             | Renamed to `snake_case`                                                     |
    | `run.promptTokens`         | `run.prompt_tokens`            | Renamed to `snake_case`                                                     |
    | `run.completionTokens`     | `run.completion_tokens`        | Renamed to `snake_case`                                                     |
    | `run.totalCost`            | `run.total_cost`               | Renamed to `snake_case`                                                     |
    | `run.promptCost`           | `run.prompt_cost`              | Renamed to `snake_case`                                                     |
    | `run.completionCost`       | `run.completion_cost`          | Renamed to `snake_case`                                                     |
    | `run.firstTokenTime`       | `run.first_token_time`         | Renamed to `snake_case`                                                     |
    | `run.latency`              | `run.latency_seconds`          | Renamed; was a computed property, now a native `number` field (seconds)     |
    | `run.inDataset`            | `run.is_in_dataset`            | Renamed                                                                     |
    | `run.childRunIds`          | *(removed)*                    | No equivalent                                                               |
    | `run.childRuns`            | *(removed)*                    | No equivalent                                                               |
    | `run.serialized`           | *(removed)*                    | Use `run.manifest`                                                          |
    | `run.manifestId`           | *(removed)*                    | Use `run.manifest`                                                          |
    | `run.shareToken`           | *(removed)*                    | Use `run.share_url` (full URL, only set when the run has been shared)       |
    | *(not available)*          | `run.is_root`                  | New                                                                         |
    | *(not available)*          | `run.manifest`                 | New: full manifest object (replaces `serialized` and `manifestId`)          |
    | *(not available)*          | `run.error_preview`            | New: truncated error snippet                                                |
    | *(not available)*          | `run.inputs_preview`           | New: truncated inputs preview                                               |
    | *(not available)*          | `run.outputs_preview`          | New: truncated outputs preview                                              |
    | *(not available)*          | `run.thread_id`                | New: conversation thread UUID                                               |
    | *(not available)*          | `run.reference_dataset_id`     | New: dataset UUID for the reference example                                 |
    | *(not available)*          | `run.share_url`                | New: public share URL (only set when the run has been shared)               |
    | *(not available)*          | `run.prompt_token_details`     | New: per-category prompt token breakdown                                    |
    | *(not available)*          | `run.completion_token_details` | New: per-category completion token breakdown                                |
    | *(not available)*          | `run.prompt_cost_details`      | New: per-category prompt cost breakdown                                     |
    | *(not available)*          | `run.completion_cost_details`  | New: per-category completion cost breakdown                                 |
  </Tab>

  <Tab title="Java">
    Add `RunRetrieveV2Params.Select` values (eg. `Select.NAME`, `Select.STATUS`) via `.addSelect(...)` to control which fields are populated; unselected fields return empty `Optional` values. `selects()` defaults to `ID` only.

    | Before (`RunSchema` method)    | After (`Run` method)           | Notes                                                                                          |
    | ------------------------------ | ------------------------------ | ---------------------------------------------------------------------------------------------- |
    | `run.id()`                     | `run.id()`                     | Unchanged                                                                                      |
    | `run.name()`                   | `run.name()`                   | Unchanged                                                                                      |
    | `run.runType()`                | `run.runType()`                | Values are now uppercase: `"LLM"`, `"CHAIN"`, etc.                                             |
    | `run.status()`                 | `run.status()`                 | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                    |
    | `run.startTime()`              | `run.startTime()`              | Unchanged                                                                                      |
    | `run.endTime()`                | `run.endTime()`                | Unchanged                                                                                      |
    | `run.error()`                  | `run.error()`                  | Unchanged                                                                                      |
    | `run.inputs()`                 | `run.inputs()`                 | Unchanged                                                                                      |
    | `run.outputs()`                | `run.outputs()`                | Unchanged                                                                                      |
    | `run.tags()`                   | `run.tags()`                   | Unchanged                                                                                      |
    | `run.extra()`                  | `run.extra()`                  | Unchanged                                                                                      |
    | `run.events()`                 | `run.events()`                 | Unchanged                                                                                      |
    | `run.feedbackStats()`          | `run.feedbackStats()`          | Unchanged                                                                                      |
    | `run.inputsPreview()`          | `run.inputsPreview()`          | Unchanged                                                                                      |
    | `run.outputsPreview()`         | `run.outputsPreview()`         | Unchanged                                                                                      |
    | `run.referenceExampleId()`     | `run.referenceExampleId()`     | Unchanged                                                                                      |
    | `run.traceId()`                | `run.traceId()`                | Unchanged                                                                                      |
    | `run.dottedOrder()`            | `run.dottedOrder()`            | Unchanged                                                                                      |
    | `run.parentRunId()`            | *(removed)*                    | Use `run.parentRunIds()` (list of all ancestor UUIDs, root first)                              |
    | `run.parentRunIds()`           | `run.parentRunIds()`           | Unchanged                                                                                      |
    | `run.sessionId()`              | `run.projectId()`              | Renamed; `sessionId()` returned the project UUID                                               |
    | `run.appPath()`                | `run.appPath()`                | Unchanged                                                                                      |
    | `run.firstTokenTime()`         | `run.firstTokenTime()`         | Unchanged                                                                                      |
    | `run.totalTokens()`            | `run.totalTokens()`            | Unchanged                                                                                      |
    | `run.promptTokens()`           | `run.promptTokens()`           | Unchanged                                                                                      |
    | `run.completionTokens()`       | `run.completionTokens()`       | Unchanged                                                                                      |
    | `run.totalCost()`              | `run.totalCost()`              | Return type changed from `Optional<String>` to `Optional<Double>`                              |
    | `run.promptCost()`             | `run.promptCost()`             | Return type changed from `Optional<String>` to `Optional<Double>`                              |
    | `run.completionCost()`         | `run.completionCost()`         | Return type changed from `Optional<String>` to `Optional<Double>`                              |
    | `run.promptTokenDetails()`     | `run.promptTokenDetails()`     | Unchanged                                                                                      |
    | `run.completionTokenDetails()` | `run.completionTokenDetails()` | Unchanged                                                                                      |
    | `run.promptCostDetails()`      | `run.promptCostDetails()`      | Unchanged                                                                                      |
    | `run.completionCostDetails()`  | `run.completionCostDetails()`  | Unchanged                                                                                      |
    | `run.priceModelId()`           | `run.priceModelId()`           | Unchanged                                                                                      |
    | `run.inDataset()`              | `run.isInDataset()`            | Renamed                                                                                        |
    | `run.referenceDatasetId()`     | `run.referenceDatasetId()`     | Unchanged                                                                                      |
    | `run.threadId()`               | `run.threadId()`               | Unchanged                                                                                      |
    | `run.shareToken()`             | *(removed)*                    | Use `run.shareUrl()` (full URL, only set when the run has been shared)                         |
    | `run.childRunIds()`            | *(removed)*                    | No equivalent                                                                                  |
    | `run.directChildRunIds()`      | *(removed)*                    | No equivalent                                                                                  |
    | `run.serialized()`             | *(removed)*                    | Use `run.manifest()`                                                                           |
    | `run.manifestId()`             | *(removed)*                    | Use `run.manifest()`                                                                           |
    | `run.messages()`               | *(removed)*                    | No equivalent                                                                                  |
    | `run.executionOrder()`         | *(removed)*                    | No equivalent                                                                                  |
    | `run.lastQueuedAt()`           | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceFirstReceivedAt()`   | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceMaxStartTime()`      | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceMinStartTime()`      | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceTier()`              | *(removed)*                    | No equivalent                                                                                  |
    | `run.traceUpgrade()`           | *(removed)*                    | No equivalent                                                                                  |
    | `run.ttlSeconds()`             | *(removed)*                    | No equivalent                                                                                  |
    | *(not available)*              | `run.attachments()`            | New: pre-signed download URLs for attachments (replaces S3 URL fields)                         |
    | *(not available)*              | `run.latencySeconds()`         | New: wall-clock duration in seconds                                                            |
    | *(not available)*              | `run.isRoot()`                 | New                                                                                            |
    | *(not available)*              | `run.errorPreview()`           | New: truncated error snippet                                                                   |
    | *(not available)*              | `run.manifest()`               | New: full manifest, typed as `Optional<Manifest>` (replaces `serialized()` and `manifestId()`) |
    | *(not available)*              | `run.metadata()`               | New: metadata, typed as `Optional<Metadata>` (was derived from `extra.metadata`)               |
    | *(not available)*              | `run.shareUrl()`               | New: public share URL (only set when the run has been shared)                                  |
    | *(not available)*              | `run.threadEvaluationTime()`   | New                                                                                            |
  </Tab>

  <Tab title="Go">
    Pass `RunGetV2ParamsSelect` constants (eg. `RunGetV2ParamsSelectName`, `RunGetV2ParamsSelectStatus`) to `Selects` to control which fields are populated; unselected fields are zero-valued on the returned struct. `Selects` defaults to `ID` only.

    | Before (`RunSchema` field)   | After (`Run` field)              | Notes                                                                                        |
    | ---------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------- |
    | `run.ID`                     | `run.ID`                         | Unchanged                                                                                    |
    | `run.Name`                   | `run.Name`                       | Unchanged                                                                                    |
    | `run.RunType`                | `run.RunType`                    | Values changed to uppercase: `"LLM"`, `"CHAIN"`, etc.                                        |
    | `run.Status`                 | `run.Status`                     | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                  |
    | `run.TraceID`                | `run.TraceID`                    | Unchanged                                                                                    |
    | `run.DottedOrder`            | `run.DottedOrder`                | Unchanged                                                                                    |
    | `run.AppPath`                | `run.AppPath`                    | Unchanged                                                                                    |
    | `run.StartTime`              | `run.StartTime`                  | Unchanged                                                                                    |
    | `run.EndTime`                | `run.EndTime`                    | Unchanged                                                                                    |
    | `run.Error`                  | `run.Error`                      | Unchanged                                                                                    |
    | `run.Events`                 | `run.Events`                     | Unchanged; element type is now `RunEvent` (was `map[string]interface{}`)                     |
    | `run.Extra`                  | `run.Extra`                      | Unchanged; type is now `interface{}` (was `map[string]interface{}`)                          |
    | `run.FeedbackStats`          | `run.FeedbackStats`              | Unchanged; element type is now `RunFeedbackStat`                                             |
    | `run.FirstTokenTime`         | `run.FirstTokenTime`             | Unchanged                                                                                    |
    | `run.Inputs`                 | `run.Inputs`                     | Unchanged; type is now `interface{}` (was `map[string]interface{}`)                          |
    | `run.InputsPreview`          | `run.InputsPreview`              | Unchanged                                                                                    |
    | `run.Outputs`                | `run.Outputs`                    | Unchanged; type is now `interface{}` (was `map[string]interface{}`)                          |
    | `run.OutputsPreview`         | `run.OutputsPreview`             | Unchanged                                                                                    |
    | `run.ParentRunIDs`           | `run.ParentRunIDs`               | Unchanged                                                                                    |
    | `run.PriceModelID`           | `run.PriceModelID`               | Unchanged                                                                                    |
    | `run.PromptCost`             | `run.PromptCost`                 | Unchanged                                                                                    |
    | `run.PromptCostDetails`      | `run.PromptCostDetails.Raw`      | Field now wraps the map; access `.Raw` to get `map[string]float64` (was `map[string]string`) |
    | `run.PromptTokenDetails`     | `run.PromptTokenDetails.Raw`     | Field now wraps the map; access `.Raw` to get `map[string]int64` (element type unchanged)    |
    | `run.PromptTokens`           | `run.PromptTokens`               | Unchanged                                                                                    |
    | `run.CompletionCost`         | `run.CompletionCost`             | Unchanged                                                                                    |
    | `run.CompletionCostDetails`  | `run.CompletionCostDetails.Raw`  | Field now wraps the map; access `.Raw` to get `map[string]float64` (was `map[string]string`) |
    | `run.CompletionTokenDetails` | `run.CompletionTokenDetails.Raw` | Field now wraps the map; access `.Raw` to get `map[string]int64` (element type unchanged)    |
    | `run.CompletionTokens`       | `run.CompletionTokens`           | Unchanged                                                                                    |
    | `run.TotalCost`              | `run.TotalCost`                  | Unchanged                                                                                    |
    | `run.TotalTokens`            | `run.TotalTokens`                | Unchanged                                                                                    |
    | `run.ReferenceDatasetID`     | `run.ReferenceDatasetID`         | Unchanged                                                                                    |
    | `run.ReferenceExampleID`     | `run.ReferenceExampleID`         | Unchanged                                                                                    |
    | `run.Tags`                   | `run.Tags`                       | Unchanged                                                                                    |
    | `run.ThreadID`               | `run.ThreadID`                   | Unchanged                                                                                    |
    | `run.SessionID`              | `run.ProjectID`                  | Renamed                                                                                      |
    | `run.InDataset`              | `run.IsInDataset`                | Renamed                                                                                      |
    | `run.ChildRunIDs`            | *(removed)*                      | No equivalent                                                                                |
    | `run.DirectChildRunIDs`      | *(removed)*                      | No equivalent                                                                                |
    | `run.ExecutionOrder`         | *(removed)*                      | No equivalent                                                                                |
    | `run.InputsS3URLs`           | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.LastQueuedAt`           | *(removed)*                      | No equivalent                                                                                |
    | `run.ManifestID`             | *(removed)*                      | Use `run.Manifest`                                                                           |
    | `run.ManifestS3ID`           | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.Messages`               | *(removed)*                      | No equivalent                                                                                |
    | `run.OutputsS3URLs`          | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.ParentRunID`            | *(removed)*                      | Use `run.ParentRunIDs`                                                                       |
    | `run.S3URLs`                 | *(removed)*                      | Internal storage URL; not exposed in v2                                                      |
    | `run.Serialized`             | *(removed)*                      | Use `run.Manifest`                                                                           |
    | `run.ShareToken`             | *(removed)*                      | Use `run.ShareURL`                                                                           |
    | `run.TraceFirstReceivedAt`   | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceMaxStartTime`      | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceMinStartTime`      | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceTier`              | *(removed)*                      | No equivalent                                                                                |
    | `run.TraceUpgrade`           | *(removed)*                      | No equivalent                                                                                |
    | `run.TtlSeconds`             | *(removed)*                      | No equivalent                                                                                |
    | *(not available)*            | `run.Attachments`                | New: maps attachment filename to pre-signed download URL                                     |
    | *(not available)*            | `run.ErrorPreview`               | New: truncated error snippet                                                                 |
    | *(not available)*            | `run.IsRoot`                     | New                                                                                          |
    | *(not available)*            | `run.LatencySeconds`             | New: wall-clock duration in seconds                                                          |
    | *(not available)*            | `run.Manifest`                   | New: full manifest object (replaces `Serialized` and `ManifestID`)                           |
    | *(not available)*            | `run.Metadata`                   | New: arbitrary user-defined JSON metadata                                                    |
    | *(not available)*            | `run.ShareURL`                   | New: public share URL (only set when the run has been shared)                                |
    | *(not available)*            | `run.ThreadEvaluationTime`       | New                                                                                          |
  </Tab>

  <Tab title="cURL">
    Pass SCREAMING\_SNAKE\_CASE strings as repeated `selects` query parameters (eg. `selects=NAME&selects=STATUS`) to control which fields are populated. Default `selects` contains only `"ID"`.

    | Before (v1 response field) | After (v2 response field)      | Notes                                                                                                                  |
    | -------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
    | `id`                       | `id`                           | Unchanged                                                                                                              |
    | `name`                     | `name`                         | Unchanged                                                                                                              |
    | `run_type`                 | `run_type`                     | Values changed to uppercase: `"LLM"`, `"CHAIN"`, etc.                                                                  |
    | `status`                   | `status`                       | Values: `"SUCCESS"`, `"ERROR"`, `"PENDING"`                                                                            |
    | `trace_id`                 | `trace_id`                     | Unchanged                                                                                                              |
    | `dotted_order`             | `dotted_order`                 | Unchanged                                                                                                              |
    | `app_path`                 | `app_path`                     | Unchanged                                                                                                              |
    | `start_time`               | `start_time`                   | Unchanged                                                                                                              |
    | `end_time`                 | `end_time`                     | Unchanged                                                                                                              |
    | `error`                    | `error`                        | Unchanged                                                                                                              |
    | `events`                   | `events`                       | Unchanged                                                                                                              |
    | `extra`                    | `extra`                        | Unchanged                                                                                                              |
    | `feedback_stats`           | `feedback_stats`               | Unchanged                                                                                                              |
    | `first_token_time`         | `first_token_time`             | Unchanged                                                                                                              |
    | `inputs`                   | `inputs`                       | Unchanged                                                                                                              |
    | `inputs_preview`           | `inputs_preview`               | Unchanged                                                                                                              |
    | `outputs`                  | `outputs`                      | Unchanged                                                                                                              |
    | `outputs_preview`          | `outputs_preview`              | Unchanged                                                                                                              |
    | `parent_run_ids`           | `parent_run_ids`               | Unchanged                                                                                                              |
    | `price_model_id`           | `price_model_id`               | Unchanged                                                                                                              |
    | `prompt_cost`              | `prompt_cost`                  | Unchanged                                                                                                              |
    | `prompt_cost_details`      | `prompt_cost_details.raw`      | Field now wraps the object; read `.raw` for the same `{category: cost}` mapping, now with numeric values (was strings) |
    | `prompt_token_details`     | `prompt_token_details.raw`     | Field now wraps the object; read `.raw` for the same `{category: count}` mapping (values unchanged)                    |
    | `prompt_tokens`            | `prompt_tokens`                | Unchanged                                                                                                              |
    | `completion_cost`          | `completion_cost`              | Unchanged                                                                                                              |
    | `completion_cost_details`  | `completion_cost_details.raw`  | Field now wraps the object; read `.raw` for the same `{category: cost}` mapping, now with numeric values (was strings) |
    | `completion_token_details` | `completion_token_details.raw` | Field now wraps the object; read `.raw` for the same `{category: count}` mapping (values unchanged)                    |
    | `completion_tokens`        | `completion_tokens`            | Unchanged                                                                                                              |
    | `total_cost`               | `total_cost`                   | Unchanged                                                                                                              |
    | `total_tokens`             | `total_tokens`                 | Unchanged                                                                                                              |
    | `reference_dataset_id`     | `reference_dataset_id`         | Unchanged                                                                                                              |
    | `reference_example_id`     | `reference_example_id`         | Unchanged                                                                                                              |
    | `tags`                     | `tags`                         | Unchanged                                                                                                              |
    | `thread_id`                | `thread_id`                    | Unchanged                                                                                                              |
    | `session_id`               | `project_id`                   | Renamed                                                                                                                |
    | `in_dataset`               | `is_in_dataset`                | Renamed                                                                                                                |
    | `child_run_ids`            | *(removed)*                    | No equivalent                                                                                                          |
    | `direct_child_run_ids`     | *(removed)*                    | No equivalent                                                                                                          |
    | `execution_order`          | *(removed)*                    | No equivalent                                                                                                          |
    | `inputs_s3_urls`           | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `last_queued_at`           | *(removed)*                    | No equivalent                                                                                                          |
    | `manifest_id`              | *(removed)*                    | Use `manifest`                                                                                                         |
    | `manifest_s3_id`           | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `messages`                 | *(removed)*                    | No equivalent                                                                                                          |
    | `outputs_s3_urls`          | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `parent_run_id`            | *(removed)*                    | Use `parent_run_ids`                                                                                                   |
    | `s3_urls`                  | *(removed)*                    | Internal storage URL; not exposed in v2                                                                                |
    | `serialized`               | *(removed)*                    | Use `manifest`                                                                                                         |
    | `share_token`              | *(removed)*                    | Use `share_url`                                                                                                        |
    | `trace_first_received_at`  | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_max_start_time`     | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_min_start_time`     | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_tier`               | *(removed)*                    | No equivalent                                                                                                          |
    | `trace_upgrade`            | *(removed)*                    | No equivalent                                                                                                          |
    | `ttl_seconds`              | *(removed)*                    | No equivalent                                                                                                          |
    | *(not available)*          | `attachments`                  | New: maps attachment filename to pre-signed download URL                                                               |
    | *(not available)*          | `error_preview`                | New: truncated error snippet                                                                                           |
    | *(not available)*          | `is_root`                      | New                                                                                                                    |
    | *(not available)*          | `latency_seconds`              | New: wall-clock duration in seconds                                                                                    |
    | *(not available)*          | `manifest`                     | New: full manifest object (replaces `serialized` and `manifest_id`)                                                    |
    | *(not available)*          | `metadata`                     | New: previously nested under `extra.metadata`                                                                          |
    | *(not available)*          | `share_url`                    | New: public share URL (only set when the run has been shared)                                                          |
    | *(not available)*          | `thread_evaluation_time`       | New                                                                                                                    |
  </Tab>
</Tabs>

### Examples

#### Fetch a single run by ID

<Tabs>
  <Tab title="Python">
    `runs.retrieve` requires two additional parameters that `read_run` did not need: `project_id` (UUID) and `start_time`. Both are required by the SmithDB storage model to locate a run efficiently. Resolve the project UUID via `client.aread_project()` first.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        run_id = "<run-id>"
        run = client.read_run(run_id)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            run_id = "<run-id>"
            start_time = "2026-06-01T12:00:00Z"
            run = await client.runs.retrieve(
                run_id=run_id,
                project_id=str(project.id),
                start_time=start_time,
            )


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `client.runs.retrieve` requires two additional parameters that `readRun` did not need: `project_id` (UUID) and `start_time`. Both are required by the SmithDB storage model to locate a run efficiently. Resolve the project UUID via `client.readProject()` first.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        let runId = "<run-id>";
        await client.readRun(runId);
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        const project = await client.readProject({ projectName: "default" });
        let runId = "<run-id>";
        let startTime = "2026-06-01T12:00:00Z";
        await client.runs.retrieve(runId, {
          project_id: project.id,
          start_time: startTime,
        });
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `retrieveV2()` requires two additional parameters that `client.runs().retrieve()` did not need: `projectId()` (UUID) and `startTime()`. Both are required by the SmithDB storage model to locate a run efficiently. Resolve the project UUID via `client.sessions().list()` first.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        var runId = "<run-id>"
        client.runs().retrieve(runId)
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import java.time.OffsetDateTime

        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunRetrieveV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()

        var runId = "<run-id>"
        var startTime = "<run-start-time-rfc3339>"
        client.runs().retrieveV2(
            runId,
            RunRetrieveV2Params.builder()
                .projectId(project.id())
                .startTime(OffsetDateTime.parse(startTime))
                .build()
        )
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `GetV2()` requires two additional parameters that `client.Runs.Get()` did not need: `ProjectID` (UUID) and `StartTime`. Both are required by the SmithDB storage model to locate a run efficiently. Resolve the project UUID via `client.Sessions.List()` first.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        runID := "<run-id>"
        run, err := client.Runs.Get(ctx, runID, langsmith.RunGetParams{})
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"time"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        runID := "<run-id>"
        startTime := time.Date(2026, 6, 1, 12, 0, 0, 0, time.UTC)
        projectID := "<project-id>"
        run, err := client.Runs.GetV2(ctx, runID, langsmith.RunGetV2Params{
        	ProjectID: langsmith.F(projectID),
        	StartTime: langsmith.F(startTime),
        })
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `GET /v2/runs/{run_id}` requires two additional query parameters that `GET /api/v1/runs/{run_id}` did not need: `project_id` (UUID) and `start_time`. Both are required by the SmithDB storage model to locate a run efficiently. Resolve the project UUID via a `GET /api/v1/sessions` request first.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        RUN_ID="<run-id>"

        curl "https://api.smith.langchain.com/api/v1/runs/$RUN_ID" \
          -H "x-api-key: $LANGSMITH_API_KEY"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        RUN_ID="<run-id>"
        START_TIME="2025-01-01T12:00:00Z"

        curl "https://api.smith.langchain.com/v2/runs/$RUN_ID?project_id=$PROJECT_ID&start_time=$START_TIME" \
          -H "x-api-key: $LANGSMITH_API_KEY"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

#### Selecting fields

<Tabs>
  <Tab title="Python">
    `read_run` returns a full run object with no selection needed. `runs.retrieve` returns only `id` by default—pass `selects=[...]` to request more.

    <Tabs sync={false}>
      <Tab title="Before">
        ```python Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        from langsmith import Client

        client = Client()
        run_id = "<run-id>"
        run = client.read_run(run_id=run_id)
        print(run.name, run.status, run.total_tokens)
        ```
      </Tab>

      <Tab title="After">
        ```python After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import asyncio

        from langsmith import Client


        async def main():
            client = Client()
            project = await client.aread_project(project_name="default")
            run_id = "<run-id>"
            start_time = "2026-06-01T12:00:00Z"
            run = await client.runs.retrieve(
                run_id=run_id,
                project_id=str(project.id),
                start_time=start_time,
                selects=["NAME", "STATUS", "TOTAL_TOKENS"],
            )
            print(run.name, run.status, run.total_tokens)


        asyncio.run(main())
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="TypeScript">
    `readRun` returns a full run object with no selection needed. `client.runs.retrieve` returns only `id` by default—pass `selects: [...]` to request more.

    <Tabs sync={false}>
      <Tab title="Before">
        ```ts Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        let runId = "<run-id>";
        const retrievedRun = await client.readRun(runId);
        console.log(retrievedRun.name, retrievedRun.status, retrievedRun.total_tokens);
        ```
      </Tab>

      <Tab title="After">
        ```ts After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import { Client } from "langsmith";

        const client = new Client();
        let runId = "<run-id>";
        let startTime = "2026-06-01T12:00:00Z";
        let projectId = "<project-id>";
        const retrievedRun = await client.runs.retrieve(runId, {
          project_id: projectId,
          start_time: startTime,
          selects: ["NAME", "STATUS", "TOTAL_TOKENS"],
        });
        console.log(retrievedRun.name, retrievedRun.status, retrievedRun.total_tokens);
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Java">
    `.retrieve()` returns a full run object with no selection needed. `.retrieveV2()` returns only `id` by default—call `.addSelect(...)` for each field you need.

    <Tabs sync={false}>
      <Tab title="Before">
        ```kotlin Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        var runId = "<run-id>"
        val run = client.runs().retrieve(runId)
        println("${run.name()} ${run.status()} ${run.totalTokens()}")
        ```
      </Tab>

      <Tab title="After">
        ```kotlin After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        import java.time.OffsetDateTime

        import com.langchain.smith.client.LangsmithClient
        import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
        import com.langchain.smith.models.runs.RunRetrieveV2Params
        import com.langchain.smith.models.sessions.SessionListParams

        val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()

        val project = client.sessions().list(
            SessionListParams.builder().name("default").limit(1L).build()
        ).items().first()

        var runId = "<run-id>"
        var startTime = "<run-start-time-rfc3339>"
        val run = client.runs().retrieveV2(
            runId,
            RunRetrieveV2Params.builder()
                .projectId(project.id())
                .startTime(OffsetDateTime.parse(startTime))
                .addSelect(RunRetrieveV2Params.Select.NAME)
                .addSelect(RunRetrieveV2Params.Select.STATUS)
                .addSelect(RunRetrieveV2Params.Select.TOTAL_TOKENS)
                .build()
        )
        println("${run.name()} ${run.status()} ${run.totalTokens()}")
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Go">
    `Get` returns a full run struct with no selection needed. `GetV2` returns only `ID` by default—pass `Selects` with the fields you need.

    <Tabs sync={false}>
      <Tab title="Before">
        ```go Before theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"fmt"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        runID := "<run-id>"
        run, err := client.Runs.Get(ctx, runID, langsmith.RunGetParams{})
        fmt.Println(run.Name, run.Status, run.TotalTokens)
        ```
      </Tab>

      <Tab title="After">
        ```go After theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        package main

        import (
        	"context"
        	"fmt"
        	"time"

        	"github.com/langchain-ai/langsmith-go"
        )

        ctx := context.Background()
        client := langsmith.NewClient()

        runID := "<run-id>"
        startTime := time.Date(2026, 6, 1, 12, 0, 0, 0, time.UTC)
        projectID := "<project-id>"
        run, err := client.Runs.GetV2(ctx, runID, langsmith.RunGetV2Params{
        	ProjectID: langsmith.F(projectID),
        	StartTime: langsmith.F(startTime),
        	Selects: langsmith.F([]langsmith.RunGetV2ParamsSelect{
        		langsmith.RunGetV2ParamsSelectName,
        		langsmith.RunGetV2ParamsSelectStatus,
        		langsmith.RunGetV2ParamsSelectTotalTokens,
        	}),
        })
        fmt.Println(run.Name, run.Status, run.TotalTokens)
        ```
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="cURL">
    `GET /api/v1/runs/{run_id}` returns a full run object with no selection needed. `GET /v2/runs/{run_id}` returns only `id` by default—pass `selects` query parameters for the fields you need.

    <Tabs sync={false}>
      <Tab title="Before">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        RUN_ID="<run-id>"

        curl "https://api.smith.langchain.com/api/v1/runs/$RUN_ID" \
          -H "x-api-key: $LANGSMITH_API_KEY"
        ```
      </Tab>

      <Tab title="After">
        ```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
        PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
          -H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')

        RUN_ID="<run-id>"
        START_TIME="2026-06-01T12:00:00Z"

        curl "https://api.smith.langchain.com/v2/runs/$RUN_ID?project_id=$PROJECT_ID&start_time=$START_TIME&selects=NAME&selects=STATUS&selects=TOTAL_TOKENS" \
          -H "x-api-key: $LANGSMITH_API_KEY"
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

***

<div className="source-links">
  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>

  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/smithdb-sdk-migration.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>
</div>
