Agent Office v0.2.1 · POC Get started
Menu: Reference

Reference

Capability catalog

Every power an agent can be granted in its personnel file, and the concrete enforcement each one compiles into.

A capability is a named power. Agents start with none: anything not listed in the capabilities of their personnel file is denied. Each entry is a bare name (mail.read) or a single-key mapping with parameters (mail.send: { to: ["*"] }). Unknown names, bad parameters and duplicates are validation errors.

The office compiles the list (compile(personnel, office, context) in src/core/capabilities.ts, a pure function) into:

OutputWhere it is enforcedWhen
Forge grantsThe agent's forge user: read or write collaborator on each listed repo.Applied by the reconciler when the personnel file changes; stale grants are removed.
Token scopesThe forge token minted for one run (run-<runId>), revoked when it ends.Every run.
Sandbox egressThe hosts the run's sandbox may reach.Every run.
Claude Code settingsPermission mode and allow/deny rules, passed to the run with --settings.Every run.
Office MCP toolsWhich office tools the agent may call. A call without the capability is denied and ledgered as run.denied.Every call.

Capabilities from an approved, still-open approval window are added to the personnel list for runs and MCP calls in that window. See Capabilities for the idea, and Permissions & capabilities for how to change them.

Summary#

CapabilityParametersGrants
vault.writenoneEdit and push its own vault.
mail.sendto (optional)Start mail threads to colleagues.
mail.readnoneRead, reply to and close its own mail.
office.readnoneSee colleagues and what they are working on.
forge.readreposRead and clone the listed repos.
forge.writerepos, viaPush branches and open pull requests on the listed repos.
hr.proposenonePropose hires and capability changes as policy PRs.
artifact.publishnonePublish deliverables to its desk, committed to its vault.
approval.requestnoneAsk a human to approve something, including a temporary capability.
net.egresslist of hostsReach those hosts from the sandbox.
shellprofile (optional)Run a profile's shell commands.
budget.overrideusd (optional)Approval-only: keep running past the daily budget.

Every run's forge token has the scopes read:repository and write:issue (mail threads are issues). write:repository is added when the agent has vault.write or forge.write.

vault.write#

capabilities:
  - vault.write

Lets the agent change its own vault. Git is allowed as a whole rather than subcommand by subcommand: listing subcommands left agents stuck on harmless calls (git --version, git rev-parse), and the limits that matter are the run token's forge permissions and branch protection. Every hired agent is a write collaborator on its vault (that comes from provisioning, not from this capability); without vault.write its Claude Code settings deny editing the vault.

Compiles into:

  • Claude Code settings: allow Edit under the vault, and git as a whole (Bash(git *)). Without it: deny Edit on the vault, and deny Bash entirely unless the agent also has shell, forge.read or forge.write.
  • Token scopes: write:repository.

CLAUDE.md and .office/** stay read-only either way: denied in the settings, in the sandbox's denyWrite, and as protected files on the vault's main branch, so the forge rejects a push that changes them.

mail.send#

capabilities:
  - mail.send                          # anyone (same as to: ["*"])
  - mail.send: { to: [cos, analyst] }  # only these agents
ParameterTypeMeaning
tolist["*"] for anyone, or agent slugs. Each slug must be an agent in the policy. Omitted = anyone.

Compiles into:

  • Office MCP tools: mail_send. Mail to a recipient outside to is refused and ledgered as run.denied.

mail.read#

capabilities:
  - mail.read

Lets the agent list and read the mail in its own inbox, reply, and close threads.

Compiles into:

office.read#

capabilities:
  - office.read

An overview of colleagues: who exists, their roles and status, who is running now and how much open mail each has.

Compiles into:

forge.read#

capabilities:
  - forge.read: { repos: ["northwind-handbook"] }
ParameterTypeMeaning
reposlist of repo names (at least one)Repos in the office org the agent may read.

Compiles into:

  • Forge grants: read collaborator on each listed repo.
  • Claude Code settings: allow git as a whole (Bash(git *)), so the agent can clone the repos into work/<repo> inside its vault and inspect them. See Agents that open pull requests.
  • Office MCP tools: forge_list_prs.

forge.write#

capabilities:
  - forge.write: { repos: ["northwind-office"], via: pull_request }
ParameterTypeMeaning
reposlist of repo names (at least one)Repos the agent may push branches to and open pull requests on.
viapull_request (the only value, and the default)Changes arrive as pull requests. On a repo whose main is protected (the office, handbook and policy repos are, from officectl init), the agent can open PRs but can't merge them.

Compiles into:

  • Forge grants: write collaborator on each listed repo (write wins if a repo is also in forge.read).
  • Token scopes: write:repository.
  • Claude Code settings: allow git as a whole (Bash(git *)), and deny Bash(git push * main), Bash(git push * HEAD:main) and Bash(git push origin main). Those deny rules are a speed bump, not the boundary: a refspec can be spelled many ways. The boundary is branch protection on main, so protect main on every repo you grant this on (officectl init does it for the policy, office and handbook repos).
  • Office MCP tools: forge_open_pr and forge_list_prs.

The workflow (clone into work/<repo>, branch <slug>/<topic>, push, forge_open_pr) is in Agents that open pull requests.

hr.propose#

capabilities:
  - hr.propose

Lets the agent read personnel files and draft hires and changes. Each proposal is a pull request on the policy repo. It grants nothing by itself: a human approver has to merge it.

Compiles into:

artifact.publish#

capabilities:
  - artifact.publish

Lets the agent publish deliverables: reports, HTML pages, images, PDFs, CSV or JSON files. The office (not the agent) commits each one to the agent's vault under artifacts/<date>-<title>/ and lists it on the desk and the Artifacts page, for every human who may see the agent. Every role template grants it. See Artifacts.

Compiles into:

  • Office MCP tools: artifact_publish, artifact_list.
  • Nothing else: no sandbox paths, forge scopes or hosts. The agent never writes the files itself.

approval.request#

capabilities:
  - approval.request

Lets the agent ask a human for a decision. The request appears in Needs you in the web UI and in the human MCP tool approvals_list. A lead (approval.decide) approves or denies it; nobody can decide their own request.

A request can be a one-off action, a capability.window (a capability for a limited time, default 4 hours, at most 168), or a budget.override. Approving a window opens it (ledger capability.window.opened): until it ends, the capability is added to the agent's runs and MCP calls. Windows can carry any capability, including the approval-only budget.override.

Compiles into:

net.egress#

capabilities:
  - net.egress: ["api.anthropic.com", "*.example.org"]

A list of host names (wildcards like *.example.org allowed) the run may reach.

Compiles into:

  • Sandbox: the hosts are added to the sandbox's allowed domains (strictAllowlist), together with the forge host and the office host. When the forge or office resolves to an address of the office machine itself, its <ip>:<port> is allowlisted too, because the Linux sandbox otherwise refuses names that resolve to the local host.
  • Claude Code settings: allow WebFetch(domain:<host>) for each host, and Bash(curl *), Bash(wget *). Without net.egress: deny WebFetch, Bash(curl *) and Bash(wget *). WebSearch is always denied (it can't be limited to domains).

shell#

capabilities:
  - shell                      # same as { profile: basic }
  - shell: { profile: node }
ParameterTypeMeaning
profilebasic (default) | node | pythonA named set of commands.

Compiles into Claude Code settings allow rules (Bash(<command> *)) for:

ProfileCommands
basicmkdir, touch, cp, mv, rm, sed, awk, sort, uniq, cut, tr, jq, date, xargs, tee, ls, cat, head, tail, grep, wc, diff, echo, printf, pwd, basename, dirname
nodebasic plus node, npm, npx
pythonbasic plus python3, python, pip, pip3

Commands run inside the sandbox, and only allow-listed ones run (autoAllowBashIfSandboxed is off), plus Claude Code's built-in read-only commands. An agent without shell but with vault.write, forge.read or forge.write runs only git and read-only commands. An agent with none of these gets Bash denied entirely.

budget.override#

# not allowed in personnel.yaml: granted only through an approved window
{ "budget.override": { "usd": 5 } }
ParameterTypeMeaning
usdpositive number, optionalExtra allowance beyond budget.usd_per_day. Omitted = no cap while the window is open.

Approval-only: putting it in personnel.yaml is a validation error. An agent asks for it with approval_request (kind: budget.override); while the approved window is open, a hard_stop budget admits runs past the daily limit.

The floor every run gets#

Whatever the capabilities say, every run's compiled Claude Code settings include:

  • permissions.defaultMode from run.mode (default, acceptEdits or dontAsk). bypassPermissions is rejected, permissions.disableBypassPermissionsMode: "disable" and permissions.disableAutoMode: "disable" are set, and blockReadsOutsideWorkingDirectories: true.
  • Deny Read and Edit on the office state directory and every other agent's home, and Edit on /etc. Reads of /etc by Claude's file tools are refused by blockReadsOutsideWorkingDirectories; sandboxed commands get /etc in denyRead with only the CA trust paths re-opened (below).
  • Deny Bash(sudo *), Bash(su *), Bash(doas *), and Edit on the vault's CLAUDE.md and .office/.
  • Deny WebSearch; deny WebFetch, curl, wget unless net.egress is granted.
  • Allow exactly the office MCP tools the capabilities unlock (mcp__office__<tool>); deny the rest.
  • With host.sandbox: true: sandbox enabled with failIfUnavailable: true and allowUnsandboxedCommands: false, autoAllowBashIfSandboxed: false (sandboxed commands still need an allow rule), network limited (strictAllowlist) to net.egress + the forge host + the office host (plus their <ip>:<port> when they resolve to this machine), denyRead on the state directory, other agents' homes and /etc (on macOS also /private/etc), allowRead re-opening only the CA trust paths git, curl and node need for TLS (Linux: /etc/ssl/certs, /etc/ca-certificates, /usr/share/ca-certificates, /etc/pki/tls/certs, /etc/pki/ca-trust; macOS: /etc/ssl, /private/etc/ssl), and denyWrite on the vault's CLAUDE.md and .office.
  • enableAllProjectMcpServers: false. env is empty, except on Linux, where SSL_CERT_FILE and GIT_SSL_CAINFO point at the host's CA bundle (/etc/ssl/certs/ca-certificates.crt or /etc/pki/tls/certs/ca-bundle.crt).

The harness also passes --strict-mcp-config with the office MCP as the only server, and --setting-sources "" so no user, project or local settings file (the vault is agent-writable) can add rules. The run's model credential, its office MCP token and its forge token reach the process as environment variables, piped through stdin, never on the command line.

A system-wide floor is also written to Claude Code's managed settings file by officectl install. It binds every Claude Code session on the host and can't be overridden by --settings: deny Read/Edit on the state directory, bypass and auto mode disabled, sandbox enabled and failing closed with allowUnsandboxedCommands: false, strictAllowlist networking, and denyRead on the state directory.

OSPath
Linux/etc/claude-code/managed-settings.json
macOS/Library/Application Support/ClaudeCode/managed-settings.json

Custom capabilities#