Hooks
What it is
Event-driven extension points that run around sessions, model calls, tool calls, approvals, and compression.
In plain terms
Picture a stage manager who clips small cue lights at specific points in a play’s script — one right before a scene change, one right after the final line — so each cue fires automatically as the performance runs, without anyone rewriting the script itself. That’s how hooks work inside Hermes: small callbacks attach to fixed moments in a turn, such as right before a tool runs or right after the model answers, and they fire automatically while the core loop stays untouched.
Why it matters
Plugins react to specific moments in the turn lifecycle — before or after a tool call, before or after a model call, session start and end, even approval requests — through hooks, without ever touching the core runtime directly. Observability plugins use exactly this surface to log every tool and model interaction for later debugging, while something like disk-cleanup runs housekeeping off post-tool-call and session-end hooks without being invoked explicitly. This event-driven design is what keeps 88 plugin manifests from needing to fork or patch the agent loop.
How it works
A plugin’s register() function calls ctx.register_hook() with a fixed name — pre_tool_call, post_llm_call, on_session_start, and others from a defined VALID_HOOKS set — and PluginManager files the callback into a plain dict keyed by that name (hermes_cli/plugins.py). At the matching moment in a turn, every registered callback fires with keyword arguments describing what’s happening; most are fire-and-forget observers, but pre_tool_call can veto a tool call outright and pre_llm_call can inject extra context before the model runs, including right after a long conversation’s context has just been compressed. If a callback throws an exception it’s caught and logged rather than crashing the agent (website/docs/user-guide/features/hooks.md). The langfuse observability plugin, for example, registers six separate hooks just to trace requests and results end to end (plugins/observability/langfuse/init.py).
A concrete example
Debugging a flaky integration, a team writes a plugin that registers callbacks on pre_tool_call, post_tool_call, pre_llm_call, and post_llm_call instead of touching Hermes’s core loop at all. From then on, every session — CLI or gateway — silently reports each tool call and model response to an external dashboard as it happens. If the logging code throws an error one day, Hermes catches it, logs it, and keeps answering the user normally; the observer plugin never gets a vote over whether the conversation continues.
How it connects
This note belongs to the Skills family. Its closest neighboring concepts are: BOOT.md, Skills, Agent Runtime, Personal OS.
Source evidence
vendor/hermes-agent/hermes_cli/plugins.py:1302-1313#PluginManager.discover_and_load— Verified Source Map evidence for PluginManager. The directory scanner forwards discovered plugin.yaml or plugin.yml files to_parse_manifest; PluginManager parses them with a safe YAML loader, normalizes the kind, and auto-loads bundled backend manifests through_load_plugin.
Workflows
- No first-pass workflow mapping yet; this concept still appears in the vault graph through articles and source evidence.
Related articles
- Ten Underused Hermes Features That Reveal Its Real Power
