Skip to content

Dimension 1: Hermes Agent Memory Provider Ecosystem

The Comparison Table (8 Providers)

Provider Storage Cost Tools Dependencies Unique Feature
Honcho Cloud Paid 5 honcho-ai Dialectic user modeling + session-scoped context
OpenViking Self-hosted Free 5 openviking + server Filesystem hierarchy + tiered loading
Mem0 Cloud Paid 3 mem0ai Server-side LLM extraction
Hindsight Cloud/Local Free/Paid 3 hindsight-client Knowledge graph + reflect synthesis
Holographic Local Free 2 None HRR algebra + trust scoring
RetainDB Cloud $20/mo 5 requests Delta compression
ByteRover Local/Cloud Free/Paid 3 brv CLI Pre-compression extraction
Supermemory Cloud Paid 4 supermemory Context fencing + session graph ingest + multi-container

How Hermes Memory Providers Work

When a memory provider is active, Hermes automatically: 1. Injects provider context into the system prompt (what the provider knows) 2. Prefetches relevant memories before each turn (background, non-blocking) 3. Syncs conversation turns to the provider after each response 4. Extracts memories on session end (for providers that support it) 5. Mirrors built-in memory writes to the external provider 6. Adds provider-specific tools so the agent can search, store, and manage memories

The built-in memory (MEMORY.md / USER.md) continues to work exactly as before. The external provider is additive. Only one external provider can be active at a time.

The MemoryProvider Protocol (ABC)

from agent.memory_provider import MemoryProvider

class MyMemoryProvider(MemoryProvider):
    @property
    def name(self) -> str:
        return "my-provider"

    def is_available(self) -> bool:
        """Check if this provider can activate. NO network calls."""
        return bool(os.environ.get("MY_API_KEY"))

    def initialize(self, session_id: str, **kwargs) -> None:
        """Called once at agent startup."""
        self._api_key = os.environ.get("MY_API_KEY", "")
        self._session_id = session_id

    def sync_turn(self, user_message, assistant_response, **kwargs) -> None:
        """Sync conversation turn to provider"""
        ...

    def prefetch(self, query: str, **kwargs) -> str | None:
        """Prefetch relevant memories before turn"""
        ...

def register(ctx):
    ctx.register_memory_provider(MyMemoryProvider())

Directory structure:

plugins/memory/<name>/
  __init__.py      # MemoryProvider implementation + register() entry point
  plugin.yaml      # Metadata (name, description, hooks)
  README.md        # Setup instructions, config reference, tools

Profile Isolation

Each provider's data is isolated per profile: - Local storage providers (Holographic, ByteRover) use $HERMES_HOME/ paths which differ per profile - Config file providers (Honcho, Mem0, Hindsight, Supermemory) store config in $HERMES_HOME/ so each profile has its own credentials - Cloud providers (RetainDB) auto-derive profile-scoped project names - Env var providers (OpenViking) are configured via each profile's .env file