Agents, tools & grants
The grant model
An agent reaches nothing by default. Every folder it reads and every account it touches is a switch you flipped, and the kernel, not the model, decides whether a tool call is allowed.
Hand a model a folder and a few tools and it stops being a chat box. That is what an agent is, and it raises the only question that matters: what can this thing actually do? Conifer answers with deny-by-default authority. A fresh agent holds no grants. It cannot read your notes, write a file, reach a host, or post to a channel until you flip a switch, one capability at a time.
What a grant is
A grant is a scoped, revocable permission bound to one agent. Each one names a capability and the resource it covers: read this folder, write inside the watched folder, reach this host, read this Slack channel. The model never writes a grant and cannot widen one. It asks for a tool call. The runtime checks that call against the grants you set, and either runs it or refuses. Grants are per agent. Turning on Notes for your research agent leaves every other agent untouched, and switching between agents carries no permission across.
The check sits below the model on purpose. You can argue with a language model. Text in a document can tell it to ignore its instructions, and sometimes that lands. So the gate that counts is not a sentence in the prompt, it is code. The runtime kernel holds the grant list, and a tool call outside that list is refused before it runs, however the model was talked into asking. The refusal shows up in the agent room as its own row, so a denied call is visible rather than silent.
Read, write, and reach
Grants divide by what they let an agent do, and that division is the safety story. Most grants only read. The connectors for Calendar, Reminders, Notes, and Contacts are read-only by construction: the agent can pull up a note or answer “what’s on tomorrow,” and there is no code path for it to edit or delete one. Reads also stay local. A connector reads a store on the machine and sends nothing.
Anything that changes the world outside the model is treated as heavier. A file write, a Slack post, a reaction: each one stages first and asks you before it commits. The agent proposes the action, you see exactly what it would do, and nothing happens until you confirm. The model can draft a message a hundred times. It cannot send one on its own.
| Grant | Scope | Kind |
|---|---|---|
| Write to this folder | The agent's watched folder, nothing above it | Stage and confirm |
| Read my notes | The local Notes store, read-only | Read, on-device |
| Slack | Only the channels you allowlist | Read; posts stage and confirm |
| Read these folders | The absolute paths you list | Read, wrapped as untrusted |
| Reach these hosts | Only the hosts you name | Network egress, opt-in |
The full list of integrations and the grant each one maps to lives in the connectors catalog.
For what every built-in integration grants, see the connectors catalog. To scope a tool you wrote yourself, see custom tools.
Three gates, not one
A capability that reaches the operating system, like reading your calendar on a Mac, passes three independent checks. They stack. All three must be true before a single event is read, and any one held back keeps the agent out.
- The OS permission
- macOS owns its own gate. The first time an agent reaches a protected store, the system asks you directly, and that prompt is the OS’s, not Conifer’s. A grant you flipped on stays inert until that one-time permission clears.
- The grant
- The per-agent switch above. This is the authority the kernel enforces on every tool call.
- The default
- A preference, set once, that turns a capability on for every agent you create next. It only ever flips grants on. It strips nothing, and it grants nothing the OS has not already cleared.
Keeping the three apart is what makes a grant honest. A default cannot bypass the macOS prompt. Clearing the macOS prompt grants nothing on its own. The path lands in the same place every time: a capability is live only when you have said yes in every layer that asks.
Nothing leaves the machine
A grant decides what an agent can do. It does not, on its own, open the network. Running a model makes no outbound call, and the read connectors send nothing. Two grants can touch the network, and both are explicit and narrow: web search, off until you turn it on, and reach these hosts, which permits exactly the hosts you name and no others.
Secrets follow the same rule. A Slack bot token is pasted once and held in the Mac Keychain by the kernel. It never lands in the agent’s config and never reaches the model, so a prompt cannot read it back or leak it. The grant carries the allowlist and the write toggle, not the credential.
Output the agent reads is still untrusted
A grant lets an agent read a folder. It does not make what is in that folder trustworthy. Everything a tool returns, a file’s contents, a note, a web page, comes back to the model wrapped as untrusted external data, so instructions hidden inside it cannot pose as commands from you. That boundary has its own page: untrusted output.