?

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: ".*"}

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.reason set 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.

Related pages

Type to search 150+ pages. Ranking: BM25 with title/description boost.