PAT scopes
A personal access token (bbpat_…) carries a list of permission scopes, fixed when the token is minted. This page states exactly which scopes exist, what each one grants today, and which endpoints check them.
Two independent axes
Two separate things are called "scope" in the product, and they are checked independently. A request has to satisfy both.
| Axis | Values | What it decides |
|---|---|---|
| Permission scope | read, publish, admin | Whether the token may write. Chosen at mint time with --scopes. |
| Resource scope | user-wide, or one agent / thread | Whether the token acts for the whole user or for a single resource. Not selectable from the CLI. |
Every PAT from brainbase token create is user-wide. Resource-scoped PATs exist, but only Brainbase mints them — see Resource scope.
Permission scopes
brainbase token create accepts a comma-separated list. Three values are allowed; anything else is rejected locally before the request is sent, and again by the server.
brainbase token create --name ci # scopes: read, publish
brainbase token create --name ci-readonly --scopes read
brainbase token list # scopes per token
| Scope | What it grants |
|---|---|
read | Every read endpoint. Grants no writes. Nothing checks for it — it is simply the absence of publish. |
publish | Every write endpoint. Of the three scopes you can mint, this is the only one anything checks. |
admin | Nothing beyond read. Accepted at mint time; no endpoint requires it. |
admin. A token minted with --scopes admin and nothing else is refused on writes with the same "lacks required scope: publish" error a read-only token gets. If you want a token that can write, include publish.Two further scopes exist in the platform and are enforced, but you cannot mint them: the token endpoint rejects anything outside read, publish and admin. They are issued internally to the credentials Brainbase plants in a sandbox, listed here so an unfamiliar scope name in an error is identifiable.
| Scope | Required by |
|---|---|
code:execute | POST /v2/tasks/{task_id}/code/run/sync and GET /v2/tasks/{task_id}/code/capabilities, in addition to publish. |
messages:write_roles | Appending a message whose role is not user, when the caller is a resource-scoped PAT rather than an agent manager. |
Scopes are immutable. token rename changes only the label; to change what a token can do, mint a replacement and revoke the old one.
brainbase token create with no --scopes sends read,publish. The underlying mint endpoint defaults to read alone when the field is omitted, so a token created outside the CLI may be read-only even though the CLI's default is not.What is actually enforced
On the CLI control plane at /v2/cli, the rule has no exceptions: every write requires the publish scope, and no read requires any scope. All 13 mutating endpoints carry the check; all 15 read endpoints carry none.
| Endpoint | Scope required |
|---|---|
POST /v2/cli/agents | publish |
PUT /v2/cli/agents/{agent_id} | publish |
PUT /v2/cli/agents/{agent_id}/manifest | publish |
PUT /v2/cli/agents/{agent_id}/secrets | publish |
POST /v2/cli/agents/{agent_id}/keys | publish |
DELETE /v2/cli/keys/{key_id} | publish |
PUT /v2/cli/agents/{agent_id}/connections/slack | publish |
DELETE /v2/cli/agents/{agent_id}/connections/slack | publish |
PUT /v2/cli/agents/{agent_id}/connections/meeting | publish |
DELETE /v2/cli/agents/{agent_id}/connections/meeting | publish |
POST /v2/cli/orgs/{org_id}/teams | publish |
POST /v2/cli/orchestrations | publish |
PUT /v2/cli/orchestrations/{orch_id} | publish |
Every GET under /v2/cli | none |
Outside /v2/cli the rule is patchier. Some writes check publish unconditionally: agent secrets, file uploads, thread creation, orchestration writes, and the benchmark mutations. Others are covered only by a newer blanket guard that is deployed but not yet enforcing — it is gated on a server setting that currently logs a would-be denial and lets the request through. Templates, machines, evals, alerts, orchestration templates and most of PATCH /v2/agents/{agent_id} sit in that group.
/v2/cli it is, with no exceptions. Elsewhere, a read-only PAT can still reach the writes covered only by the non-enforcing guard. Treat read as a guardrail for CLI use, not as a product-wide read-only credential. The one place a read is gated at all is task code execution, which needs code:execute on both its read and its write.The check applies to PATs only. A browser login session is a Supabase JWT and carries no scope list, so it is never scope-checked and can always write whatever the user's role allows.
Error responses
A token without the scope a write needs gets 403 before the handler runs, so nothing is created or modified:
{
"detail": "PAT lacks required scope: publish"
}
Two nearby failures that are not scope failures, and have different fixes:
| Response | Meaning |
|---|---|
401 missing bearer token | No Authorization header. |
401 invalid or expired PAT | The token does not resolve — revoked, expired, or mistyped. |
403 credential_scope_denied | The token resolved and has the right permission scope, but it is bound to a single resource. Only one /v2/cli route raises this today — see Resource scope. |
Resource scope
Independently of read/publish/admin, a credential is either user-wide or bound to exactly one resource. The intent is that a resource-bound credential cannot reach routes that configure things above a single resource — orgs, teams, agent creation — even when it carries publish.
| Binding | Minted by | Reaches |
|---|---|---|
| User-wide | brainbase token create, or the dashboard | Everything the user can reach. |
| One agent | Brainbase, when an agent's sandbox starts or a scheduled trigger fires | That agent, plus orchestration peers it has an edge to. |
| One thread | Brainbase, per running thread | That thread. |
/v2/cli refuse unconditionally today — listing a team's agents, and the five orchestration endpoints. Everything else admits a resource-scoped credential for now, so do not treat resource binding as a security boundary you can rely on.The two refusals also read differently. GET /orgs/{org_id}/teams/{team_id}/agents answers with the credential_scope_denied object listed above. The orchestration endpoints answer with a plain string naming the binding, for example agent-scoped PATs cannot access orchestration configuration.
You cannot mint a resource-scoped PAT from the CLI, and you do not need to: the resource-scoped tokens an agent uses are planted in its sandbox automatically. The distinction matters when reading an error — a 403 naming credential_scope_denied came from a token Brainbase minted for a sandbox, not from a token you created.
Which credential each surface accepts
A PAT and a login session are not interchangeable everywhere. Three rules cover it:
- Minting and managing PATs requires a login session.
token create,list,renameandrevokeall reject a PAT withjwt_required— a PAT cannot mint another PAT. - Everything else on the control plane accepts either. A PAT with the right scopes can do anything a session can, subject to the
publishrule above. - The PAT has to be in the BRAINBASE_TOKEN environment variable for control-plane commands. A PAT saved on disk by
token createis not read byagent,orchestration,link,unlink,sync,statusorteam. See Authentication.