feat: add Hermes Agent integration (proxy + plugin)#465
Merged
Conversation
Two-layer integration for Hermes Agent (github.com/NousResearch/hermes-agent):
1. Proxy redirect via `lore run hermes`:
- Add Hermes to agent auto-detection in agents.ts
- Sets OPENAI_BASE_URL + HERMES_INFERENCE_PROVIDER=custom to route
all LLM calls through the Lore gateway
2. Python plugin (lore-hermes) for Hermes's plugin system:
- Context engine: passthrough that disables Hermes's ContextCompressor,
delegating all compression to the gateway's gradient system
- Gateway auto-discovery/startup on session start
- pre_llm_call hook injects [lore:session-id=...] and [lore:project=...]
markers for reliable session/project identification
- CLI commands: `hermes lore status` and `hermes lore recall`
3. Gateway-side context marker parsing (pipeline.ts):
- Tier 2.5 session identification from [lore:session-id=...] markers
- Project path extraction from [lore:project=...] markers
- Injected into both handleConversationTurn and handleCompaction paths
Includes 20 unit tests for marker extraction and an integration test script.
Critical fixes:
- C1: Strip [lore:session-id=...] and [lore:project=...] context markers
from user messages before forwarding to upstream LLM (prevents token
waste, LLM confusion, and temporal storage pollution)
- C2: Always hash session IDs to hex in _derive_session_id() so they
match the gateway regex [a-f0-9]{8,64} regardless of Hermes ID format
- C3: Add control character stripping, length validation, and path
traversal rejection to extractProjectMarker() (parity with
extractProjectHeader in config.ts)
- C4: Add __init__ to LoreContextEngine with default attribute values
to prevent AttributeError when get_status() called before first response
Medium fixes:
- M1: Terminate orphaned gateway process when startup times out
- M2: Remove unreachable dead code in _on_pre_llm_call
- M3: Use tier 2.5 literal in identifySession return type instead of
casting tier 2 (accurate telemetry/logging)
- M5: Use exact URL equality instead of substring match for gateway
URL comparison
- M7: Reject .. path components in extractProjectMarker
Tests: 29 tests pass (9 new for stripping, sanitization, path traversal)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two-layer integration for Hermes Agent (163K stars, by Nous Research) — gives Hermes users the full Lore memory pipeline with minimal code.
Architecture
Layer 1: Proxy redirect (
lore run hermes)Adds Hermes to agent auto-detection in
agents.ts. Whenlore rundetectshermeson PATH, it setsOPENAI_BASE_URLandHERMES_INFERENCE_PROVIDER=customto route all LLM calls through the Lore gateway. This alone provides all 20+ gateway features (temporal storage, distillation, knowledge curation, gradient compression, hybrid recall, cache warming, etc.).Layer 2: Python plugin (
lore-hermes)A Hermes general plugin (
pip install lore-hermes) that addresses limitations of the proxy-only approach:lore runon_session_starthook discovers/starts gatewaypre_llm_callhook injects[lore:session-id=...]markershermes lore status,hermes lore recallLayer 3: Gateway-side marker parsing
Parses
[lore:session-id=...]and[lore:project=...]context markers from user messages for reliable session/project identification (Tier 2.5 between learned headers and fingerprint fallback).Changes
Gateway (TypeScript)
packages/gateway/src/cli/agents.ts— Hermes entry in AGENTS arraypackages/gateway/src/cli/run.ts— Updated error messagepackages/gateway/src/pipeline.ts— Context marker extraction functions + Tier 2.5 session identification + project marker injection at both handleConversationTurn and handleCompactionPlugin (Python, new package)
packages/hermes/pyproject.toml— pip package with entry pointpackages/hermes/lore_hermes/engine.py—LoreContextEnginepassthroughpackages/hermes/lore_hermes/gateway.py— Gateway discovery + auto-startuppackages/hermes/lore_hermes/__init__.py— Registration (context engine + hooks + CLI)packages/hermes/lore_hermes/plugin.yaml— Hermes plugin manifestTests
packages/gateway/test/context-markers.test.ts— 20 unit tests for marker parsing (all pass)packages/hermes/tests/test_engine.py— Context engine testspackages/hermes/tests/test_gateway.py— Gateway discovery testspackages/hermes/test-integration.sh— End-to-end integration test scriptUsage
Verification
bun run typecheck— all 4 packages passbun test— 1825 pass, 20 new tests all pass, 3 pre-existing failures (unrelated)