草稿、审计日志,还是「别连」:三家平台怎么处理 AI Agent 的写入

Sanity 默认写进草稿,Notion 事后记日志,Supabase 说别连。三家文档里的三段引文,以及它们共同留下的缺口。

返回博客

过去一年里,三家平台先后放开了 AI Agent 的写入权限。它们都要回答同一个问题——Agent 写错了会怎样——而给出的是三个真正不同的答案。

我为一组对比页读它们的文档,最后手里剩下三段引文。这三段分开看都平常,放在一起才有意思。三家都没有错,它们只是在不同的层上解决问题;知道自己的问题在哪一层,能省下采用错机制的代价。

Sanity:默认落草稿

Sanity 的 Agent Actions 是事件驱动的 API,用来生成、转换和翻译内容。值得注意的是它的默认值:

默认情况下,Agent Actions 绝不会改动已发布的文档。当你提供一个已发布文档的 ID 时,操作会先创建草稿,再施加任何改动。

而如果你对着一个已发布文档运行它,新值「会被写入一个新的草稿文档,并且需要被发布」。

这个行为可以关掉(forcePublishedWrite: true,以及标了 liveEdit: true 的 schema 本来就是那样),但安全的那条路是默认值——这和大多数产品放开 Agent 写入的做法正好相反,值得给它比现在更多的信用。

它买到了什么:在人发布之前,没有东西会到达读者。

它没有回答什么:这个对不对。一份写着自信错误数字的草稿,看起来和一份写对了的草稿一模一样。

Notion:事后的审计日志

Notion 3.6(2026 年 7 月)上线了 External Agents,首批就是 Claude 和 Cursor。你可以「从全团队共享的看板给它派活、像 @ 同事一样 @ 它、看着它跑」。Custom Agents 按计划和触发器运行;AI Autofill 把它们直接带进数据库。

监管方面,Enterprise 计划有这个:

审计日志包含 Custom Agent 的活动,你可以看到 Agent 什么时候跑的、改了什么、谁触发的。

这是真机制。它回答的是谁改的、什么时候改的

它没有回答的是:这条该不该成立——而且它回答第一个问题时,写入已经落地了。

这一点值得多停一会儿。审计日志是为另一个世界设计的:写入很慢,下一个读的人是人。而 Agent 一分钟能改 800 行,下一个读它的往往是下一轮 Agent、是定时报表、是客户看到的那个页面。等到有人发现,那个错值已经被读过、汇总过、拿去做决定了。

「你能看到 Agent 改了什么」和「你能控制 Agent 改什么」,已经悄悄不是同一个承诺了。

Supabase:别把它接到生产库

Supabase 把自己定位成「为 agentic 工作负载打造的完整 Postgres 开发者平台」——MCP server、Agent Skills、每次调用都过 RLS。而它自己那篇关于 Agent 的工程博客,诚实得少见。它写道,Agent 会:

  • 「在暴露的 schema 上跳过 RLS 策略」
  • 建出没有 security_invoker = true 的视图,「这会静默绕过 RLS」
  • 不知道「UPDATE 需要 SELECT 策略。没有它,更新会静默返回 0 行」
  • 「幻觉出根本不存在的 CLI 命令」
  • 「完全无视文档,依赖可能已经过时几个月的训练数据」

以及直白的一句:「Agent 在这件事上很懒。」

它的结论顺理成章:

我们强烈不建议把 Supabase MCP server 连到你的生产数据库。

只连本地或 staging。

这个建议是对的,而且值得注意它为什么对。再看一遍那张清单:每一条都是正确性的失败,而被指望拦住它们的机制——RLS——管的是权限。RLS 回答的是「这个调用方可以写这一行吗」,它回答不了「这个值对吗」。一个权限完全正确的 Agent,写进一个自信但错误的数字,能通过数据库的每一道检查。

在引擎这一层没有别的答案可选——这正是「别让 Agent 碰生产」是诚实建议而不是推脱的原因。

三个层,不是三个等次

把三家并排放,它们不是同一个想法的三种实现,而是三个不同的层:

平台关卡在哪单位拦得住什么
Sanity发布之前文档版本未经审阅的内容到达读者
Notion写入之后会话归因——谁在什么时候跑了什么
Supabase连接处环境Agent 根本不该碰生产

每一种都和那个产品的目的匹配得很好。Sanity 的终点是读者,所以关卡设在发布;Notion 的场景是协作工作区、多数编辑后果很轻,所以机制是归因;Supabase 是基础设施,唯一可用的杠杆就是谁能连。

而三家留下的缺口是同一个:一次被授权、格式正确、但是假的写入。

怎么判断你需要哪一种

三个问题,按顺序问:

  1. 产出会被发布给受众吗? 会的话,发布关卡就是对的机制,Sanity 的默认值就是你要的形状。
  2. 下一个读它的人,是不是全程看着的那个人? 是的话,归因就够了——审计日志回答的正是会被问出口的那些问题。
  3. 下一个读它的是另一个 Agent、一张报表、还是一个应用? 那么前两道关卡都帮不上,因为路径上没有任何东西会在下游消费它之前判断这个值是不是真的。

第三种情况最容易让人措手不及。它看起来和前两种一样,直到一行错数据已经被四个东西读过,才有人打开它。

真正堵上它的:给数据用的 pull request

开发者早就有这个心智模型。代码不会直接进 main,它要走一个 pull request:一份写明改了什么的 diff、一个作者、一个可以评论的地方、一次批准,以及一条记录它何时成为现实的 merge commit。

**今天 Agent 对数据的写入,相当于给每个人开了 main 的直接 push 权限。**上面那三道关卡各自都是部分替代品——发布审核是一条 release 分支,审计日志是没有审核步骤的 git log,而「别连生产库」则是干脆不给权限。

它们都不是的那样东西,是 pull request。用在数据上,意味着:

Pull request用在一次数据写入上
diff哪些字段会变,从什么变成什么
作者是哪个 Agent 提的,依据什么证据
审核有人在它成为事实之前看到,而不是之后
merge commit它何时成为正式数据,谁做的决定

同样的形状也适用于 Agent 知道的东西,而不只是它写下的东西——提示词、指令和可复用技能,漂移的方式和代码一模一样,也受益于完全相同的处理。

它在实践中长什么样

Busabase 就是第三种选择——一个把写入路径默认做成 pull request 的工作区。它是 MIT 许可、可以本地跑的,所以判断它最快的方式是跑一下,而不是读介绍:

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

不用注册、不用账号、不用云。启动时自带内嵌 Postgres(PGlite)、本地文件存储和已经放好的演示内容。

把一个 Agent 指过去——MCP、Agent Skill,或者 /api/v1 的 OpenAPI 接口——让它写点东西。到达的是这个:

Busabase 的 Change Request 审核界面:提案的改动以前后对照的 diff 呈现,右侧是批准与要求修改

改动的字段带着改前和改后、是哪个 Agent 提的、它用了什么来源,以及一条评论线索。你可以批准、要求修改或驳回。通过的值成为正式数据,并且一直带着提案人、审核人和提交记录。

两个诚实的边界:审核与后果成正比——低风险写入照样快,密钥本来就有合并权限的会直接合并;以及,如果你的 Agent 写的东西没有一样值得检查,那这整套机制就是你不需要的开销。


利益相关声明:我在 Busabase 工作,它是面向 AI Agent 的开源数据库与工作区,走的是第三条路——重要写入以带字段级 diff 的提案形态到达。上面每组对比的长版本我们都发了,带来源:对比 Notion对比 Sanity对比 Supabase。每一篇都会写明对方更合适的场景——一份让人一眼看出被做过手脚的对比,毫无价值。

来源:Sanity Agent Actions 文档Notion 3.6 发布说明Supabase — AI Agents Know About Supabase. They Don't Always Use It Right.。核实于 2026 年 9 月 21 日;三家迭代都很快。