Overview
Hermes Agent (Nous Research) has a first-class hook system built for exactly this. Itspre_tool_call hook fires
immediately before every tool executes, built-in tools and plugin tools
alike, and can veto the call. Sigil Open Framework (SOF) registers a shell hook
that forwards each intended tool call to Sigil Sign /v1/authorize and blocks
when the policy returns DENIED.
Of the popular agent runtimes, Hermes offers the most complete pre-execution
surface: a single hook governs terminal, write_file, patch, web_search,
read_file, and any plugin or MCP tool the agent can reach.
Prerequisites
You need a Sigil API key and a signedwarranty.md policy file deployed to Sigil Sign.
- Get an API key: sigilcore.com/tools/keys
- Generate a policy: sigilcore.com/tools/warrant
1. Add the shell hook
Hermes shell hooks are declared in~/.hermes/config.yaml and run as
subprocesses when the matching event fires, in both CLI and gateway sessions.
matcher is a regex over the tool name. Widen or narrow it to match the
actions your policy governs.
2. Add the hook script
~/.hermes/agent-hooks/sigil-pre-tool-call.mjs:
SIGIL_API_KEY in your environment. On first use Hermes prompts once to
approve the (event, command) pair and persists the decision. For non-interactive
gateway or cron runs, pre-approve with HERMES_ACCEPT_HOOKS=1 or
hooks_auto_accept: true in config.yaml.
How It Works
Hermes pipes a JSON payload to the hook onstdin and reads JSON back from
stdout. The script maps the Hermes tool name to a Sigil action type, submits the
intent to /v1/authorize, and on a DENIED or PENDING decision returns the
canonical block shape. Hermes then short-circuits the tool and hands the reason
back to the model as the tool error.
{"decision": "block", "reason": "..."} and
{"action": "block", "message": "..."}.
Tool Name Mapping
| Hermes Tool | Sigil Action |
|---|---|
terminal | bash |
write_file, patch | file_write |
web_search, web_extract | web_fetch |
| Any other tool | the tool name, lowercased |
Plugin Hook Alternative
If you ship a Hermes plugin, you can register the same check in-process instead of as a subprocess. In your plugin’sregister():
Fail Mode
The script usesfailMode: 'closed', so a tool is blocked if Sigil Sign is
unreachable. Switch to failMode: 'open' for local development. Use closed mode
for any environment that touches production, external systems, or on-chain actions.
Configuration
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey | string | Yes | — | Sigil API key (sk_sigil_...) |
apiUrl | string | No | https://sign.sigilcore.com | Sigil Sign endpoint |
agentId | string | No | 'agent' | Agent identifier |
framework | string | No | 'agent-hooks' | Use 'hermes' for telemetry and audit routing |
failMode | 'open' | 'closed' | No | 'open' | Block (closed) or allow (open) when Sigil is unreachable |
Source
- github.com/Sigil-Core/agent-hooks — TypeScript package, MIT License
- Hermes Agent Event Hooks documentation