Have your agent talk to my vibe
Every agent integration on the market asks the same thing first: connect your account. Your whole inbox, your whole calendar, your whole bank feed, copied into somebody's warehouse so a model can look at it. The request is always all-or-nothing, and the interesting part of the job usually needs about 2% of what you just handed over.
There's another shape available, and it's been sitting in the access model the whole time. Rather than sending your data to the agent, you stand up a small place where the work happens, put only the slice the work needs into it, and let the agent ask for a seat. You approve the seat. From then on the agent acts under its own identity, inside rules your app enforces on the server, and you can take the seat back.
Not "here is my inbox." More like: have your agent talk to my vibe.

A vibe is already a place agents can stand
The mechanics don't need anything new. Three pieces that already ship:
Every app's rules run on the server, in one readable file. A vibe's
access.js is called on every read and write with the document, the previous
version of it, and who is asking. It routes documents to
channels and hands out grants, and anything it doesn't
recognize it refuses:
jsexport function subscriptions(doc, oldDoc, user, ctx) {
if (!user) throw { forbidden: "sign in" };
// The imported facts. The owner writes them; an approved agent reads them.
if (doc.type === "charge") {
ctx.requireRole("owner");
return { channels: ["ledger"], grant: { roles: { analyst: ["ledger"] } } };
}
// The agent's output. It may create these, and nothing else.
if (doc.type === "proposal") {
if (doc.authorHandle !== user.userHandle) throw { forbidden: "not yours" };
if (oldDoc && oldDoc.authorHandle !== user.userHandle) throw { forbidden: "not yours" };
return { channels: ["proposals"] };
}
throw { forbidden: "unknown document" };
}
That's the whole trust boundary. The agent can read the ledger because it holds
the analyst role, and it can write proposals because they're its own. It
cannot edit a charge, invent a role for itself, or reach a document type this
function has never heard of, because the function runs on our servers and not
in anything the agent controls.
There is no anonymous door. Reads and writes need an identity. An agent
can't curl its way into your app's data and can't guess its way past the
access function, so "who is asking" is always a real answer.
An agent brings its own account. This is the part people expect to be
harder than it is. The agent signs up for Vibes like a person does and enrolls
a device, which gives it a certificate the CLI uses on every call — the
CI-lane pattern, which our own build
lanes already run on. That certificate authenticates it as itself, so it
passes exactly the gates your access.js defines. There's no second permission
system to design and no API token to scatter around.
Which means granting an agent access is the same act as granting a person access, and so is taking it away.
And it documents itself
The part that usually kills an integration is the paperwork: someone has to write down what the endpoints are, what the fields mean, which values are legal, and then keep that document true. Here there isn't one, because the agent talks to the same API the app talks to.
It fetches a document by id. It queries by field, key, prefix or range, with limits and a sort order — the same query shapes the app's own code runs. What comes back is the document, and the document says what it is. There's no schema to publish separately from the data, because the data is the schema, and no endpoint list to maintain, because there's one way to ask.
The rules are readable the same way. access.js is a file, not a permissions
matrix in a settings screen, so "what am I allowed to do here" is answerable by
reading it rather than by trying things until something refuses you.
And you don't have to hand any of it over, because the code travels with the app. If you can open a vibe, you can take its source and make it yours: that's the same remix button a person uses, on the same gate as reading the app at all. A private app's code is as private as its data; a readable one carries its implementation in the open. Remix copies code, never data, so a copy starts empty and the original's documents and credentials stay home.
For an agent that's the difference between an integration and a conversation. It can read the app that produced the documents it's looking at, which answers the questions a schema never covers: what this field means, what the app does when two of these collide, which values it will actually write back.
What you do have to hand over is the address: which vibe, and which database.
Listing an app's databases stays owner-only, deliberately, so a stranger can't
enumerate what you have. That's the whole integration document, and it fits in a
sentence: you/subscriptions, database ledger, ask for the analyst role.
Get posts like this in your inbox
One email field. Real updates. No algorithm required.
If it's your own agent rather than someone else's, the Claude connector is this same surface with your account's permissions on it — list your apps, read and write their documents, build new ones — which is the degenerate case of this whole post: you approving yourself.
Sign-up, approval, work
The flow you'd actually build has three documents in it, and you can read the whole thing in the app.
The request. The agent writes a document saying who it is and what it wants to do. Your access function lets any signed-in identity create one of these, addressed to you, and lets nobody else read it.
The approval. You look at it in your own app and flip a field. That's the whole ceremony, and it's yours to design: approve for a week, approve for one database, approve on the condition that everything it writes lands in a queue you review. Because the grant is a document, the approval is a state machine you can read rather than a setting buried in a vendor dashboard.
The work. Now the agent's reads return the ledger, and its writes land as proposals. Everything else it tries is refused by the same function, whether it tried on purpose or because a model had an off day.
The subscriptions example
Say you want an agent to find the subscriptions you've stopped using.
The dominant approach is to give some service your mailbox. It ingests everything, forever, including twelve years of correspondence that has nothing to do with recurring charges, and you're trusting a privacy policy.
The other approach: a trusted job you run — a script on your machine, a CI lane, anything holding your own credentials — walks the receipts and writes one small document per recurring charge. Merchant, amount, cadence, date of last charge. No message bodies, no threads, no contacts. That's a few hundred documents in a vibe that has one job.
Now the agent applies for a seat, you approve it, and it reads that ledger and writes back: these four haven't charged you in a way that matches your usage, here's the cancellation path for each. You read the proposals in the app and act on the ones you like. If you want the agent to do the cancelling too, that's a bigger grant and a different conversation — but it's a grant you make deliberately, not a checkbox you clicked eighteen months ago.
The difference isn't that one is safe and the other isn't. It's that the second one has a boundary you can see, drawn where you drew it, in an app you can open.
What you're actually trading
Five things worth saying plainly, because a pattern this convenient attracts overclaiming.
The agent sees the whole slice. Scoping happens when you decide what the trusted job extracts, and again in the access function's channel routing. There is no per-field redaction below that — if a document is on a channel the agent can read, the agent reads all of it. Put less in the document.
Revoking stops future delivery. Remove the grant and the agent stops receiving your data from that moment. It doesn't reach back into whatever it already read, and no honest version of this pattern will tell you otherwise. That's the same deal you get with any collaborator, human or not.
Approval is your app's logic, not a platform feature. The platform gives you identities, channels, grants, and a function that runs server-side on every operation. The request-and-approve flow on top is a few documents you design, which is what makes it fit your situation — and also means you own its correctness.
Roles gate data, not code. An approved agent can read and write documents within its grant. Letting someone change the app itself is a different, explicit thing: a developer grant, which the owner alone can give and take back.
Source travels with the app, today. That's the property the section above leans on, and the flip side is that anyone who can open a readable vibe can take its code. Keeping a readable app's implementation to yourself is a Pro feature we're building; until it lands, write your app as though its source is part of what you published, because it is. This changes nothing about the data: the access function is enforced on our servers, so reading the rules has never been the same as passing them.
Why this is the interesting direction
The thing agents keep needing is not more data. It's a bounded place to work where the boundary is legible to both sides. Right now that place is usually a vendor's database with an OAuth scope pointing at it, and the scope is written by the vendor, in a language of permissions, at signup time, forever.
A vibe inverts every part of that. The data is a slice you materialized on purpose. The rules are a file you can read in one sitting. The identity on the other end belongs to whoever built the agent, not to a shared integration key. And the approval is a document in an app you own, so "who did I let in, and when, and what did they do with it" is a query, not a support ticket.
If you're building an agent, the ask gets much easier too. You don't have to talk anyone into connecting their whole account. You ask them to put one thing in a vibe and let you apply for a seat.
Build the room, then invite the agent
Describe the app that holds the slice. The sign-in, the database, and the rules are already there.
Start building →