DocsAccess control
Start here
Build and run
DocsReference
Access control
Every call answers three questions in order. Which projects can this caller reach, which of the toolkit's actions does the project allow, and which of those was this agent granted.
The three levels
Each level can only narrow what the one above it left open. Nothing lower down widens anything, so a project's own settings are the outer edge of what any member or agent in it can do.
- The projectWho is on it, and who runs it
- A project is public to the whole team or private to the people named on it. Anyone in the workspace can create one, and becomes its first admin. Project admins add and remove people, promote other admins, flip the visibility, install and remove toolkits, and delete the project. Organisation owners and admins reach every project by role.
- The toolkitWhich of its actions the project allows
- Each installed toolkit's actions can be switched off individually, for everyone in the project at once. What is stored is the list of what is off, so an empty list means every action the toolkit declares, and a connector that grows a new operation has it available without anybody opting in.
- The agentWhat one key gets of that
- An agent key is granted projects. Within a project it can be narrowed to particular toolkits, and within a toolkit to particular actions. A key with no narrowing in a project reaches everything installed there, which is what every key issued before this existed still does.
An agent key is capped by its owner
Every agent key belongs to a member of the workspace. What it reaches is the grant it was given, intersected with what that person can reach at the moment of the call, not with what they could reach when the key was issued.
So taking somebody off a private project takes it out of their agents' reach on the next call, and removing them from the workspace stops their keys resolving at all. The same rule applies whether the call arrives on a raw agent key or through a connector that person signed into over OAuth. The cost is that an agent stops working when the colleague who created it moves on; a project admin can hand the agent to somebody else, and that hand-over is recorded, because it changes what a live token reaches without the token changing.
How an action is classified
Every operation a toolkit exposes carries one of three kinds. The words are the same on every screen that shows them, so a person who meets the same tool twice in one session does not have to work out that two colours mean one thing.
| Kind | Meaning | Example |
|---|---|---|
read | No side effects. | Fetching an issue, listing messages, running a query. |
write | Changes data. | Opening a pull request, posting to a channel, updating a record. |
destructive | Deletes data. | Dropping a branch, deleting a file, closing an account. |
What the classification is for
The project's action screen groups a toolkit's actions by kind, so turning off everything classified destructive is one click rather than a pass down a list. What that click writes down is an explicit list of switched-off action names.
There is no standing rule behind it. Nothing means “read-only, including whatever gets added later”: an action a connector gains in a later release is available until somebody switches it off. An action carrying no kind at all, which is possible for a toolkit you build yourself, is shown under write, so selecting the read group never sweeps it in by accident.
Where a method cannot tell a read from a write, the request body is inspected instead. A GraphQL document carrying a mutation under an operation declared read is refused, when the toolkit is built and again when the call goes out, so a kind a screen shows cannot quietly be wrong about what the call does.
Where the check happens
Twice, on two different questions. What is allowed shapes what an agent can see: a search only ever returns actions the caller could actually run, so an agent is never told about a tool it would be refused. Then the same question is asked again server side when the call is made, because visibility is not permission and the agent may have learned a name some other way.
The project's switch is applied first and the agent's grant second, and the order decides the wording. An action the project turned off is refused with a sentence saying so, even when the agent's grant lists it. The permission was never this caller's to lose, and a message blaming their own grant would send them looking in the wrong place.
A refusal comes back as a result rather than a transport error, with a sentence naming the reason, and it costs no credit. Neither does a request that never resolves to a real tool.
Arguments are retained unless the operation says otherwise. A connector can name the arguments that must never be stored, and those are replaced before the row is written, which is what covers content arriving under an ordinary name. Everything else is redacted by key name on read: a value under a key that looks like a secret is masked wherever it appears. An operation that carries content and declares nothing keeps that content in the row, even when its response is withheld.
An install lives in a project, so the same toolkit can allow different actions in two of them. See Projects.