开源写作应用如何管理长程 Agent 状态
Goink 是基于 Wails、Go 和 React 的开源桌面 AI 写作系统,结合结构化记忆、Agent 状态维护、本地语义搜索与 Git 版本控制。文章从长篇故事的一致性问题出发,讨论如何用显式状态管理补足聊天记录的局限。
AI 深度解读
让 AI 连续写几十章小说,难点往往是记住谁认识谁、伏笔埋在哪里、哪些秘密读者已经知道。作者为此做了开源桌面工具 Goink,把创作状态存进数据库,让模型通过工具查询和更新,再用本地检索找回旧章节。
这套设计对程序员的价值,在于展示了一个长任务 AI 应用如何管理状态、检索证据和控制修改。作者认为,可靠性需要靠系统机制补齐;但文中没有提供对照实验,实际提升有多大,还需要验证。
为什么故事状态要搬出聊天记录
聊天窗口按时间堆积消息,小说却需要持续维护一组互相关联的事实:人物知道什么、关系怎样变化、向读者许下的叙事承诺有没有兑现。作者把它称为状态机,可以理解为一份会随章节推进而变化的故事账本。
把设定集塞进系统提示词,短期能用。章节增加后,上下文逐渐装满,压缩又可能删掉后来才派上用场的细节。Goink 的选择是把状态移到 SQLite,由模型按需读取。
它维护六类信息:
- 人物档案和有向关系图。A 对 B 的信任与 B 对 A 的态度分开记录,关系变化追加保存。
- 伏笔及其重要程度、预计回收章节。临近期限会提示,逾期视为异常。
- 跨章节的故事线节点。章节完成后推进节点,作者称一本书通常并行维护三到五条故事线。
- 地点的包含关系与空间连接。王国、宫殿、大厅形成层级,山路连接的地点则用无向边表示。
- 读者已经知道、等待知道和暂时误解的信息,用来安排悬念。
- 全局与单本小说的写作偏好,让对白风格等要求持续生效。
数据库负责保存事实,模型负责在需要时读取和更新事实。
这里真正关键的不是多建几张表,而是给模型配套的查询、编辑工具。否则,用户仍然需要充当人工同步器。
31 个工具如何串起写作和维护
常见写作流水线按大纲、初稿、润色依次执行。Goink 提供 31 个结构化工具,让模型自行决定调用顺序:查人物、搜旧章节、读大纲、起草,再更新状态,都放在同一段对话里完成。
为避免模型写完就忘记维护,系统会在长篇内容生成后注入检查清单,要求检查人物变化、伏笔回收、故事线推进和读者认知更新。这一步由系统触发,不依赖用户想起来再提醒。
不过,注入清单只能确保提出了维护要求,原文没有说明如何验证每一项都更新正确。
系统还支持独立的审查子代理,从头对照章节和数据库,把不一致之处报告回主对话,减少审查过程对主上下文的干扰。但数据库自身如果记错,审查结果也可能受影响。
工具数量同样有代价。作者发现,31 个工具对强模型尚可管理,对弱模型可能造成困惑;工具描述和参数命名比单纯增加数量更重要。这是实际开发中的经验判断,文章没有列出模型间的调用成功率。
写作方法则放在带 YAML frontmatter 的 .md 文件中。内置、用户、单本小说三层支持覆盖优先级,激活方式包括自动、手动斜杠命令和始终启用,并支持热重载。风格提炼工具还能分析样文的句式、选词、修辞、节奏、叙事距离和语气,生成可手工修改的模仿技能。
这些文件便于扩展,但方法文件能否被准确执行,仍取决于模型。
检索旧章节和批准修改,解决的是两类问题
在 500,000 词的故事里查找某件物品首次出现的位置,关键词可能不够用:相关段落未必使用同一个名称。
Goink 用 ONNX Runtime 在本地运行 int8 BGE 中文语义模型,把向量存进 sqlite-vec 虚拟表,再通过 MMR 重排减少重复片段。MMR 可以理解为兼顾相关性和差异性,避免搜索结果全是相似段落。索引在每章完成后于后台增量更新,不需要外部向量数据库或额外服务。
作者把它称为质量提升最大的一步,认为检索能减少模型编造早期情节。但原文没有提供召回率、错误率或检索前后的量化对照。内置模型优先支持中文,提示层也假定中文网文习惯,英文长篇的效果仍待反馈。
检索负责找证据,修改审批负责控制落盘。
默认情况下,AI 的修改先生成 diff,用户可以接受、拒绝或要求重改;另有连续起草的自动模式。每次接受的变更都会提交到该小说独立的 Git 仓库,章节保存在 chapters/NNN.md,大纲保存在 outlines/NNN.md,方便查看历史和回滚。
文件写入还有两层限制:正则白名单限制可写路径,同时阻止路径穿越。写入前重新读取并比较文件,避免静默覆盖手工修改。原文没有展开冲突处理细节,也没有说明数据库状态怎样与 Git 回滚保持一致。
桌面端采用 Wails v2、Go 1.25、React 19、TypeScript 和 Tailwind 4,支持 Windows/macOS/Linux,采用 AGPL v3,安装包小于 60MB。除用户配置的模型调用外,其余部分离线运行。它提供 7 个内置 LLM 服务商预设:DeepSeek、GLM、MiniMax、Kimi、Qwen、Doubao,以及 OpenAI-compatible endpoints。
我的判断
我认可它把长期状态、历史证据和文件修改拆开处理。单靠提示词,很难同时承担记忆、检索和版本管理;把这些职责交给数据库、搜索和 Git,更容易检查问题出在哪一步。
但自由调用工具未必适合所有团队。固定流程更容易预测和排查,开放式代理则更能处理写作中临时出现的信息需求。如果模型能力有限,可以先固定检索、生成、维护和审查的顺序,再逐步开放决策空间。
追加保存关系历史也很合理,不过六类状态的粒度是为小说设计的,不宜整套照搬。对于其他应用,应先确认哪些信息需要长期保存、谁能修改、怎样纠错。
作者称几乎所有用户最终都保留了 diff 审批,但没有交代样本规模。因此可以把它作为产品设计线索,不能据此判断普遍偏好。安装包小于 60MB 也不代表完整运行资源占用很小,文中没有说明模型文件是否包含其中,以及内存和硬件要求。
能拿来做什么
- 做长任务 AI 应用时,先列出需要跨轮次保留的状态,并提供明确的查询和更新接口,减少反复拼接整段历史。
- 做前端或 Node 的文件编辑工具时,可以借鉴 diff 预览、接受后提交 Git、写入前重读比较的流程,让修改可检查、可撤销。
- 给代理增加工具前,先检查工具描述和参数名称,并用目标模型验证调用效果,不要把工具数量当成能力指标。
- 借鉴本地语义检索时,用实际内容测试召回效果,尤其要覆盖别名、间接描述和跨段信息;中文小说中的经验不能直接替代英文材料的验证。