Skip to content

Feat: make mnemon plugin content caps configurable - #11

Merged
gitricko merged 2 commits into
mainfrom
cap-adjustment
May 21, 2026
Merged

gitricko merged 2 commits into
mainfrom
cap-adjustment

Conversation

@gitricko

@gitricko gitricko commented May 21, 2026

Copy link
Copy Markdown
Owner

Feat: make mnemon plugin content caps configurable; raise mirror ceiling to 8000

Problem

The mnemon Hermes plugin had two hardcoded character caps that were unnecessarily
conservative — both below the mnemon binary's own content too long (max 8000)
error message:

Hook Hardcoded cap mnemon binary ceiling Gap
on_pre_compress 600 chars 8 000 chars 7 400 chars wasted
on_memory_write 2 500 chars 8 000 chars 5 500 chars wasted

Other Hermes memory plugins (Mem0, RetainDB, Hindsight, Honcho) either send raw
content or rely on their backends for chunking — Mnemon was the only plugin with
redundant content truncation that had nothing to do with any actual constraint.

Users who wanted to store longer insights were silently losing information with
no way to opt in.

Design rationale: why the limits differ from the binary ceiling

on_pre_compress — kept at 600 (configurable, not the binary ceiling)

The on_pre_compress hook fires at the end of every turn and stores the last 10
substantive messages as individual graph nodes under category context. Its purpose
is to be a compression breadcrumb trail — lightweight, scannable after-images of
recent exchanges — so recall can still surface relevant context after the full
conversation window has been compacted.

600 chars ≈ 3–4 sentences. For this hook that is a feature, not a bug:

  • Embedding quality. Short snippets produce tighter vector embeddings; a 600-char
    summary scores better against user queries than a 1 500-char chunk that averages
    away edge-case semantics.
  • Graph traversal cost. Each remember call creates a node with edges. More
    nodes from the same turn = more edges = marginally higher traversal cost per
    recall call.
  • Hook frequency. This runs once per turn. Slicing to a fixed cap keeps the hook
    cheap and predictable regardless of turn length.
  • Discard at the next compression. These breadcrumbs are superseded on the next
    on_pre_compress call. Investing 4 000 chars per turn for content that will be
    replaced next turn is wasted graph storage.

The mnemon binary's 8 000-char ceiling is an upper bound for a persistent node
that represents a lasting insight — exactly what on_memory_write captures. The
600-char cap for the transient compression hook reflects the different lifetime
semantics
, not a technical mismatch.

on_memory_write — default 8000 to match the binary ceiling

These are intentional, persistent memory writes (user preferences, decisions,
factual claims). They benefit from being as complete as the binary will accept. The
previous 2 500-char cap was a defensive guardrail from early prototyping that was
never revisited once the binary's own error path was confirmed. Setting it to 8000
removes that redundant truncation while keeping the plugin-level cap configurable so
users can opt lower if needed. Setting it to 0 removes it entirely and lets the
binary's own error become the sole gate.

30-char minimum — hard skip, not configurable

No memory plugin in the Hermes ecosystem (Mnemon, Honcho, Mem0, RetainDB,
Hindsight, Holographic, SuperMemory) makes the minimum content length configurable.
Single-word or two-word utterances ("ok", "sure", "done") carry negligible
signal and everyone agrees filtering them out is a quality gate, not a usability
restriction. It stays hardcoded.


Changes

mnemon/__init__.py

1. Config schema — two new keys (get_config_schema)

{
    "key": "max_compress_chars",
    "default": 600,
    ...
},
{
    "key": "max_mirror_chars",
    "default": 8000,
    ...
},

2. initialize() — load new keys from ~/.hermes/mnemon.json

self._max_compress_chars = int(plugin_config.get("max_compress_chars", 600))
self._max_mirror_chars   = int(plugin_config.get("max_mirror_chars", 8000))

3. on_pre_compress() — use self._max_compress_chars instead of literal 600

msg["content"][: self._max_compress_chars]

4. on_memory_write() — replace literal 2500 with configured cap + warning

if self._max_mirror_chars > 0 and len(content) > self._max_mirror_chars:
    logger.warning(
        "mnemon mirror: entry is %d chars; truncating to max_mirror_chars=%d. "
        "Set max_mirror_chars: 0 in the mnemon provider config to store full content.",
        len(content), self._max_mirror_chars,
    )
content[: self._max_mirror_chars] if self._max_mirror_chars > 0 else content

max_mirror_chars: 0 means no plugin-level cap; the mnemon binary's own
8 000-char guardrail (content too long (max 8000); consider chunking into multiple remember calls) remains the final gatekeeper.

5. _auto_remember() — documentation-only change

Added an inline comment explaining the 30-char noise filter. Behaviour unchanged.


tests/test_mnemon.py

test_get_config_schema — updated assertion from len(schema) == 1 to == 3
and added explicit key checks for the two new entries.

Default values (backwards compatible)

Config key Default What changed
max_compress_chars 600 No behavioural change; previously hardcoded, now configurable
max_mirror_chars 8000 Changed from 2500 → 8000 — aligns with mnemon binary ceiling

Configuration

Users override in ~/.hermes/mnemon.json (same file as the existing store key):

{
  "store": "my-store",
  "max_compress_chars": 1200,
  "max_mirror_chars": 0
}

Verification

$ cd /config/.hermes/_code/hermes-plugin-mnemon && pytest tests/ -v
============================= test session starts ==============================
collected 36 items
tests/test_mnemon.py ................................  [100%]
========================= 36 passed in 0.07s ==============================

Files changed

  • mnemon/__init__.py — +43 −6
  • tests/test_mnemon.py — +4 −1

Copilot AI review requested due to automatic review settings May 21, 2026 06:19
@gitricko gitricko changed the title dev Feat: make mnemon plugin content caps configurable May 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the Mnemon Hermes memory provider’s content truncation limits configurable and raises the default mirror truncation ceiling to align with the mnemon CLI’s apparent 8000-character limit.

Changes:

  • Added max_compress_chars and max_mirror_chars to the provider config schema and load them from mnemon.json during initialization.
  • Updated on_pre_compress and on_memory_write to use configurable caps (and added a truncation warning for mirror writes).
  • Updated the config schema test to account for the two new keys.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
mnemon/__init__.py Introduces configurable character caps for pre-compress storage and memory-write mirroring; increases default mirror cap and adds a truncation warning.
tests/test_mnemon.py Updates config schema assertions for the new configuration keys.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread mnemon/__init__.py
Comment on lines 316 to 321
def on_pre_compress(self, messages: list[dict]) -> str:
key_msgs = [m for m in messages if m.get("role") in ("assistant","user")
and len(m.get("content","")) > 80][-10:]
for msg in key_msgs:
self._remember_and_index(msg["content"][: 600],
self._remember_and_index(msg["content"][: self._max_compress_chars],
category="context", importance=2)
Comment thread mnemon/__init__.py
Comment on lines 160 to +180
# Load store config if it exists
store_config = None
if hermes_home:
config_file = Path(hermes_home) / "mnemon.json"
if config_file.exists():
try:
config_data = json.loads(config_file.read_text())
store_config = config_data.get("store")
except Exception as e:
logger.warning("Failed to load mnemon.json: %s", e)

# Load plugin-specific config (max_compress_chars, max_mirror_chars)
max_compress_chars = 600
max_mirror_chars = 8000
if hermes_home:
config_file = Path(hermes_home) / "mnemon.json"
if config_file.exists():
try:
plugin_data = json.loads(config_file.read_text())
max_compress_chars = int(plugin_data.get("max_compress_chars", 600))
max_mirror_chars = int(plugin_data.get("max_mirror_chars", 8000))
Comment thread mnemon/__init__.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@gitricko
gitricko merged commit ff61383 into main May 21, 2026
7 checks passed
@gitricko
gitricko deleted the cap-adjustment branch May 21, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants