Loading...
Loading...
Lossless Context Management plugin for Hermes Agent with DAG-based compression and drill-down tools
npx skill4agent add aradotso/hermes-skills hermes-lcm-context-managementSkill by ara.so — Hermes Skills collection.
lcm_greplcm_expandlcm_expand_query# General user plugin (all profiles)
git clone https://github.com/stephenschoettler/hermes-lcm \
~/.hermes/plugins/hermes-lcm
# Profile-specific install
git clone https://github.com/stephenschoettler/hermes-lcm \
~/.hermes/profiles/myprofile/plugins/hermes-lcmcd hermes-lcm
./scripts/install.sh
# Profile-specific
HERMES_PROFILE=myprofile ./scripts/install.shplugins:
enabled:
- hermes-lcm
context:
engine: lcm
# Keep compression enabled - LCM needs this gate
compression:
enabled: truehermes pluginshermes-lcmlcmlcm_greplcm_describelcm_expandlcm_expand_querylcm_statuslcm_doctorlcm_load_session~/.hermes/profiles/<profile>/lcm.db # Default pathRaw messages → Leaf summaries → Branch summaries → Rootlcm_greplcm_describelcm_expandlcm_expand_query# Compaction trigger (fraction of context window)
export LCM_CONTEXT_THRESHOLD=0.75
# Recent messages protected from compaction
export LCM_FRESH_TAIL_COUNT=64
# Raw backlog floor before leaf compaction
export LCM_LEAF_CHUNK_TOKENS=20000
# Enable dynamic chunk-sized leaf compaction
export LCM_DYNAMIC_LEAF_CHUNK_ENABLED=false
export LCM_DYNAMIC_LEAF_CHUNK_MAX=40000# DAG depth retained after /new (-1 all, 0 none)
export LCM_NEW_SESSION_RETAIN_DEPTH=2
# Exclude sessions from LCM storage (glob patterns)
export LCM_IGNORE_SESSION_PATTERNS="test-*,debug-*"
# Keep sessions read-only (glob patterns)
export LCM_STATELESS_SESSION_PATTERNS="readonly-*"
# Exclude messages by content regex (comma-separated)
export LCM_IGNORE_MESSAGE_PATTERNS="^SYSTEM:,^\[INTERNAL\]"# Store oversized payloads externally
export LCM_LARGE_OUTPUT_EXTERNALIZATION_ENABLED=true
export LCM_LARGE_OUTPUT_EXTERNALIZATION_THRESHOLD_CHARS=12000
# Compact already-externalized tool results
export LCM_LARGE_OUTPUT_TRANSCRIPT_GC_ENABLED=false# Override summarization model
export LCM_SUMMARY_MODEL=claude-3-5-sonnet-20241022
# Override expansion synthesis model
export LCM_EXPANSION_MODEL=gpt-4-turbo
export LCM_EXPANSION_CONTEXT_TOKENS=32000
# Timeouts
export LCM_SUMMARY_TIMEOUT_MS=60000
export LCM_EXPANSION_TIMEOUT_MS=120000# Custom database path
export LCM_DATABASE_PATH=/custom/path/lcm.db
# Enable slash commands
export LCM_ENABLE_SLASH_COMMAND=true
# Allow destructive doctor clean operations
export LCM_DOCTOR_CLEAN_APPLY_ENABLED=false
# Critical pressure bypass (0.0 = disabled)
export LCM_CRITICAL_BUDGET_PRESSURE_RATIO=0.0compaction_trigger = effective_context_window * LCM_CONTEXT_THRESHOLD| Context Window | Desired Trigger | Threshold | Use Case |
|---|---|---|---|
| 128K | 96K | 0.75 | Standard |
| 200K | 140K | 0.70 | Balanced |
| 400K | 240K | 0.60 | Long context |
| 1M | 250K | 0.25 | Cost-optimized |
| 1M | 400K | 0.40 | Balanced large |
| 1M | 600K | 0.60 | Max raw context |
# Cost-optimized: trigger at 300K tokens
export LCM_CONTEXT_THRESHOLD=0.30
# Balanced: trigger at 400K tokens
export LCM_CONTEXT_THRESHOLD=0.40
# Max context: trigger at 600K tokens
export LCM_CONTEXT_THRESHOLD=0.60# Agent calls this to check compression state
{
"tool": "lcm_status",
"params": {}
}# Search for keyword in raw messages
{
"tool": "lcm_grep",
"params": {
"pattern": "database schema",
"search_raw": true,
"search_summaries": false,
"max_results": 10
}
}
# Search summaries only
{
"tool": "lcm_grep",
"params": {
"pattern": "migration",
"search_raw": false,
"search_summaries": true,
"max_results": 5
}
}
# Filter by source (files/tools mentioned)
{
"tool": "lcm_grep",
"params": {
"pattern": "error",
"source_filter": "src/database.py",
"search_raw": true
}
}# Describe a specific summary node
{
"tool": "lcm_describe",
"params": {
"summary_id": "s_abc123"
}
}# Expand a summary to see its children
{
"tool": "lcm_expand",
"params": {
"summary_id": "s_abc123",
"max_children": 5,
"max_raw": 10
}
}
# Get raw messages with source filter
{
"tool": "lcm_expand",
"params": {
"summary_id": "s_abc123",
"source_filter": "config.py",
"max_raw": 20
}
}# Ask a question about compacted history
{
"tool": "lcm_expand_query",
"params": {
"query": "What database migrations were discussed earlier?",
"summary_id": "s_abc123", # optional: scope to subtree
"max_raw": 50
}
}LCM_EXPANSION_MODELLCM_EXPANSION_CONTEXT_TOKENS# Load previous session
{
"tool": "lcm_load_session",
"params": {
"session_id": "previous-session-abc123"
}
}# Check for issues
{
"tool": "lcm_doctor",
"params": {
"action": "check"
}
}
# Preview cleanup (dry run)
{
"tool": "lcm_doctor",
"params": {
"action": "clean_preview"
}
}
# Apply cleanup (requires LCM_DOCTOR_CLEAN_APPLY_ENABLED=true)
{
"tool": "lcm_doctor",
"params": {
"action": "clean_apply"
}
}LCM_ENABLE_SLASH_COMMAND=true# Check status
/lcm status
# Search
/lcm grep pattern search_raw=true
# Describe summary
/lcm describe summary_id=s_abc123
# Expand
/lcm expand summary_id=s_abc123 max_raw=20
# Query
/lcm query What was discussed about the API?
# Doctor
/lcm doctor check
/lcm doctor clean_preview# 1. Verify installation
hermes plugins
# 2. Send a test message to initialize session
hermes chat "Hello"
# 3. Check LCM status
hermes chat "Can you run lcm_status?"
# 4. Verify tools are available
# Agent should have access to lcm_grep, lcm_expand, etc.# Scenario: Agent forgot details about earlier discussion
# 1. Search for topic
{
"tool": "lcm_grep",
"params": {
"pattern": "API authentication",
"search_raw": true,
"search_summaries": true,
"max_results": 10
}
}
# 2. Expand relevant summary
{
"tool": "lcm_expand",
"params": {
"summary_id": "s_found_in_grep",
"max_raw": 20
}
}
# 3. Synthesize answer
{
"tool": "lcm_expand_query",
"params": {
"query": "What authentication method did we decide to use?",
"summary_id": "s_found_in_grep"
}
}# Check current state
export LCM_ENABLE_SLASH_COMMAND=true
hermes chat "/lcm status"
# Run diagnostics
hermes chat "/lcm doctor check"
# Preview cleanup
hermes chat "/lcm doctor clean_preview"
# Check for orphaned summaries or raw messages
# Doctor will report:
# - Orphaned summaries (no parent)
# - Dangling raw messages (session mismatch)
# - Missing required tables# Exclude test sessions from LCM
export LCM_IGNORE_SESSION_PATTERNS="test-*,temp-*,debug-*"
# Keep readonly sessions from being stored
export LCM_STATELESS_SESSION_PATTERNS="readonly-*,audit-*"
# Restart Hermes
hermes restart# Enable external storage for large outputs
export LCM_LARGE_OUTPUT_EXTERNALIZATION_ENABLED=true
export LCM_LARGE_OUTPUT_EXTERNALIZATION_THRESHOLD_CHARS=12000
# Enable transcript GC for already-externalized content
export LCM_LARGE_OUTPUT_TRANSCRIPT_GC_ENABLED=true
# Restart Hermes
hermes restart~/.hermes/profiles/<profile>/lcm_externalized/hermes pluginslcm (not found)# Verify tools exist
hermes chat "Run lcm_status"
# If tools work, plugin is functional/lcm statussession_id: (unbound)threshold_tokens: (uninitialized)hermes chat "Hello"
hermes chat "/lcm status" # Now shows live session data# Get current context window
hermes chat "What's your context window?"
# Calculate expected trigger
# trigger = context_window * LCM_CONTEXT_THRESHOLD
# Example: 128K window, 0.75 threshold = 96K trigger
export LCM_CONTEXT_THRESHOLD=0.75# In Hermes config
compression:
enabled: true # Must be trueregexpip install regexregexLCM_IGNORE_MESSAGE_PATTERNS# For 1M token model, don't wait until 750K
# Trigger earlier to reduce costs
# Trigger at 250K (25% of 1M)
export LCM_CONTEXT_THRESHOLD=0.25
# Trigger at 400K (40% of 1M)
export LCM_CONTEXT_THRESHOLD=0.40# Run doctor check
export LCM_ENABLE_SLASH_COMMAND=true
hermes chat "/lcm doctor check"
# Preview cleanup
hermes chat "/lcm doctor clean_preview"
# Apply cleanup (if safe)
export LCM_DOCTOR_CLEAN_APPLY_ENABLED=true
hermes chat "/lcm doctor clean_apply"# From plugin directory
cd ~/.hermes/plugins/hermes-lcm
git pull --ff-only
# Or for symlinked install
cd /path/to/hermes-lcm
./scripts/update.sh
# Restart Hermes
hermes restart# Example: Agent helper to search and expand context
async def recover_context(topic: str, max_depth: int = 2):
"""Search LCM and expand results to recover context."""
# Search for topic
grep_result = await hermes.call_tool("lcm_grep", {
"pattern": topic,
"search_raw": True,
"search_summaries": True,
"max_results": 5
})
if not grep_result.get("matches"):
return f"No context found for: {topic}"
# Expand first match
first_match = grep_result["matches"][0]
if "summary_id" in first_match:
expand_result = await hermes.call_tool("lcm_expand", {
"summary_id": first_match["summary_id"],
"max_raw": 10
})
return expand_result
return first_match
async def query_history(question: str, scope_summary_id: str = None):
"""Ask a question about compacted history."""
params = {"query": question, "max_raw": 50}
if scope_summary_id:
params["summary_id"] = scope_summary_id
result = await hermes.call_tool("lcm_expand_query", params)
return result.get("answer", "No answer generated")#!/bin/bash
# lcm-config.sh - LCM configuration template
# Core compaction settings
export LCM_CONTEXT_THRESHOLD=0.75
export LCM_FRESH_TAIL_COUNT=64
export LCM_LEAF_CHUNK_TOKENS=20000
# Dynamic chunking (optional)
export LCM_DYNAMIC_LEAF_CHUNK_ENABLED=true
export LCM_DYNAMIC_LEAF_CHUNK_MAX=40000
# Session management
export LCM_NEW_SESSION_RETAIN_DEPTH=2
export LCM_IGNORE_SESSION_PATTERNS="test-*,temp-*"
export LCM_STATELESS_SESSION_PATTERNS="readonly-*"
# Large payload handling
export LCM_LARGE_OUTPUT_EXTERNALIZATION_ENABLED=true
export LCM_LARGE_OUTPUT_EXTERNALIZATION_THRESHOLD_CHARS=12000
export LCM_LARGE_OUTPUT_TRANSCRIPT_GC_ENABLED=false
# Model overrides (use env vars for API keys)
# export LCM_SUMMARY_MODEL=claude-3-5-sonnet-20241022
# export LCM_EXPANSION_MODEL=gpt-4-turbo
# Advanced
export LCM_ENABLE_SLASH_COMMAND=true
export LCM_DOCTOR_CLEAN_APPLY_ENABLED=false
# Start Hermes
hermes startlcm_statusLCM_ENABLE_SLASH_COMMAND=true/lcm doctor check