# Permissions — agents and grants

An **agent** (Claude Code, Codex, any MCP client) reaches a workspace's **capabilities** through
one door on the Cowork daemon, signed in with its own login. What it may run is **granted**, one
routine at a time, by the person who owns the workspace. Everything else — the app's panes, a
terminal's `cowork routine run`, schedules, webhooks, `ctx.routines.run` — is the owner, and grants
never gate it.

## What a capability author marks

A capability's routines ARE its tools: each entry in `routines` says what it does and what it
changes, as an MCP tool says it.

```json
{ "name": "clickup", "version": "1.1.0", "kind": "capability",
  "credential": { "key": { "fields": ["token"], "url": "https://app.clickup.com/settings/apps", "hint": "Settings › Apps › API Token" } },
  "routines": {
    "clickup-tasks":   { "file": "tasks.ts", "readOnly": true, "description": "Lists the tasks of a list",
                         "input": { "type": "object", "properties": { "list": { "type": "string", "description": "The list id" } }, "required": ["list"] } },
    "clickup-comment": { "file": "comment.ts", "reachesOthers": true, "description": "Comments on a task (its watchers are notified)" },
    "clickup-delete":  { "file": "delete.ts", "destructive": true, "description": "Deletes a task" }
  } }
```

- `readOnly: true` — it changes nothing: no write at the service, no money spent, no user or project
  code run, nothing written in the workspace but its own cache (no view state, no export, no file a
  person could have edited). Granted to every agent by default, and an agent's client may run it without
  asking — so when in doubt it is not a read. A read cannot also be `destructive` or `reachesOthers`
  (then `readOnly` is ignored, with a line).
- `destructive: true` — what it changes cannot be undone. `reachesOthers: true` — it reaches people
  beyond the account (sends, posts, pays).
- `description` (≤ 400 characters) and `input` (a JSON Schema `{"type": "object", …}` of its
  arguments, ≤ 8 KB) are what the agent reads before calling it — write them for an agent.
- A bare `"id": "file.ts"` is a write tool with no description: off for agents until granted.
- Risk is derived, never stored: a read is low; destructive or reaching others is high; the rest
  medium. Manage Workspace shows it beside each routine.
- Only `"kind": "capability"` packages are offered to agents — an app's own routines and loose
  routines are not. The capability's `SKILL.md` is the guide an agent gets with its tools.

## How the owner grants

Per workspace: a **default** for each `<capability>/<routine>`, and an **override** per agent. The
rule: the agent's own setting, else the workspace default, else on only for a read. A routine whose
connection is not connected (its `credential`) is unavailable whatever is granted.

- **Manage Workspace › Permissions › Agent access** — Add agent (the token is shown once, with the
  lines that connect a client), and per agent: each capability's routines with Default / Allow /
  Deny. **Capability defaults** — the workspace default, one switch per routine.
- **The CLI** (a headless server has no page):

```bash
cowork agent create claude                          # prints the token ONCE + the connect lines
cowork agent list                                    # name, id, last seen, revoked
cowork agent grants [--agent claude]                 # every routine: the default and each agent's answer
cowork agent grant clickup/clickup-comment allow --agent claude
cowork agent grant clickup/* deny                    # the default for every agent without its own setting
cowork agent grant clickup/clickup-comment default --agent claude   # back to the rule
cowork agent token claude                            # a new token; the old one stops working
cowork agent revoke claude --yes
```

Connect the agent from the workspace folder (Claude Code's local scope: private to that folder,
never in git — the URL names the workspace):

```bash
claude mcp add --transport http cowork 'http://127.0.0.1:47913/api/mcp?ws=%2Fpath%2Fto%2Fws' --header "Authorization: Bearer cwa_…"
```

(Codex: the `[mcp_servers.cowork]` block `cowork agent create` prints, in `~/.codex/config.toml`.)
The agent then starts a task, lists the capabilities it may use, and calls `read` (a granted read)
or `run` (anything else granted); a call that is not granted says so and names who to ask.

## What gets recorded

Every agent call is a routine run like any other — the same off switch, the same audit record —
naming the agent and its task: Manage Workspace › Observability › Executions shows **Who** (you,
or the agent) and the task; `cowork routine runs` lists them. A call that is not granted is
recorded `denied` and never starts.

## Who is this run for

`ctx.identity` (routines) is `{ user: {uid, email} | null, organization: {id, slug, name} | null }`
— who is signed into Cowork, frozen at the start of the run; use it to stamp who did what.
`cowork.identity.currentUser()` is the same user in a widget. `cowork status` and `cowork org`
show the organization.

## Known limit

Grants are policy on the owner's own machine: a process holding the daemon token is the owner and
can make agents or grants. They keep agents to what you allowed; they are not a wall against the
machine's owner.
