langchain-ai/deepagents · error · NotImplementedError

NotImplementedError raised by abstract `execute` (backend do

Error message

NotImplementedError raised by abstract `execute` (backend does not implement `execute`)

What it means

`SandboxBackendProtocol.execute` is the core shell-execution method of a sandbox backend; the base-class stub raises `NotImplementedError` because every concrete sandbox must implement it. Calling `execute`/`aexecute` (directly or via setup helpers like `_run_sandbox_setup`) on a subclass that didn't override it raises this error. The async wrapper only forwards `timeout` when signature introspection (`execute_accepts_timeout`) shows support, so older backend packages also fail here in related ways.

Source

Thrown at libs/deepagents/deepagents/backends/protocol.py:910

    ) -> ExecuteResponse:
        """Execute a shell command in the sandbox environment.

        Simplified interface optimized for LLM consumption.

        Args:
            command: Full shell command string to execute.
            timeout: Maximum time in seconds to wait for the command to complete.

                If None, uses the backend's default timeout.

                Callers should provide non-negative integer values for portable
                behavior across backends. A value of 0 may disable timeouts on
                backends that support no-timeout execution.

        Returns:
            `ExecuteResponse` with combined output, exit code, and truncation flag.
        """
        raise NotImplementedError

    async def aexecute(
        self,
        command: str,
        *,
        # ASYNC109 - timeout is a semantic parameter forwarded to the sync
        # implementation, not an asyncio.timeout() contract.
        timeout: int | None = None,  # noqa: ASYNC109
    ) -> ExecuteResponse:
        """Async version of execute."""
        # The middleware layer validates timeout support before calling, so
        # this guard only protects direct callers bypassing the middleware.
        if timeout is not None and execute_accepts_timeout(type(self)):
            return await asyncio.to_thread(self.execute, command, timeout=timeout)
        return await asyncio.to_thread(self.execute, command)


@lru_cache(maxsize=256)

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Implement `execute(self, command, *, timeout=None) -> ExecuteResponse` in your sandbox backend class (and have `aexecute`/inherited async path delegate to it)
  2. Use a concrete sandbox backend (e.g. LocalShellBackend or a partner sandbox package) instead of the protocol/base class directly
  3. Align package versions so the backend satisfies the current `SandboxBackendProtocol` contract including the `timeout` kwarg
  4. Inspect with `execute_accepts_timeout(type(backend))` before passing `timeout=` to older backends

Example fix

// before
class MySandbox(SandboxBackendProtocol):
    @property
    def id(self): return 'sb-1'

// after
class MySandbox(SandboxBackendProtocol):
    @property
    def id(self): return 'sb-1'

    def execute(self, command: str, *, timeout: int | None = None) -> ExecuteResponse:
        proc = subprocess.run(command, shell=True, capture_output=True, timeout=timeout)
        return ExecuteResponse(output=proc.stdout + proc.stderr, exit_code=proc.returncode)
Defensive patterns

Strategy: try-catch

Validate before calling

from inspect import signature

def is_executable(backend) -> bool:
    fn = getattr(type(backend), 'execute', None)
    if fn is SandboxBackendProtocol.execute:
        return False
    try:
        return 'command' in signature(fn).parameters
    except (TypeError, ValueError):
        return False

Type guard

def accepts_timeout(backend) -> bool:
    return 'timeout' in signature(type(backend).execute).parameters

Try / catch

try:
    resp = backend.execute(cmd, timeout=30)
except NotImplementedError as e:
    raise RuntimeError('backend does not support shell execution') from e

Prevention

When it happens

Trigger: Calling `backend.execute('ls')` on a sandbox backend subclass missing an override; running sandbox setup/tests (`_run_sandbox_setup`, setup_test_dir) against an incomplete backend; instantiating the protocol class itself instead of a concrete backend.

Common situations: Custom sandbox backends that implemented file ops but not execution; passing the abstract protocol where a concrete backend is expected; mixed deepagents/backend package versions where the backend predates the `timeout` kwarg contract.

Related errors


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