bytedance/deer-flow · error · NotImplementedError

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

Error message

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

What it means

MemoryManager.create_fact raises NotImplementedError as the base-class default for the manual fact-creation API. The method is part of the optional per-fact CRUD contract ('manually add one fact', returning (memory_data, fact_id)); only document-style backends that store discrete facts locally — DeerMem — implement it. Backends that delegate representation-building to a remote service (honcho), an external store (mem0, openviking), or that store nothing (noop) intentionally do not, so any direct create_fact call against them raises.

Source

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

        agent_name: str | None = None,
    ) -> dict[str, Any]:
        """Drop the cached memory document and reload from storage. Default:
        unsupported (callers fall back to :meth:`get_memory`). Backends with a
        cache override."""
        raise NotImplementedError(f"reload_memory not supported by {type(self).__name__}")

    def create_fact(
        self,
        content: str,
        category: str = "context",
        confidence: float = 0.5,
        *,
        agent_name: str | None = None,
        user_id: str | None = None,
    ) -> tuple[dict[str, Any], str | None]:
        """Manually add one fact. Returns ``(memory_data, fact_id)`` -- ``fact_id``
        is None when a storage cap evicted the just-added fact. Default: unsupported."""
        raise NotImplementedError(f"create_fact not supported by {type(self).__name__}")

    def delete_fact(
        self,
        fact_id: str,
        *,
        agent_name: str | None = None,
        user_id: str | None = None,
    ) -> dict[str, Any]:
        """Delete one fact by id. Default: unsupported."""
        raise NotImplementedError(f"delete_fact not supported by {type(self).__name__}")

    def update_fact(
        self,
        fact_id: str,
        content: str | None = None,
        category: str | None = None,
        confidence: float | None = None,
        *,

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Use a backend that implements fact CRUD: set memory.manager_class: deermem (the default file backend).
  2. For remote backends, add facts through the backend's own supported write path (e.g. middleware-mode conversation capture, or the backend's native API) instead of create_fact.
  3. Custom backend authors: override create_fact (and delete_fact/update_fact) on the MemoryManager subclass.
  4. Gate UI/script features on backend capability rather than calling create_fact unconditionally.

Example fix

# before
memory, fact_id = manager.create_fact("User prefers dark mode", category="preference")

# after
if not hasattr(type(manager), "create_fact") or type(manager).create_fact is MemoryManager.create_fact:
    raise UnsupportedOperation("backend does not support manual fact creation")
memory, fact_id = manager.create_fact("User prefers dark mode", category="preference")
Defensive patterns

Strategy: type-guard

Validate before calling

from deerflow.agents.memory.manager import MemoryManager

def supports_fact_crud(manager: MemoryManager) -> bool:
    return type(manager).create_fact is not MemoryManager.create_fact

Type guard

def supports_fact_crud(manager: MemoryManager) -> bool:
    """True when the backend implements manual per-fact creation."""
    return type(manager).create_fact is not MemoryManager.create_fact

Try / catch

try:
    memory, fact_id = manager.create_fact(content, user_id=uid)
except NotImplementedError as e:
    # permanent capability gap: do not retry; use backend-supported write path
    raise UnsupportedMemoryOperation(str(e)) from e

Prevention

When it happens

Trigger: Calling MemoryManager.create_fact(content, category=..., confidence=..., agent_name=..., user_id=...) — via the memory tool API, the /api/memory management surface, or directly — while memory.manager_class is noop, mem0, honcho, or openviking. Also fires in tool mode (memory.mode: tool) if the memory_add tool is routed to a backend without the primitive.

Common situations: Enabling memory.mode: tool with a remote backend selected in config.yaml; porting scripts that seed facts via create_fact from a deermem deployment to a mem0/honcho deployment; unit tests asserting CRUD behavior but running against the noop manager.

Related errors


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