langchain-ai/deepagents · error · NotImplementedError

NotImplementedError raised by abstract `grep` (backend does

Error message

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

What it means

The base Backend class defines `grep` as an abstract method raising NotImplementedError; subclasses must implement content search to support the grep tool. Calling `grep` on a backend without an override raises this error. `_grep_backend` (the middleware path backing the grep tool) invokes it, so agents attached to such a backend fail on any grep request.

Source

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

                matches are returned; if more exist the search stops and the
                result is flagged with `GrepResult.truncated=True`. Exactly
                `max_count` matches with none dropped is reported complete
                (`truncated=False`). Interpreted as a total cap, not a per-file
                cap.

        Examples:
            - `'*.py'` - only search Python files
            - `'**/*.txt'` - search all `.txt` files recursively
            - `'src/**/*.js'` - search JS files under src/
            - `'test[0-9].txt'` - search `test0.txt`, `test1.txt`, etc.

        Returns:
            `GrepResult` with matches or error.

        Raises:
            NotImplementedError: If the backend does not implement `grep`.
        """
        raise NotImplementedError

    async def agrep(
        self,
        pattern: str,
        path: str | None = None,
        glob: str | None = None,
        *,
        max_count: int | None = None,
    ) -> "GrepResult":
        """Async version of `grep`.

        Wraps the sync call with an async timeout as a safety net. The timeout
        bounds how long the caller waits; it does not stop the worker thread
        created by `asyncio.to_thread`.

        `max_count` is forwarded when the concrete `grep` accepts it (so the
        search can bound itself); backends that don't accept it run uncapped and
        are trimmed afterward. Either way the return value is always passed

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Implement `grep(self, pattern, path=None, glob=None, ...) -> GrepResult` in your backend subclass (regex or literal search over readable files).
  2. If search is intentionally unsupported, have grep return a GrepResult with an error field instead of raising, and disable the grep tool for the agent.
  3. Use or compose with a backend that implements grep (e.g. filesystem backend) when possible.

Example fix

// before
class ApiBackend(Backend):
    def read(self, file_path, offset=0, limit=2000): ...
    # no grep -> agent grep tool raises NotImplementedError
// after
class ApiBackend(Backend):
    def read(self, file_path, offset=0, limit=2000): ...
    def grep(self, pattern, path=None, glob=None, **kwargs):
        return search_remote_files(pattern, path=path, glob=glob)
Defensive patterns

Strategy: try-catch

Validate before calling

if type(backend).grep is Backend.grep:
    raise RuntimeError('backend does not implement grep; disable the grep tool or switch backends')

Type guard

def supports_grep(backend) -> bool:
    return type(backend).grep is not Backend.grep

Try / catch

try:
    result = backend.grep(pattern, path=path)
except NotImplementedError:
    return GrepResult(matches=[], error='grep not supported by this backend')

Prevention

When it happens

Trigger: Agent issues a grep tool call against a custom backend that implements read/write but not grep; direct call backend.grep(pattern) on a partial subclass or on Backend itself.

Common situations: Custom object-store or database backends that skip search; stub backends in tests when the agent unexpectedly calls grep; missing override after renaming during a refactor.

Related errors


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