Skip to content

Grants

A grant gives the agent permission for one type of action. The grants list is necessary, and the list must contain at least one grant.

The registrar denies each action that no grant permits. There is no way to turn off this rule.

grants:
- read: { paths: ["**/*"] }
- shell: { commands: ["pytest *"] }
- edit: { paths: ["src/**"] }

Each item in the list contains exactly one grant. To give two permissions, write two items.

Grant Permission
read Read a file.
write Create a file.
edit Change a file.
search Search the code of the repository.
shell Run a command.
web_fetch Get a page from a domain.
web_search Search the web.
open_pr Open a pull request.
request_feedback Ask a person a question.
mcp Call a tool of an MCP server.

These three grants control files. Each one takes a list of path patterns.

grants:
- read: { paths: ["**/*"] }
- write: { paths: ["reports/**"] }
- edit: { paths: ["src/**", "docs/*.md"] }
Grant Permission
read Read a file that a pattern matches.
write Create a file that a pattern matches.
edit Change a file that exists and that a pattern matches.

A path pattern is a glob. The rules are these:

  • The path is relative to the root of the repository.
  • A * matches the characters in one segment.
  • A ** matches any number of segments. A ** must fill a complete segment, so write src/** and do not write src**.
  • A path must not start with /.
  • A path must use / as the separator.
  • A path must not contain a . segment or a .. segment.

The registrar refuses a path that breaks these rules, so an agent cannot leave the repository with ../.

The search grant lets the agent search the code. The scope must be repo.

grants:
- search: { scope: repo }

The shell grant takes a list of command patterns.

grants:
- shell: { commands: ["pytest *", "git diff", "go test ./..."] }

The registrar compares each command with each pattern, word by word. A * as a complete word at the end of a pattern matches each remaining word. So pytest * matches pytest -x tests/test_sync.py, and pytest * does not match pip install pytest.

Commands do not run in a shell. The registrar refuses a command that contains one of these:

  • A shell operator: ;, &, |, <, or >.
  • An expansion: $ or a backtick.
  • A newline.

A command that needs a pipe must become a script in the repository. Then grant the script.

The sandbox setting controls where these commands run. The none engine runs each command on your machine.

The web_fetch grant takes a list of domains, and an optional size limit in bytes.

grants:
- web_fetch: { domains: ["docs.python.org", "pkg.go.dev"], max_bytes: 500000 }

The registrar denies a fetch from a domain that the list does not contain.

The web_search grant takes no options.

grants:
- web_search: {}

The open_pr grant lets the agent open a pull request. To make a person approve each pull request, add requires: assent.

grants:
- open_pr: { requires: assent }

With requires: assent, the run stops at the pull request and waits for a person. You must configure an assent transport, because the run cannot ask anybody without one.

The request_feedback grant lets the agent ask a person a question during the run. The from field names the person or the role.

grants:
- request_feedback: { from: issuer }

The mcp grant permits tools of an MCP server by name.

grants:
- mcp: { tools: ["search_issues", "get_issue"] }

A * as the complete list of tools permits each tool. Write that pattern only when you accept each tool that the server has now and each tool that the server adds later.

Give the agent the smallest set of grants that can do the work. Then read the record. The record shows each denied action, so the record tells you which grant to add.

A grant that you add after a denial is a grant that the work needs. A grant that you add before the first run is a guess.