Task policies
A TaskPolicy is the contract for one task. Here is the policy for “Find my latest mortgage statement and summarize the balance.”:
purpose: summarize_mortgage_statementallowed_risk_classes: [READ]allowed_tools: [email.search, email.read, file.read]denied_tools: [email.send, file.share, file.delete]allow_external_writes: falseallow_destructive_actions: falseallow_financial_actions: falsemax_external_writes: 0And for “Read the report and email the summary to john@example.com.”:
purpose: email_report_summaryallowed_risk_classes: [READ, COMMUNICATION]allowed_tools: [file.read, email.send]allow_external_writes: trueallowed_recipients: [john@example.com]tool_constraints: email.send: {allowed_recipients: [john@example.com]}Fields
Section titled “Fields”| Field | Meaning |
|---|---|
purpose, summary |
short task name and description |
allowed_tools |
tool names, capabilities (email.read), globs, or risk classes |
denied_tools |
same syntax; deny beats allow |
allowed_risk_classes |
classes allowed without listing each tool (default [READ]) |
allow_local_writes … allow_permission_changes |
ceilings, one per consequential class |
tool_constraints |
per tool or capability: allowed_recipients, allowed_domains, allowed_paths, max_calls |
allowed_recipients, allowed_external_domains, allowed_paths |
task-wide target allowlists |
max_external_writes |
outbound budget for the whole task (sends + external writes) |
requires_approval |
always ASK_USER for these |
user_prohibitions |
things you explicitly forbade; checked before everything else except guards |
grants |
minimal deltas you approved at runtime |
expires_at |
default 12 hours after creation |
The full schema is in the policy schema reference.
When is a call authorized?
Section titled “When is a call authorized?”Two things must both be true:
- The class ceiling is on. For example, COMMUNICATION and EXTERNAL_WRITE need
allow_external_writes, and DELETE needsallow_destructive_actions. - The call is listed. Its tool name, capability or a matching glob is in
allowed_tools, or its risk class is inallowed_risk_classes.
Requiring both means one stray entry can’t grant a dangerous capability. A policy with allowed_tools: [file.delete] but allow_destructive_actions: false still blocks deletes. The compiler turns a ceiling on only when your own words contain the evidence.
UNKNOWN tools can only be allowed by their exact name, and only in a policy you write yourself (source: manual). A compiled policy never allows a tool AgentsFence can’t classify.
Default behaviour when a call isn’t authorized
Section titled “Default behaviour when a call isn’t authorized”| Risk class | Default verdict |
|---|---|
| READ | ALLOW |
| LOCAL_WRITE, EXTERNAL_WRITE, COMMUNICATION, EXECUTION, UNKNOWN | ASK_USER |
| DELETE, PERMISSION_CHANGE, FINANCIAL | BLOCK |
You can change these under evaluation.unauthorized. See Configuration.
Inspecting policies
Section titled “Inspecting policies”- In Hermes:
/fence - From the command line, compile any request without running it:
agentsfence compile "Clean up my Downloads and delete duplicates" --json