Skip to main content

Context

In May 2026, we released SmithDB, 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. New SDK methods are required to query your traces with SmithDB. This guide helps you migrate your codebase.

Deprecation and removal

Each SDK method and its underlying endpoint share the same deprecation date. For details on how LangSmith deprecates and removes API endpoints and SDK methods, see API and SDK deprecation policy.

Minimum SDK version

The new SDK methods are available starting at these SDK versions:

About self-hosted

  • The new methods documented in this guide require >=0.16 self-hosted version, independent of the data store used.
  • The deprecated methods stop working once ClickHouse is disabled.
  • Where possible, the SDK raises a warning or error identifying the version to upgrade to, instead of failing without explanation.

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.

Runs: query

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

Main changes

Method name

client.runs.query() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

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

Response fields

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".

Examples

List all runs in a project

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.
Before

Selecting fields

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").
Before

Filter by run type and time range

start_time is renamed to min_start_time, and run_type values are now uppercase ("llm""LLM").
Before

Filter root runs only

is_root is unchanged.
Before
To enumerate traces specifically, use traces.query instead of is_root=True. See Traces: query: it also exposes trace-wide total_tokens/total_cost via trace_aggregates.

Fetch runs by ID list

id=[...] is renamed to ids=[...]. project_ids is now required even when filtering by run IDs—v1 allowed omitting the project context.
Before

Iterate through runs

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.
Before

Filter runs with errors

error=True/False is renamed to has_error=True/False.
Before

Filter by metadata

The filter string syntax is unchanged: eq(metadata_key, ...) checks for key presence, combined with eq(metadata_value, ...) to match a specific value.
Before

Complex boolean filters

Nested and() / or() filter expressions are unchanged.
Before

Scoped filters: filter, trace_filter, tree_filter

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).
Before

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

client.runs.retrieve() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

runs.retrieve requires a new project_id field that read_run did not need. It also accepts an optional start_time—providing it speeds up retrieval but is not required.

Response fields

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".

Examples

Fetch a single run by ID

runs.retrieve requires an additional project_id (UUID) parameter that read_run did not need. It also accepts an optional start_time—providing it speeds up retrieval but is not required. Resolve the project UUID via client.aread_project() first.
Before

Selecting fields

read_run returns a full run object with no selection needed. runs.retrieve returns only id by default—pass selects=[...] to request more.
Before

Handle a not-found run

read_run raised LangSmithNotFoundError from langsmith.utils for a missing run. runs.retrieve raises NotFoundError from langsmith instead.
Before

Load a run’s child runs

The load_child_runs flag and the nested child_runs field are removed. Fetch every run in the trace with traces.list_runs, then filter on parent_run_ids, which holds each run’s full ancestor chain, root first and closest parent last.
Replace read_run(run_id, load_child_runs=True) with client.traces.list_runs.
Before

Runs: get URL

Get the LangSmith UI URL for a run.

Main changes

Method name

client.runs.get_url() is now async. Call it with await.
See the reference for the full parameter list.

Parameters

runs.get_url needs the run’s project_id and trace_id passed directly, instead of resolving them from a run object or a project_name/project_id fallback.

Response

Examples

Get a run’s URL

get_run_url accepts a full run object. runs.get_url is async and needs the run’s project_id (its session_id under the old v1 schema) and trace_id passed individually, with start_time optional.
Before

Traces: query

Returns a list of traces (root runs) for a single tracing project. Each item carries the trace’s root run plus optional trace-wide aggregates (total_tokens, total_cost, first_token_time) under trace_aggregates, so clients never have to merge by trace_id. Traces are scanned within a start_time window: min_start_time defaults to 24 hours before the request, max_start_time defaults to the request time. Set either explicitly to widen or narrow the window. Supports filters (trace_filter, tree_filter) and field projection (selects).

Main changes

Method name

client.traces.query() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

  • session (a list of project UUIDs) becomes project_id, a single UUID; traces.query scopes to exactly one project per call.
  • is_root is removed: traces.query is always scoped to root runs implicitly.
  • The generic filter (evaluated against any run) has no direct equivalent; use trace_filter or tree_filter instead.
  • trace_filter and tree_filter carry over unchanged; both already existed on list_runs.
  • trace_ids is new: a fast-path restriction to a known set of trace UUIDs, more efficient at scale than an equivalent trace_filter.
  • start_time (no default) becomes min_start_time, which defaults to 24 hours ago when omitted.
  • max_start_time is new, defaulting to the request time; list_runs’s end_time filtered by a run’s own end timestamp, not a scan-window bound.
  • select is renamed selects; entries route to trace_aggregates (total_tokens, total_cost, first_token_time) or root_run (everything else).

Response fields

  • root_run carries the same Run shape as Runs: query (id, name, run_type, status, and so on), gated by selects.
  • total_tokens/total_cost move off root_run onto trace_aggregates, summed across every run in the trace instead of just the root run. trace_aggregates is omitted entirely from the response when no aggregate field was selected.
  • trace_aggregates.first_token_time is new

Examples

List traces (root runs)

Fetch every trace (root run) in a project, replacing list_runs(is_root=True).
Before

Get a trace’s total tokens and cost

Read a trace’s token and cost totals from trace_aggregates instead of the root run, where v1 kept them.
Before

Find traces by status, or fetch traces by ID

Filter traces by status (for example, errored) with trace_filter, or skip filtering and fetch known traces directly and faster with trace_ids.
Before

Traces: list runs

Returns runs for a trace ID within min/max start time. Optional filter; repeatable selects to select fields to return.

Main changes

Method name

client.traces.list_runs() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

  • trace_id/trace moves from a query param to a path param.
  • project_id is new and required (the SmithDB partition key); list_runs(trace_id=...) did not need it.
  • filter is unchanged.
  • min_start_time/max_start_time are new. Unlike traces.query, neither has a default: omit both and runs are not filtered by time at all. They are individually optional but must be passed together if either is set.
  • select is renamed selects, using the same 44-value enum as traces.query.

Response fields

The response has a single items field: a list of Run objects in start_time order, same shape as the Runs: query response above.

Examples

List every run in a trace

Fetch all the runs that belong to one trace, given its trace ID.
Before

Get only the LLM calls in a trace

Narrow a trace’s runs down to a specific run type, for example just the LLM calls.
Before

Threads: query

Query threads within a project, with cursor-based pagination. Returns threads matching the given time range and optional filter.

Main changes

Method name

client.threads.query() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

Response fields

Python’s legacy ListThreadsItem only has thread_id, runs (full embedded Run[]), count, min_start_time, max_start_time. It has no token/cost/latency/feedback fields at all.The new Thread never embeds the full run list (that is what threads.list_traces is for) but adds real feedback_stats, latency_p50/latency_p99, cost/token sums with per-category _details, first_trace_id/last_trace_id, first_inputs/last_outputs previews, last_error, num_errored_turns.

Examples

List threads in a project

Fetch every thread with activity in a project during a time range.
Before

Find threads with errors

Find threads that had a turn end in an error.
Before

Threads: list traces

Retrieve all traces belonging to a specific thread within a project.

Main changes

Method name

client.threads.list_traces() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

read_thread’s is_root has no new equivalent. list_traces always returns traces (root runs) only, matching its name. read_thread’s order (asc/desc) also has no new equivalent: results are always sorted by start_time ascending, a fixed server-side order.

Response fields

The legacy read_thread returns full Run objects (a generator). The new ThreadTrace is lightweight: preview fields (inputs_preview/outputs_preview) instead of full inputs/outputs, no embedded child runs. selects controls what’s populated, the same as traces.query.

Examples

List every trace (turn) in a thread

Fetch all the traces (conversation turns) that belong to one thread.
Before

Select specific trace’s fields

Request just the fields you need instead of every field, to reduce response size.
Before

Dataset experiment runs: query

Query dataset examples together with the experiment runs recorded against each example. Accepts one or more experiment_ids so you can view runs from multiple experiments side by side; results are returned as a cursor-paginated page.

Main changes

Method name

client.datasets.experiment_runs.query() is now async. Call it with await.
See the reference for the full parameter and field list.

Query parameters

experiment_ids is required and replaces session_ids. Values are still experiment tracing-project UUIDs—if you only know the experiment’s name, resolve it first: client.read_project(project_name="my-experiment").id, or await client.aread_project(project_name="my-experiment") in async code.

Response fields

Each page item is a dataset example paired with the runs produced for it—not a bare Run. Its runs field holds the same Run objects returned by Querying runs; see that section for the per-run fields. The tables below describe the rest of the item: the example fields alongside runs.
get_experiment_results returned experiment results with an examples_with_runs iterator. datasets.experiment_runs.query returns a paginated page object (page.items, page.next_cursor); each item has:

Examples

Query experiment runs and request preview fields

preview=True returned truncated inputs/outputs automatically. In the new API, request that explicitly: pass INPUTS_PREVIEW and OUTPUTS_PREVIEW in selects for the same truncated shape, or INPUTS/OUTPUTS for the untruncated values. Omitting selects returns only id.
Before

Page through results

Both examples below fetch up to 100 results across as many pages as that takes, then stop—so the two are comparable operations, not “one page” vs. “everything.” Adjust the 100/page_size values for your own use case.
get_experiment_results paginates internally and stops once limit total results are returned. datasets.experiment_runs.query has no total-count limit; iterate the returned page with async for and break once you have enough.
Before

Sort by feedback score

Sort dataset examples by a feedback score, supported only when you query a single experiment. In Go and Java, this replaces the legacy sort_params.sort_by/sort_params.sort_order (now sort.by/sort.order); Python and TypeScript gain sorting for the first time in the new API.
get_experiment_results did not support sorting by feedback score.

Annotation queues: add runs

Add runs to an annotation queue. The SmithDB-backed path takes each run’s full lookup key—its ID plus the session_id (project UUID) and start_time partition keys—so the run can be located directly instead of scanned for.
This method stays on the existing client, not the new runs v2 client, so the Exceptions table above does not apply—error handling is unchanged.

Main changes

Method name

No change—client.add_runs_to_annotation_queue(). The SmithDB path is selected by the parameters you pass (see Inputs below).See the reference for the full parameter list.

Inputs

The SmithDB path needs each run’s session_id (project UUID) and start_time in addition to its run_id. These are already present on the run objects you fetch (for example from client.list_runs()).
Provide exactly one of runs or run_ids; passing both raises a LangSmithUserError.

Response

No change. Both run_ids= and runs= return None.

Examples

Add runs to a queue

run_ids= takes a plain list of run IDs. runs= takes each run’s full lookup key—read run_id, session_id, and start_time off the run objects you already have.
Before

Share and read public runs

Share a trace, remove its public access, or read the runs in a publicly shared trace. The v2 methods use explicit SmithDB coordinates and return select-driven run objects. Public read methods do not require a LangSmith API key. Treat the share token as a secret because anyone with the token can read the shared trace.

Main changes

Method names

The v2 resource methods are async. Call them with await.

Share and unshare parameters

  • runs.share.create takes the run ID as its positional argument. Pass session_id (the tracing project UUID) and trace_id (the root trace UUID).
  • runs.share.delete takes the root trace ID, not an arbitrary child run ID. Pass the tracing project UUID as session_id.
  • share_id is removed. The server generates the share token.
Although generated parameter types may mark these coordinates as optional, provide session_id and trace_id when sharing, and provide session_id when unsharing. SmithDB uses these coordinates for the lookup.

Public read parameters

  • public.runs.query takes the share token and a selects list. The token scopes the query to the complete shared trace. The legacy run-ID filter and cursor response are removed.
  • public.runs.retrieve requires the run ID, share token, exact run start_time, and a selects list. Obtain the exact stored start time from public.runs.query.
  • The public point read returns only selected fields. Use ID, NAME, RUN_TYPE, STATUS, and START_TIME for the examples below.
  • To retrieve the public URL for an authenticated run, call runs.retrieve with selects=["SHARE_URL"], then read run.share_url. Supplying start_time gives SmithDB the most efficient lookup.
Do not construct the public URL from the API origin. Retrieving share_url uses the deployment’s configured application origin and works for both Cloud and self-hosted deployments.

Responses

Examples

The examples query the public trace before the point read because public.runs.retrieve requires the run’s exact stored start_time.

Feedback: create

Create feedback (a score, correction, or comment) for a run.

Main changes

Required parameter

The method name and endpoint are unchanged. Only the session (project) ID requirement changes.
create_feedback now requires session_id, the UUID of the project (session) that owns the run. It was previously optional.

Examples

Provide session_id when creating feedback

create_feedback now requires session_id in addition to run_id.
Before

Exceptions

The SmithDB-backed methods raise new exception classes instead of the legacy langsmith.utils exception classes.

Discontinued

The following methods are discontinued. They call the retired /feedback/formulas endpoints, which return 410 Gone on composite-feedback v2 and are scheduled for removal on 2026-08-20. Composite scores are now managed as composite evaluators, which implement a composite score as a code evaluator plus a run rule. There is no SDK replacement.

Feedback formula methods