{"record":{"id":"b9853cdc8a331861","repo":"langchain-ai/deepagents","slug":"the-subagent-task-tool-cannot-be-exposed-via-pt","errorCode":null,"errorMessage":"The subagent `task` tool cannot be exposed via `ptc`. It is always available as the top-level `task()` global inside the REPL (with `subagentType`, `label`, and `responseSchema` support); exposing it through the `tools.*` namespace would create a second, conflicting dispatch path that drops `responseSchema`. Remove \"task\" from `ptc`.","messagePattern":"The subagent `task` tool cannot be exposed via `ptc`\\. It is always available as the top-level `task\\(\\)` global inside the REPL \\(with `subagentType`, `label`, and `responseSchema` support\\); exposing it through the `tools\\.\\*` namespace would create a second, conflicting dispatch path that drops `responseSchema`\\. Remove \"task\" from `ptc`\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/partners/quickjs/langchain_quickjs/_ptc.py","lineNumber":87,"sourceCode":"    Duplicate tool names are deduplicated.\n\n    The subagent `task` tool is reserved and may not appear in `config`\n    (by name or instance) — it is always available as the `task()` global,\n    so a `tools.task` PTC variant would be a conflicting, degraded duplicate.\n    A `\"task\"` entry raises `ValueError`.\n\n    Warning:\n        PTC tool calls execute through the REPL bridge and currently do\n        not respect `interrupt_on` / HITL approval hooks for each\n        individual tool invocation.\n    \"\"\"\n    if isinstance(config, list):\n        explicit_tools: list[BaseTool] = []\n        allow_names: set[str] = set()\n        for entry in config:\n            if isinstance(entry, BaseTool):\n                if entry.name == _RESERVED_SUBAGENT_TASK_NAME:\n                    raise ValueError(_TASK_IN_PTC_MSG)\n                if entry.name != self_tool_name:\n                    explicit_tools.append(entry)\n                continue\n            if isinstance(entry, str):\n                if entry == _RESERVED_SUBAGENT_TASK_NAME:\n                    raise ValueError(_TASK_IN_PTC_MSG)\n                allow_names.add(entry)\n                continue\n            msg = \"ptc list entries must be str or BaseTool\"\n            raise TypeError(msg)\n        selected = [\n            *explicit_tools,\n            *[t for t in tools if t.name != self_tool_name and t.name in allow_names],\n        ]\n        deduped: list[BaseTool] = []\n        seen_names: set[str] = set()\n        for tool in selected:\n            if tool.name in seen_names:","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/partners/quickjs/langchain_quickjs/_ptc.py#L69-L105","documentation":"The `task` subagent tool is reserved: it is always injected as the top-level `task()` REPL global with full support for `subagentType`, `label`, and `responseSchema`. Exposing it through the `ptc` tools namespace would create a conflicting second dispatch path that silently drops `responseSchema`, so listing it in a ptc include list raises.","triggerScenarios":"Calling `filter_tools_for_ptc` (directly or via `_prepare_for_call`) with a list-form `ptc` config that includes the `task` tool instance or the string `\"task\"`.","commonSituations":"Passing through all agent tools including the subagent task tool; building a tool allowlist from a tool registry without filtering reserved names; users explicitly requesting 'task' in their ptc tool list.","solutions":["Remove `\"task\"` from the ptc list config","Filter reserved tool names before constructing the ptc list","Rely on the built-in `task()` global — no ptc exposure is needed for subagent spawning"],"exampleFix":"// before\nconst ptc = [\"websearch\", \"task\"];\n// after\nconst ptc = [\"websearch\"];","handlingStrategy":"validation","validationCode":"if any(getattr(t, \"name\", None) == \"task\" for t in tool_objects):\n    raise ValueError(\"remove reserved 'task' tool from ptc list\")","typeGuard":"def is_ptc_safe_tool(t: BaseTool) -> bool:\n    return t.name != \"task\"","tryCatchPattern":"try:\n    selected = filter_tools_for_ptc(tools, config)\nexcept ValueError as e:\n    if \"task\" in str(e) and \"ptc\" in str(e):\n        config = [t for t in config if (t.name if isinstance(t, BaseTool) else t) != \"task\"]\n        selected = filter_tools_for_ptc(tools, config)\n    else:\n        raise","preventionTips":["Keep a RESERVED_TOOL_NAMES = {\"task\"} constant and filter lists against it","Never enumerate the full tool registry into ptc config unfiltered","Remember subagent spawning is always available via the top-level task() global"],"tags":["ptc","quickjs","reserved-name","tools"],"backgroundTag":"reserved-tool-name","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}