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

Reference

Permission catalog (humans)

The roles humans hold, the scopes they apply to, and the minimum role for every action in the web UI and the human MCP.

Humans get roles on scopes, set in access.yaml. Agents get capabilities instead; see the Capability catalog.

Roles#

viewer  <  operator  <  lead  <  admin  <  owner

Each role includes everything below it. The office owner from office.yaml is always owner on office, even if access.yaml is missing or broken.

Scopes#

ScopeCovers
officeAll agents and everything else.
dept:<name>Agents whose department is <name>.
agent:<slug>One agent.

How a check resolves#

For an action on a target, the office takes the highest role among the human's grants whose scope covers the target, and compares it to the permission's minimum role:

can(human, permission, target?) -> boolean
  • office covers every target.
  • dept:x covers agents with department: x.
  • agent:s covers agent s.

Example: Dana holds lead on dept:engineering and nothing else. She can kill a run of an engineering agent (run.kill needs lead), but can only see agents elsewhere if she also holds a role that covers them.

Checks come in three shapes, declared per route or tool: against one agent (its slug and department, as above); anywhere, for list pages and list tools, which need the permission on some scope and then show only the items each grant covers; and office, which counts only grants on office (the Audit and Settings pages, the ledger tools, access proposals).

The catalog#

The complete list (PERMISSIONS in src/core/rbac.ts). The Allows text is what the People and Account pages show.

PermissionMinimum roleAllowsUsed by
office.readviewerSee the office floor: agents, their status and what they are doingFloor / and its 2D/3D data GET /api/floor, live updates /events; MCP office_overview, agents_list
agent.readviewerOpen an agent's desk: charter, capabilities, runs, mailDesk /agents/<slug>; the chat page /agents/<slug>/chat[/<id>], GET /api/chats, GET /api/chats/<id> (your own threads only); MCP agent_get
mail.readviewerRead mail threads with agents/mail, /mail/<slug>/<number>
artifact.readviewerSee and download the reports and files agents publishArtifacts /artifacts, /artifacts/<id>, /artifacts/<id>/raw/<file>, GET /api/artifacts, the Artifacts card on the Desk
run.readviewerSee runs and their timelines/runs, /runs/<id>; MCP runs_list, run_get
approval.readviewerSee pending approvalsNeeds you /needs-you; MCP approvals_list
people.readviewerSee who has access to the office/people
account.manageviewerManage your own account and MCP tokens/account, token create and revoke, theme (POST /account/theme)
agent.chatoperatorChat with agentsSending, new threads, rename, pulling a queued message back, and Stop on the run answering your own thread (/api/chats*, the chat page's form); MCP agent_chat
mail.sendoperatorSend mail to agents/mail/new, replies on /mail; MCP mail_send
run.startoperatorStart runs manuallyGive … a one-off task on the Desk (a manual run)
run.transcript.readleadRead full run transcripts/runs/<id>/transcript, full event contents in run_get; live chat text (delta events on /events) of that agent's runs, besides the thread's owner
run.killleadStop running runsStop run on a run page (stopping the run of your own chat thread needs only agent.chat)
approval.decideleadApprove or deny agent requestsDecide on Needs you, and End now on an open window (POST /windows/<id>/revoke); MCP approval_decide
hire.proposeleadPropose hires and capability changes (opens a policy PR)/hire; MCP hire_propose
agent.suspendadminSuspend or resume agentsSuspend / Resume on the Desk (opens a policy PR)
access.proposeadminPropose access changes for people (opens a policy PR)Changes and invite links on /people
ledger.readadminRead the audit ledgerAudit /audit; MCP ledger_query, ledger_verify
settings.readadminSee office settings and health checks/settings
verify.runadminRun the security verification suiteDeclared; no web route or MCP tool uses it yet. Run the suite with officectl verify on the host.

One permission per door#

Every HTTP route declares exactly one permission, or is explicitly public with a reason: sign-in pages (/login, /logout, /invite/<token>), /healthz, static assets, the forge webhook (authenticated by HMAC) and the two MCP endpoints (authenticated by bearer token inside the handler). Registering a route without a declaration throws, and the test suite checks it. Every human MCP tool also declares exactly one permission.

Chat threads are personal#

On top of the permission, a chat thread is checked for ownership. Reading a thread needs agent.read on the agent and the thread being yours; sending, renaming, pulling a queued message back and stopping the thread's run need agent.chat and the thread being yours. Someone else's thread is a 404, not a 403, so thread ids don't reveal who chats with whom. Stop is deliberately narrow: it stops only the run answering your thread; any other run needs run.kill. See Chat with an agent.