智能代理体验:代理错误日志是你命令行界面的蓝图

我有一个代码代理——Claude Code,每月与我的问题跟踪工具Linear交互大约800次:列出任务、创建问题、更改状态、发表评论。我检查了其中165次会话,并统计出了超过500个错误和超过370次重试。 这些错误没有一个是Linear的API故障引起的,全部都是接口错误:代理与命令行通信,但命令行无法理解。 保守估计,每月大约浪费了70万个token仅仅是与工具“斗争”:重试、读取错误信息、纠正再尝试。这种无形的成本不会出现在任何账单中,但却存在于每次会话中。 背景:代理现在是主要用户 命令行工具(CLI)——从历史上看,是为人类设计的。而人类用户是非常灵活的。如果一个命令失败了,他们会通过 --help 查看帮助。如果错误信息很难理解,他们会去查阅文档。如果该工具有某些特性,他们会记住并避免再犯同样的错误。 而AI代理基本不会这么做。它在不同会话之间不会积累经验,也不会投入太多精力去阅读文档。当某些操作失败时,它也不会深入分析问题所在,而是根据认为最有可能的方式尝试再次执行。 这改变了你的工具客户是谁的定义。如果代理每月调用该工具800次,而你手动使用它只有三次,那么这个接口的主要使用者就是代理。为了人类用户设计工具并期待代理能适应,这是在为次要用户优化。 为这个主要用户专门设计有一个名字:智能代理体验(agentic experience)。它之于代理,正如用户体验(UX)之于人类用户,开发者体验(DX)之于API的开发者。更重要的是,一种最有效的测量工具早已存在——代理的错误日志。 错误有其规律 我将所有以非零退出代码结束的CLI调用定义为错误。根据这一标准,这500多个错误并非随机发生:几乎全部集中在三个模式中。 错误模式 代理行为 设计暴露的问题 虚构的标志 输入 --status 而非 --state;--priority urgent 而非 --priority 1 真正的标志不是人们会优先猜到的名称 缺少的操作过程 尝试搜索文本、按项目筛选或在创建时分配项目:CLI不具备这些功能 工具未涉及实际的工作流程 忘记必要的标志 忽略 --sort,--no-pager,--no-interactive 要求人工决策,而工具本可以自动处理 当代理输入 --status 时,它并非胡乱猜测,而是在推测出最可能的接口名称。--status 和 --state 都非常合理。而我设计的CLI并未与这种直觉一致。 还有一个问题没有反映在统计数据中,因为它不会导致命令失败:冗长的输出。CLI以JSON格式返回列表,每个问题大约50个token。如果命令成功返回(退出代码为零),这类问题就不会被统计为错误;但长列表和每月800次调用叠加起来,这就是那70万个token成本的另一半。这种成本往往被忽视,因为不会妨碍任务完成。 重新审视错误 容易的解释是直接了当的:代理在错误使用工具。这是错误的解释,应逐一反驳。 虚构的标志表明真正的标志名称不够直观。忘记的必要标志表明这些标志完全不应该是必要项:如果工具可以推测出合理的默认值,那么强制要求填写这些标志只会额外增加使用者的工作量。一段没有用的输出或者产生过多token意味着选错了应对的输出格式。 代理的错误日志不是错误列表,而是一个规范: 每个错误都“否定性”地描述了你原本该如何设计接口。而这个规范是你最真实的反馈:无需代价,无数的真实数据,且没有人为善意隐藏工具缺陷。一个人类用户遇到糟糕的CLI时,可能会保持沉默并自动适应它。但代理不会适应:它会一遍又一遍地犯同样的错误,并记录下每一次。 这与我在另一篇文章中提出的一个原则有关:不应允许错误路径存在,而非仅仅禁止其使用。禁止只是一种文档说明——“不要使用--status“——而文档取决于是否有人认真阅读。让错误变得不可能,是设计的职责。 因此,解决方案并非更好的文档,而是更好的工具。 重设计 我围绕这个原则重写了CLI,工具叫做lql。以下四个设计决策贯穿整个改进过程。 宽容优于拒绝。 如果代理输入了 --status,工具会将其接受为 --state 的别名并继续运行。如果输入了 --priority urgent,将其解析为 --priority 1 并说明假定的结果。最常见的“错误”路径直接被转变为正确路径。工具不会因为合理的猜测而惩罚用户,而是直接适应它。 通过错误信息指导正确方向。 当某个功能确实不存在时,错误信息不会简单地说 unknown flag,而是给出具体指导:--filter 不存在。要按状态筛选,请使用:--state <状态>。要搜索,请使用:lql search "文本"。 错误消息本身变成了文档,并且恰好呈现在用户最专注的时间点:他们刚刚失败时。 取消所有强制标志。 lql list 无需提供任何参数即可运行:默认按优先级排序,筛选出活跃状态,并根据工作目录自动检测团队。因为不存在 --sort 参数,自然也就没有遗漏它的可能性。一个代理无法忘记不存在的标志。 ...

2026年5月22日 · Fernando

Agentic体验:1,324次调用我的CLI,15.9%的错误率

我的CLI最常见的用户并不是我自己 lql 是一个用 Rust 开发的CLI工具,用于管理Linear的问题任务。我开发这个工具是因为现有的替代方案并不能满足我的实际使用需求:让一个自主的AI代理来管理问题任务。 为什么我必须开发自己的CLI Linear的MCP服务是我的第一个尝试。这个想法很优雅:搭建一个MCP服务器,从而直接向代理公开Linear的API。但是在实际使用中,它的运行速度很慢且非常不稳定,每次调用时,代理都需要从头开始构建GraphQL查询。这增加了在每次调用中引发不存在字段的机会。用了一两周后,我把这个方案卸载了。 社区版CLI(schpet 的 linear)是我的第二个尝试。这个工具主要是为人类用户设计的,带有交互式菜单、箭头选择以及确认提示。但问题是,一个代理不能操作交互式菜单。也不适合。 Linear 的“智能代理”功能。 2026年3月,Linear 发布了一个集成了 AI 的智能代理。乍一看听起来很理想,直到你发现其局限性:它仅能在Linear的Web界面内使用,没有终端调用功能,没有API,也无法与外部工具集成。它就是一个嵌在自己用户界面中的聊天机器人。如果你的工作流包括“编程的代理也需要管理问题”,Linear 的代理功能无法满足需求。 基于数据的设计:初步分析 在开发 lql 之前,我解析了Claude Code与Linear交互时165次会话中的每一个错误。结果表明,共记录了500多个错误,370次重试,并估算出每月约有700,000个token被浪费。--sort忘记使用40次;写成了--state "Todo" 而非 --state unstarted共12次;--no-interactive未添加导致CLI挂起,等待键盘输入64次。(全套数据细节见原始文章。) 基于这些数据,我设计了 lql 的用户界面。我并没有猜测一个代理需要什么,而是使用测量得到的数据。这形成了一些基础设计决策:输出格式为精简化版本TOON(每个问题约25个token,而不是繁多的JSON格式),为LLM容易混淆的选项添加别名(例如--status → --state),对值进行标准化(比如Todo 转化为 unstarted,urgent 转化为 1),并提供建议正确命令的错误提示信息,而不是简单地显示“未知选项”。 当时我并不清楚,实际上自己是在应用Postel法则。这是后来才意识到的。 第二次分析:lql在生产环境中的一个月 lql上线已经一个月。Claude Code每天会调用它30到50次,用于创建问题、更新状态、链接依赖、查询细节等。我自己从来不手动使用它,因为对我而言,手动管理问题不是兴趣所在。我有代理来解决这些事情。如果哪天我必须亲自执行lql,那说明出了严重的问题。 lql唯一的用户是一个LLM。这让整个设计变得完全不同。 所以我再次解析了Claude Code调用lql的会话日志,搜寻错误。 指标 数值 分析的会话数 200 lql 的调用次数 1,324 错误数 (is_error: true) 210 错误率 15.9% 15.9%的错误率未包括因为并行调用失败且被Claude取消的调用。这里只计算CLI实际发生的错误。 错误分类 并非所有错误都是一样的。有些表明缺乏约定,而有些则表明需要添加操作。 错误 频率 实例 未找到Label 20 --label tokamak (在该团队中不存在) --title 用作 create 的选项 8 lql create --title "Epic: ..." --team PROD 将 show/get 写成 view 6 lql show PROD-911 relate 参数顺序错误 12 lql relate PROD-834 PROD-833 blocked-by 尝试 update --team (移动问题任务) 超过15次 lql update PRIV-32 --team PROD relates 写成 related 2 lql relate PROD-912 relates PROD-910 --body 用于 comment 1 lql comment PROD-926 --body "文本" --comments 用于 view 1 lql view PROD-824 --comments 其余是Linear的API错误、1Password认证问题、或shell错误(长heredocs中的引号破裂)。 ...

2026年4月29日 · Fernando

我花了 $15 百万 token 写了 'fix: typo'

昨天我用 Claude Code 写了一条 commit message。diff 是一行修改:一个注释里的拼写错误。Claude Opus 读取了 diff,思考了两秒钟,生成了 fix: correct typo in auth comment。为此,它用了大约 800 个输入 token 和 30 个输出 token,分别花费 $15 和 $75 每百万 token。总成本:不到一分钱。但是,把这个过程放大到一天 40 次 commits,250 个工作日,一家公司有 200 名开发者使用 coding agents,那么这些看似微不足道的花费会积累成数千美元的开销,付出的只是等同于贴创可贴的智力劳动。 问题并不是 Opus 太贵。问题在于 coding agents 不会区分 $0.001 的任务和 $0.10 的任务。一切都通过同样的大模型执行。生成 commit 信息、分类一个 issue、验证格式 —— 全部使用高成本的模型,就像雇用一位外科医生来贴创可贴。 数据与成本 我们用 Claude Opus 4(上一代,目前大部分生产环境还在用的版本)的价格来算一个账: 任务 输入 Token 数 输出 Token 数 成本 生成 commit 信息(小型 diff) ~800 ~30 $0.014 分类某个 issue ~500 ~50 $0.011 验证 commit 格式 ~300 ~20 $0.006 生成 standup 报告 ~2000 ~200 $0.045 这些任务都不需要一个拥有 2 万亿参数和多步推理能力的大模型。这些仅仅是带有强约束的分类和生成任务。本质上就像是根据颜色对卡片进行分类。 ...

2026年4月5日 · Fernando