- name
- hermes-lcm-context-management
- description
- Lossless Context Management plugin for Hermes Agent with DAG-based compression and drill-down tools
- triggers
- ["install hermes lcm plugin","configure lossless context management","use hermes lcm tools","tune lcm compaction settings","debug hermes context compression","expand lcm summary nodes","manage hermes conversation history","configure lcm for long context models"]
# Hermes LCM Context Management
> Skill by [ara.so](https://ara.so) — Hermes Skills collection.
## Overview
Hermes-LCM is a lossless context management plugin for [Hermes Agent](https://github.com/NousResearch/hermes-agent) that prevents message loss during context compression. Instead of replacing old messages with flat summaries, it:
- Stores all messages in SQLite before compaction
- Compacts old context into a hierarchical summary DAG
- Provides agent tools to drill back into compacted material
- Maintains source lineage for filtered retrieval
- Externalizes large payloads to prevent bloat
**Key difference from built-in compression**: LCM makes recall part of the active context engine with drill-down tools (`lcm_grep`, `lcm_expand`, `lcm_expand_query`) rather than relying on auxiliary cross-session search.
## Installation
### Standard Installation
Clone into Hermes plugins directory:
```bash
# 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-lcm
```
### Symlink Installation
From an existing checkout:
```bash
cd hermes-lcm
./scripts/install.sh
# Profile-specific
HERMES_PROFILE=myprofile ./scripts/install.sh
```
### Configuration
Enable in Hermes config (YAML):
```yaml
plugins:
enabled:
- hermes-lcm
context:
engine: lcm
# Keep compression enabled - LCM needs this gate
compression:
enabled: true
```
Restart Hermes after configuration changes.
### Verification
```bash
hermes plugins
```
Expected output includes:
- Plugin list shows `hermes-lcm`
- Context engine shows `lcm`
- Tools include: `lcm_grep`, `lcm_describe`, `lcm_expand`, `lcm_expand_query`, `lcm_status`, `lcm_doctor`, `lcm_load_session`
## Core Concepts
### Message Storage
LCM stores messages in SQLite before compaction happens:
```
~/.hermes/profiles/<profile>/lcm.db # Default path
```
### Summary DAG
Old messages are compacted into hierarchical summary nodes:
```
Raw messages → Leaf summaries → Branch summaries → Root
```
Each node tracks:
- Descendant message count
- Source lineage (for filtering)
- Depth in DAG
- Token counts
### Bounded Recovery
Agent can page back into compacted material without flooding active context:
- `lcm_grep`: Search raw messages and summaries
- `lcm_describe`: Get summary metadata
- `lcm_expand`: Retrieve child summaries or raw messages
- `lcm_expand_query`: Synthesize answer from DAG material
## Environment Configuration
### Core Settings
```bash
# 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
```
### Session Management
```bash
# 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\]"
```
### Large Payload Handling
```bash
# 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
```
### Model Overrides
```bash
# 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
```
### Advanced
```bash
# 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.0
```
## Tuning for Long Context Models
For large context windows, tune threshold to avoid excessive prompt costs:
**Calculation**:
```
compaction_trigger = effective_context_window * LCM_CONTEXT_THRESHOLD
```
**Examples**:
| 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 |
**Example configuration for 1M token model**:
```bash
# 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 Tools Usage
### lcm_status
Get current LCM state:
```python
# Agent calls this to check compression state
{
"tool": "lcm_status",
"params": {}
}
```
Returns:
- Session ID
- Threshold tokens
- Current prompt tokens
- Raw message count
- Summary DAG structure
- Storage path
- Git commit (if source checkout)
### lcm_grep
Search messages and summaries:
```python
# 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
}
}
```
### lcm_describe
Get summary node metadata:
```python
# Describe a specific summary node
{
"tool": "lcm_describe",
"params": {
"summary_id": "s_abc123"
}
}
```
Returns:
- Summary text
- Descendant count
- Token counts
- Depth in DAG
- Source lineage
### lcm_expand
Retrieve child summaries or raw messages:
```python
# 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
}
}
```
### lcm_expand_query
Synthesize answer from DAG material using auxiliary LLM:
```python
# 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
}
}
```
This tool:
1. Retrieves relevant raw messages and summaries
2. Calls auxiliary LLM with query + material
3. Returns synthesized answer
4. Uses `LCM_EXPANSION_MODEL` and `LCM_EXPANSION_CONTEXT_TOKENS`
### lcm_load_session
Load historical session into current context:
```python
# Load previous session
{
"tool": "lcm_load_session",
"params": {
"session_id": "previous-session-abc123"
}
}
```
### lcm_doctor
Diagnose and repair LCM state:
```python
# 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"
}
}
```
## Slash Commands (Optional)
Enable with `LCM_ENABLE_SLASH_COMMAND=true`:
```bash
# 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
```
## Common Patterns
### Initial Setup After Installation
```bash
# 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.
```
### Recovering Lost Context
```python
# 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"
}
}
```
### Debugging Compaction Issues
```bash
# 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
```
### Session Isolation
```bash
# 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
```
### Large Payload Management
```bash
# 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
```
External payloads stored in:
```
~/.hermes/profiles/<profile>/lcm_externalized/
```
## Troubleshooting
### Plugin Shows as Not Found
**Symptom**: `hermes plugins` shows `lcm (not found)` but tools exist
**Solution**: If tools are available, LCM is loaded. This is a host discovery mismatch, not a plugin failure.
```bash
# Verify tools exist
hermes chat "Run lcm_status"
# If tools work, plugin is functional
```
### Status Shows Unbound After Restart
**Symptom**: `/lcm status` shows `session_id: (unbound)` or `threshold_tokens: (uninitialized)`
**Solution**: Send one normal message first:
Auf GitHub ansehen