bytedance/deer-flow · error · NotImplementedError

search not supported by

Error message

search not supported by {type(self).__name__}

What it means

The base MemoryManager.search() deliberately raises NotImplementedError naming the backend class: search is an optional capability, and only backends that override search() AND set supports_search=True advertise it. This default exists so unsupported retrieval fails loudly and immediately instead of silently returning empty results that would look like 'no memories found'.

Solutions

  1. Check the backend's supports_search ClassVar before calling search()
  2. Switch to a retrieval-capable backend ( DeerMem default file storage or honcho implement search) if you need programmatic search
  3. In custom backends, override search() and set supports_search=True

Example fix

# before
results = manager.search('user preferences')

# after
results = manager.search('user preferences') if type(manager).supports_search else []
Defensive patterns

Strategy: type-guard

Validate before calling

from deerflow.agents.memory.manager import MemoryManager
if type(manager).search is MemoryManager.search:
    return []  # backend has no retrieval capability; skip the call
return manager.search(query, top_k=5, user_id=user)

Type guard

def backend_can_search(manager) -> bool:
    from deerflow.agents.memory.manager import MemoryManager
    return type(manager).supports_search is True and type(manager).search is not MemoryManager.search

Try / catch

try:
    results = manager.search(query, user_id=user)
except NotImplementedError:
    results = []  # retrieval unsupported on this backend; degrade gracefully

Prevention

When it happens

Trigger: Calling manager.search(query, ...) on a backend that did not override search (e.g. the noop backend, or a custom backend in middleware mode). In supported configurations the mode='tool' instantiation validator (error 636) blocks this earlier; direct calls (e.g. custom code, /api/memory search endpoints) can still reach it.

Common situations: Custom integration code calling search() unconditionally across backends; tool-mode attempts on a passive-only backend that slipped past construction (e.g. constructed directly instead of via the validating path).

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/4c70fe1a9521632c. Report an issue: GitHub.

Appendix: source

Thrown at backend/packages/harness/deerflow/agents/memory/manager.py:281

        """
        self.add(thread_id, messages, agent_name=agent_name, user_id=user_id)

    def search(
        self,
        query: str,
        top_k: int = 5,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
        category: str | None = None,
    ) -> list[dict[str, Any]]:
        """Search the bucket's memory for facts matching ``query``; return up to
        ``top_k`` ranked by relevance. ``category`` (optional) filters BEFORE the
        ``top_k`` slice so a category-scoped search is not starved by other
        categories' higher-ranked facts. Default: unsupported (raise); backends
        with retrieval override AND set ``supports_search = True`` (required for
        ``mode='tool'``)."""
        raise NotImplementedError(f"search not supported by {type(self).__name__}")

    def get_memory(
        self,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
    ) -> dict[str, Any]:
        """Return the full memory document for the bucket. Default: unsupported."""
        raise NotImplementedError(f"get_memory not supported by {type(self).__name__}")

    def delete_memory(
        self,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
    ) -> None:
        """Delete the entire memory document for the bucket. Default: unsupported
        (dead contract -- zero callers)."""

View on GitHub (pinned to 1dd6ba1acb)