跳到正文
Hacker News· skolos·· 9 天前AI 评分50

Claude 被禁止为我写散文式报告:用结构化块替代

Claude Isn't Allowed to Write Me Prose

AI 导读

一位同时运行约十几个 agent 的用户在全局 CLAUDE.md 中禁用 "honestly"、"genuine" 等措辞和虚假对比句式,但发现风格规则只改变用词、不改变报告形态,Opus 5 之后散文变得难以忍受。

正文 · AI 翻译

我的全局 CLAUDE.md 里有一个叫 Wording 的部分。它禁止使用“honestly”、“genuine”、“landed”以及短语“earns its keep”。后面还有一个部分禁止虚假对比的配对,比如“This is not theoretical. It is standard engineering.”,以及为追求冲击力而写的一连串短句和单行结尾。每条规则的存在都是因为日复一日地读 Claude 的文字让我疲惫不堪。

我同时运行大约十几个代理,因此我能否在几秒钟内阅读和处理来自代理的报告,还是需要几分钟,会影响我的工作速度。直到最近,我都把这当作一个写作风格问题:如果报告仍然难以阅读,那么风格规则就还不完整。这个列表不断增长,在 Opus 5 发布后增长最快,那时文字变得令人难以忍受。

Opus 5.5 写得好多了,但找到报告中重要的部分仍然是一件苦差事:模型会详细告诉我它遇到了哪些问题、如何尝试解决以及走了哪些路径,而其中大部分我都不需要。在中间某个地方,往往是顺便提到,它注意到某件事可能是个问题,可能需要进一步查看,而那句话通常埋在我本可以跳过的细节中。

我现在确信我一直在错误的层面上工作。告诉模型如何写,以及不要写什么,仍然让它写出任意长度和形状的文章;规则只改变了其中的文字。而 CLAUDE.md 中的规则只是一个请求。我需要从报告中得到的是我必须决定的两三件事,而文字即使写得很好也会隐藏这些。

Captain Barbossa from Pirates of the Caribbean, captioned: CLAUDE.md is more of what you'd call guidelines than actual rules.

如果,相反,模型只能通过一小组预定义的块与我交流,每个块都有它必须填写的字段,会怎样?

  • 为了告诉我它改变了什么,它使用一个 change 块:一句话总结,加上一个在我打开之前保持折叠的较长描述。
  • 为了告诉我它学到了什么,它使用一个 finding 块,该块还必须说明这个发现有多重要,以及它是否阻止工作。
  • 为了告诉我它如何检查工作,它使用一个 check 块:通过、失败或未运行,如果未运行,为什么没有运行。
  • 为了让我决定某事,它使用一个 question 块,包含两到六个选项,每个选项说明选择它会做什么。

一个测试框架会在每份报告到达我之前检查它,并退回任何不符合要求的内容(作为工具调用错误),因此模型永远无法递给我一篇文章。它仍然决定告诉我什么,但它告诉我的一切都必须放入这些块之一。

UI 可以用块做什么

一旦输出是一个类型化块的列表,UI 就可以按照我想阅读的方式呈现它。以下是可以做什么的例子:

我选择顺序

UI 不需要按照模型发送块的顺序显示它们:

决策变成按钮

点击一个选项,或者点击面板并按 1 或 2。

推荐的选项被标记

当模型建议做什么的选项时,我经常要求告诉我它推荐什么以及为什么。不需要往返——块可以直接要求预先提供这些信息:

细节可用但折叠

长描述、日志和证据隐藏在一行摘要后面,直到我打开我想要的那些:

一切都在一张卡片中

或者以下是我会如何将其组织成一张卡片:

点击一张卡片,然后按 1 到 4 选择一个选项,或按 0 打开或关闭细节。

作为对比,这是 Claude Code 实际结束该会话时使用的文本:

A reply ending in several paragraphs of prose about dplay.dll and ORION95.EXE, with the decisions buried in the text.

在卡片上,我花10-15秒检查标题、可能的选项,也许扫一眼“发生了什么”部分。而模型生成的文字,我需要逐字阅读和处理——花费的时间和精力要多得多。

这改变了什么

这把“智能体可以向你展示什么”的问题,从模型转移到了运行它的人身上。如今,模型决定一切,以文字形式呈现,界面则原样打印收到的内容。有了固定的块集合,模型仍然选择使用哪些块以及块里放什么,而由我决定存在哪些块以及每个块必须包含什么。

这也让交互更加稳健。模型撰写报告的方式因模型而异,甚至同一模型的次要版本之间也不同。有了块,新模型改变的是填入字段的内容,而我阅读的布局和按下的按钮保持不变。

来自一个工作智能体的同一份报告

为了尝试这个想法,我把它构建进了kvit-coder,一个我在开发的小型编码智能体。下面是同一个结果,写成它的一份报告并由其渲染器打印出来:

kvit-coder’s terminal UI showing the same report: the headline, a four-line What happened checklist, and two next steps with numbered options.

这与风格规则的区别在于,报告是一次工具调用,也是模型在kvit-coder中停止工作的唯一方式。

一组块

存在哪些块是一种设计选择,以下是kvit-coder目前使用的一组:

块 用于 必须包含
change 编辑和其他输出 摘要
finding 学到的东西:根本原因、答案 为什么重要;程度(从低到关键)是可选的
check 工作是如何被检查的 通过、失败、部分完成或未运行;对于部分完成或未运行,说明未检查什么以及原因
warning 风险,或阻碍工作的因素 严重程度,以及如果被忽略会破坏什么
question 只有我能决定的事:一个选择,或我掌握的信息 2到6个选项,每个说明选择它会做什么;推荐选项的理由,或为什么没有推荐
next 提议的后续步骤 一个运行它的选项,附带将发送的指令,以及至少一个替代方案;推荐选项及其理由
unclassified 当其他都不合适时的最后手段 为什么没有其他类型合适

通过改变块来改变智能体的行为

当文字报告出错时,唯一的补救办法是在提示词中再加一行。当块报告出错时,失败通常是某个特定块缺失或某个字段被用错了地方,修复就针对那个地方。

非文本的块

这种方法不要求块必须是文本。一个块类型是模型填充的schema加上UI中绘制它的代码,因此能绘制图片的UI可以为模型提供图片块:

  • 图表块。模型提供节点和边,或Mermaid源码,以及说明文字,检查可以确保源码在报告被接受前能解析。重构之后,“请求现在按此顺序经过这三个服务”就属于这里。
  • 绘图块。模型提供数据系列、轴标签和单位,以及生成这些数字的命令,检查可以确保每个系列与轴匹配。基准测试结果,或更改前后的内存使用,会放在这里。
  • 分步块。模型提供有序的状态列表,每个状态附有说明,UI将它们作为动画播放或按一次键逐步查看,这适合竞态条件或数据迁移。

下面是本文前面提到的游戏 bug 的分步演示。方框、箭头以及每一步的变化都来自“模型发送的内容”下的数据;页面只负责绘制。

在这些情况中,模型都不绘制任何东西:它决定应该显示什么并提供内容,而 UI 代码每次都以相同的方式绘制。如今,一个想要解释三个服务如何协同工作的 agent 会写三段文字或一个 ASCII 图,因为文本是其界面所能显示的全部。上图是一个原型:这些块在 kvit-coder 中尚不存在。

试用一下

完整版本在 kvit-coder 中,位于 internal/report 下:report.go 包含块类型和 schema,validate.go 是检查,render.go 是布局。

其中一部分通过 What’s Next 插件 在 Claude Code 中工作,该插件使用一个 hook 来要求改变了某些内容的回合以 Claude Code 内置的问题卡片结束。

Claude Code’s question card from the What’s Next plugin: “dplay.dll is replaced and all imports resolve. What next?” with numbered options, the first, Launch ORION95.EXE, marked as recommended.

来源:Hacker News · blog.kvit.app