Hermes agent hooks earn an 8.4 out of 10 from me: the deepest hook system I've read in an open agent, held back mainly by fail-open defaults and a headline feature that hasn't shipped in a tagged release.
That headline feature is the pre_llm_call turn block, merged to main on 1 Nov 2026, which lets a policy end a turn before any inference request goes out.
Below is the scorecard, criterion by criterion, with the reason for every score taken from the docs and the commits.
If you'd like my team to tell you whether hooks fit your stack, book a free SEO strategy session.
The Scorecard
| Criterion | Score | Why |
|---|---|---|
| Event coverage | 9.5/10 | The shipped catalog runs from tool calls and turns to streaming, approvals, compaction, subagents and Kanban workers. |
| Control power | 9/10 | pre_tool_call can block, rewrite arguments or escalate to approval; pre_llm_call can now veto the turn. |
| Language flexibility | 9/10 | Shell hooks take any executable with a shebang; plugin and gateway hooks are Python only. |
| Safe defaults | 6.5/10 | Shell hooks fail open, fail_closed only covers pre_tool_call, and a crashed turn policy lets the turn run. |
| Consent and audit | 7.5/10 | First-use prompts and hermes hooks doctor help, but edited scripts aren't re-approved and gateway hooks have no prompt. |
| Privacy of blocked prompts | 9/10 | The 1 Nov fixes store only a placeholder, so compaction, search and memory never read the vetoed text. |
| Compatibility | 9/10 | Accepts Claude Code style decision/reason JSON, exit code 2 and the failClosed spelling. |
| Release readiness | 7/10 | The turn block is on main only; the latest tagged release is v0.22.5 from 23 Oct. |
| Documentation | 9/10 | Each event lists exact timing, payload fields and a privacy note, with worked examples. |
The 8.4 is the plain average of those nine scores, rounded.
These are editorial ratings from reading the official hooks docs and the commits, not a benchmark.
What's Actually New: The Turn Veto
Commit ad9229c843 is the reason this review exists today.
Before it, pre_llm_call could only add context to a turn.
Now its first valid {"action": "block", "message": "..."} return ends the turn with zero model calls.
The user sees the message, the transcript stores it as the assistant reply, and the turn exits with blocked_by_plugin_pre_llm_call.
The commit names its purpose directly: DLP, privacy and policy plugins no longer need to patch core.
That's a real gap closed, because tool-level blocks can't stop a prompt that contains the sensitive data itself.
Both hook styles get it: a Python plugin returns the dict, and a shell hook prints either shape on stdout.
A block with no message is ignored, the same rule pre_tool_call already used, so a half-written policy can't silently swallow turns.
The design keeps resume working too, since the transcript still holds a normal user-then-assistant pair after the veto.
One caveat the docs flag: model metadata lookups, such as a context-length probe on a fresh session, can still run before the hook, but they carry no message content.
The Follow-Ups Show The Team Took Privacy Seriously
The first version had a hole, and the maintainers said so in the commit message.
The vetoed text still sat in the stored row, where compaction, session_search and memory providers could read it.
Commit 792330dc91 fixed that by storing [Message withheld: a pre_llm_call policy hook blocked it.] as the content.
Commit c0bcfe2bb2 stopped a blocked turn from making a stray auxiliary call for micro-compaction.
Commit 4061818385 made /retry and /undo use the typed text, so the policy re-checks a retry.
All three landed on 1 Nov, the same day as the merge, and that's why privacy scores 9 rather than 7.
๐ฅ Want hooks set up by people who already run them? Inside the AI Profit Boardroom you get step-by-step video trainings, the installable Agent OS with Hermes inside, four coaching calls a week and 3,400+ members comparing agent setups. โ Join the AI Profit Boardroom
Strength: Four Systems For Four Jobs
Hermes doesn't force one mechanism onto every problem.
- Shell hooks are for drop-in scripts that block, rewrite or inject.
- Plugin hooks are for in-process Python that needs state.
- Gateway hooks are for messaging-bot alerts and logs.
- Outbound webhooks are for signed notifications to other systems.
Shell hooks also cover the most surfaces: CLI, gateway, Desktop, TUI and dashboard chat, each using that session's profile configuration and allowlist.
Each one has a clear runtime boundary, and the docs' comparison table spells out which can block, which can inject context and how consent works.
Strength: The Tool Gate Is Mature
pre_tool_call is the strongest single hook here.
Precedence is fixed at block over approve over nothing, regardless of registration order.
Multiple modify returns accumulate into one merged argument set.
A plugin callback that times out or raises fails closed, and a permanently hung plugin blocks calls with a warning naming it rather than freezing the agent.
That's the behaviour you want from a security gate.
The approve path is a smart touch: rather than a flat yes or no, a policy can hand an edge case to a human, and denial, timeout or a gate error all fail closed.
Strength: Shell Hooks Speak Claude Code
If you already wrote hooks for Claude Code or Cursor, most of them translate.
The JSON accepts both decision/reason and the Hermes-native action/message shape.
Exit code 2 blocks a tool call even with no JSON output.
And the docs say Claude Code's UserPromptSubmit maps onto pre_llm_call, which fires at the same point.
One difference to watch: Claude Code's {"decision": "approve"} means auto-allow and is not mapped to Hermes's approval gate.
Strength: Outbound Webhooks Are Built Like Production Infrastructure
The notify-only side of the system gets the details right.
Each POST can carry an X-Hermes-Signature-256 header, an HMAC-SHA256 of the raw body in the same style GitHub uses.
The delivery_id and timestamp sit inside the signed body, so a receiver can dedupe and reject stale events.
Delivery runs on one background thread off the hot path, so a dead endpoint never stalls a tool call.
Connection errors and 5xx responses get one retry; 4xx responses get none.
Redirects are never followed, and a backed-up queue drops new events with a warning instead of eating memory.
The docs recommend secret_env over an inline secret, which keeps credentials out of the config file.
The one thing missing is guaranteed delivery, and the docs say plainly it's best-effort.
Limit: Fail-Open Is The Default
This is the biggest drag on the score.
A shell hook that can't be found, times out or prints junk logs a warning and lets the action go ahead.
fail_closed: true fixes that, but only on pre_tool_call.
For the new turn block, the docs say a callback that raises or runs past plugins.hook_callback_timeout (30 seconds by default) is skipped and the turn goes ahead.
So a DLP policy has to catch its own errors and return a block when unsure.
That's honest documentation, but it puts the burden on every policy author.
Limit: Consent Has Soft Spots
Shell hook approval is keyed on the exact command string, not the script's hash.
Editing an approved script never triggers a new prompt.
Gateway hooks go further: anything placed in ~/.hermes/hooks/ loads at gateway start with no enable list, no first-use prompt and no sandbox.
hermes hooks doctor flags mtime drift, which helps, but it's a check you have to remember to run.
๐ Want a second opinion before you trust a hook with client data? Book a free SEO strategy session and my team will review your setup with you. โ Book your free strategy session
Limit: Two Timeout Systems To Keep Straight
Python plugin callbacks on bounded hooks use plugins.hook_callback_timeout, which defaults to 30 seconds, can be set to 0 to disable it, and maxes out at 600.
Shell hooks ignore that and use their own per-entry timeout, which defaults to 60 seconds and is capped at 300.
What happens on a timeout also differs by event.
A timed-out plugin pre_tool_call fails closed, other bounded plugin hooks fail open, and a shell hook only fails closed when you set the flag.
None of this is hidden, but it's easy to assume one rule covers everything when it doesn't.
I'd like a single "policy mode" switch that makes every directive hook fail closed; until then, the scorecard reflects the extra care it takes.
Limit: The Best Part Isn't Released Yet
The turn block merged to main on 1 Nov 2026.
The releases page still shows v0.22.5, from 23 Oct, as the latest tag.
So on a stock release install today, pre_llm_call can inject context but can't veto a turn.
That's a timing issue, not a design flaw, and the score will move once a release carries it.
Who Should Use Hermes Hooks
- Teams sending client or regulated data through an agent, who need a policy that stops a prompt before a provider sees it.
- Operators running agents unattended on the gateway or cron, who need tool gates that fail closed.
- Anyone moving Claude Code or Cursor hooks over to Hermes.
- Agencies that want signed lifecycle events in their own dashboards.
Who Should Skip Them For Now
- Solo users who only chat with Hermes and never let it run terminal commands.
- Anyone who can't review a script before approving it, because hooks run with your full user credentials.
- Teams that need the turn block today on a release build, until it lands in a tagged release.
If plugins are your next question, see the best Hermes Agent plugins, ranked.
Final Verdict
Hermes hooks are the most complete control layer I've seen documented for an open agent.
The tool gate is ready now, the outbound webhooks are well designed, and the new turn veto finally gives privacy policies a clean place to live.
Turn on fail_closed for every security gate, write your turn policy to block on error, and re-run hermes hooks doctor after every config pull.
Developers who want the plugin-side contract can read the observer hooks reference.
For the full Agent OS and the trainings behind it, join the AI Profit Boardroom; for a plan built around your data, book a free strategy call with my team.
Also On Our Network
- ๐ The six-step operator setup for shell hooks, fail-closed gates and turn blocks
- ๐ How a shop, a service firm and an agency use hooks to protect client data
- ๐ Five copy-paste prompts that set up hooks inside your Agent OS
- ๐ Which AI model to pair with each hook setup, by real GoldieBench scores
- ๐ The complete Hermes Agent Hooks guide on the AI Profit Boardroom blog
FAQ: Hermes Agent Hooks Verdict
What score do Hermes agent hooks get?
8.4 out of 10 as an editorial rating from the docs: top marks for coverage, control and docs, lower marks for fail-open defaults and release timing.
What is the weakest part of Hermes hooks?
Safe defaults. Shell hooks fail open, fail_closed only applies to pre_tool_call, and a pre_llm_call callback that crashes lets the turn run.
Does a blocked prompt still reach the model later?
No, after the 1 Nov fixes. The prompt is stored as a withheld placeholder, which is all later turns, compaction, search and memory providers read.
Are Hermes hooks compatible with Claude Code hooks?
Largely. Hermes accepts decision/reason JSON, exit code 2 and failClosed, but Claude Code approve means auto-allow and is not mapped.
๐บ Video notes + links to the tools ๐
๐ฅ Learn how I make these videos ๐
๐ Get a FREE AI Course + Community + 1,000 AI Agents ๐
About Julian
I'm Julian Goldie, an SEO entrepreneur, author and founder of the AI Profit Boardroom, which has 3,400+ members.
I help business owners scale with AI agents, automation and SEO.
- I've built a 7-figure SEO and link building agency, Goldie Agency, with a team of 70+ SEO experts.
- I've grown a YouTube channel to 400,000+ subscribers.
- I wrote "Link Building Mastery".
- My Udemy courses have taught over 29,000 students.
โ Get my best AI training inside the AI Profit Boardroom
Score your own setup against the table, fix the fail-open gaps first, and if you want my team to check it, book a free strategy session about your Hermes agent hooks.











