Skip to content

Evaluation order

The evaluator is deterministic. For each call, the first check that decides wins.

# Check Verdict rule_id
1 Policy expired BLOCK policy-expired
2 Modifies protected paths (AgentsFence state, the plugin, any profile’s Hermes config/.env/auth.json/plugins/), or runs hermes plugins/config/hooks… or pip uninstall agentsfence BLOCK self-protection
3 Matches a user prohibition BLOCK user-prohibition
4 Matches the deny list BLOCK policy-deny
— Touches a secret file (~/.ssh, ~/.aws/credentials, ~/.hermes/.env, …) ASK_USER, combined at the end secret-access
— Any other state-changing shell command inside the Hermes home ASK_USER, combined at the end hermes-home-access
— Writes into another profile (cross_profile) ASK_USER, combined at the end cross-profile
— Patch text names no files AgentsFence can parse ASK_USER, combined at the end path-unverifiable
5 A grant for this exact action (tool, capability, risk class, fingerprint) with uses left ALLOW approved-grant
6 Violates a tool_constraints recipient, domain or path limit BLOCK recipient-not-authorized, domain-not-authorized, path-not-authorized
6 max_calls reached (including calls waiting on approval) BLOCK call-limit-exceeded
6 Recipient can’t be determined under a recipient constraint ASK_USER recipient-unverifiable
7 Class ceiling off, or not listed (UNKNOWN tools: exact name in a manual policy only) per evaluation.unauthorized unauthorized-<class>
8 Recipient (of a message, share, or an external write that names people, such as calendar attendees) not named by the user in a compiled policy BLOCK recipient-not-authorized
8 Compiled communication authorized but no recipients bound ASK_USER unbound-recipient
9 Domain outside allowed_external_domains BLOCK (writes) / ASK_USER (reads) domain-not-authorized
10 URL looks like it carries data out ASK_USER exfil-url
11 Write or delete outside allowed_paths BLOCK path-not-authorized
12 Outbound budget exhausted BLOCK external-write-budget
13 Matches requires_approval ASK_USER requires-approval
14 Otherwise ALLOW policy-allow

A manually written policy can deliberately allow a recipient domain when it lists no individual recipients. A compiled policy cannot use a browsing domain as recipient authority.

The “combined at the end” questions stand even if the policy would allow the call; a BLOCK from any check still wins over them. A grant for the exact action satisfies them, because you approved exactly that.

After evaluation:

  • When Hermes would auto-approve, ASK_USER becomes BLOCK: always under the read-only fallback policy (fallback-no-human), and otherwise when strict_yolo is on (strict-yolo).
  • With plugin_conflicts: strict and other pre_tool_call plugins present, ASK_USER becomes BLOCK (plugin-conflict).
  • A call that carries only a task id unknown to AgentsFence is blocked before evaluation (no-policy-for-task).

In the plugin, an internal error at any step returns BLOCK, and the audit log records an error event.

  • Guards first. Nothing, not even a policy you wrote by hand, lets the agent turn off its own fence.
  • Hard stops are combined. A BLOCK from any of them wins, so a question from one check can never pre-empt a block from another.
  • Prohibitions before grants. What you forbade can’t be approved away mid-task by clicking “yes”.
  • Grants before class checks. An approval you gave for an exact action is honoured without asking again.
  • Constraints before ceilings. An explicit “only John” is reported as the reason for a block, rather than a generic “outside authority”.