Policy rules

Describe what one runtime may do, in one JSON file.

The configuration file

{
  "runtime": {
    "human": "[email protected]",
    "agent": "coding-agent",
    "runtimeId": "local-development",
    "task": "bootstrap"
  },
  "repositories": [
    {
      "name": "acme/payments",
      "id": 123456789,
      "installationId": 12345678,
      "allowWorkflowWrites": false,
      "protectedBranches": ["main"]
    }
  ],
  "rules": [
    { "id": "read-repository", "action": "git.read", "repository": "acme/payments", "effect": "allow" },
    { "id": "feature-branches", "action": "git.push", "repository": "acme/payments", "ref": "refs/heads/agent/*", "effect": "allow" },
    { "id": "review-main", "action": "git.push", "repository": "acme/payments", "ref": "refs/heads/main", "effect": "approval", "approvals": 2, "reviewerSources": ["oidc"] },
    { "id": "protect-tags", "action": "git.push", "repository": "*", "ref": "refs/tags/*", "effect": "deny" },
    { "id": "protect-deletions", "action": "git.push", "repository": "*", "ref": "*", "operation": "delete", "effect": "deny" }
  ]
}

Evaluation

  • Unmatched actions are denied.
  • Deny beats approval, approval beats allow.
  • Repository reads (git.read) are required for both fetch and push discovery.
  • Each push is inspected before forwarding. If any ref is denied, none of the request is forwarded.

Rule fields

FieldValues
idUnique rule name, recorded in audit
actiongit.read, git.push, git.lfs.upload, github.pr.read, github.pr.create, github.pr.comment, github.pr.merge, github.actions.read
repositoryOWNER/REPO or *
refExact ref, trailing-* prefix (refs/heads/agent/*), or *
operationOptional: create, update, or delete
effectallow, deny, or approval
approvals1–5 distinct reviewers (approval rules)
reviewerSourcesSubset of local, oidc (approval rules)
requiresEntitlement requirements

A push touching several approval-gated refs takes the maximum approvals across matching rules.

Repository options

Workflow files

To allow pushes that edit .github/workflows, grant the App Workflows: write and set allowWorkflowWrites: true. This defaults to false and only applies to Git write tokens.

Push options

git push -o <option> is forwarded only when the option is listed in allowedPushOptions (exact strings or a prefix* wildcard; up to 32 entries; default none). A bare * allows any value. Disallowed options get 403 PUSH_OPTION_DENIED.

Option values are agent-controlled free text, so they are never stored — only a count and a SHA-256 digest, which binds the exact set into any approval.

Unicode ref names

Refs are ASCII-only by default. allowUnicodeRefs: true accepts NFC-normalized names without control characters, whitespace, bidirectional overrides, or zero-width characters. Rule patterns and protectedBranches stay ASCII-only, so a Cyrillic homoglyph of main can never match the rule written for the real main.

Content scanning

See Content scanning.

Reloading

Send SIGHUP to reload (docker compose kill -s HUP agentd). Invalid configs, and new protected branches without GitHub rules, are rejected; the previous policy keeps serving. A reload that changes policy supersedes outstanding approvals — reviewing one returns 409 APPROVAL_SUPERSEDED, and the agent retries to create a new request.

API actions

API actions default to deny and are separate from Git push authorization. All also require git.read.

ActionScopeGitHub App permission
github.pr.readRepository; allow/denyPull requests: read
github.pr.createRepository, head ref, optional headRepository; allow/deny/approvalPull requests: write
github.pr.commentRepository; allow/denyPull requests: write
github.pr.mergeRepository, base ref, headRepository, mergeMethods; approval/deny onlyPull requests: read, Contents: write
github.actions.readRepository; allow/denyActions: read