diff --git a/libs/sdk-py/langgraph_sdk/_async/threads.py b/libs/sdk-py/langgraph_sdk/_async/threads.py index a25c21ba5..a4439c22d 100644 --- a/libs/sdk-py/langgraph_sdk/_async/threads.py +++ b/libs/sdk-py/langgraph_sdk/_async/threads.py @@ -260,6 +260,7 @@ class ThreadsClient: sort_by: ThreadSortBy | None = None, sort_order: SortOrder | None = None, select: list[ThreadSelectField] | None = None, + extract: dict[str, str] | None = None, headers: Mapping[str, str] | None = None, params: QueryParamTypes | None = None, ) -> list[Thread]: @@ -275,6 +276,13 @@ class ThreadsClient: offset: Offset in threads table to start search from. sort_by: Sort by field. sort_order: Sort order. + select: List of fields to include in the response. + extract: Dictionary mapping aliases to JSONB paths to extract + from thread data. Paths use dot notation for nested keys and + bracket notation for array indices (e.g., + `{"last_msg": "values.messages[-1]"}`). Extracted values are + returned in an `extracted` field on each thread. Maximum 10 + paths per request. headers: Optional custom headers to include with the request. params: Optional query parameters to include with the request. @@ -312,6 +320,8 @@ class ThreadsClient: payload["sort_order"] = sort_order if select: payload["select"] = select + if extract: + payload["extract"] = extract return await self.http.post( "/threads/search", json=payload, diff --git a/libs/sdk-py/langgraph_sdk/_sync/threads.py b/libs/sdk-py/langgraph_sdk/_sync/threads.py index 172faf43b..b1ebf6b59 100644 --- a/libs/sdk-py/langgraph_sdk/_sync/threads.py +++ b/libs/sdk-py/langgraph_sdk/_sync/threads.py @@ -255,6 +255,7 @@ class SyncThreadsClient: sort_by: ThreadSortBy | None = None, sort_order: SortOrder | None = None, select: list[ThreadSelectField] | None = None, + extract: dict[str, str] | None = None, headers: Mapping[str, str] | None = None, params: QueryParamTypes | None = None, ) -> list[Thread]: @@ -268,7 +269,17 @@ class SyncThreadsClient: Must be one of 'idle', 'busy', 'interrupted' or 'error'. limit: Limit on number of threads to return. offset: Offset in threads table to start search from. + sort_by: Sort by field. + sort_order: Sort order. + select: List of fields to include in the response. + extract: Dictionary mapping aliases to JSONB paths to extract + from thread data. Paths use dot notation for nested keys and + bracket notation for array indices (e.g., + `{"last_msg": "values.messages[-1]"}`). Extracted values are + returned in an `extracted` field on each thread. Maximum 10 + paths per request. headers: Optional custom headers to include with the request. + params: Optional query parameters to include with the request. Returns: List of the threads matching the search parameters. @@ -303,6 +314,8 @@ class SyncThreadsClient: payload["sort_order"] = sort_order if select: payload["select"] = select + if extract: + payload["extract"] = extract return self.http.post( "/threads/search", json=payload, headers=headers, params=params ) diff --git a/libs/sdk-py/langgraph_sdk/schema.py b/libs/sdk-py/langgraph_sdk/schema.py index 7567f4077..163f13bb7 100644 --- a/libs/sdk-py/langgraph_sdk/schema.py +++ b/libs/sdk-py/langgraph_sdk/schema.py @@ -15,7 +15,7 @@ from typing import ( Union, ) -from typing_extensions import TypedDict +from typing_extensions import NotRequired, TypedDict Json = dict[str, Any] | None """Represents a JSON-like structure, which can be None or a dictionary with string keys and any values.""" @@ -304,6 +304,8 @@ class Thread(TypedDict): """The current state of the thread.""" interrupts: dict[str, list[Interrupt]] """Mapping of task ids to interrupts that were raised in that task.""" + extracted: NotRequired[dict[str, Any]] + """Extracted values from thread data. Only present when `extract` is used in search.""" class ThreadTask(TypedDict):