TL;DR:我的AI代理有一个246行的指令文件用于管理Linear中的问题。其中150行是变通方法:硬编码的UUID、对curl的回退、“CLI不支持X"的注释。我没有重写它们——而是构建了一个让它们变得不必要的工具。现在那150行变成了零行。


你是否曾经写过一份指令文档,它的长度本身就证明了有什么地方不对劲?

我指的不是合理的文档。我指的是那些开头说"使用工具X”,然后花80%的篇幅解释工具X什么时候不工作以及应该如何替代的文件。那些实际上是为本应构建的工具道歉清单的指令。

我有一个这样的文件。而且很令人尴尬。

150行垃圾的解剖

背景:我与一个AI代理(Claude Code)合作,它管理我在Linear中的问题。为了让代理知道如何操作,我有一个技能文件——一个代理在需要创建、列表或更新问题时会读取的指令文件。

这个文件有246行。其中约100行是合理的文档:存在哪些命令、有哪些团队、使用哪些标签。这是合理的。

其他150行是防御性垃圾。三个类别:

约30行硬编码的UUID。 我使用的CLI不支持--project。所以技能文件在XML表格中包含了17个UUID(5个团队+12个项目)。代理必须找到正确的UUID并手动构建GraphQL突变来分配项目。一个应该是--project Tokamak的操作需要记住一个36字符的UUID。

约25行对curl的回退。 CLI没有搜索功能。没有按项目过滤。创建时没有项目分配。三个基本操作,三个嵌入GraphQL查询的curl块,引号转义,以及认证头。每一个都是等待代理吃掉引号的定时炸弹。

约15行"不支持X"。 五个"CLI不支持"的警告和两个"必需"(每次列表时的–sort和–no-pager)。注意这点:我在工具使用指令中记录工具的缺陷。这就像汽车手册花三页解释雨刷只有在先敲击仪表板后才能工作。

约80行防御性上下文。 整整一节标题为"何时使用API而不是CLI"。目录→UUID映射表。选择标签的启发式方法。当CLI挂起时该怎么办的规则。这些材料存在的唯一原因是工具无能为力。

“小心台阶"的标志

当一个工具有不舒适的界面时,自然的反应是记录变通方法。你写指令。你放警告。你创建一个"常见错误"部分。文档越详细,你就越相信问题已经解决了。

但实际上没有。你放了一个"小心台阶"的标志,而不是修复台阶。

当那些指令的用户是LLM时,问题就成倍增加了。人类读到"不支持–project"会记住(多多少少)。LLM读到它,处理它,三轮对话后还是会使用--project。这不是因为它笨——而是因为它优化完成任务,而--project是分配项目的逻辑路径。禁令在信号的海洋中是噪音。

我在另一篇文章中写过这个问题:对LLM的冗长指令完全等同于放置标志。LLM忽略它们不是因为叛逆。它忽略它们是因为它的功能是找到最直接的路径,而"不要使用–project,而是在这个表格中查找UUID,然后用这个GraphQL查询做curl"不是直接路径——这是一个粗糙的修补。

解决方案不是更好的技能文件

我本可以用更好的指令重写技能文件。更清晰的。有例子的。有图表的。我本可以从246行增加到400行并覆盖每个边缘情况。

这就像扩大标志。

我所做的是构建lql——一个用Rust编写的CLI,专门设计让AI代理(或人类,但主要是代理)可以与Linear交互而不需要生存手册。

设计理念是一句话:错误的路径不应该被禁止,应该是不可能的。

换句话说:你不在文档中禁止--status——你让它工作。你不记录--project在create中不存在——你让它存在。你不维护UUID表格——你自动解析名称。你不提供curl回退——工具没有做不到的事情。你不写"必需:–sort”——你设置合理的默认值。

消失的东西

这是我删除的清单:

防御性垃圾删除的行数删除原因
硬编码的UUID(17个ID)~30lql自动解析名称
对curl + GraphQL的回退~25lql原生支持search、project、relate
“不支持X"的注释(5个)~15代理期望的一切都存在
“必需"标志(2个)~5合理的默认值,没有必需标志
“何时使用API vs CLI"部分~15没有"vs”——lql什么都能做
上下文→UUID映射表(XML)~20从TOML配置自动检测
启发式和防御性规则~40工具是容错的,多余了
总计~150

剩下的是合理的文档:存在哪些命令,有哪些团队,使用哪些标签。零变通方法。零道歉。

为什么有效(有趣的部分)

行数的减少很引人注目,但这不是重点。重点是_为什么_那些行是多余的。

旧技能文件中的每行变通方法都存在是因为底层工具是脆弱和不宽容的。脆弱是因为它在合理输入面前失败(--status而不是--state)。不宽容是因为它拒绝而不提供替代(--project不存在,自己想办法)。

当你用容错工具替换脆弱工具时,指令_自动_简化。你不必重写手册——手册自己重写,因为不再有什么需要警告的。

这是解释为什么iPhone手册有10页而打印机手册有200页的同一原理。不是苹果写更好的文档。而是iPhone不需要你解释如何装纸、对齐打印头或清洁滚筒。

容错工具生成简短文档。脆弱工具生成生存手册。

当用户是LLM时,这更加重要。每行指令都是可能被误解、遗忘或矛盾的一行。有150行变通方法的技能文件给它150个错误遵循变通方法的机会。没有变通方法的技能文件给它…零个出错的机会。

一般模式

这不仅限于CLI或Linear。模式是通用的:

  1. 你有一个界面不舒适的工具
  2. 你写详细指令来补偿
  3. 指令变成生存手册
  4. 有人(人类或LLM)忽略部分手册
  5. 事情出错
  6. 你添加更多指令
  7. 回到步骤4

跳出循环的方法不是写更好的指令。而是修复工具。

如果你的CLAUDE.md有超过20行专门解释如何_不_使用某些东西,那些东西需要重写。如果你的技能文件有"常见错误及如何避免"部分,那些错误应该是不可能的,而不是记录在案的。

每个"小心台阶"的标志都是你没有修复台阶的承认。

轮到你了

下次当你发现自己写冗长的指令来补偿不舒适的工具时——无论是CLAUDE.md、README还是内部wiki——停一下问自己:

  • 我在记录_如何使用_工具,还是_如何在工具中生存_?
  • 如果工具接受用户自然给出的输入,会有多少行消失?
  • 我在放标志还是修复台阶?

如果你超过30%的指令是变通方法,工具就是坏的。不是用户。不是文档。是工具。

修复台阶。


系列:对抗式编程