From 838e042fe4d761b66452faf93986193dec64d2a4 Mon Sep 17 00:00:00 2001 From: aran-yogesh Date: Tue, 10 Feb 2026 17:30:45 -0800 Subject: [PATCH 1/3] fix: avoid ARG_MAX on sandbox writes by using SDK write() --- apps/agent/agent/integrations/langsmith.py | 31 ++++++++++++++-------- apps/agent/uv.lock | 8 +++--- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/apps/agent/agent/integrations/langsmith.py b/apps/agent/agent/integrations/langsmith.py index a7015d96..29df7ddf 100644 --- a/apps/agent/agent/integrations/langsmith.py +++ b/apps/agent/agent/integrations/langsmith.py @@ -16,11 +16,12 @@ from deepagents.backends.protocol import ( FileDownloadResponse, FileUploadResponse, SandboxBackendProtocol, + WriteResult, ) from deepagents.backends.sandbox import BaseSandbox -from langsmith.sandbox import Sandbox, SandboxClient, SandboxTemplate - +if TYPE_CHECKING: + from langsmith.sandbox import Sandbox, SandboxClient, SandboxTemplate class SandboxProvider(ABC): @@ -82,14 +83,25 @@ class LangSmithBackend(BaseSandbox): truncated=False, ) + def write(self, file_path: str, content: str) -> WriteResult: + """Write content using the LangSmith SDK to avoid ARG_MAX. + + BaseSandbox.write() sends the full content in a shell command, which + can exceed ARG_MAX for large content. This override uses the SDK's + native write(), which sends content in the HTTP body. + """ + try: + self._sandbox.write(file_path, content.encode("utf-8")) + return WriteResult(path=file_path, files_update=None) + except Exception as e: + return WriteResult(error=f"Failed to write file '{file_path}': {e}") + def download_files(self, paths: list[str]) -> list[FileDownloadResponse]: """Download multiple files from the LangSmith sandbox.""" responses: list[FileDownloadResponse] = [] for path in paths: content = self._sandbox.read(path) - responses.append( - FileDownloadResponse(path=path, content=content, error=None) - ) + responses.append(FileDownloadResponse(path=path, content=content, error=None)) return responses def upload_files(self, files: list[tuple[str, bytes]]) -> list[FileUploadResponse]: @@ -148,10 +160,7 @@ class LangSmithProvider(SandboxProvider): template_name=resolved_template_name, timeout=timeout ) except Exception as e: - msg = ( - f"Failed to create sandbox from template " - f"'{resolved_template_name}': {e}" - ) + msg = f"Failed to create sandbox from template '{resolved_template_name}': {e}" raise RuntimeError(msg) from e # Verify sandbox is ready by polling @@ -160,7 +169,7 @@ class LangSmithProvider(SandboxProvider): result = sandbox.run("echo ready", timeout=5) if result.exit_code == 0: break - except Exception: + except Exception: pass time.sleep(2) else: @@ -171,7 +180,7 @@ class LangSmithProvider(SandboxProvider): return LangSmithBackend(sandbox) - def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: + def delete(self, *, sandbox_id: str, **kwargs: Any) -> None: """Delete a LangSmith sandbox.""" self._client.delete_sandbox(sandbox_id) diff --git a/apps/agent/uv.lock b/apps/agent/uv.lock index 82e476f4..e0802b2c 100644 --- a/apps/agent/uv.lock +++ b/apps/agent/uv.lock @@ -976,7 +976,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.6.9" +version = "0.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -989,9 +989,9 @@ dependencies = [ { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/e0/463a70b43d6755b01598bb59932eec8e2029afcab455b5312c318ac457b5/langsmith-0.6.9.tar.gz", hash = "sha256:aae04cec6e6d8e133f63ba71c332ce0fbd2cda95260db7746ff4c3b6a3c41db1", size = 973557, upload-time = "2026-02-05T20:10:55.629Z" } +sdist = { url = "https://files.pythonhosted.org/packages/67/48/3151de6df96e0977b8d319b03905e29db0df6929a85df1d922a030b7e68d/langsmith-0.7.1.tar.gz", hash = "sha256:e3fec2f97f7c5192f192f4873d6a076b8c6469768022323dded07087d8cb70a4", size = 984367, upload-time = "2026-02-10T01:55:24.696Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/8e/063e09c5e8a3dcd77e2a8f0bff3f71c1c52a9d238da1bcafd2df3281da17/langsmith-0.6.9-py3-none-any.whl", hash = "sha256:86ba521e042397f6fbb79d63991df9d5f7b6a6dd6a6323d4f92131291478dcff", size = 319228, upload-time = "2026-02-05T20:10:54.248Z" }, + { url = "https://files.pythonhosted.org/packages/ce/87/6f2b008a456b4f5fd0fb1509bb7e1e9368c1a0c9641a535f224a9ddc10f3/langsmith-0.7.1-py3-none-any.whl", hash = "sha256:92cfa54253d35417184c297ad25bfd921d95f15d60a1ca75f14d4e7acd152a29", size = 322515, upload-time = "2026-02-10T01:55:22.531Z" }, ] [package.optional-dependencies] @@ -1028,6 +1028,7 @@ dependencies = [ { name = "langgraph" }, { name = "langgraph-cli", extra = ["inmem"] }, { name = "langgraph-sdk" }, + { name = "langsmith" }, { name = "markdownify" }, { name = "pyjwt" }, { name = "uvicorn" }, @@ -1051,6 +1052,7 @@ requires-dist = [ { name = "langgraph", specifier = ">=1.0.8" }, { name = "langgraph-cli", extras = ["inmem"], specifier = ">=0.4.12" }, { name = "langgraph-sdk", specifier = ">=0.1.0" }, + { name = "langsmith", specifier = ">=0.7.1" }, { name = "markdownify", specifier = ">=1.2.2" }, { name = "pyjwt", specifier = ">=2.8.0" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=7.0.0" }, From e7085154daae49ef741d58f554010a7fc33d044f Mon Sep 17 00:00:00 2001 From: aran-yogesh Date: Tue, 10 Feb 2026 17:38:32 -0800 Subject: [PATCH 2/3] refactor:langsmith.py changes --- apps/agent/agent/integrations/langsmith.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/agent/agent/integrations/langsmith.py b/apps/agent/agent/integrations/langsmith.py index 29df7ddf..7e90e11c 100644 --- a/apps/agent/agent/integrations/langsmith.py +++ b/apps/agent/agent/integrations/langsmith.py @@ -20,8 +20,7 @@ from deepagents.backends.protocol import ( ) from deepagents.backends.sandbox import BaseSandbox -if TYPE_CHECKING: - from langsmith.sandbox import Sandbox, SandboxClient, SandboxTemplate +from langsmith.sandbox import Sandbox, SandboxClient, SandboxTemplate class SandboxProvider(ABC): @@ -101,7 +100,9 @@ class LangSmithBackend(BaseSandbox): responses: list[FileDownloadResponse] = [] for path in paths: content = self._sandbox.read(path) - responses.append(FileDownloadResponse(path=path, content=content, error=None)) + responses.append( + FileDownloadResponse(path=path, content=content, error=None) + ) return responses def upload_files(self, files: list[tuple[str, bytes]]) -> list[FileUploadResponse]: @@ -160,7 +161,10 @@ class LangSmithProvider(SandboxProvider): template_name=resolved_template_name, timeout=timeout ) except Exception as e: - msg = f"Failed to create sandbox from template '{resolved_template_name}': {e}" + msg = ( + f"Failed to create sandbox from template " + f"'{resolved_template_name}': {e}" + ) raise RuntimeError(msg) from e # Verify sandbox is ready by polling From 4fd73e9f2d02b13db9086a0abef2434003a11866 Mon Sep 17 00:00:00 2001 From: aran-yogesh Date: Tue, 10 Feb 2026 18:18:04 -0800 Subject: [PATCH 3/3] refactor: server.py changes --- apps/agent/agent/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/agent/agent/server.py b/apps/agent/agent/server.py index 18fce83e..907446ab 100644 --- a/apps/agent/agent/server.py +++ b/apps/agent/agent/server.py @@ -22,6 +22,7 @@ warnings.filterwarnings("ignore", message=".*Pydantic V1.*", category=UserWarnin # Now safe to import agent (which imports LangChain modules) from deepagents import create_deep_agent +from deepagents.backends.protocol import SandboxBackendProtocol # Local import for encryption from langchain_anthropic import ChatAnthropic @@ -34,7 +35,6 @@ from .middleware import ( post_to_linear_after_model, ) from .prompt import construct_system_prompt -from deepagents.backends.protocol import SandboxBackendProtocol from .tools import commit_and_open_pr, fetch_url, http_request