honcho-integration-spec

Comparison of Hermes Agent vs. openclaw-honcho — and a porting spec for bringing Hermes patterns into other Honcho integrations.

hermes-agent / openclaw-honcho Python + TypeScript 2026-03-09

Overview

Two independent Honcho integrations have been built for two different agent runtimes: Hermes Agent (Python, baked into the runner) and openclaw-honcho (TypeScript plugin via hook/tool API). Both use the same Honcho peer paradigm — dual peer model, session.context(), peer.chat() — but they made different tradeoffs at every layer.

This document maps those tradeoffs and defines a porting spec: a set of Hermes-originated patterns, each stated as an integration-agnostic interface, that any Honcho integration can adopt regardless of runtime or language.

Scope Both integrations work correctly today. This spec is about the delta — patterns in Hermes that are worth propagating and patterns in openclaw-honcho that Hermes should eventually adopt. The spec is additive, not prescriptive.

Architecture comparison

Hermes: baked-in runner

Honcho is initialised directly inside AIAgent.__init__. There is no plugin boundary. Session management, context injection, async prefetch, and CLI surface are all first-class concerns of the runner. Context is injected once per session (baked into _cached_system_prompt) and never re-fetched mid-session — this maximises prefix cache hits at the LLM provider.

%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1f3150', 'primaryTextColor': '#c9d1d9', 'primaryBorderColor': '#3d6ea5', 'lineColor': '#3d6ea5', 'secondaryColor': '#162030', 'tertiaryColor': '#11151c' }}}%% flowchart TD U["user message"] --> P["_honcho_prefetch()
(reads cache — no HTTP)"] P --> SP["_build_system_prompt()
(first turn only, cached)"] SP --> LLM["LLM call"] LLM --> R["response"] R --> FP["_honcho_fire_prefetch()
(daemon threads, turn end)"] FP --> C1["prefetch_context() thread"] FP --> C2["prefetch_dialectic() thread"] C1 --> CACHE["_context_cache / _dialectic_cache"] C2 --> CACHE style U fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style P fill:#1f3150,stroke:#3d6ea5,color:#c9d1d9 style SP fill:#1f3150,stroke:#3d6ea5,color:#c9d1d9 style LLM fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style R fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style FP fill:#2a1a40,stroke:#bc8cff,color:#c9d1d9 style C1 fill:#2a1a40,stroke:#bc8cff,color:#c9d1d9 style C2 fill:#2a1a40,stroke:#bc8cff,color:#c9d1d9 style CACHE fill:#11151c,stroke:#484f58,color:#6e7681

openclaw-honcho: hook-based plugin

The plugin registers hooks against OpenClaw's event bus. Context is fetched synchronously inside before_prompt_build on every turn. Message capture happens in agent_end. The multi-agent hierarchy is tracked via subagent_spawned. This model is correct but every turn pays a blocking Honcho round-trip before the LLM call can begin.

%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1f3150', 'primaryTextColor': '#c9d1d9', 'primaryBorderColor': '#3d6ea5', 'lineColor': '#3d6ea5', 'secondaryColor': '#162030', 'tertiaryColor': '#11151c' }}}%% flowchart TD U2["user message"] --> BPB["before_prompt_build
(BLOCKING HTTP — every turn)"] BPB --> CTX["session.context()"] CTX --> SP2["system prompt assembled"] SP2 --> LLM2["LLM call"] LLM2 --> R2["response"] R2 --> AE["agent_end hook"] AE --> SAVE["session.addMessages()
session.setMetadata()"] style U2 fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style BPB fill:#3a1515,stroke:#f47067,color:#c9d1d9 style CTX fill:#3a1515,stroke:#f47067,color:#c9d1d9 style SP2 fill:#1f3150,stroke:#3d6ea5,color:#c9d1d9 style LLM2 fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style R2 fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style AE fill:#162030,stroke:#3d6ea5,color:#c9d1d9 style SAVE fill:#11151c,stroke:#484f58,color:#6e7681

Diff table

Dimension Hermes Agent openclaw-honcho
Context injection timing Once per session (cached). Zero HTTP on response path after turn 1. Every turn, blocking. Fresh context per turn but adds latency.
Prefetch strategy Daemon threads fire at turn end; consumed next turn from cache. None. Blocking call at prompt-build time.
Dialectic (peer.chat) Prefetched async; result injected into system prompt next turn. On-demand via honcho_recall / honcho_analyze tools.
Reasoning level Dynamic: scales with message length. Floor = config default. Cap = "high". Fixed per tool: recall=minimal, analyze=medium.
Memory modes user_memory_mode / agent_memory_mode: hybrid / honcho / local. None. Always writes to Honcho.
Write frequency async (background queue), turn, session, N turns. After every agent_end (no control).
AI peer identity observe_me=True, seed_ai_identity(), get_ai_representation(), SOUL.md → AI peer. Agent files uploaded to agent peer at setup. No ongoing self-observation seeding.
Context scope User peer + AI peer representation, both injected. User peer (owner) representation + conversation summary. peerPerspective on context call.
Session naming per-directory / global / manual map / title-based. Derived from platform session key.
Multi-agent Single-agent only. Parent observer hierarchy via subagent_spawned.
Tool surface Single query_user_context tool (on-demand dialectic). 6 tools: session, profile, search, context (fast) + recall, analyze (LLM).
Platform metadata Not stripped. Explicitly stripped before Honcho storage.
Message dedup None (sends on every save cycle). lastSavedIndex in session metadata prevents re-sending.
CLI surface in prompt Management commands injected into system prompt. Agent knows its own CLI. Not injected.
AI peer name in identity Replaces "Hermes Agent" in DEFAULT_AGENT_IDENTITY when configured. Not implemented.
QMD / local file search Not implemented. Passthrough tools when QMD backend configured.
Workspace metadata Not implemented. agentPeerMap in workspace metadata tracks agent→peer ID.

Hermes patterns to port

Six patterns from Hermes are worth adopting in any Honcho integration. They are described below as integration-agnostic interfaces — the implementation will differ per runtime, but the contract is the same.

Patterns Hermes contributes

  • Async prefetch (zero-latency)
  • Dynamic reasoning level
  • Per-peer memory modes
  • AI peer identity formation
  • Session naming strategies
  • CLI surface injection

Patterns openclaw contributes back

  • lastSavedIndex dedup
  • Platform metadata stripping
  • Multi-agent observer hierarchy
  • peerPerspective on context()
  • Tiered tool surface (fast/LLM)
  • Workspace agentPeerMap

Spec: async prefetch

Problem

Calling session.context() and peer.chat() synchronously before each LLM call adds 200–800ms of Honcho round-trip latency to every turn. Users experience this as the agent "thinking slowly."

Pattern

Fire both calls as non-blocking background work at the end of each turn. Store results in a per-session cache keyed by session ID. At the start of the next turn, pop from cache — the HTTP is already done. First turn is cold (empty cache); all subsequent turns are zero-latency on the response path.

Interface contract

// TypeScript (openclaw / nanobot plugin shape)

interface AsyncPrefetch {
  // Fire context + dialectic fetches at turn end. Non-blocking.
  firePrefetch(sessionId: string, userMessage: string): void;

  // Pop cached results at turn start. Returns empty if cache is cold.
  popContextResult(sessionId: string): ContextResult | null;
  popDialecticResult(sessionId: string): string | null;
}

type ContextResult = {
  representation: string;
  card: string[];
  aiRepresentation?: string;  // AI peer context if enabled
  summary?: string;            // conversation summary if fetched
};

Implementation notes

openclaw-honcho adoption

Move session.context() from before_prompt_build to a post-agent_end background task. Store result in state.contextCache. In before_prompt_build, read from cache instead of calling Honcho. If cache is empty (turn 1), inject nothing — the prompt is still valid without Honcho context on the first turn.

Spec: dynamic reasoning level

Problem

Honcho's dialectic endpoint supports reasoning levels from minimal to max. A fixed level per tool wastes budget on simple queries and under-serves complex ones.

Pattern

Select the reasoning level dynamically based on the user's message. Use the configured default as a floor. Bump by message length. Cap auto-selection at high — never select max automatically.

Interface contract

// Shared helper — identical logic in any language

const LEVELS = ["minimal", "low", "medium", "high", "max"];

function dynamicReasoningLevel(
  query: string,
  configDefault: string = "low"
): string {
  const baseIdx = Math.max(0, LEVELS.indexOf(configDefault));
  const n = query.length;
  const bump = n < 120 ? 0 : n < 400 ? 1 : 2;
  return LEVELS[Math.min(baseIdx + bump, 3)]; // cap at "high" (idx 3)
}

Config key

Add a dialecticReasoningLevel config field (string, default "low"). This sets the floor. Users can raise or lower it. The dynamic bump always applies on top.

openclaw-honcho adoption

Apply in honcho_recall and honcho_analyze: replace the fixed reasoningLevel with the dynamic selector. honcho_recall should use floor "minimal" and honcho_analyze floor "medium" — both still bump with message length.

Spec: per-peer memory modes

Problem

Users want independent control over whether user context and agent context are written locally, to Honcho, or both. A single memoryMode shorthand is not granular enough.

Pattern

Three modes per peer: hybrid (write both local + Honcho), honcho (Honcho only, disable local files), local (local files only, skip Honcho sync for this peer). Two orthogonal axes: user peer and agent peer.

Config schema

// ~/.openclaw/openclaw.json  (or ~/.nanobot/config.json)
{
  "plugins": {
    "openclaw-honcho": {
      "config": {
        "apiKey": "...",
        "memoryMode": "hybrid",          // shorthand: both peers
        "userMemoryMode": "honcho",       // override for user peer
        "agentMemoryMode": "hybrid"       // override for agent peer
      }
    }
  }
}

Resolution order

  1. Per-peer field (userMemoryMode / agentMemoryMode) — wins if present.
  2. Shorthand memoryMode — applies to both peers as default.
  3. Hardcoded default: "hybrid".

Effect on Honcho sync

Spec: AI peer identity formation

Problem

Honcho builds the user's representation organically by observing what the user says. The same mechanism exists for the AI peer — but only if observe_me=True is set for the agent peer. Without it, the agent peer accumulates nothing and Honcho's AI-side model never forms.

Additionally, existing persona files (SOUL.md, IDENTITY.md) should seed the AI peer's Honcho representation at first activation, rather than waiting for it to emerge from scratch.

Part A: observe_me=True for agent peer

// TypeScript — in session.addPeers() call
await session.addPeers([
  [ownerPeer.id, { observeMe: true,  observeOthers: false }],
  [agentPeer.id, { observeMe: true,  observeOthers: true  }], // was false
]);

This is a one-line change but foundational. Without it, Honcho's AI peer representation stays empty regardless of what the agent says.

Part B: seedAiIdentity()

async function seedAiIdentity(
  session: HonchoSession,
  agentPeer: Peer,
  content: string,
  source: string
): Promise<boolean> {
  const wrapped = [
    `<ai_identity_seed>`,
    `<source>${source}</source>`,
    ``,
    content.trim(),
    `</ai_identity_seed>`,
  ].join("\n");

  await agentPeer.addMessage("assistant", wrapped);
  return true;
}

Part C: migrate agent files at setup

During openclaw honcho setup, upload agent-self files (SOUL.md, IDENTITY.md, AGENTS.md, BOOTSTRAP.md) to the agent peer using seedAiIdentity() instead of session.uploadFile(). This routes the content through Honcho's observation pipeline rather than the file store.

Part D: AI peer name in identity

When the agent has a configured name (non-default), inject it into the agent's self-identity prefix. In OpenClaw this means adding to the injected system prompt section:

// In context hook return value
return {
  systemPrompt: [
    agentName ? `You are ${agentName}.` : "",
    "## User Memory Context",
    ...sections,
  ].filter(Boolean).join("\n\n")
};

CLI surface: honcho identity subcommand

openclaw honcho identity <file>    # seed from file
openclaw honcho identity --show    # show current AI peer representation

Spec: session naming strategies

Problem

When Honcho is used across multiple projects or directories, a single global session means every project shares the same context. Per-directory sessions provide isolation without requiring users to name sessions manually.

Strategies

StrategySession keyWhen to use
per-directorybasename of CWDDefault. Each project gets its own session.
globalfixed string "global"Single cross-project session.
manual mapuser-configured per pathsessions config map overrides directory basename.
title-basedsanitized session titleWhen agent supports named sessions; title set mid-conversation.

Config schema

{
  "sessionStrategy": "per-directory",   // "per-directory" | "global"
  "sessionPeerPrefix": false,            // prepend peer name to session key
  "sessions": {                            // manual overrides
    "/home/user/projects/foo": "foo-project"
  }
}

CLI surface

openclaw honcho sessions              # list all mappings
openclaw honcho map <name>           # map cwd to session name
openclaw honcho map                   # no-arg = list mappings

Resolution order: manual map wins → session title → directory basename → platform key.

Spec: CLI surface injection

Problem

When a user asks "how do I change my memory settings?" or "what Honcho commands are available?" the agent either hallucinates or says it doesn't know. The agent should know its own management interface.

Pattern

When Honcho is active, append a compact command reference to the system prompt. The agent can cite these commands directly instead of guessing.

// In context hook, append to systemPrompt
const honchoSection = [
  "# Honcho memory integration",
  `Active. Session: ${sessionKey}. Mode: ${mode}.`,
  "Management commands:",
  "  openclaw honcho status                    — show config + connection",
  "  openclaw honcho mode [hybrid|honcho|local] — show or set memory mode",
  "  openclaw honcho sessions                  — list session mappings",
  "  openclaw honcho map <name>                — map directory to session",
  "  openclaw honcho identity [file] [--show]  — seed or show AI identity",
  "  openclaw honcho setup                     — full interactive wizard",
].join("\n");
Keep it compact. This section is injected every turn. Keep it under 300 chars of context. List commands, not explanations — the agent can explain them on request.

openclaw-honcho checklist

Ordered by impact. Each item maps to a spec section above.

Already done in openclaw-honcho (do not re-implement): lastSavedIndex dedup, platform metadata stripping, multi-agent parent observer hierarchy, peerPerspective on context(), tiered tool surface (fast/LLM), workspace agentPeerMap, QMD passthrough, self-hosted Honcho support.

nanobot-honcho checklist

nanobot-honcho is a greenfield integration. Start from openclaw-honcho's architecture (hook-based, dual peer) and apply all Hermes patterns from day one rather than retrofitting. Priority order:

Phase 1 — core correctness

Phase 2 — configuration

Phase 3 — tools and CLI