Engineering NotesSecurity and audit
Customers know their connector tools' risks, so tool policy is per install

Say a customer turns its internal e-approval system into an MCP server and attaches it to OwlAI as a connector (an external service, such as an MCP server, that a company connects to OwlAI). The server has one tool that looks up approval documents and another that approves them. Approving is hard to undo, so that tool should run only after a person confirms it. But the product has never seen this server. If the product code hard-codes a table of risky tools, the approve tool isn't in it, gets the default, and runs without confirmation.
The party that knows what an external tool does is the customer that attached the server. So whether an external tool is allowed, needs approval on every call, or is blocked is a rule that administrators set for each installation (each organization on OwlAI SaaS). What the product code decides is which rule wins when several match one tool, and the defaults for built-in tools, which the product wrote and whose risk it knows. This post covers what those rules look like, the order they are judged in, and why the defaults are what they are.
A risk table in product code doesn't know tools on servers it hasn't seen
Keeping a risk table in product code has real advantages. The same standard applies the moment the product is installed, and administrators have nothing to set. The limit is that the table only knows servers the product has seen. Tools on a server the customer built aren't in it, and a name that is in it may do something else on a customer's server. Changing the standard means waiting for a product release.
Guessing from tool names has the same problem. Sort tools into risky and safe by prefixes like delete_ or send_, and any server that doesn't follow that naming convention gets sorted wrong. Whether the approve tool is called approve or sign, a prefix list can't know before it has seen the server.
Another option is readOnlyHint, an annotation on MCP tool declarations. The server marks each tool as read-only or not. But it is a hint the server reports about itself, and the MCP specification says annotations from untrusted servers should be treated as untrusted. When a server leaves the value out, the default is "not read-only," so every lookup tool on a server that gives no hints is classed as not read-only. Classify the 77 external tools attached in production (observed September 2026) by the hint, and 46 come out as not read-only, five of which are document search tools. So whether a call needs approval is decided only by the rules administrators write.
A rule has three fields: scope, target and decision
A tool policy rule that an administrator sets has three fields.
| Field | Values |
|---|---|
| Scope | Global (whole organization), role |
| Target | Tool name, connector, category |
| Decision | Allow, approval required, block |
A role-scoped rule can't name a tool, and its decision is either allow or block. Whether each individual tool is allowed, needs approval or is blocked is set by global rules that cover the whole organization. The admin API answers 400 with TOOL_POLICY_ROLE_TOOL_UNSUPPORTED when a role-scoped rule tries to name a tool, and with TOOL_POLICY_ROLE_APPROVAL_UNSUPPORTED when it tries to require approval.
The split follows from the fact that a tool's risk is a property of the tool, the same no matter who calls it. The approve tool approves documents whether finance calls it or sales does. So risk is set once per tool with a global rule, and a role only decides which connectors it may use. On the connectors page, administrators pick Allow, Approval or Block for each tool in the tool table. On the role page, the only choice is whether to allow each connector.
When several rules match, one ranking of scope and decision picks the winner
One tool can match several rules. If the approvals server is allowed for the finance role and the approve tool carries a global approval-required rule, both rules match when a finance user calls that tool. The winner is decided by a five-step ranking that combines scope and decision.
- Global block
- Role block
- Global approval required
- Role allow
- Global allow
When several rules share a rank, the more narrowly targeted one wins: a tool name beats a connector, and a connector beats a category.
In the example, global approval required (3) ranks above role allow (4), so finance users must get approval every time they call the approve tool. Roles that aren't allowed the approvals server don't see the tool at all. A tool an administrator has blocked for the whole organization sits at the top of the ranking, and no role's allow opens it again.
Specificity could have been the first criterion. It matches the intuition that the most narrowly targeted rule wins, and it makes exceptions easy to stack. But then a connector allow on a role would beat a category block set globally, and external tools the administrator turned off for the whole organization would come back for a single role. So specificity is the second criterion, used only within a rank.
Connectors open to a role only when allowed, tools inside them close only when blocked
The two axes have opposite defaults. The axis linking roles to connectors defaults to block: a role's users see a connector's tools only after the connector is allowed for that role. The one exception is the system role given to the administrator user type, which has every connector open. Tools inside a connector, on the other hand, are allowed when no rule matches. Administrators pick the tools to restrict and set approval required or block on them.
The defaults differ because the units differ. Opening a connector to a role is one decision per connector. A connector carries dozens of tools, and if each had to be allowed before use, a newly attached connector would have no usable tools for a while. A new connector is visible only to the roles the administrator picked, so tools nobody has looked at are never opened to the whole organization.
A connector's tool table fills from the tools that connecting users receive. On a connector where each user authenticates separately, people have different permissions in the outside service and receive different tools, so whoever connects, the tools they receive are added to the organization's list. A newly arrived tool has no rule, so it is allowed, and it is marked "New" in the administrator's tool table. The list received when the connector is first attached carries no such mark, and the mark goes away once an administrator opens the tool or changes its permission. A daily cleanup job removes tools that nobody's connection has returned for toolPolicy.mcpCatalogUnseenDays (30 days by default).
A blocked tool drops out of the tools the model can choose from, and the permission check right before execution blocks it again. When an administrator blocks several tools at once, the Block tools dialog appears first and shows how many tools will be blocked and how many playbook tasks that use them will fail. Rules are read fresh at every decision, so a change an administrator makes takes effect from the next question in chat.
Built-in tools, whose risk the product knows, are decided by code constants
The product wrote its built-in tools and knows what they do. So decisions for built-in tools come from code constants rather than administrator rules. The desktop app's tools that read and write files on the user's PC require approval whatever administrator rules exist, and no administrator rule can lift that approval. This keeps one broad allow rule from wiping out approval for these tools. “Told to confirm first, the model still sends the email, so approval happens right before execution” lists which built-in tools accept "Always allow."
The exception is three built-in tools that can send sandbox files or conversation content to outside hosts. Their use varies from customer to customer, so administrators can tighten their defaults.
| Tool | Product default |
|---|---|
| Upload a sandbox file to an outside URL | Approval required |
| Fetch a file from an outside URL | Approval required |
| Extract the body of a web page | Allow |
Web page extraction is allowed by default because runs with nobody to answer an approval prompt, such as deep research researchers and playbooks, need it. A customer who wants to stop it from opening outside pages tightens it with one approval-required or block rule that names the tool. These three tools read only rules that name them, and ignore broad rules set on a connector or category. Administrator rules can only tighten the defaults, so the admin API answers 400 with TOOL_POLICY_BUILTIN_LOOSEN_UNSUPPORTED when someone tries to save an allow rule on a tool whose default is approval required. “A URL in a tool result stays closed if the model wrote it first” covers the address provenance check that keeps the web page extraction tool from opening any address it likes.
A tool that can't be judged can't be used
If the rules have never been read, or an error occurs during the decision, there is no way to know whether an administrator blocked a given tool. In that case external tools and the three built-in tools that send data out can't be used. They are treated as blocked: they drop out of the tools the model can choose from, and calls to them are refused. Leaving an unjudged tool open would let an approve tool the administrator had blocked run without confirmation at that moment. Failures aren't remembered, so once a later decision succeeds, the tool returns to its normal permissions.
Design choices
External tools are judged by administrator rules rather than annotations. Annotations would have one advantage: some tools would get approval before an administrator sets anything. But the values are the server's own claims. Mistake a lookup tool for a risky one and approval prompts appear for nothing; mistake a tool that writes to an outside service for a read-only one and it runs without confirmation. So administrators decide approval and blocking. When they attach a connector, and whenever the "New" mark appears, they review the tool table and pick approval required or block for each tool.
The rule order is fixed at five ranks instead of letting administrators order rules. Letting administrators set the order, as in a firewall, gives more expressive power, but as rules pile up it gets hard to tell from the screen which one wins. With a fixed ranking, one table explains the outcome however many rules match, and no combination lifts a global block. The cost is that a rule like "approval required for this role only" can't be written. A tool that requires approval requires it for every role that uses it.
Roles are set per connector instead of in a role-by-tool table. Such a table would allow finer splits inside one mail connector: reading mail for every role, sending mail for just one. The cost is that granularity. Every role gets the same decision for the tools inside an open connector, and stopping a tool for only some roles means blocking it globally or closing the connector for those roles. In return, administrators set exactly one value per tool, and the tool table doesn't grow as roles are added.
If your product lets each customer attach different plugins, start by sorting tools by who knows their risk. Put the tools the product wrote in code constants and the tools customers attach in per-installation rules set by administrators, and no tool ends up judged in two places.
What problem does this solve?

Insights · Security and audit
Once the AI sends email and edits tickets, who approves it?
"File last week's meeting action items as issues." "Find open slots in the team's calendar next week." Once em…

Insights · Security and audit
Email can't be unsent. So can you let an AI hit send?
Say you ask the AI to "let everyone from last week's meeting know the schedule changed," and it misreads the a…

Insights · Security and audit
A hidden line in an email you asked it to summarize. Will the AI obey?
You ask the AI to summarize twenty emails from business partners.
More in Security and audit

Engineering Notes · Security and audit
External models never see internal-only data, not even its name
Put a model running inside the customer network and an external API model in one installation, and deciding wh…

Engineering Notes · Security and audit
A URL in a tool result stays closed if the model wrote it first
Tools that read a web page or download a file from a URL only open addresses that appeared earlier in the conv…

Engineering Notes · Security and audit
Scrubbing answers is too late for phone numbers. We mask tool results
"Find the customers who asked for a refund more than three times last week and summarize what they said" is no…