Docs Frameworks
Hermes Agent (Nous Research)
Status: verified. The adapter ships in
kiff-guard and passes the
conformance suite. The seam was source-verified against the
NousResearch/hermes-agent source on main, not just the docs — and a
doc-vs-source discrepancy was resolved in favor of the source (see
below).
Shape: inverted-control. Hermes runs the tool after the hook
returns; the hook only votes. So the adapter uses Guard.observe() /
Guard.decide_only(), not a run callback. See
how the guard works.
Hermes is a CLI-first agent that takes real, irreversible actions (terminal, code execution, file writes, messaging gateways) — exactly the “actor takes consequential action” profile KIFF governs.
Install
The guard ships to Hermes as a plugin — a directory with
plugin.yaml + __init__.py exposing register(ctx). No fork, no
monkeypatch.
pip install "git+https://github.com/kiffhq/kiff-guard.git#subdirectory=packages/python/kiff-guard"
Then create the plugin at ~/.hermes/plugins/kiff-guard/.
Observe — audit with zero config
__init__.py:
from kiff_guard import Guard
from kiff_guard.adapters.hermes import register_kiff_guard
_GUARD = Guard(mode="observe") # zero-config audit; no KIFF account
def register(ctx):
register_kiff_guard(ctx, _GUARD)
The hook fires before every tool (terminal, browser, code-exec, file writes, MCP) in both the CLI and the gateway, records a receipt, and never blocks.
Activate
from kiff_guard import export_yaml
print(export_yaml("my-domain", _GUARD.catalog))
Review and activate in the dashboard.
Enforce — govern at runtime
Build the guard with a client and mode="enforce":
from kiff_guard import Guard, HTTPClient, ToolMap
client = HTTPClient(api_key="kiff_live_...", tool_map=ToolMap().bind(...))
_GUARD = Guard(client=client, tenant="<tenant>", agent="hermes", mode="enforce")
On a withheld decision the adapter returns Hermes’
{"action": "block", "message": ...} directive — Hermes short-circuits
the tool and hands message to the model as the tool’s error result.
The tool never runs. Enforce fails closed on a guard error by
default; pass fail_closed=False to override.
The seam (verified)
The pre-execution seam is the pre_tool_call plugin hook. In source
(model_tools.py → handle_function_call), Hermes calls
get_pre_tool_call_block_message(...) before dispatch; a non-None
block result short-circuits the tool. The hook fires exactly once per
tool execution and the first block wins.
Doc-vs-source discrepancy (resolved). Hermes’ plugin-build guide lists
pre_tool_call’s return as “ignored” (observer-only), but the hooks reference says it can block — and the source confirms the hooks reference is correct. The block directive is supported and stable. KIFF complements Hermes’ ownDANGEROUS_PATTERNSlocal check by adding the tenant-wide policy + audit.
Links
- Adapter code:
kiff_guard/adapters/hermes.py - Seam research (full, source-verified): hermes.md
- Hermes docs: hermes-agent.nousresearch.com