Overview
agent.approver decides whether every tool call runs. Three modes: allow_all, deny_all, pattern. This page catalogues pattern-mode configs by role.
Deny wins over allow. Unmatched requests use default. The full field reference lives at Reference: Config: Agent.
Role playbooks
Reads/greps everywhere, no writes.
agent:
approver:
mode: pattern
default: deny
allow:
- {tool: read, match: ".*"}
- {tool: grep, match: ".*"}
- {tool: bash, match: "^(git (log|diff|show|blame|status)|gh pr (view|diff|checks) [0-9]+|rg )"}
deny:
- {tool: bash, match: "gh pr (merge|close|edit|approve)"}
- {tool: write, match: ".*"}
- {tool: edit, match: ".*"}
Read runbooks, tail logs, inspect kubernetes but never mutate.
agent:
approver:
mode: pattern
default: deny
allow:
- {tool: read, match: ".*"}
- {tool: grep, match: ".*"}
- {tool: bash, match: "^(kubectl get|kubectl describe|kubectl logs|journalctl -u [a-z0-9-]+|dmesg|systemctl status [a-z0-9-]+)"}
deny:
- {tool: bash, match: "kubectl (delete|scale|patch|apply|edit|exec)|systemctl (stop|restart|start)|sudo"}
Reads docs only. No shell, no writes.
agent:
approver:
mode: pattern
default: deny
allow:
- {tool: read, match: "^/workspace/docs/.*"}
- {tool: grep, match: "^/workspace/docs/.*"}
Reads and edits docs; no other tools.
agent:
approver:
mode: pattern
default: deny
allow:
- {tool: read, match: ".*"}
- {tool: grep, match: ".*"}
- {tool: edit, match: "^/workspace/docs/.*"}
- {tool: write, match: "^/workspace/docs/.*"}
Runs vulnerability scanners; no writes, no destructive shell.
agent:
approver:
mode: pattern
default: deny
allow:
- {tool: read, match: ".*"}
- {tool: grep, match: ".*"}
- {tool: bash, match: "^(govulncheck ./...|npm audit --json|trivy fs .|semgrep --config auto .)"}
Universally-safe deny rules
Add these to every pattern config:
deny:
- {tool: bash, match: "rm -rf|:\\(\\)\\{ :\\|:& \\};:"} # fork bomb, rm -rf
- {tool: bash, match: "sudo|doas|pkexec"} # privilege escalation
- {tool: bash, match: "curl [^|]*\\| *sh|wget [^|]*\\| *sh"} # pipe to shell
- {tool: write, match: "\\.ssh/|\\.aws/|\\.gnupg/|/etc/"} # sensitive paths
- {tool: edit, match: "\\.ssh/|\\.aws/|\\.gnupg/|/etc/"}
Testing
- Log every denial with
agent.approver.reasonset to a descriptive string. Denials appear in the transport reply so users know why. - Grep
journalctl … | grep "denied by pattern policy"in staging to find prompts that hit unexpected denies.