Runs: query
Query runs from a project with optional filtering and field projection. Returns a paginated result set.Main changes
Method name
- Python
- TypeScript
- Java
- Go
- cURL
| Before | After |
|---|---|
client.list_runs() | client.runs.query() |
client.runs.query() is now async. Call it with await.| Before | After |
|---|---|
client.listRuns() | client.runs.query() |
| Before | After |
|---|---|
client.runs().query() | client.runs().queryV2() |
| Before | After |
|---|---|
client.Runs.Query() | client.Runs.QueryV2() |
| Before | After |
|---|---|
POST /api/v1/runs/query | POST /api/v2/runs/query |
Query parameters
- Python
- TypeScript
- Java
- Go
- cURL
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.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 |
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" }).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.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 |
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.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() |
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.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 |
min_start_time defaults to 1 day ago when omitted. POST /api/v1/runs/query with no start_time returned all historical runs; POST /api/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.Before (v1 POST /api/v1/runs/query body field) | After (v2 POST /api/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 |
Response fields
- Python
- TypeScript
- Java
- Go
- cURL
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]) |
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 |
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 |
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 |
Field names in the JSON response use
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 |
Examples
List all runs in a project
- Python
- TypeScript
- Java
- Go
- cURL
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
- After
Before
from langsmith import Client
client = Client()
runs = client.list_runs(project_name="default")
After
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())
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.- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const runs = client.listRuns({ projectName: "default" });
After
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
const runs = client.runs.query({ project_ids: [project.id] });
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().- Before
- After
Before
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()
After
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()
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.- Before
- After
Before
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}),
})
After
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}),
})
POST /api/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.- Before
- After
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]}')"
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/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]}')"
Selecting fields
- Python
- TypeScript
- Java
- Go
- cURL
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
- After
Before
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)
After
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())
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").- Before
- After
Before
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);
}
After
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);
}
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.- Before
- After
Before
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()}")
}
After
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.runs.RunSelectField
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(RunSelectField.ID)
.addSelect(RunSelectField.NAME)
.addSelect(RunSelectField.RUN_TYPE)
.addSelect(RunSelectField.STATUS)
.addSelect(RunSelectField.START_TIME)
.addSelect(RunSelectField.INPUTS)
.addSelect(RunSelectField.ERROR)
.build()
).items()
for (run in runs) {
println("${run.id()} ${run.name()} ${run.runType()} ${run.status()} ${run.startTime()} ${run.inputs()} ${run.error()}")
}
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).- Before
- After
Before
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)
}
After
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.RunSelectField{
langsmith.RunSelectFieldID,
langsmith.RunSelectFieldName,
langsmith.RunSelectFieldRunType,
langsmith.RunSelectFieldStatus,
langsmith.RunSelectFieldStartTime,
langsmith.RunSelectFieldInputs,
langsmith.RunSelectFieldError,
}),
})
for _, run := range runs.Items {
fmt.Println(run.ID, run.Name, run.RunType, run.Status, run.StartTime, run.Inputs, run.Error)
}
POST /api/v1/runs/query returns a default set of fields with no selection needed. POST /api/v2/runs/query returns only id by default—pass selects with the uppercase field names you need (e.g. "NAME").- Before
- After
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]}')"
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/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"]}')"
Filter by run type and time range
- Python
- TypeScript
- Java
- Go
- cURL
start_time is renamed to min_start_time, and run_type values are now uppercase ("llm" → "LLM").- Before
- After
Before
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",
)
After
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())
startTime (camelCase) becomes min_start_time (snake_case, matching the v2 request body), and runType values are now uppercase ("llm" → "LLM").- Before
- After
Before
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",
});
After
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",
});
.startTime() is renamed to .minStartTime(), and .runType() now takes the new RunQueryV2Params.RunType enum instead of RunTypeEnum.- Before
- After
Before
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()
After
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.runs.RunType
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(RunType.LLM)
.build()
).items()
StartTime is renamed to MinStartTime, and RunType now takes the new RunQueryV2ParamsRunType enum instead of RunTypeEnum.- Before
- After
Before
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),
})
After
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.RunTypeLlm),
})
start_time is renamed to min_start_time, and run_type values are now uppercase ("llm" → "LLM").- Before
- After
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"}')"
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/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"}')"
Filter root runs only
- Python
- TypeScript
- Java
- Go
- cURL
is_root is unchanged.- Before
- After
Before
from langsmith import Client
client = Client()
runs = client.list_runs(project_name="default", is_root=True)
After
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())
isRoot (camelCase) becomes is_root (snake_case, matching the v2 request body).- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const runs = client.listRuns({ projectName: "default", isRoot: true });
After
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,
});
.isRoot() is unchanged.- Before
- After
Before
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()
After
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()
IsRoot is unchanged.- Before
- After
Before
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),
})
After
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),
})
is_root is unchanged.- Before
- After
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}')"
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/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}')"
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
- Python
- TypeScript
- Java
- Go
- cURL
id=[...] is renamed to ids=[...]. project_ids is now required even when filtering by run IDs—v1 allowed omitting the project context.- Before
- After
Before
from langsmith import Client
client = Client()
runs = client.list_runs(id=["<run-id-1>", "<run-id-2>"])
After
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())
id: [...] is renamed to ids: [...]. project_ids is now required even when filtering by run IDs—v1 allowed omitting the project context.- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const runs = client.listRuns({ id: ["<run-id-1>", "<run-id-2>"] });
After
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>"],
});
.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.- Before
- After
Before
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()
After
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()
ID: [...] is renamed to IDs: [...]. ProjectIDs is now required even when filtering by run IDs—v1 allowed omitting the project context.- Before
- After
Before
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}),
})
After
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}),
})
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.- Before
- After
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]}')"
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/api/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]}')"
Iterate through runs
- Python
- TypeScript
- Java
- Go
- cURL
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
- After
Before
from langsmith import Client
client = Client()
runs = client.list_runs(project_name="default", limit=150)
After
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())
listRuns auto-paginates transparently. client.runs.query returns an async iterable of individual runs—use for await and break once you have enough.- Before
- After
Before
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;
}
After
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;
}
.autoPager() is used the same way on both query() and queryV2()—break out of the loop once you have enough runs.- Before
- After
Before
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
}
After
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
}
QueryAutoPaging is renamed to QueryV2AutoPaging; both use the same iter.Next()/iter.Current() pattern—break out of the loop once you have enough runs.- Before
- After
Before
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
}
}
After
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
}
}
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.- Before
- After
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}')"
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/api/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
Filter runs with errors
- Python
- TypeScript
- Java
- Go
- cURL
error=True/False is renamed to has_error=True/False.- Before
- After
Before
from langsmith import Client
client = Client()
runs = client.list_runs(project_name="default", error=True)
After
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())
error: true/false is renamed to has_error: true/false.- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const runs = client.listRuns({ projectName: "default", error: true });
After
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,
});
.error(true/false) is renamed to .hasError(true/false).- Before
- After
Before
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()
After
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()
Error is renamed to HasError.- Before
- After
Before
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),
})
After
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),
})
error is renamed to has_error.- Before
- After
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}')"
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/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}')"
Filter by metadata
- Python
- TypeScript
- Java
- Go
- cURL
The
filter string syntax is unchanged: eq(metadata_key, ...) checks for key presence, combined with eq(metadata_value, ...) to match a specific value.- Before
- After
Before
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)
After
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())
The
filter string syntax is unchanged: eq(metadata_key, ...) checks for key presence, combined with eq(metadata_value, ...) to match a specific value.- Before
- After
Before
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 });
After
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,
});
The
.filter(...) string syntax is unchanged: eq(metadata_key, ...) checks for key presence, combined with eq(metadata_value, ...) to match a specific value.- Before
- After
Before
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()
After
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()
The
Filter string syntax is unchanged: eq(metadata_key, ...) checks for key presence, combined with eq(metadata_value, ...) to match a specific value.- Before
- After
Before
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),
})
After
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),
})
The
filter string syntax is unchanged: eq(metadata_key, ...) checks for key presence, combined with eq(metadata_value, ...) to match a specific value.- Before
- After
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}')"
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/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}')"
Complex boolean filters
- Python
- TypeScript
- Java
- Go
- cURL
Nested
and() / or() filter expressions are unchanged.- Before
- After
Before
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)
After
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())
Nested
and() / or() filter expressions are unchanged.- Before
- After
Before
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 });
After
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,
});
Nested
and() / or() filter expressions are unchanged.- Before
- After
Before
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()
After
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()
Nested
and() / or() filter expressions are unchanged.- Before
- After
Before
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),
})
After
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),
})
Nested
and() / or() filter expressions are unchanged.- Before
- After
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}')"
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/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}')"
Scoped filters: filter, trace_filter, tree_filter
- Python
- TypeScript
- Java
- Go
- 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).- Before
- After
Before
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")',
)
After
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())
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
- After
Before
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")',
});
After
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")',
});
.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).- Before
- After
Before
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()
After
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()
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).- Before
- After
Before
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")`),
})
After
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")`),
})
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
- After
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}')"
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/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}')"
See also
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

