langchain-ai/deepagents · error · NotImplementedError

NotImplementedError raised by abstract `download_files` (bac

Error message

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

What it means

`BackendProtocol.download_files` is an optional bulk-download API whose base-class stub raises `NotImplementedError`. Backends that don't override it raise this when called. Internally, skill loading (`load_namespaced_skills`, `_list_skills_with_errors`) and output offloading (`_offload_to_backend`) depend on it, so those features fail on backends without download support.

Source

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

        return await asyncio.to_thread(self.upload_files, files)

    def download_files(self, paths: list[str]) -> list[FileDownloadResponse]:
        """Download multiple files from the sandbox.

        This API is designed to allow developers to use it either directly or
        by exposing it to LLMs via custom tools.

        Args:
            paths: List of file paths to download.

        Returns:
            List of `FileDownloadResponse` objects, one per input path.

                Response order matches input order (`response[i] for paths[i]`).

                Check the error field to determine success/failure per file.
        """
        raise NotImplementedError

    async def adownload_files(self, paths: list[str]) -> list[FileDownloadResponse]:
        """Async version of download_files."""
        return await asyncio.to_thread(self.download_files, paths)


@dataclass
class ExecuteResponse:
    """Result of code execution.

    Simplified schema optimized for LLM consumption.
    """

    output: str
    """Combined stdout and stderr output of the executed command."""

    exit_code: int | None = None
    """The process exit code.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Switch to or configure a backend implementing `download_files` (e.g. a sandbox backend)
  2. Check capability before calling: `type(backend).download_files is not BackendProtocol.download_files`
  3. Catch NotImplementedError around skill-loading/offload code paths and degrade gracefully (skip skills/offload)
  4. Implement `download_files` in your custom backend subclass

Example fix

// before
responses = backend.download_files(['/app/out.log'])

// after
if type(backend).download_files is not BackendProtocol.download_files:
    responses = [FileDownloadResponse(path='/app/out.log', error='download unsupported')]
else:
    responses = backend.download_files(['/app/out.log'])
Defensive patterns

Strategy: validation

Validate before calling

def supports_download(backend) -> bool:
    return type(backend).download_files is not BackendProtocol.download_files

if supports_download(backend):
    responses = backend.download_files(paths)
else:
    responses = [FileDownloadResponse(path=p, error='download unsupported') for p in paths]

Type guard

def is_download_capable(backend) -> bool:
    return type(backend).download_files is not BackendProtocol.download_files

Try / catch

try:
    responses = backend.download_files(paths)
except NotImplementedError:
    logger.warning('Backend %s lacks download_files; skipping', type(backend).__name__)
    responses = []

Prevention

When it happens

Trigger: Calling `backend.download_files([...])` or `adownload_files` on a backend without an override; invoking namespace skill loading or output offloading with a backend that lacks bulk downloads.

Common situations: Running agents with a minimal custom backend or one configured for execution-only use; composite backends routing to a child that can't download; expecting sandbox file transfer APIs on a state-backed agent.

Related errors


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