跳到主要内容

6 篇博文 含有标签「tool-design」

查看所有标签

你的 Agent 读不懂的生产日志

· 阅读需 10 分钟
Tian Pan
Software Engineer

你把事故响应 agent 接入了 Splunk。你在系统提示里给了它查询语法,给了它执行 SPL 的工具,还有一个新鲜的 API token。第一次真正处理告警时,它拉了错的日志,总结了错的服务,信誓旦旦地报了错的客户。集成做得完美无缺,agent 却一文不值。

你忘了什么。十五年的日志惯例、没文档的字段名、跨越三次重组从 ERR 漂移到 error 再到 ERROR 的告警级别字符串、把 customer_id 在认证服务里变成 cust_id_v2_actual、在计费服务里变成 tenant.user.id 的团队特定后缀——这些东西没有一条出现在 prompt 里。你给了 agent 对 API 的访问权,但你没有给它访问那些让 API 变得有用的机构知识的权力。

这种失败的形状比 Splunk 大得多。任何把查询语言暴露给 agent、而底层语料是团队手工塑造了十年的工具,都会撞上这堵墙。Agent 拿到了动词,没拿到名词。

工具的默认参数其实是伪装的策略决策

· 阅读需 11 分钟
Tian Pan
Software Engineer

打开任何智能体运行的 trace(追踪),观察一次工具调用。你会看到工具名称以及模型选择传递的参数。你没看到的是它 没有 传递的所有内容。一个仅设置了 querysearch 调用,在运行时仍然具有页面大小、超时时间、结果排序和可见性范围。这些都不是智能体决定的。而是你在几个月前编写工具 schema 时决定的,当时你将这些参数设为可选并留下了默认值。

默认值并非为了方便。它是伪装成合理留白的策略决策。默认的页面大小限制了智能体在一次调用中能看到的范围。默认的超时时间决定了智能体何时放弃并开始即兴发挥。默认的可见性范围决定了“搜索文档”是指公共手册,还是包含未发布路线图在内的整个内部维基。默认的 dry_run 标志决定了智能体的行为是一场演习,还是生产环境中真实的、不可逆转的事件。

原本运行良好的工具,直到两个智能体同时调用它

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个工具通过了测试。你从一个智能体(agent)调用它,看着它读取记录、转换、写回并返回一个清晰的结果。几周以来,它每次都表现完美。然后你将智能体集群从一个 worker 扩展到十二个,结果一个客户报告说他们的订阅在同一分钟内被升级了两次。工具没有变,只是调用它的并发量变了。

这是单智能体测试无法捕获的失败模式,因为单智能体测试永远不会产生触发该模式的条件。从结构上看,单个调用者是一个串行工作负载。你的工具默默依赖的所有并发假设——读取时没有其他人在写入、自增的计数器是属于它自己的、保存时正在编辑的草稿依然存在——在只有一个调用者时都是理所当然成立的。工具并非正确,只是未经过测试。这两者是不同的,而在第二个智能体出现之前,这种差异是不可见的。

分页是一项工具目录规范:为什么智能体在处理列表返回时会耗尽上下文

· 阅读需 12 分钟
Tian Pan
Software Engineer

在你的技术栈中,每一个设计良好的 HTTP API 都会返回分页结果。没有人会把一百万行数据加载进内存并祈祷一切顺利。然而,你的智能体(agent)所调用的工具却会返回整个列表,而智能体也会尽职尽责地阅读它,因为函数签名写的是 list_orders() -> Order[],且智能体不像人类用户那样拥有“滚动并加载更多”的协议。

智能体在原本可以跳过的行上浪费了 Token。拥有 50K 记录的长尾客户遇到了中等规模客户从未见过的上下文窗口失败。工具作者无法从追踪(trace)中判断智能体是需要所有这些行,还是仅仅因为无法请求更少的数据。而且,在你评估套件的某个地方,原本会标记这种退化的回归测试从未运行,因为每个测试固件(test fixture)的记录都少于 100 条。

分页不是一种 UI 交互功能。它是一种负载卸载(load-shedding)原语 —— 而在没有分页的情况下使用工具的智能体,正在重新犯下你们公司的 API 设计师们花了十年时间才学会避免的每一个 SELECT * FROM orders 错误。

无结果并不代表不存在:为什么智能体将检索失败视为证明

· 阅读需 11 分钟
Tian Pan
Software Engineer

智能体对话记录中最危险的一句话不是幻觉。而是四个冷静的词:“我没有找到。”智能体听起来在认知上表现出谦逊。听起来像是完成了尽职调查。对于任何下游读者或调用者来说,这听起来完全像是一个事实。然而,这句话并没有提供关于该事物是否存在的信息。它只提供了关于特定工具在使用特定查询、咨询特定索引(而智能体恰好在那个时刻有权访问该索引)时发生了什么的信息。

在这两种解读之间,隐藏着一个随时可能发生的生产事故。支持智能体告诉客户“我们没有你的订单记录”,因为同步延迟导致写入只读副本的时间推迟了 90 秒。编码智能体声明“该模块没有测试”,因为它搜索了一个不包含测试文件夹的目录。合规智能体回答“档案中没有先前的违规记录”,因为审计索引尚未摄取上周的报告。在每种情况下,智能体的输出在语法上都是一种否定,但在认知上,它只是一个被重新表述为断言的“耸肩”。

为智能体编写工具:ACI 与 API 同等重要

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数工程师对待智能体工具的方式与编写 REST 接口或库函数如出一辙:清晰地暴露功能、记录参数、处理错误。这对人类来说是正确的直觉。但对于 AI 智能体(AI Agents)来说,这完全是错误的。

智能体使用的工具是以非确定性的方式被消耗的,它被逐个 Token 解析,并由一个对上周二使用过什么工具没有持久记忆的模型来选择。你编写的工具 Schema 并不是文档——它是运行时提示词(runtime prompt),在推理时被注入到模型的上下文中,塑造着智能体做出的每一个决策。每一个字段名称、每一段描述、每一个返回值的结构都是一个设计决策,具有可衡量的性能影响。这就是智能体-计算机接口(ACI,Agent-Computer Interface),它值得你像对待任何关键的面向用户的界面一样投入工程精力。