diff --git a/libs/sdk-py/langgraph_sdk/client.py b/libs/sdk-py/langgraph_sdk/client.py index 4418e66de..5f95b9582 100644 --- a/libs/sdk-py/langgraph_sdk/client.py +++ b/libs/sdk-py/langgraph_sdk/client.py @@ -208,9 +208,15 @@ class HttpClient: def __init__(self, client: httpx.AsyncClient) -> None: self.client = client - async def get(self, path: str, *, params: Optional[QueryParamTypes] = None) -> Any: + async def get( + self, + path: str, + *, + params: Optional[QueryParamTypes] = None, + headers: Optional[dict[str, str]] = None, + ) -> Any: """Send a GET request.""" - r = await self.client.get(path, params=params) + r = await self.client.get(path, params=params, headers=headers) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -222,13 +228,22 @@ class HttpClient: raise e return await adecode_json(r) - async def post(self, path: str, *, json: Optional[dict]) -> Any: + async def post( + self, + path: str, + *, + json: Optional[dict], + headers: Optional[dict[str, str]] = None, + ) -> Any: """Send a POST request.""" if json is not None: - headers, content = await aencode_json(json) + request_headers, content = await aencode_json(json) else: - headers, content = {}, b"" - r = await self.client.post(path, headers=headers, content=content) + request_headers, content = {}, b"" + # Merge headers, with runtime headers taking precedence + if headers: + request_headers.update(headers) + r = await self.client.post(path, headers=request_headers, content=content) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -240,10 +255,14 @@ class HttpClient: raise e return await adecode_json(r) - async def put(self, path: str, *, json: dict) -> Any: + async def put( + self, path: str, *, json: dict, headers: Optional[dict[str, str]] = None + ) -> Any: """Send a PUT request.""" - headers, content = await aencode_json(json) - r = await self.client.put(path, headers=headers, content=content) + request_headers, content = await aencode_json(json) + if headers: + request_headers.update(headers) + r = await self.client.put(path, headers=request_headers, content=content) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -255,10 +274,14 @@ class HttpClient: raise e return await adecode_json(r) - async def patch(self, path: str, *, json: dict) -> Any: + async def patch( + self, path: str, *, json: dict, headers: Optional[dict[str, str]] = None + ) -> Any: """Send a PATCH request.""" - headers, content = await aencode_json(json) - r = await self.client.patch(path, headers=headers, content=content) + request_headers, content = await aencode_json(json) + if headers: + request_headers.update(headers) + r = await self.client.patch(path, headers=request_headers, content=content) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -270,9 +293,15 @@ class HttpClient: raise e return await adecode_json(r) - async def delete(self, path: str, *, json: Optional[Any] = None) -> None: + async def delete( + self, + path: str, + *, + json: Optional[Any] = None, + headers: Optional[dict[str, str]] = None, + ) -> None: """Send a DELETE request.""" - r = await self.client.request("DELETE", path, json=json) + r = await self.client.request("DELETE", path, json=json, headers=headers) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -290,14 +319,18 @@ class HttpClient: *, json: Optional[dict] = None, params: Optional[QueryParamTypes] = None, + headers: Optional[dict[str, str]] = None, ) -> AsyncIterator[StreamPart]: """Stream results using SSE.""" - headers, content = await aencode_json(json) - headers["Accept"] = "text/event-stream" - headers["Cache-Control"] = "no-store" + request_headers, content = await aencode_json(json) + request_headers["Accept"] = "text/event-stream" + request_headers["Cache-Control"] = "no-store" + # Add runtime headers with precedence + if headers: + request_headers.update(headers) async with self.client.stream( - method, path, headers=headers, content=content, params=params + method, path, headers=request_headers, content=content, params=params ) as res: # check status try: @@ -2447,9 +2480,15 @@ class SyncHttpClient: def __init__(self, client: httpx.Client) -> None: self.client = client - def get(self, path: str, *, params: Optional[QueryParamTypes] = None) -> Any: + def get( + self, + path: str, + *, + params: Optional[QueryParamTypes] = None, + headers: Optional[dict[str, str]] = None, + ) -> Any: """Send a GET request.""" - r = self.client.get(path, params=params) + r = self.client.get(path, params=params, headers=headers) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -2461,13 +2500,21 @@ class SyncHttpClient: raise e return decode_json(r) - def post(self, path: str, *, json: Optional[dict]) -> Any: + def post( + self, + path: str, + *, + json: Optional[dict], + headers: Optional[dict[str, str]] = None, + ) -> Any: """Send a POST request.""" if json is not None: - headers, content = encode_json(json) + request_headers, content = encode_json(json) else: - headers, content = {}, b"" - r = self.client.post(path, headers=headers, content=content) + request_headers, content = {}, b"" + if headers: + request_headers.update(headers) + r = self.client.post(path, headers=request_headers, content=content) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -2494,10 +2541,14 @@ class SyncHttpClient: raise e return decode_json(r) - def patch(self, path: str, *, json: dict) -> Any: + def patch( + self, path: str, *, json: dict, headers: Optional[dict[str, str]] = None + ) -> Any: """Send a PATCH request.""" - headers, content = encode_json(json) - r = self.client.patch(path, headers=headers, content=content) + request_headers, content = encode_json(json) + if headers: + request_headers.update(headers) + r = self.client.patch(path, headers=request_headers, content=content) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -2509,9 +2560,15 @@ class SyncHttpClient: raise e return decode_json(r) - def delete(self, path: str, *, json: Optional[Any] = None) -> None: + def delete( + self, + path: str, + *, + json: Optional[Any] = None, + headers: Optional[dict[str, str]] = None, + ) -> None: """Send a DELETE request.""" - r = self.client.request("DELETE", path, json=json) + r = self.client.request("DELETE", path, json=json, headers=headers) try: r.raise_for_status() except httpx.HTTPStatusError as e: @@ -2529,11 +2586,16 @@ class SyncHttpClient: *, json: Optional[dict] = None, params: Optional[QueryParamTypes] = None, + headers: Optional[dict[str, str]] = None, ) -> Iterator[StreamPart]: """Stream the results of a request using SSE.""" - headers, content = encode_json(json) + request_headers, content = encode_json(json) + request_headers["Accept"] = "text/event-stream" + request_headers["Cache-Control"] = "no-store" + if headers: + request_headers.update(headers) with self.client.stream( - method, path, headers=headers, content=content, params=params + method, path, headers=request_headers, content=content, params=params ) as res: # check status try: