langchain-ai/deepagents · error · ValueError

Cannot enforce --allow-fs-tools on compiled subagent {subage

Error message

Cannot enforce --allow-fs-tools on compiled subagent {subagent.get('name', '<unnamed>')!r}: its middleware is not configurable, so the filesystem restriction would be silently bypassed.

What it means

When --allow-fs-tools is used, create_cli_agent injects filesystem restrictions into each subagent's middleware. A subagent supplied as an already-compiled graph (the 'runnable' branch of the SubAgent union) has no configurable middleware, so the restriction could not be applied — the code raises instead of silently allowing the subagent to bypass the filesystem restriction.

Source

Thrown at libs/code/deepagents_code/agent.py:262

    Raises:
        ValueError: If a `CompiledSubAgent` (identified by a `"runnable"` key,
            matching the SDK's own `"runnable" in spec` discriminator in
            `deepagents.middleware.subagents`) is present. Such a spec is used
            as-is by the SDK and its `middleware`
            key is never read, so we cannot enforce the restriction on it. dcode
            adds only raw `SubAgent` dicts today, but the declared type admits
            compiled specs: fail loud rather than silently exposing an
            unrestricted filesystem via `task` delegation.
    """
    for subagent in custom_subagents:
        if "runnable" in subagent:
            msg = (
                "Cannot enforce --allow-fs-tools on compiled subagent "
                f"{subagent.get('name', '<unnamed>')!r}: its middleware is "
                "not configurable, so the filesystem restriction would be "
                "silently bypassed."
            )
            raise ValueError(msg)
        # `"runnable" in subagent` above narrows the union to `SubAgent`.
        subagent_tool_descriptions = (
            _get_harness_tool_descriptions(subagent["model"])
            if "model" in subagent
            else main_tool_descriptions
        )
        subagent["middleware"] = cast(
            "list[AgentMiddleware]",
            [
                *subagent.get("middleware", []),
                FilesystemMiddleware(
                    backend=backend,
                    tools=fs_tools,
                    custom_tool_descriptions=subagent_tool_descriptions,
                ),
            ],
        )

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Replace the compiled subagent with a declarative SubAgent dict (name/model/prompt/tools/middleware) so _inject_fs_tools_into_subagents can configure its middleware.
  2. If the subagent must stay compiled, wrap or rebuild its graph with the equivalent filesystem-restricting middleware yourself before passing it in.
  3. Disable --allow-fs-tools only if you can guarantee the compiled subagent exposes no unrestricted filesystem tools; otherwise it is not a valid alternative.

Example fix

# before
subagents = [{"name": "researcher", "runnable": compiled_graph}]
create_cli_agent(subagents=subagents, allow_fs_tools=True)
# after
subagents = [{"name": "researcher", "model": "...", "prompt": "..."}]
create_cli_agent(subagents=subagents, allow_fs_tools=True)
Defensive patterns

Strategy: validation

Validate before calling

def assert_fs_tools_enforceable(subagents, allow_fs_tools):
    if not allow_fs_tools:
        return
    for s in subagents:
        if "runnable" in s:
            raise ValueError(
                f"Cannot enforce --allow-fs-tools on compiled subagent {s.get('name', '<unnamed>')!r}; "
                "use a declarative subagent instead"
            )

Type guard

def is_declarative_subagent(s: dict) -> bool:
    return "runnable" not in s and "name" in s

Try / catch

try:
    agent = create_cli_agent(subagents=subagents, allow_fs_tools=True)
except ValueError as exc:
    if "compiled subagent" in str(exc):
        subagents = [declarative_form(s) for s in subagents]
        agent = create_cli_agent(subagents=subagents, allow_fs_tools=True)
    else:
        raise

Prevention

When it happens

Trigger: Calling create_cli_agent with --allow-fs-tools enabled and a subagents list containing a compiled subagent (a dict with a 'runnable' key, e.g. {'name': ..., 'runnable': compiled_graph}). Also reproduced by the test test_compiled_subagent_raises_rather_than_bypassing.

Common situations: Users composing pre-compiled LangGraph subagents for performance/reuse while simultaneously trying to sandbox filesystem tool access; copying agent definitions that embed compiled graphs.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/734a985ca5afe15d. Report an issue: GitHub.