How Hermes Agent Implements Memory and User Modeling Using Honcho

Hermes Agent implements memory and user modeling using Honcho by creating AI-native sessions per chat, synchronizing conversation history to a long-term memory service, prefetching distilled user representations into system prompts, and exposing a query_user_context tool for dynamic retrieval.

The NousResearch/hermes-agent repository augments its built-in SQLite session store with Honcho, an AI-native long-term memory service. When configured, Hermes Agent automatically manages memory synchronization, user modeling, and contextual retrieval through three core modules: honcho_integration/session.py, tools/honcho_tools.py, and run_agent.py.

Honcho Session Architecture and Initialization

Session Creation and Peer Configuration

When Hermes Agent receives a new channel-chat identifier, the HonchoSessionManager.get_or_create() method in honcho_integration/session.py initializes a local wrapper and corresponding Honcho session. The system creates distinct peers for the user and assistant:


# From honcho_integration/session.py

user_peer_id = self._sanitize_id(self._config.peer_name or f"user-{channel}-{chat_id}")
assistant_peer_id = self._config.ai_peer if self._config else "hermes-assistant"
honcho_session_id = self._sanitize_id(key)

user_peer = self._get_or_create_peer(user_peer_id)
assistant_peer = self._get_or_create_peer(assistant_peer_id)

honcho_session, existing_messages = self._get_or_create_honcho_session(
    honcho_session_id, user_peer, assistant_peer)

ID Sanitization and Peer Setup

The _sanitize_id() function ensures all identifiers conform to Honcho's requirements (^[a-zA-Z0-9_-]+$). The SDK call session.add_peers() configures observation rules where the user peer observes both itself and the assistant, while the assistant only observes the user. This dialectic setup enables Honcho to build a semantic user model through peer interactions.

Synchronizing Conversation History to Honcho

Message Sync Implementation

The HonchoSessionManager.save() method handles bidirectional synchronization. It extracts unsynced messages from the local cache and pushes them to Honcho:


# From honcho_integration/session.py

new_messages = [m for m in session.messages if not m.get("_synced")]
honcho_messages = [
    (user_peer if msg["role"] == "user" else assistant_peer).message(msg["content"])
    for msg in new_messages
]
honcho_session.add_messages(honcho_messages)

Idempotent Sync Guarantees

After successful upload, each message receives a "_synced": True flag. This ensures idempotent synchronization—running the save operation multiple times will not create duplicate entries in Honcho's long-term memory store.

Prefetching User Context for System Prompts

Semantic User Representation

The get_prefetch_context() method in honcho_integration/session.py performs a single Honcho context() call with semantic search against the user's message. It returns two critical components:

  • Representation: A concise textual summary of the user's persona and goals.
  • Card: A structured list of salient facts from the peer card.

# From honcho_integration/session.py

ctx = honcho_session.context(
    summary=False,
    tokens=self._context_tokens,
    peer_target=session.user_peer_id,
    search_query=user_message,
)
return {"representation": ctx.peer_representation or "", "card": "\n".join(ctx.peer_card or [])}

Context Injection in run_agent.py

In run_agent.py, the _honcho_prefetch() method retrieves this context and injects it into the system prompt:


# From run_agent.py

def _honcho_prefetch(self, user_message: str) -> str:
    if not self._honcho or not self._honcho_session_key:
        return ""
    ctx = self._honcho.get_prefetch_context(self._honcho_session_key, user_message)
    parts = [ctx.get("representation", ""), ctx.get("card", "")]
    return "# Honcho User Context\n" + "\n\n".join(p for p in parts if p)

This ensures the LLM receives up-to-date user context at the start of every turn.

Dynamic User Modeling with query_user_context

Tool Registration and Schema

The tools/honcho_tools.py file registers the query_user_context tool, making it available to the LLM for dynamic retrieval:


# From tools/honcho_tools.py

registry.register(
    name="query_user_context",
    toolset="honcho",
    schema=HONCHO_TOOL_SCHEMA,
    handler=_handle_query_user_context,
    check_fn=_check_honcho_available,
)

The tool schema accepts a single parameter: query (a natural-language question about the user).

Dialectic Retrieval via User Peer

When invoked, the handler calls HonchoSessionManager.get_user_context():


# From honcho_integration/session.py

def get_user_context(self, session_key: str, query: str) -> str:
    session = self._sessions.get(session_key)
    if not session:
        return "No active Honcho session found."
    user_peer = self._get_or_create_peer(session.user_peer_id)
    return user_peer.chat(query)

This executes a dialectic chat query against the Honcho user peer, allowing the model to ask specific questions like "What are the user's top three interests?" and receive synthesized answers based on the accumulated memory.

Migrating Legacy Memory Files

When Honcho is enabled mid-conversation, honcho_integration/session.py provides migrate_local_history() and migrate_memory_files() to preserve existing context. These methods upload prior transcripts as prior_history.txt and migrate local MEMORY.md and USER.md files into Honcho's long-term store, ensuring zero knowledge loss during the transition.

Summary

  • Hermes Agent integrates Honcho through honcho_integration/session.py, tools/honcho_tools.py, and hooks in run_agent.py.
  • Session management creates AI-native Honcho sessions with sanitized IDs and configured peer observation rules.
  • Synchronization pushes local messages to Honcho after every turn using idempotent sync with _synced flags.
  • Prefetching retrieves semantic user representations and peer cards to inject into system prompts automatically.
  • Dynamic queries expose the query_user_context tool, allowing the LLM to perform dialectic retrieval against the user peer.
  • Migration utilities preserve legacy local memory when upgrading to Honcho.

Frequently Asked Questions

How does Hermes Agent handle Honcho session IDs?

Hermes Agent sanitizes all session identifiers using the _sanitize_id() method in honcho_integration/session.py, ensuring they match Honcho's required pattern of alphanumeric characters, underscores, and hyphens (^[a-zA-Z0-9_-]+$). This prevents validation errors when creating sessions with complex channel identifiers like telegram:123456.

What is the difference between prefetch context and query_user_context?

Prefetch context operates automatically at the start of each turn via _honcho_prefetch() in run_agent.py, retrieving a semantic summary and peer card to inject into the system prompt. query_user_context is a dynamic tool registered in tools/honcho_tools.py that the LLM can explicitly invoke mid-conversation to ask specific questions about the user, triggering a dialectic chat query against the Honcho user peer.

How does the agent ensure no duplicate messages are synced to Honcho?

The HonchoSessionManager.save() method in honcho_integration/session.py filters messages using the _synced flag, only selecting entries where not m.get("_synced"). After successfully uploading to Honcho via honcho_session.add_messages(), it marks each message with "_synced": True, making subsequent save operations idempotent and preventing duplicate entries in the long-term memory store.

Can I use Hermes Agent memory features without Honcho?

Yes, Hermes Agent maintains a fallback architecture using SQLite-based session stores and file-based memory (MEMORY.md, USER.md) when Honcho is not configured. However, enabling Honcho in ~/.honcho/config.json upgrades the system to AI-native long-term memory with semantic search, dialectic user modeling, and automatic context prefetching, providing significantly richer user modeling capabilities than the local file-based approach.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →