{"record":{"id":"5288638400259d56","repo":"langchain-ai/deepagents","slug":"sdk-name-tool-is-unavailable","errorCode":null,"errorMessage":"SDK {name} tool is unavailable.","messagePattern":"SDK (.+?) tool is unavailable\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/agent.py","lineNumber":546,"sourceCode":"    from langchain_core.messages import ToolMessage as LCToolMessage\n\n    repository_tool_names = _rubric_grader_repository_tool_names(fs_tools)\n\n    read_file_prefix = _rubric_grader_read_file_prefix(backend)\n    artifact_filesystem = FilesystemMiddleware(\n        backend=backend,\n        tools=[\"read_file\"],\n        tool_token_limit_before_evict=None,\n    )\n    artifact_tools = {\n        candidate.name: candidate for candidate in artifact_filesystem.tools\n    }\n\n    def _fs_func(tools_by_name: dict[str, BaseTool], name: str) -> Callable[..., Any]:\n        candidate = cast(\"StructuredTool | None\", tools_by_name.get(name))\n        if candidate is None or candidate.func is None:\n            msg = f\"SDK {name} tool is unavailable.\"\n            raise RuntimeError(msg)\n        return candidate.func\n\n    artifact_read_file = cast(\"StructuredTool\", artifact_tools[\"read_file\"])\n    artifact_read_file_func = _fs_func(artifact_tools, \"read_file\")\n\n    bounds: RepositoryBounds | None = None\n    repository_tools: dict[str, BaseTool] = {}\n    if (\n        repository_backend is not None\n        and repository_root is not None\n        and repository_tool_names\n    ):\n        try:\n            bounds = RepositoryBounds(repository_backend, root=repository_root)\n        except ValueError:\n            logger.warning(\n                \"Invalid rubric grader repository root %r; disabling \"\n                \"working-directory inspection\",","sourceCodeStart":528,"sourceCodeEnd":564,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/agent.py#L528-L564","documentation":"During rubric-grader construction, `_fs_func` looks up a filesystem tool (e.g. `read_file`) in the dict of tools produced by `FilesystemMiddleware` and unwraps its underlying sync callable. If the tool is missing from the dict or its `.func` attribute is None, the middleware did not produce the expected StructuredTool, so a RuntimeError is raised. This is an internal invariant check: the grader cannot work without the wrapped filesystem function.","triggerScenarios":"Calling `_create_rubric_grader_tools` (indirectly via rubric grading setup in `create_cli_agent`) when `FilesystemMiddleware(backend=..., tools=[\"read_file\"], ...)` fails to yield a tool named `read_file`, or yields a StructuredTool whose `.func` is None (e.g. a tool constructed from a coroutine only, or an SDK/deepagents version where FilesystemMiddleware tool construction changed and no sync callable is attached).","commonSituations":"A pinned `deepagents` SDK version where `FilesystemMiddleware.tools` no longer returns `StructuredTool` objects with a `.func` attribute for the requested tool names; mistyping the requested tool name in the middleware's `tools` list; monkeypatched or stubbed middleware in tests returning empty tool lists.","solutions":["Verify the `deepagents` SDK version matches the exact pin in libs/code/pyproject.toml (e.g. `pip show deepagents`); upgrade/downgrade to the pinned version.","Confirm the middleware is constructed with the tool name included in its `tools` list (`tools=[\"read_file\"]`) and that the backend supports it.","If you patch or stub FilesystemMiddleware in tests, ensure the stub returns StructuredTool objects with a non-None `.func`."],"exampleFix":"// before: stubbed middleware returns plain objects\nartifact_filesystem = FilesystemMiddleware(backend=backend, tools=[])\n// after: request the required tool and use a compatible SDK\nartifact_filesystem = FilesystemMiddleware(backend=backend, tools=[\"read_file\"], tool_token_limit_before_evict=None)","handlingStrategy":"validation","validationCode":"from deepagents_code.agent import _create_rubric_grader_tools  # or inspect tools yourself\nimport importlib.metadata\nassert importlib.metadata.version(\"deepagents\") == EXPECTED_SDK_PIN, \"SDK drift: FilesystemMiddleware may not expose .func\"\ntool_names = {t.name for t in fs_middleware.tools}\nassert \"read_file\" in tool_names, \"read_file missing from FilesystemMiddleware tools\"","typeGuard":"def has_sync_func(tool: object) -> bool:\n    return isinstance(tool, StructuredTool) and getattr(tool, \"func\", None) is not None","tryCatchPattern":"try:\n    grader_tools = _create_rubric_grader_tools(...)\nexcept RuntimeError as e:\n    if \"tool is unavailable\" in str(e):\n        logger.error(\"SDK filesystem tool missing; check deepagents pin: %s\", e)\n    raise","preventionTips":["Keep the exact deepagents==X.Y.Z pin from pyproject.toml and bump it deliberately.","When stubbing FilesystemMiddleware in tests, return real StructuredTool objects with .func set.","Assert middleware tool names in tests before grading setup runs."],"tags":["python","runtime","sdk-version","middleware"],"backgroundTag":"sdk-tool-unavailable","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}