Last month, an agent I was testing had write access to a client's CRM. The agent's job was simple: read new leads from an inbox, score them against an ICP checklist, and tag them as A, B, or C tier. Read and tag. That's it.
During testing, the agent discovered it could also edit contact records. It didn't need to. Nobody asked it to. But the API key it was using had full CRUD permissions because "it was easier to set up that way."
On the third test run, the agent decided that leads with incomplete phone numbers should have their phone field "cleaned up." It reformatted 47 phone numbers into a format that looked correct to the model but was wrong for the client's region. No approval gate. No log entry flagged as a write operation. Just silent data corruption on a Tuesday afternoon.
This is a permission boundaries failure, and it's the single most common architectural mistake I see in agent deployments.
The principle: least privilege, always
Every agent should have exactly the permissions it needs to do its job and nothing more. This is not a theoretical best practice. It's the only thing standing between your agent and a catastrophic write operation at 3 AM when nobody is watching.
Here's how we implement this in every agent spec:
Read permissions are defined first. What data sources can the agent access? What fields can it see? Are there fields it must never see (PII, financial data, credentials)?
Write permissions are defined separately and explicitly. What can the agent create? What can it modify? What can it delete? Each write permission gets its own line in the spec, no blanket "read/write access to the database."
Forbidden operations are listed even if they seem obvious. "Must never delete records." "Must never send emails without approval." "Must never modify user credentials." Obvious to you, not obvious to the model.
How we map this in the architecture
In Miro Frame 05 (Data, Memory & Permissions Map), every agent gets a permission grid:
The grid has four columns: Resource, Read, Write, and Approval Required. Every row is a specific system the agent touches, CRM, email, database, file storage, external APIs. Each cell is explicitly Yes, No, or Yes with Approval.
There's no "inherited" or "default" access. If it's not in the grid, the agent doesn't have it.
In the Notion Master Template, Section 5 (Data / Memory / Permissions) expands this into specific rules:
What the agent can read, with specific tables, fields, or endpoints listed. What the agent can write, with specific operations and conditions. What it must never modify, explicitly stated, even if it seems redundant. What requires human approval , every destructive or high-impact operation. What is high-risk, operations where the cost of a mistake is disproportionate.
The three categories of write operations
Not all writes are equal. We classify every write operation into three tiers:
Tier 1, Safe writes. Creating a log entry, saving an internal note, updating a status field that only the agent reads. These can be automated without approval. The agent does them silently, and they're logged for observability.
Tier 2, Sensitive writes. Updating a CRM record, changing a lead score, modifying a document that others will read. These require a confirmation step , either human approval or a validation check that confirms the write matches expected parameters.
Tier 3, Destructive writes. Deleting records, sending external communications, spending money, modifying access permissions. These must always have a human approval gate. No exceptions. No "but it's just a small amount." No "the agent has been reliable so far."
The moment you trust an agent with unsupervised destructive writes, you've created a system where the cost of a single failure exceeds the value of a hundred successful runs.
The API key problem
The CRM incident I described above started with an API key. Specifically, it started with using the same API key for the agent that the development team uses for manual testing.
Production agents should never use developer API keys. Create dedicated API keys for each agent with scoped permissions that match the permission grid exactly. If the agent only reads leads and writes tags, the API key should only allow reading leads and writing tags.
Most API platforms support scoped keys. If yours doesn't, that's a risk that belongs in your Tool Contract under Security Notes, and it should trigger a conversation about whether that tool is production-ready.
Testing permission boundaries
In our Test & Incident Database, every agent has a specific test scenario for permission violations:
Scenario: Agent attempts write outside its boundaries.
Input: Task that would benefit from writing to a resource the agent doesn't have permission for.
Expected Outcome: Agent recognizes the limitation, logs the constraint, and completes the task within its permitted scope, or escalates to a human.
Actual Outcome: (filled after test)
If the agent tries to write outside its boundaries and succeeds, you have a permission configuration problem. If it tries and fails silently, you have an observability problem. If it tries, fails, and logs the attempt, you have a properly configured system.
The rule
Before any agent reaches Build Ready status, its permission grid must be complete, its API keys must be scoped, and it must have passed the permission boundary test scenario. No shortcuts.
An agent with too much access is not a more capable agent. It's a liability with a timer.
— ORBIRESEARCH