别让本地 AI 直接改你的待办:Lotti 用双数据库把 Agent 建议隔离在待审批区
很多“AI 生产力”产品的承诺都很诱人:录一段会议、扔进几条笔记,Agent 自动整理任务、调整截止日期、补全清单。真正该先问的问题却是:模型判断错了,或者某个自动化链路被提示注入影响了,哪些数据能被它改写?如果答案只是“提示词要求它谨慎”,那条边界其实并不牢靠。
开源项目 Lotti 提供了一个更值得开发者借鉴的答案。它是用 Flutter/Dart 编写的跨平台私有日志、任务与时间记录工具,许可证为 GPL-3.0;AI 是可选能力。它把用户真实记录与 Agent 的推理、记忆和提议拆进两个本地数据库,再把“进入事实数据”的最后一步留给人确认。这个设计不只适用于个人待办,也适用于任何要把本地模型接进内部工作流的应用。
不要把 Agent 的想法直接当作事实
Lotti 将任务、笔记、音频、时间记录、日志和指标放进 user database。这是系统记录(system of record):用户真正写过什么、做过什么、当前任务状态是什么,都以它为准。
另一侧的 agentic database 存放完全不同的东西:Agent 定义、工作记忆、唤醒历史、推理痕迹、中间结果和 suggestions(建议)。这份数据可以增长、清理,甚至整个删除后重建;删除它不应抹去用户的原始工作记录。
这不是把同一张表加一个 source=ai 字段,而是把生命周期和信任级别分开。用户数据库需要备份、同步和谨慎迁移;Agent 数据可以被视为可再生的计算缓存。于是当模型换代、上下文污染或策略调整时,清掉 Agent 工作区不会把任务历史一起带走。
更关键的是写入路径。项目文档说明,Agent 生成的内容先以建议存在于 agentic database;要修改任务标题、清单、状态或日期,必须经过需要用户批准的代码路径。文档仅列出两个很窄的初始例外:未命名任务的初始标题,以及尚未设置语言的任务初始语言;后续编辑仍需确认。边界由存储布局和写入通道实施,而不是指望模型“记住不要乱改”。
一个可复现的本地安装起点
在 Linux 上,Lotti 可通过 Flathub 分发。官方 Flathub 应用 ID 为 com.matthiasn.lotti;已配置 Flathub 的环境可执行:
flatpak install flathub com.matthiasn.lotti flatpak run com.matthiasn.lotti
安装后,先把它当作普通任务/日志工具使用,而非立刻开启自动化。创建一条会议或工作记录,再观察 Agent 建议是否是独立的“待处理变更”,而不是已写入任务字段的结果。这个顺序很重要:先确认人工操作与数据归属,再给模型接入读写权限,才能知道自动化到底替你做了什么。
Lotti 允许不配置任何模型;关闭 AI 后,它仍是任务管理、时间追踪和日志工具。若希望数据与推理都尽量留在自己的环境,项目 README 明确支持 Ollama,也支持指向自建网关的 OpenAI-compatible endpoint。这里应把“接模型”理解为一个可替换的推理提供方,而不是把个人数据自动交给某家云服务。
从会议记录到待审批清单的正确链路
一个较稳妥的工作流可以是:先记录会议或语音内容;由本地转写或指定模型产生摘要;Agent 从摘要中提出候选任务、负责人提示和截止日期;最后逐项确认,才让这些字段落入用户数据库。重点不在于让 Agent 一次性“全自动完成”,而在于每一个有副作用的变更都能被看见、拒绝和追溯。
可以把这套设计抽象成四层:
- 事实层:用户输入和确认后的业务状态,必须可备份、可审计。
- 推理层:提示、记忆、模型输出和中间工具结果,默认可清理、可重算。
- 提议层:把模型输出转换为结构化变更,但尚未获得写入事实层的资格。
- 批准层:由人或独立的确定性策略明确放行,再执行写入。
这也解释了为什么“模型有工具权限”不等于“模型应拥有数据库写权限”。在企业内部系统里,可以让 Agent 读取工单、生成 SQL 修复建议或创建部署计划,但将实际更新动作放到批准层。若业务需要批量自动批准,批准层也应记录规则版本、输入摘要和执行结果,而不应悄悄绕过隔离。
同步与本地优先不是同一件事
本地保存并不自动等于多设备安全。Lotti 的 README 描述了本地 SQLite 与文件系统附件,并说明同步使用端到端加密:中继只看到密文。离线设备重新上线后的冲突处理采用 vector clocks(向量时钟),而不是简单地按“最后写入时间”覆盖。
这给开发者一个很实用的提醒:把 Agent 数据与用户数据分开后,同步策略也要分开思考。事实层应优先保证冲突可解释、历史不丢失;推理层则可以采用更激进的过期和重建策略。若把二者混在一个不可区分的同步日志里,模型生成的大量临时状态既会污染备份,也会提高冲突处理成本。
设计成待审批区后,怎样避免“确认疲劳”
把所有输出都抛给用户确认,也可能把安全问题变成体验问题:建议太多时,用户会习惯性点“全部接受”。因此,批准层不该只是一组按钮,还要有合并、解释与最小化变更三个工程约束。
第一,建议应绑定来源。比如一项“把周五设为截止日”的提议,应能回看它来自哪段会议记录或哪条笔记,而不是只显示一句模型结论。第二,将有关联的字段组成一次可读的变更集:新增一个任务、附加两个 checklist 项、写入日期,比分三次分别弹窗更容易审查。第三,默认只提议最小变更;不确定负责人、日期或优先级时,保留为空比编造一个看似完整的答案更好。
在 Lotti 的模型中,agentic database 也让这类策略有了安全的试验场。可以改变提示词、替换模型、清理旧记忆,或调整 Agent 模板,而无需迁移用户任务的权威记录。对于自己构建的系统,则可以把每份建议附上输入记录的标识、生成时间、模型或规则版本与确认结果。这样出了问题,排查的是一次可定位的提议,而不是从一团混杂的最终数据库状态里反推模型做过什么。
给内部工具落地时的检查清单
如果准备把这一模式移植到工单、知识库或运维平台,可以先做四个检查:
- 写入权威性:明确哪些表或事件流是事实源,Agent 是否只有读取权限。
- 提议可重放性:保存结构化变更和必要的输入引用,使同一提议能被复查,而非只保存自然语言回复。
- 批准不可绕过:将批准校验放在 API 或服务层;不要只在前端隐藏“保存”按钮。
- 临时状态可回收:为向量检索缓存、模型记忆和推理轨迹设置保留期限,避免它们无限进入备份和同步范围。
这些约束会让首版自动化慢一些,却能换来更清晰的责任边界:模型负责提出、系统负责限制、人负责对事实状态作最终承诺。当需求逐渐成熟,再把少数重复、低风险且有审计记录的动作交给确定性规则自动放行,比一开始给 Agent 全库写权限更容易扩展和回滚。
适用边界:它不是通用 Agent 权限系统
Lotti 的双数据库并不能替代账号权限、加密密钥管理、服务端审计或高风险操作的审批制度。它解决的是一个更具体的问题:在个人或本地优先应用里,不要让不确定的模型输出直接覆盖确定的用户事实。对于转账、生产部署、删除数据等动作,仍应增加最小权限、独立审批与可验证的执行日志。
不过,这个模式本身很通用。构建 AI 日志、知识库、CRM 助手或本地工作台时,不妨先问:哪些内容是“用户已经确认的事实”,哪些只是“模型暂时的猜测”?只要两者能被物理地、在写入路径上分开,Agent 即使出错,错误也更容易停留在一个可见、可拒绝、可重建的待审批区。