Drafts, audit logs, or read-only: three ways platforms handle AI agent writes

Sanity writes to a draft by default, Notion logs it afterwards, Supabase keeps agents read-only near production. Three answers from three sets of docs, and the gap all three leave open.

Busabase Team
← Back to Blog
Drafts, audit logs, or read-only: three ways platforms handle AI agent writes

Updated 13 November 2026: an earlier version of this post summed up Supabase's position as "don't connect agents to production." That was too broad. The "strongly discourage" line comes from a schema-management workflow in Supabase's engineering blog; its MCP documentation allows connecting to a production project when the task requires production evidence, with project scoping, read-only mode, and restricted feature groups. The Supabase section and the table below now say so. We also corrected how we describe review in Busabase: every write is a Change Request, and review is optional.

Three platforms shipped AI agent write access in the last year. All three had to answer the same question — what happens when the agent writes something wrong — and they gave three genuinely different answers.

I read the documentation for a comparison project and ended up with three quotes that are more interesting side by side than apart. None of these companies is wrong. They are solving the problem at different layers, and knowing which layer yours is on saves you from adopting the wrong mechanism.

Sanity: drafts, by default

Sanity's Agent Actions are event-driven APIs that generate, transform and translate content. The notable part is the default:

By default, Agent Actions never mutate a published document. Whenever you supply a published ID, the action creates a draft first before applying any changes.

And if you run one against a published document, the new value "was written to a new draft document and will need to be published."

You can turn this off with forcePublishedWrite: true, and schemas marked liveEdit: true already behave that way. But the safe path is the default — which is the opposite of how most products shipped agent write access, and it deserves more credit than it gets.

What it buys: nothing reaches a reader until a human publishes it.

What it does not answer: whether the value is correct. A draft with a confidently wrong number in it looks exactly like a draft with a right one.

Notion: audit logs, after the fact

Notion 3.6 (July 2026) shipped External Agents, and the first two are Claude and Cursor. You "assign them tasks from a board shared with your whole team, @-mention them like teammates, and watch them run." Custom Agents run on schedules and triggers; AI Autofill brings them directly into databases.

For oversight, Enterprise plans get this:

The audit log includes Custom Agent activity, so you can see when an agent runs, what it changed, and who triggered it.

That is a real mechanism. It answers who changed this, and when.

What it does not answer: should this have become true — and it answers the first question only after the write has landed.

This is the part worth sitting with. Audit logs were designed for a world where writes were slow and the next reader was a person. An agent can update 800 rows in a minute, and the next reader is usually the next agent run, a scheduled report, or a page a customer sees. By the time a human notices, the wrong value has been read, summarized and acted on.

"You can see what the agent changed" and "you can control what the agent changes" quietly stopped being the same promise.

Supabase: read-only near production

Supabase positions itself as "the complete Postgres developer platform built for agentic workloads" — MCP server, Agent Skills, RLS on every call. Their own engineering post about agents is unusually candid. Agents, they write:

  • "skip RLS policies on exposed schemas"
  • create views without security_invoker = true, "which silently bypasses RLS"
  • miss that "UPDATE requires a SELECT policy. Without one, updates silently return 0 rows"
  • "hallucinate CLI commands that don't exist"
  • "ignore the docs entirely, relying on training data that may be months out of date"

And plainly: "agents are lazy about it."

Their conclusion follows from the evidence. For the schema-management workflow the post describes, they write:

We strongly discourage connecting the Supabase MCP server to your production database.

That workflow was designed for a local or staging database. Supabase's MCP documentation draws the general line more carefully: connect to a production project "only when the task requires production evidence," and then use "project scoping, read-only mode, restricted feature groups, and the narrowest data query that can answer the question." Near production, in other words, the agent is a reader. Our Busabase vs Supabase comparison quotes both passages.

That is sound advice, and it is worth noticing why it is sound. Look at their list again: every item is a failure of correctness, and the mechanism being asked to catch it — RLS — governs permission. RLS answers may this caller write this row. It cannot answer is this the right value. An agent with entirely correct permissions writing a confidently wrong number passes every check the database has.

At the engine layer there is no other answer available, which is exactly why "keep agents read-only near production" is the honest recommendation rather than a cop-out.

Three layers, not three grades

Put the three next to each other and they are not competing implementations of one idea. They are three different layers:

PlatformGateUnitCatches
SanityBefore publicationThe document versionContent reaching an audience unreviewed
NotionAfter the writeThe sessionAttribution — who ran what, when
SupabaseAt the connectionThe project and its access modeAgents writing where they should only read

Each is well-matched to what that product is for. Sanity's destination is a reader, so the gate is publication. Notion's surface is a collaborative workspace where most edits are low-stakes, so the mechanism is attribution. Supabase is infrastructure, where the levers available are who may connect, to which project, and whether they may write.

The gap all three leave open is the same one: a write that is permitted, well-formed, and false.

How to tell which one you need

Three questions, in order:

  1. Does the output get published to an audience? If yes, a publication gate is the right mechanism, and Sanity's default is the shape you want.
  2. Is the next reader a person who was watching? If yes, attribution is enough — an audit log answers the questions that actually get asked.
  3. Is the next reader another agent, a report, or an app? Then neither gate helps, because nothing in the path evaluates whether the value is true before something downstream consumes it.

The third case is where teams get surprised. It looks like the first two until a wrong row has been read by four things before anyone opens it.

What closes it: a pull request for your data

Developers already have the mental model. Code does not go straight into main. It goes through a pull request: a diff of exactly what changes, an author, a place to comment, an approval, and a merge commit that records when it became real.

Agent writes to data today are the equivalent of giving everyone direct push access to main. The three gates above are each a partial substitute — publication review is a release branch, an audit log is git log with no review step, and "read-only near production" is not granting write access at all.

What none of them is, is a pull request. Applied to data, that means:

Pull requestApplied to a data write
The diffWhich fields change, from what to what
The authorWhich agent proposed it, on what evidence
ReviewA person sees it before it is true, not after
The merge commitWhen it became canonical, and who decided

The same shape applies to what an agent knows, not just what it writes — prompts, instructions and reusable skills drift exactly the way code does, and benefit from exactly the same treatment.

What that looks like in practice

Busabase is the third option — a workspace built so the write path is a pull request by default. It is MIT-licensed and runs locally, so the fastest way to judge it is to run it rather than read about it:

npx busabase server
# → http://localhost:15419/dashboard/local

No signup, no account, no cloud. It starts with an embedded Postgres (PGlite), local file storage, and demo content already in place.

Point an agent at it — MCP, an Agent Skill, or the OpenAPI surface at /api/v1 — give it a proposal-only key, and have it write something. This is what arrives in the Inbox:

A Busabase Change Request in review: the proposed edit shown as a before/after diff, with Approve and Request changes on the right

That is a Change Request: the changed fields with before and after, which agent proposed it and through which key or tool, and a comment thread. You approve, request changes, or reject; approved values become canonical and keep the proposer, reviewer and commit attached. With a write-level key, the same Change Request merges immediately — the diff and history are still kept, and any change can be rolled back.

Two honest limits: review is opt-in, so it only protects the writes you route through it — a key with write access merges immediately; and if nothing your agents write is worth inspecting, you can leave review off entirely and simply keep the diff and history.


Disclosure: I work on Busabase, which is an open-source database and workspace for AI agents and takes the third approach — every write is a Change Request with a field-level diff and a history, and review is there when you want it. If you want the longer version of these comparisons, we publish them with the sources: vs Notion, vs Sanity, vs Supabase. Each one states where the other product is the better choice, because a comparison you can tell is rigged is worth nothing.

Sources: Sanity Agent Actions docs, Notion 3.6 release notes, Supabase — AI Agents Know About Supabase. They Don't Always Use It Right., Supabase MCP documentation. Verified 21 September 2026; Supabase re-verified 13 November 2026. All three ship frequently.