跳到主要内容

161 篇博文 含有标签「agents」

查看所有标签

你的 stop_reason 在说谎:构建生产环境故障排查真正需要的停止分类法

· 阅读需 14 分钟
Tian Pan
Software Engineer

运维工程师调出一个 trace。模型已返回,span 正常关闭,API 调用显示 stop_reason: end_turn。从平台提供的各种信号来看,这是一次成功的生成。3 分钟后,客户报告说 Agent 煞有介事地写了半个配置文件,宣布操作完成,然后就继续下一步了。Trace 里没有任何预警信号,因为预警信号不在 API 协议里 —— 供应商提供的停止原因只有四到七类,而你的事故排查所需要的答案,恰恰隐藏在这些类别的缝隙之中。

停止原因(Stop reasons)是工程师在故障排查时最先查看的字段,也是最具误导性的字段。这些值是为运行时(runtime)设计的,旨在决定下一步该做什么:这一轮是否完成了?是否请求了工具?是否超出了预算?安全检查是否介入了?它们并不是为了让开发者重建答案出错的原因而设计的,而这两者之间的差异,正是生产团队耗费整个下午的时间所在。

并行工具扇出的结构化并发:谁来负责部分失败?

· 阅读需 13 分钟
Tian Pan
Software Engineer

当你的智能体(Agent)扇出五个并行工具调用——跨三个索引进行搜索、查询两个数据库、调用一个外部 API——的那一刻,你已经跨越了一道无形的界限。你不再是在编写“提示-响应”(prompt-and-response)代码,而是在编写一个并发程序。大多数智能体框架都假装你没有在这样做,而账单会在凌晨 2 点准时送达。

这种假象是令人愉悦的。规划器(Planner)发出一个工具调用列表,运行时环境(Runtime)启动它们,收集返回的任何结果,最后由规划器消费这些汇总数据。从万英尺的高空俯瞰,这就像一个扇出 / 扇入(fan-out / fan-in)流水线,大多数团队在生产环境给他们上课之前,也确实是这样对待它的。问题在于,二十年的并发编程研究——部分失败语义(partial-failure semantics)、结构化取消(structured cancellation)、背压(backpressure)、确定性错误归因(deterministic error attribution)——已经解决了你即将重新发现的那些失败模式。而你的智能体框架在默认情况下,没有引入其中的任何一项。

Token 放大:烧掉你账单的提示词注入攻击

· 阅读需 11 分钟
Tian Pan
Software Engineer

用户提交了一个 0.01的请求。你的智能体读取了一个网页。40秒后,该次对话的推理账单变成了0.01 的请求。你的智能体读取了一个网页。40 秒后,该次对话的推理账单变成了 42。该查询在技术上是成功的——智能体返回了一个合理的答案。只是为了得到这个答案,它经历了三个嵌套的子智能体、一次 200K token 的文档获取,以及一个递归的计划优化循环。这些扇出(fanout)操作并非用户的本意,而是隐藏在智能体所读取页面中的一句话。

这就是代币放大(token amplification):一种提示词注入攻击,它不窃取数据,不调用未授权工具,也不会留下明显的安全特征。它只是烧光你的账单。云账单是攻击载荷,而用户的请求则是载体。

供应商 99.9% 的 SLA 对你的 Agent 来说衡量边界错了

· 阅读需 14 分钟
Tian Pan
Software Engineer

一个模型提供商发布了 99.9% 的可用性 SLA。采购团队将其理解为“三个九,每年四个小时的停机时间,对于非 0 级(非核心)工作负载是可以接受的”。六个月后,智能体(Agent)功能上线,值班仪表板显示用户感知的任务成功率约为 98% —— 这个数字没有写进任何合同,在提供商的状态页面上也找不到,而且没有人为此负责。提供商满足了他们的 SLA,而产品却没达到其 SLO。两者同时成立,而这种差距并不是一个 bug —— 这是一个算术问题。

大多数团队都忽略了算术这部分。提供商的 99.9% 是针对同步请求工作负载进行衡量的 —— 一个用户,一个提示词,一个响应,一个计费事件。而智能体并不会产生这种工作负载。一个用户感知的任务会扇出(fan out)为 8 到 20 次推理调用,它会对瞬时错误进行重试,对慢速调用进行对冲(hedge),并聚合部分输出。每一次调用都是对提供商故障分布的一次独立抽样,如果任何关键调用失败,任务就会失败。SLA 覆盖的边界和用户感受到的边界并不是同一个边界。

你的智能体发件箱将是你的下一个送达率事故

· 阅读需 13 分钟
Tian Pan
Software Engineer

当这种情况第一次发生时,值班工程师正盯着已经全红的 Gmail Postmaster 仪表盘,支持信箱因为客户重置密码邮件落入垃圾邮件箱而告急,而导致这一切的智能体(Agent)仍在运行。在当地时间凌晨 4 点到上午 9 点之间,它从公司的主要发送域名发送了 8 万封“个性化跟进邮件”,且全部使用了计费系统所用的同一个 DKIM 密钥签名。等有人注意到时,花费三年建立的域名声誉已毁于一旦,接下来六周内,公司所依赖的每一条事务性消息的收件箱投递率也将随之化为乌有。

从智能体发送邮件看起来就像是一个单行的工具调用。send_email(to, subject, body) 是最经典的演示,每个框架都将其作为入门集成提供。但邮件不同于其他工具。错误的数据库查询可以回滚,错误的 API 调用会返回错误。而一批糟糕的邮件会降低你公司发送的每一封其他邮件的送达率,且持续数周之久。这里没有可以回滚的事务,因为邮件已经发送到了接收方的邮件服务器,而这些服务器正在记录你域名的声誉历史。

你的 API 曾假设一次只有一个人类用户。并行智能体打破了这一契约。

· 阅读需 14 分钟
Tian Pan
Software Engineer

我认识的一位后端工程师在一个周二的下午盯着一个从未有过波动的 Datadog 图表:其内部日历服务的单用户 429 计数器。投诉的客户并没有改变他们的行为。他们只是开启了助手功能,现在每当用户说“帮我找下周的时间”时,该功能就会针对同一个日历 API 并行启动八个规划线程。速率限制器(Rate Limiter)——每用户每分钟 60 次请求,这个设置非常合理,是多年前针对一个在物理上无法点击得那么快的 UI 编写的——在每次请求的前三秒内就会触发,并悄无声息地破坏了助手一半的响应。

速率限制不是 Bug。契约才是 Bug。那个后端,就像大多数在 2024 年之前编写的内部服务一样,在每一层都植入了一个悄然执行的假设:一个用户意味着一条活动流,其节奏受限于人类的反应时间,拥有一个 cookie 罐、一个 CSRF 令牌和一套在出现问题时可以重新提示的凭据。Agent 一次性粉碎了所有这五个假设,故障表现为一系列看似无关的事件——429 风暴、“最后写入者胜”(last-write-wins)导致的数据损坏、无法取证的审计日志、挂起无头工作线程的重新认证循环——在模式被命名之前,没有人会将它们联系起来。

我一直与平台团队沟通的一个简短总结是:你拥有的每一个后端都与它的调用者有一个未记录的契约,而那个契约是与人类协商达成的。现在 Agent 出现了,要求重新协商。你可以选择在代码审查中主动进行协商,也可以选择在下一次事故期间被动进行。

人格漂移:当你的智能体忘记自己的身份时

· 阅读需 12 分钟
Tian Pan
Software Engineer

系统提示词写着:“你是一名金融分析师——保持保守,永远不要给出具体的买入/卖出建议,始终披露不确定性。”在最初的二十轮对话中,智能体的表现确实像一名金融分析师。到了第五十轮,它开始推荐具体的股票,模仿用户随意的语气,且比起第三轮时更少做风险对冲。没有人修改过系统提示词。没有人注入任何恶意指令。角色只是在对话的重压下被侵蚀了,就像河岸在没有任何东西越过“攻击”阈值、但流水从未停止移动时所发生的那样。

这就是人格漂移(Persona Drift),也是你的评估套件未能捕获的退化。能力评估衡量模型是否能完成任务。而身份评估——即模型是否仍在按照系统提示词要求的方式执行任务——在研究论文之外几乎不存在。其结果是产生了一类生产环境下的失败:它们在逐轮查看时显得正确,只有当你从头到尾阅读完整记录时才会发现问题。

Agent 的链路追踪采样:每日千万级 Span 中哪些值得保留

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个 Web 服务请求在繁忙时段产生 5 个 Span。而一个现代的 Agent 会话产生 50 个,如果 Planner 决定递归,有时甚至会产生 1000 个。你们平台团队从微服务时代复制粘贴过来的 1% 均匀采样器,从定义上就会丢弃你真正关心的稀有故障——因为故障是稀有的,而均匀采样对稀有性没有任何判断力。

“我们对 Agent 拥有完全的可观测性”的真实版本听起来与营销版本不同。它听起来应该是:我们保留重要的 Trace,丢弃不重要的,并且我们预先知道哪些是哪些。这句话中的每一个词都至关重要,而那些在账单寄来之前一直忽视采样设计的平台团队,现在正被迫反向学习这一学科——在成本压力下,以及在经历了一个季度的故障之后,这些故障本应“在数据中”,但在有人查看之前就被剔除了。

冷启动评估:如何在零生产环境追踪的情况下发布 AI 功能

· 阅读需 11 分钟
Tian Pan
Software Engineer

每个 AI 功能上线前都有一个同样的静默时刻:在第一个用户看到它之前,团队中的某个人会问“我们怎么知道这个东西好不好?”,而诚实的回答是“我们现在还不知道”。你没有追踪记录 (traces),因为你还没有用户。你没有用户,因为你还没有发布。这是一个真实的死循环,而它产生的两种失败模式都是致命的——要么盲目发布,让第一周的线上问题 (escalations) 成为你的评估数据集;要么等待“真实数据”,眼睁睁地看着产品路线图推迟一个季度,而竞争对手却发布了演示视频。

摆脱困境的方法不是假装冷启动评估与发布后的评估是同一个问题(只是样本量较小)。事实并非如此。你不是在对分布进行采样,而是在构建先验 (prior)。上线首日的每一个信号都是你所做选择的产物——关于衡量什么、模拟谁的行为以及关注哪些失败的选择。能够出色发布 AI 功能的团队会将发布前的评估栈 (eval stack) 视为一等交付物——它不是在准入审查前一晚匆忙拼凑的电子表格,而是一个由内部试用 (dogfooding)、模拟、专家标注和对抗性探测 (adversarial probes) 组成的层级化系统,每一层都提供不同类型的信号,并伴随着关于它能告诉你什么以及不能告诉你什么的明确说明。

对话历史是你的提示词从未承认的负担

· 阅读需 12 分钟
Tian Pan
Software Engineer

下次当用户抱怨“AI 今天变笨了”时,去看看你产品的分析数据。筛选出对话轮次超过 20 轮的会话。你会发现每次都是同样的 U 型曲线:前几轮表现良好,中间几轮表现也不错,而到了后期轮次,质量却直线下跌。提示词没变,模型也没变。变化的是,后期每一轮对话都背负着沉重的载荷:用户的拼写错误、话说到一半的废话、模型的模棱两可、后来被撤销的更正、没人重读的工具输出,以及用户在第四轮就放弃了的目标残余。你的提示词模板把这些“沉积物”当成了信号,模型也是如此。但这不应该。

对话历史并非免费的上下文。它是一种你每一轮都在付费重新发送的负债;它变得越混乱,就越会损害你向用户收费提供的答案。“聊天”这个隐喻是混乱的根源。聊天界面让用户和工程师习惯于将记录视为神圣不可侵犯的 —— 可滚动的、仅限追加的、从不重置。这种习惯被原封不动地引入了 LLM 应用中,尽管在模型处理上下文的物理机制上并没有这种依据。模型是无状态的。对话记录只是你选择不断拉长的一段字符串。你可以缩减它,而且通常你应该这样做。

持久化智能体:为什么异步队列无法胜任长运行 AI 工作流

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个每步成功率为 95% 的智能体并不是一个 95% 可靠的智能体。将 20 个步骤串联起来,端到端的完成率就会下降到 36%。这是大多数团队在智能体上线生产环境后才发现的算数逻辑,也是为什么这么多“运行良好”的原型在真实流量涌入的瞬间就会陷入停滞。解决方法不是更好的提示词或更大的模型,而是一个乏味的分布式系统基础设施,大多数 AI 团队在第三次宕机被迫应对之前都会试图避开它。

这种基础设施就是“持久化执行”(durable execution)——这是一种让多步骤工作流在崩溃、重启和局部故障中幸存且不丢失进度的准则。这并不是什么新鲜主意。Temporal、Restate、DBOS、Inngest 和 Azure Durable Task 已经为此推销多年。2026 年的新变化是,每个严肃的智能体框架都已悄然承认持久化执行是入场券:LangGraph 现在内置了 PostgresSaver 检查点,OpenAI Agents SDK 暴露了 resume(恢复)原语,Anthropic 的 Managed Agents 运行在内部的持久化基座上。如果你的智能体架构仍然依赖 Celery 队列和乐观主义,那么你是在 2026 年解决一个整个行业在 2024 年就不再假装视而不见的问题。

本文探讨的是无状态 LLM 与必须包装它的有状态工作流引擎之间的架构接缝。接缝之处正是可靠性所在,也是大多数团队目前编写 Bug 的地方。

人机回环 (HITL) 是一个队列,而队列具有动态特性

· 阅读需 13 分钟
Tian Pan
Software Engineer

团队向 AI 工作流添加人工审批的方式,与他们在代码库中添加 if (isDangerous) requireHumanApproval() 的方式如出一辙:将其视为一个二进制开关,在设计时检查一次,然后便将其遗忘。架构图上的指标是“人工监督”旁边的一个绿色对勾。而真正重要的指标——人工花费了多长时间、他们是否阅读了任何内容、在点击批准时该条目是否仍然相关——却很少有对应的仪表板。

将人工审批者视为二进制开关,你就等于在不知不觉中构建了一个队列。而队列具有动态特性:积压量的增长速度超过了你的员工配置速度、陈旧性使昨天的决定变得毫无意义、疲劳让审查变成了“走过场”(rubber-stamping),以及优先级倒置让真正重要的那一个决策被排在三百个无关紧要的决策之后。架构图中看不到这些,但它们都会出现在事故回顾(incident retro)中。