The toggle model, and where it breaks
An integration is not one risk. It is a bundle of operations with completely different blast radii. A Stripe connection that can list invoices is a reporting tool. The same connection with refund access is a finance decision. A Linear connection that reads issues is harmless; one that closes them is not. Toggle the integration on and you granted all of it. Toggle it off and the agent cannot answer the questions it was hired for.
The failure is structural. Permissions attached to the connection cannot express the thing you actually mean, which is: this operation is fine, that one needs a human, and that one should not happen at all.
Classify by blast radius instead
The model that holds up puts the classification on the tool, at the definition layer, where the person writing the integration knows exactly what each call does to external state:
- Read retrieves data and mutates nothing. Listing customers, fetching a transcript, searching issues.
- Write creates or updates external state. Sending a message, creating an issue, updating a CRM record. Recoverable, but real.
- Destructive deletes or irreversibly alters data. Deleting a record, discarding a draft someone else wrote.
Three classes are enough. More granularity than this moves the decision back to people who lack the context to make it; less collapses back into the toggle model.
Defaults should fail safe
The classification only matters if it drives behavior nobody had to configure. The defaults that work: reads run, writes hold until a person approves them, destructive operations are restricted to admins. A new connector added on Tuesday inherits safe behavior on Tuesday, not after someone remembers to review its permission sheet.
Overrides then become deliberate exceptions rather than the whole system. Opening a specific write tool for a trusted workflow is one decision, recorded once. So is tightening a read tool that exposes something sensitive.
The caller must not matter
The subtle failure mode: one permission model for the chat agent, and a different, usually weaker one for everything else. If your agent in Slack needs approval to send an email but an editor connected over MCP can call the same tool freely, you do not have a permission model. You have a suggestion.
The rule: classification and defaults live with the tool, and every surface that can reach the tool goes through the same check. A caller-specific ceiling on top is useful (an endpoint that can never see write tools, whatever the per-tool settings say), but the floor must be shared.
How Notara implements this
Notara ships 70 connectors exposing 407 tools, and every one of them carries its capability tag in the tool definition itself. The defaults are the ones above: read tools are open, write tools require approval in Slack before they run, destructive tools are admin-only. Admins can override any tool individually from the dashboard.
The same resolution runs for every caller. An external agent calling over MCP gets the tool list with the same levels applied, plus an endpoint-level ceiling: an endpoint scoped to read can never surface a write tool, regardless of overrides. You can see the per-tool capability tags on every connector page, starting from the connector index, for example Linear (5 read, 3 write) or Stripe (18 tools, all read by design: list_customers ships, refunds do not).
Related: how to audit what agents did, which is what makes this model inspectable after the fact.