Somebody at your company has already asked whether an AI agent could read the customer data. The reason that question gets expensive has very little to do with agents.
Two layers, and only one of them has a policy
A real system has more layers than this. There is a network boundary, a gateway, whatever else your infrastructure puts in the path. But two of them decide whether a given caller can see a given record, and those two are not the same kind of thing at all.
The lower one belongs to the data store: database roles, row-level security. Those rules are data. They sit in one place, and you can read them start to finish or hand them to an auditor. That is what people mean when they call something declarative, and it is why this layer is easy to trust. It also governs very little of what you care about, because in most setups the application connects as one account with broad rights. From the data store's side there is a single caller, and it is allowed to do nearly everything.
The upper one is where the decisions that matter actually get made. Does this user's role cover this record, and is this record inside the compartment they were given? Those questions are about your application rather than about tables, and a database grant has no way to express them. So they get answered in code: a check in a service method, a filter applied before a query, a middleware guard on a route.
That upper layer is where almost all of your real authorization lives. It is also not a system. It is a pattern, repeated by hand everywhere the data is reached.
Why a new caller is expensive
This is not a mistake, and it is not a sign of a badly built application. It is what a working system normally looks like, and it holds up well, because the same small group of people writes those checks and knows roughly where they are.
It holds up because the app is the only caller.
Then something arrives that is not the app. A partner integration, and someone spends a sprint working out which of those checks apply to it. Then a batch job. Now an agent.
The agent is the hard one. A human user is limited by the product long before authorization ever comes into it: they can only click what the interface offers. An agent has no interface. It makes its own calls, in whatever order it decides, and the only thing between it and your data is what its credential allows.
So the question stops being "is this endpoint protected" and becomes "what is the complete set of things this caller could reach." For the lower layer you can answer that by reading a policy. For the upper layer, where the answer actually lives, there is no policy to read. There is a codebase.
Writing the agent's credential takes minutes. Working out what that credential would mean takes an audit, and the audit is the real bill. Faced with it, most teams reuse a credential that already exists and hope the agent stays inside the part of it that was intended.
What changes when the upper layer becomes a file
On Vectros the upper layer is the one written down. Access comes from a blueprint that names which role can do what, scoped to exactly which data, and the platform enforces it on every call rather than leaving it to whatever code is doing the calling.
A human signing in gets a credential shaped by that policy. An agent gets one the same way, from the same file, through the same mechanism. At the enforcement layer there is no difference between them.
Which makes giving an agent access the problem you already solved for people, one more time:
- Define a role scoped to what the agent needs. Usually narrower than any human role, because an agent usually needs less.
- Create a principal for it and issue that principal a scoped key, or point it at the published MCP server if you would rather not manage the credential yourself.
- Nothing about your data model or your audit trail changes, because the agent is a caller like any other.
And the question that had nothing to point at now has an answer you can read. What can this agent reach? Read its role.
What ships today
Three things:
Scoped keys. A credential issued to a principal that holds exactly the role you gave it, nothing more. Give an agent a role that can read case notes and search, and it can read case notes and search. It cannot delete a case or reach another org's clients, because the same enforcement that stops a case handler from doing that stops the agent too.
A published MCP server. Twenty-three data-plane tools, so an agent can read and write your Vectros data natively over the Model Context Protocol. Deliberately Vectros data-plane tools only: no web-fetch, nothing that reaches outside the boundary you already declared.
Code running inside the platform. A script you push, held in a sandbox, reading and writing your data under exactly the enforcement the equivalent API call would get. Run it on a record write and it executes under a grant the trigger rule declares. Call it directly and it executes under your own credential, committing everything it wrote as a single transaction. Neither path hands the script authority of its own: it acts as a principal you declared, in the same file that declares the agent.
A worked example: casework-spa
The reference app from the last post has two roles today, case-handler and
hr-admin, and neither is scoped for an agent. Adding one is worth walking through, because the
whole argument fits in a short block of policy: a case-summary-agent role that can read
case_note and run search within one client's compartment, and nothing else.
Issue that role a key, and the agent can summarize a case's history on request. It cannot see a different case. It cannot write anything. It cannot find out that a different org even exists, because the role never names it.
That block is also the audit. There is nothing to piece together from the handlers.
Where this goes next
Three kinds of caller now run against one policy: a person signing in, an external agent over MCP, and code you wrote executing inside the backend. Each holds a role you declared in the same file, and each is enforced through the same check. Which means the next kind of caller is a blueprint edit rather than a security project.
The one we are building next is the obvious one: agents that work inside the boundary rather than calling into it, under a role you declare, exactly like everything above. We are running that on our own content and outreach operations first. It will arrive the way the execution runtime did, as a capability you grant in the file you already maintain.
Try it
Request early access if you don't have a key, and see the platform overview for the MCP server and the rest of the access model this runs on.