diff --git a/libs/sdk-py/langgraph_sdk/_async/stream.py b/libs/sdk-py/langgraph_sdk/_async/stream.py index 870ce2556..bc7e68ff6 100644 --- a/libs/sdk-py/langgraph_sdk/_async/stream.py +++ b/libs/sdk-py/langgraph_sdk/_async/stream.py @@ -24,7 +24,7 @@ from langchain_core.language_models.chat_model_stream import AsyncChatModelStrea from langchain_protocol import Event, SubscribeParams from langgraph_sdk._async.http import HttpClient -from langgraph_sdk.schema import QueryParamTypes +from langgraph_sdk.schema import LangSmithTracing, QueryParamTypes from langgraph_sdk.stream.controller import _SeenEventIds from langgraph_sdk.stream.decoders import ( DataDecoder, @@ -172,6 +172,7 @@ class RunModule: input: Any = None, config: dict[str, Any] | None = None, metadata: dict[str, Any] | None = None, + langsmith_tracing: LangSmithTracing | None = None, ) -> dict[str, Any]: """Send `run.start` to the server. Returns the result (`{"run_id": ...}`).""" params: dict[str, Any] = {"assistant_id": self._owner.assistant_id} @@ -181,6 +182,8 @@ class RunModule: params["config"] = config if metadata is not None: params["metadata"] = metadata + if langsmith_tracing is not None: + params["langsmith_tracer"] = langsmith_tracing loop = asyncio.get_running_loop() gate: asyncio.Future[None] = loop.create_future() self._owner._run_start_ready = gate diff --git a/libs/sdk-py/langgraph_sdk/_sync/stream.py b/libs/sdk-py/langgraph_sdk/_sync/stream.py index 9405e7f83..fabbff24d 100644 --- a/libs/sdk-py/langgraph_sdk/_sync/stream.py +++ b/libs/sdk-py/langgraph_sdk/_sync/stream.py @@ -23,7 +23,7 @@ from langchain_core.language_models.chat_model_stream import ChatModelStream from langchain_protocol import Event, SubscribeParams from langgraph_sdk._sync.http import SyncHttpClient -from langgraph_sdk.schema import QueryParamTypes +from langgraph_sdk.schema import LangSmithTracing, QueryParamTypes from langgraph_sdk.stream.decoders import ( DataDecoder, Decoder, @@ -215,6 +215,7 @@ class SyncRunModule: input: Any = None, config: dict[str, Any] | None = None, metadata: dict[str, Any] | None = None, + langsmith_tracing: LangSmithTracing | None = None, ) -> dict[str, Any]: """Send `run.start` to the server. Returns the result (`{"run_id": ...}`).""" params: dict[str, Any] = {"assistant_id": self._owner.assistant_id} @@ -224,6 +225,8 @@ class SyncRunModule: params["config"] = config if metadata is not None: params["metadata"] = metadata + if langsmith_tracing is not None: + params["langsmith_tracer"] = langsmith_tracing result = self._owner._send_command("run.start", params) self._owner._run_seen = True controller = self._owner._controller diff --git a/libs/sdk-py/tests/streaming/test_sync_thread_stream.py b/libs/sdk-py/tests/streaming/test_sync_thread_stream.py index 59a02da5d..e5469bb59 100644 --- a/libs/sdk-py/tests/streaming/test_sync_thread_stream.py +++ b/libs/sdk-py/tests/streaming/test_sync_thread_stream.py @@ -426,11 +426,17 @@ def test_sync_run_start_sends_command(): with httpx.Client(transport=fake.transport, base_url="http://test") as raw: threads = SyncThreadsClient(SyncHttpClient(raw)) with threads.stream(thread_id="t-1", assistant_id="agent") as thread: - result = thread.run.start(input={"x": 1}) + result = thread.run.start( + input={"x": 1}, + langsmith_tracing={"project_name": "replica-project"}, + ) assert result == {"run_id": "run-1"} assert fake.received_commands[0]["method"] == "run.start" assert fake.received_commands[0]["params"]["assistant_id"] == "agent" + assert fake.received_commands[0]["params"]["langsmith_tracer"] == { + "project_name": "replica-project" + } def test_sync_events_iterates_raw_events(): diff --git a/libs/sdk-py/tests/streaming/test_thread_stream.py b/libs/sdk-py/tests/streaming/test_thread_stream.py index 4617f4690..f683928be 100644 --- a/libs/sdk-py/tests/streaming/test_thread_stream.py +++ b/libs/sdk-py/tests/streaming/test_thread_stream.py @@ -287,7 +287,7 @@ async def test_command_ids_are_monotonic(): assert [c["id"] for c in fake.received_commands] == [1, 2] -async def test_run_start_forwards_config_and_metadata(): +async def test_run_start_forwards_config_metadata_and_langsmith_tracing(): fake = FakeServer() transport = httpx.ASGITransport(app=fake.app) async with httpx.AsyncClient(transport=transport, base_url="http://test") as raw: @@ -297,10 +297,18 @@ async def test_run_start_forwards_config_and_metadata(): input={"x": 1}, config={"recursion_limit": 5}, metadata={"trace": "abc"}, + langsmith_tracing={ + "project_name": "replica-project", + "example_id": "example-1", + }, ) params = fake.received_commands[0]["params"] assert params["config"] == {"recursion_limit": 5} assert params["metadata"] == {"trace": "abc"} + assert params["langsmith_tracer"] == { + "project_name": "replica-project", + "example_id": "example-1", + } async def test_run_start_raises_outside_context_manager():