Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

106 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hermes Local Knowledge

CI Security scans License: MIT

Goal

Hermes Local Knowledge is a reusable Hermes Agent plugin that routes a local question to the whole artifact the agent should inspect first: a skill, support document, script, runbook, cron job, MCP server, or generated tool routing note.

It is an artifact router, not chunk RAG. Search results are routing hints; the agent should still read the selected source before acting.

Sources

source_root is the curated local tree to index. $HERMES_HOME remains a separate runtime source for skills, cron jobs, and MCP configuration.

Artifact type Source
skill SKILL.md files under configured custom_skill_dirs, plus $HERMES_HOME/skills
skill_support_doc Markdown support files under custom skills and runtime skill references/, templates/, scripts/, and assets/ directories
script Supported script files under configured script_dirs
memory_doc, runbook, doc Markdown under source_root when include_markdown_docs is enabled; configured memory/runbook directories determine the type
cron_job $HERMES_HOME/cron/jobs.json
mcp_server $HERMES_HOME/config.yaml entries under mcp_servers or the accepted mcp.servers form
tool_okf Validated generated notes under <state_dir>/okfs/tools/*.md

Built-in excluded directory names are .archive, .git, .mypy_cache, .pytest_cache, .venv, .worktrees, __pycache__, htmlcov, logs, node_modules, venv, and worktrees. exclude_dir_names adds deployment-specific exclusions.

Five tools

The plugin registers these native tools in the local_knowledge toolset:

Tool Purpose
knowledge_search Find likely artifacts by intent, with an optional type filter and forced rebuild.
knowledge_get Fetch one artifact by ID, optionally with graph neighbors.
knowledge_neighbors Traverse conservative graph edges for an artifact.
knowledge_feedback Record local lookup feedback such as useful, missing, stale, or wrong_artifact.
knowledge_usage_report Summarize local usage, failures, zero-result queries, and feedback.

The plugin also registers post_tool_call and on_session_finalize hooks for optional tool-OKF capture and generation.

Install and model consent

Install and enable the directory plugin:

hermes plugins install https://github.com/stepanov1975/hermes-local-knowledge.git --enable

An SSH URL is also supported on hosts with GitHub SSH access:

hermes plugins install git@github.com:stepanov1975/hermes-local-knowledge.git --enable

The Python package exposes the local_knowledge = hermes_local_knowledge.plugin entry point for environments that install plugins into Hermes' Python environment.

Automatic tool-OKF generation is opt-in

Existing-artifact lookup works without model calls. local_knowledge.okf.auto_generate defaults to false; while it is off, safe tool-use candidates can be recorded but are not automatically converted into new routing notes.

Before enabling automatic generation, an installer must explain that:

  • a detached worker invokes the active Hermes model and consumes additional model tokens;
  • one worker claims at most max_candidates_per_session candidates (default 2) and makes one structured batch call when it has claims;
  • max_generation_seconds is passed as the provider-request timeout, while provider retry/fallback policy can extend total elapsed time and token use behind that host call;
  • session finalization does not wait for generation.

Then ask explicitly:

Enable automatic OKF generation now? (Recommended; uses additional model tokens.)

Only after the user agrees, run:

hermes config set local_knowledge.okf.enabled true
hermes config set local_knowledge.okf.auto_generate true

If it is already enabled, report that instead of asking again. If the user declines, leave auto_generate disabled and report that existing lookup and manual OKF management remain available, but new tool-routing notes will not be generated automatically.

Install the proactive router skill

The tools can be called directly, but the bundled skill tells Hermes when to use them proactively:

hermes local-knowledge install-router-skill --json

installed and current are successful statuses. A different existing skill produces conflict; review it before choosing --force.

To use an intentionally customized proactive skill instead, configure its deployed runtime path before running doctor or installer commands:

local_knowledge:
  router_skill_path: skills/note-taking/local-knowledge-router/SKILL.md

Relative paths resolve from $HERMES_HOME. The path must name an active SKILL.md under $HERMES_HOME/skills; that runtime path may be a symlink to a separately managed custom-skill repository. Doctor validates the skill's frontmatter name but does not require custom content to match the bundled copy. Invalid or missing configured custom skills appear as explicit doctor warnings while doctor retains its diagnostic-success exit status; the installer fails without modifying the configured target. install-router-skill, including --force, returns current with router_skill_mode: custom and does not overwrite a valid configured custom skill.

From a source checkout before plugin CLI registration is available:

python -m hermes_local_knowledge.cli install-router-skill --json

The plugin also exposes the same file as local_knowledge:local-knowledge-router for explicit skill_view(...) loads. That namespaced copy is not a substitute for installing the normal proactive skill. After installing or changing the skill, run /reload-skills and start a new/reset session, or start a fresh Hermes session.

Configuration

Put non-secret settings in $HERMES_HOME/config.yaml:

local_knowledge:
  source_root: ~/repos/local-operations
  state_dir: ~/.hermes/local_knowledge
  # Optional: use a deployed custom proactive skill instead of the bundled copy.
  # router_skill_path: skills/note-taking/local-knowledge-router/SKILL.md
  custom_skill_dirs: [custom_skills]
  script_dirs: [scripts, hermes_home/scripts]
  memory_dirs: [memory]
  runbook_dirs: [docs]
  include_markdown_docs: true
  exclude_dir_names: [build, dist]
  known_entities: [Hermes, GitHub, MCP, Cron]
  okf:
    enabled: true
    auto_generate: false  # change only after explicit model-token consent
    max_candidates_per_session: 2
    max_generation_seconds: 120
    min_use_count: 1

Canonical settings, aliases, and defaults:

Canonical setting Accepted alias/override Default
source_root root; LOCAL_KNOWLEDGE_ROOT overrides config $HERMES_HOME
state_dir index_dir; LOCAL_KNOWLEDGE_STATE_DIR overrides config $HERMES_HOME/local_knowledge
hermes_home HERMES_HOME; explicit CLI --hermes-home selects a profile Active Hermes home, otherwise ~/.hermes
router_skill_path $HERMES_HOME/skills/local-knowledge-router/SKILL.md; an explicit relative path resolves from $HERMES_HOME and selects custom-skill validation
custom_skill_dirs [custom_skills]
script_dirs [scripts, hermes_home/scripts]
memory_dirs [memory]
runbook_dirs [docs]
known_entities entities [Hermes, GitHub, MCP, Cron]
include_markdown_docs true with an explicit source root; false when the root falls back to $HERMES_HOME
exclude_dir_names [], merged with built-in exclusions
okf.enabled flat okf_enabled true
okf.auto_generate flat okf_auto_generate false
okf.max_candidates_per_session flat okf_max_candidates_per_session 2
okf.max_generation_seconds flat okf_max_generation_seconds; okf.max_worker_seconds or flat okf_max_worker_seconds is a fallback when it is absent 120 seconds
okf.min_use_count flat okf_min_use_count 1

All nested okf keys also accept their flat okf_* form. YAML lists are preferred in config.yaml; comma-separated or bracket-list strings written by hermes config set are normalized.

When source_root is omitted, runtime skills, cron jobs, and MCP configuration are still indexed from $HERMES_HOME, but arbitrary root-level Markdown is not included by default. Generated state belongs outside a source repository and must not be committed.

CLI

The primary standalone entry point is:

python -m hermes_local_knowledge.cli build --from-hermes-config
python -m hermes_local_knowledge.cli search 'backup runbook' --from-hermes-config --limit 8
python -m hermes_local_knowledge.cli get skill:backup-runbook --from-hermes-config --json
python -m hermes_local_knowledge.cli neighbors skill:backup-runbook --from-hermes-config --json
python -m hermes_local_knowledge.cli evaluate --from-hermes-config --json --details
python -m hermes_local_knowledge.cli okf status --from-hermes-config --json
python -m hermes_local_knowledge.cli doctor --hermes-home "${HERMES_HOME:-$HOME/.hermes}" --rebuild --query 'backup runbook'

Use python -m hermes_local_knowledge.cli <command> --help for manual OKF claim, validate, complete, fail, and retry operations.

python -m hermes_local_knowledge.indexer ... is preserved as a compatibility entry point to the same CLI. New documentation and automation should use hermes_local_knowledge.cli.

The installed hermes local-knowledge surface is intentionally smaller:

hermes local-knowledge install-router-skill
hermes local-knowledge doctor --rebuild --query 'backup runbook'

The host also uses an internal bounded worker subcommand for automatic OKF generation.

Index freshness

Managed native lookups, and CLI search/get/neighbors with --from-hermes-config and no explicit --db, rebuild when the index is missing, corrupt, older than format 4, or marked dirty by completed OKF publication. A newer index format is rejected rather than overwritten.

Ordinary source-file, cron-registry, or MCP-config changes are not detected automatically. After those changes, either:

  • pass rebuild=true to knowledge_search, knowledge_get, or knowledge_neighbors; or
  • run python -m hermes_local_knowledge.cli build --from-hermes-config (or doctor --rebuild).

No rebuild cron is required. Operators who need a fixed freshness interval may optionally schedule the explicit build command. An explicit CLI --db is caller-owned: it is read as supplied and is not rebuilt automatically or used to consume shared OKF-dirty tokens.

Generated state

The plugin writes local/generated state under state_dir:

index.sqlite
index.jsonl
usage.sqlite
okf_queue.sqlite
okfs/tools/*.md
okf_worker.log
index_build.lock
index_build.sqlite
okf_index_dirty/

index_build.lock is the regular-file compatibility gate shared with v0.3.12 builders. New builders hold it and the SQLite transaction lock in index_build.sqlite for collection, validation, and publication. SQLite metadata binds index.sqlite to the exact index.jsonl bytes: a caught publication failure restores the prior pair, and a crash-split pair is classified as corrupt and rebuilt by the next managed lookup. okf_index_dirty/ contains tokens that make the next managed lookup rebuild; a successful build removes only the tokens it covered.

None of these files belong in source control.

OKF lifecycle

Tool OKFs are compact routing notes for tools Hermes has actually used. They are hints, not authoritative tool documentation.

  1. When okf.enabled is true, post_tool_call records only a bounded structural projection: tool identity/toolset, a sanitized schema shape, argument shape, counters, and a redacted error class. It does not persist raw argument values, tool output, transcripts, emails, OCR text, private documents, schema descriptions/examples/defaults, or secret values.
  2. When okf.auto_generate is true, on_session_finalize performs a read-only, tightly bounded queue check and launches a detached worker only when work is available.
  3. The worker acquires one fixed lease of max(300, 2 * max_generation_seconds + 120) seconds and claims at most max_candidates_per_session rows. Lease and claim ownership are checked again before publication.
  4. If rows were claimed, the worker makes exactly one ctx.llm.complete_structured batch call with the privacy-safe routing projection and a bounded same-toolset related-tool allowlist. The model receives no terminal or file tools.
  5. Each result is identity-checked, rendered to a worker-unique temporary file, prevalidated, and published inside a short token/lease-fenced transaction. A stale worker cannot publish. Successful publication marks the managed index dirty.

Version 0.4.0 reads the current v0.3.12 queue shape by normalizing a selected claim's stored schema into the bounded routing projection. It does not promise a general migration ladder for arbitrary older private schemas.

Feedback and evaluation

Lookup telemetry and feedback stay in <state_dir>/usage.sqlite. Tool handlers fail open for telemetry-only errors; explicit knowledge_feedback writes remain strict so callers know whether feedback was recorded. Do not put secrets or private document text in queries or feedback notes.

Managed searches may use one deterministic feedback prior when the index was built for the configured source root. Only the latest significant explicit rating for a query/artifact pair is eligible, only useful is positive, and a newer rejection for that route or matching current query suppresses an older overlap route. A matching artifact already present in current results may move to rank one. If it is absent, the plugin performs at most one retry with an accepted query no longer than the current query and the mapped artifact type, and promotes only the exact artifact when that live retry rediscovers it. Searches against an explicit caller-owned --db remain unassisted.

knowledge_usage_report summarizes recent activity before changing ranking, triggers, source coverage, or graph edges.

evaluate is read-only and intentionally measures the unassisted index ranking to avoid training/evaluation leakage. It replays positive local feedback against the current index and reports exact Hit@k/MRR plus parent-equivalent metrics. Parent equivalence is deliberately limited to a skill_support_doc and its owning skill; generic graph neighbors are not treated as successful equivalents.

For historical comparisons from a source checkout:

python scripts/compare_historical_query_versions.py \
  --usage-db ~/.hermes/local_knowledge/usage.sqlite \
  v0.4.2 WORKTREE

The comparator opens live telemetry read-only, freezes one private source/runtime/OKF corpus, and builds each ref with that ref's own code. A nonnegative recorded feedback boundary plus a matching index-corpus hash proves that the recorded event inputs are available. The report calls a ref replay event-time exact only when that ref's plugin version and index format also match the recorded event and the replay reproduces its recorded baseline/final pages plus route provenance; a changed candidate otherwise remains a counterfactual replay over exact inputs, not historical output. Migrated legacy rows use one fixed captured feedback state, while missing boundaries or input/ref/output mismatches remain explicitly non-exact best-effort evidence. The machine report counts these evidence classes without exposing raw queries.

Correction-route acceptance uses explicit_resolution Hit@1 as the primary outcome, then verified_event Hit@1/MRR, while requiring no increase in negative-artifact exposure, no unaccepted production ordering changes, and no replay errors. The comparison assessment distinguishes rejected, accepted_improved, and accepted_unchanged_or_insufficient_evidence. Direct/legacy aggregate metrics remain useful coverage and trend signals, but are not sufficient by themselves to prove a correction. Raw queries and artifact IDs appear only with --details inside the owner-only evaluation directory.

Verification

Operator checks:

hermes local-knowledge doctor
hermes local-knowledge doctor --json
hermes local-knowledge doctor --rebuild --query 'backup runbook'

doctor reports missing/outdated router skill state and disabled automatic OKF generation as nonfatal warnings. Resolve them or report the deliberate choice.

Development gates:

PYTHONDONTWRITEBYTECODE=1 python -m pytest tests/test_public_contract.py tests/test_plugin.py -q -p no:cacheprovider
PYTHONDONTWRITEBYTECODE=1 python -m pytest -q -p no:cacheprovider
python -m ruff check .
python -m mypy
python scripts/check_version_policy.py --base-ref origin/main
git diff --check

See CONTRIBUTING.md, SECURITY.md, and docs/github-security.md for contribution, vulnerability-reporting, and repository-security guidance.

Owner map

  • config.py — configuration models, aliases, defaults, and the single resolver.
  • artifacts.py — whole-artifact models, source collection, privacy-safe metadata extraction, and graph edges.
  • index.py — format-4 SQLite/JSONL publication, cross-version and SQLite build locking, managed rebuild classification, and deterministic search/get/neighbors.
  • telemetry.py — local usage and feedback persistence/reporting.
  • routing.py — bounded live-root feedback matching, promotion, and one verified typed retry.
  • evaluation.py — read-only feedback-label replay and exact/parent-equivalent metrics.
  • service.py — one resolved configuration's managed index and telemetry lifecycle.
  • okf.py — privacy-safe OKF queue, hooks, detached worker, validation, and fenced publication.
  • plugin.py — Hermes registration for five tools, two hooks, the bundled skill, and installed CLI adapter; register is its public export.
  • cli.py — primary standalone command surface and the smaller Hermes CLI adapter.
  • indexer.py — thin compatibility facade exporting exactly Artifact, Edge, IndexSettings, build_index, search_index, get_artifact, get_neighbors, and main.
  • __init__.py — package version.

About

Hermes Agent plugin for local knowledge search and artifact routing—find the right skill, script, runbook, cron job, MCP server, or document.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages