Skip to content

Risk classes

Every tool call is mapped to a capability, such as email.send, and one risk class:

Class Meaning Examples
READ observes, changes nothing read_file, web_search, mcp_gmail_get_message, ls
LOCAL_WRITE changes local state write_file, patch, memory add, skill_manage
EXTERNAL_WRITE changes remote state browser_click, mcp_*_create_*, git push, curl -X POST
COMMUNICATION sends to people or channels send_message, mcp_gmail_send_message
DELETE destroys data mcp_drive_delete_file, rm, git reset --hard
PERMISSION_CHANGE alters who can access what mcp_drive_share_file, chmod, sudo
FINANCIAL commits money mcp_shop_place_order, mcp_bank_transfer_funds
EXECUTION runs arbitrary code terminal (non-trivial), execute_code, cronjob create
UNKNOWN no signal never treated as safe

The first layer that matches wins:

  1. Explicit mapping. policies/defaults.yaml maps Hermes’ built-in tools. A mapping can depend on an argument:
    • send_message(action="list") is READ, and process(action="kill") is EXECUTION;
    • browser_console is READ, but with an expression it runs JavaScript in the page, so it is EXECUTION;
    • patch in multi-file mode names its files inside the patch text. AgentsFence reads the *** Add/Update/Delete File: headers and both sides of *** Move File: a -> b with Hermes’ own grammar (and Hermes’ patch parser when available), checks every path, and treats Delete File as DELETE;
    • a tool mapped as a read that takes an action, operation or method argument is a read only for actions declared as reads. spotify_library(action="list") is READ; action="save" is EXTERNAL_WRITE and action="remove" is DELETE. An undeclared action is classified by its verb, or as UNKNOWN.
  2. Glob patterns. For example, kanban_* → LOCAL_WRITE.
  3. Verb inference for everything else, including every MCP tool (mcp_<server>_<tool>):
    • the name is split into words, and the first verb decides: get_order is READ, place_order is FINANCIAL;
    • strong verbs anywhere in the name escalate the class: get_and_delete_record is DELETE;
    • a service keyword names the capability domain: gmail → email.*, drive → file.*, stripe → payment.*.

terminal commands are sub-classified:

Command Class
ls, cat, grep, git status, pipes of these READ, unless an option makes them write or launch something (sort -o, tree -o, rg --pre, yq -i, find -fprintf, git diff --output, git -c …)
git branch newname, git tag v1, git remote add, uniq in out LOCAL_WRITE
rm, shred, git clean, git reset --hard, git branch -D, git tag -d, git stash drop DELETE
curl -d/-F/-X POST, scp, ssh, rsync, git push EXTERNAL_WRITE (shell.network_write)
sudo, chmod, chown PERMISSION_CHANGE
anything else, or anything with ;, &&, $(…) or redirects that isn’t clearly worse EXECUTION
any command prefixed with variables (LD_PRELOAD=…, LESSOPEN=…), or a program outside system directories (./ls) EXECUTION

Compound commands are split, and the worst segment decides.

Terminal window
agentsfence classify mcp_gmail_send_message '{"to": "John <john@example.com>", "bcc": "x@y.com"}'

This prints the capability, the risk class, where the classification came from (mapped, pattern, inferred or unknown), and the extracted targets.

If a tool is misclassified, map it explicitly.