news 2026/11/3 7:43:03

Agent失败别急着怪模型:从粗错误码到失败链排查法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent失败别急着怪模型:从粗错误码到失败链排查法

凌晨三点被告警拍醒这件事,干 Agent 开发的迟早都会遇上。日志栏里只有一行粗错误码“Agent execution terminated due to error.”,团队群里第一反应是“模型服务商挂了”“换个更强的模型”。我当时没有急着去翻模型响应,而是先把整条链路拉出来看了一遍,最后发现真正的问题是宿主机上两个容器 IP 冲突,导致 Agent 调工具的网络包时通时不通——模型一直很无辜,锅却差点扣到它头上。这篇就把我总结的“从粗错误码到失败链排查”方法完整写出来,适合正在做 Agent 应用开发、框架集成,或者负责 Agent 服务稳定性的同学参考。

1. “模型不行”是最后才该下的结论

1.1 一次凌晨三点的误判

那段时间我正在做一个偏复杂的多 Agent 协作项目,任务会经过编排、模型决策、工具调用、沙盒执行好几个环节。某天夜里批量任务突然大面积失败,代运维的同学把日志贴到群里,核心信息就一句话:

Agent execution terminated due to error.

没有堆栈,没有 trace_id,没有任何上下文。群里已经有人开始讨论“是不是该换模型”“是不是上下文太长导致模型乱来”。我做的第一件事不是打开模型服务商的测试台,而是让值班同事把最近十分钟的链路日志、容器状态、网络连接情况发过来。

结果很有意思:Agent 框架侧完全正常,任务确实被创建了;模型调用也发出去了,服务商有响应;但工具执行这一跳断了——沙盒容器根本没起来,或者起来了也出不了网。再往下一查,两个容器被分配了相同的 IP,ARP 表混乱,请求发出去之后跑到错误的网卡上去了。整个过程里模型没有做错任何事,是基础设施先倒下了。

后来我统计过自己团队一个季度的 Agent 故障归因,三分之一以上出在网络和基础设施,另外三分之一出在工具参数、数据契约、解析层,真正能算到模型头上的不到三分之一。“模型不行”在多数时候只是我们最顺手的一个解释,因为它不可解释、不可观测、还经常真的“显得”很笨。

1.2 Agent 失败的环节比你想象的多

很多人对 Agent 的理解是“把 Prompt 丢给大模型,等它返回结果”。真实生产环境里,一次 Agent 任务至少经过这么几个环节:

  • 用户输入进入任务队列,编排器创建执行计划;
  • 模型被调用,完成意图识别、工具选择、参数生成;
  • 工具/技能被拉起,可能是 HTTP 调用、代码执行、容器沙盒;
  • 执行结果返回到编排层,做格式解析、Schema 校验、上下文压缩;
  • 最后更新状态、落库、触发通知。

这五段里每一跳都可能出问题。DNS 解析慢、TCP 握手失败、TLS 证书过期、请求体超大、容器 OOM、磁盘写满、数据库连接池耗尽、消息队列堆积……它们都会以“Agent 失败”的面貌出现在业务日志里。而框架为了不暴露内部细节,往往就把这一切压成一行粗错误码。

顺便说一句,市面上吴恩达那套 Agent 入门教程确实把 RAG、工具调用、多 Agent 协作讲得很清楚,但真到了线上,没人教你 Agent 失败之后该怎么“分尸”。分尸的第一步,就是把模型从怀疑名单里暂时划掉。

1.3 为什么我们习惯性归因模型

这里有个心理效应。模型输出是黑盒,你很难一眼看出它是“思考错了”还是“被误导了”。相比之下,网络问题、资源问题看起来是“外部环境”,离我们更远;模型就在调用链正中间,看起来和失败最相关。

再加上很多 Agent 框架的异常处理很粗糙,内部发生了什么都吞掉,只给一个自然语言错误信息。你越看不到细节,就越倾向于把失败解释成“模型太笨”。这是认知捷径,不是排查方法。

所以我给自己定了一个“模型背锅指数”:只有在链路日志显示请求已发出、服务商已正常返回、解析也没问题,但结果依然不符合预期时,模型嫌疑才能上升;否则先找基础设施和契约层的问题。这个习惯救了我很多次。

2. 粗错误码:只划了范围,没画线路

2.1 常见粗错误码背后各自的水有多深

我把平时生产环境里高频出现的粗错误码整理过一遍,每个都不是表面那么单纯:

错误码/信息字面含义实际可能涉及的范围
HTTP 408 / 504请求超时、网关超时模型服务商处理慢、本地 DNS 解析慢、网关超时阈值太小、请求体过大、网络抖动
HTTP 422语义错误、不可处理实体请求头缺字段、Content-Type 不对、工具参数类型不匹配、Schema 定义不一致
HTTP 429限流模型服务商限流、网关熔断、账号配额不足、本地重试风暴
HTTP 502 / 503上游不可用工具服务宕机、沙盒容器退出、模型网关节点异常、数据库连接失败
“Agent execution terminated due to error.”执行被终止容器被杀、OOM、内存超限、代码执行崩溃、编排状态机异常
“Model request failed”模型请求失败网络层断开、TLS 失败、服务商 API 返回非 2xx、请求格式非法

这里想强调一个点:422 看起来是“模型返回的东西不合法”,但很多时候真正原因是你的工具 Schema 和实际参数结构对不上。模型严格遵守了你的定义,是你的定义本身有问题。你说模型不理解工具,模型也挺冤。

2.2 错误码的粒度陷阱

粗错误码最大的问题不是“不准”,而是“没有上下文”。它只告诉你哪条路的出口被堵了,没告诉你从入口到出口中间哪段堵的。你拿着“网关超时”这个码,可能的问题有十几种,逐个试过去,运气好一两次能中,运气不好折腾到天亮。

我之前踩过的坑是:错误码显示超时,我以为是模型服务商慢了,反反复复调超时时间、开重试,结果最外层网关把超时时间设成了 10 秒,而本地 DNS 解析就要 3 秒,加上请求体 200KB,服务商实际只用了 4 秒就返回了,但整套链路已经超时。问题根本不在模型,而在 DNS 和超时配置的乘积效应。

所以我的原则是:粗错误码只是“案发现场的第一行血迹”,真正的案发过程必须靠失败链的一整串证据来还原。错误码给你方向,链路给你路径,路径上的观测点给你真相。

3. 失败链排查法:把一次执行拆成五个可观测段

3.1 五段链路与每段的成功标准

我习惯把一次 Agent 执行拆成五段,每一段都有明确的成功标准和最少观测项。没有观测项,等于没有排查入口。

第一段:入口与编排。任务从队列取出,状态机从 pending 变 executing,编排日志会出现 trace_id。成功标准:有任务记录,状态流转可见。

第二段:模型调用。包含 DNS 解析、TCP 建连、TLS 握手、HTTP 请求发出、拿到响应。成功标准:拿到模型服务商返回的 HTTP 状态码和响应体,同时记录耗时。

第三段:工具与沙盒执行。容器启动、网络命名空间就绪、工具进程运行、返回退出码。成功标准:工具进程退出码为 0 或有明确的业务错误码,容器没被异常杀死。

第四段:结果解析与反馈。模型输出或工具返回值被框架解析、Schema 校验、结构化。成功标准:校验通过标志为 true,解析后的对象与预期类型一致。

第五段:业务落库与通知。结果写库、消息队列投递、通知发出。成功标准:数据库回执、队列 ack 存在。

这五段对应到代码里就是五个埋点位置。我建议哪怕你是小团队、没有分布式追踪系统,也至少给每个 Agent 任务生成一个 trace_id,然后以结构化日志的形式输出每段的开始时间、结束时间、关键参数和错误摘要。

3.2 从错误码到失败链的映射方法

拿到的错误码先不要猜,直接落到五段链路上做嫌疑排序。

  • 如果是 timeout 类错误,先看第二段各子步骤耗时,DNS 多少秒、TCP 多少秒、TLS 多少秒、HTTP 多少秒;
  • 如果是 422、schema 校验失败,直接跳第四段,同时反查第二段模型返回的原始内容和第三段工具实际的返回结构;
  • 如果是 execution terminated,先查第三段,看容器退出码、系统日志、是否有 OOM 记录;
  • 如果是 5xx,重点看第三段和第五段,工具服务是不是还活着,数据库连接是不是正常。

这里有个技巧:不要只盯错误发生的那一段,要看它上游和下游各一段。比如第四段解析失败,可能是第三段返回的结构变了,也可能是第二段模型生成的 JSON 本身合法但字段对不上。把三段的日志拼在一起,往往一眼就能看出是谁先坏的。

3.3 埋点与日志:让链路可回放

第一次做失败链排查时,我最大的痛苦是日志没埋够,错误发生之后想回溯,发现第二段模型请求的原始报文根本没记录。后来我强制自己在四个位置保留“原稿”:

  • 模型请求体:记录了完整的 Prompt、工具定义、参数样例;
  • 模型响应体:包括原始文本、JSON 解析后的对象、HTTP 状态码;
  • 工具调用的出入参:入参是模型生成的参数快照,出参是工具实际返回值;
  • 框架侧每一次状态转换:从 pending 到 executing 再到 done/failed,失败时带上异常类名和 message。

有了这些原稿,任何一次“模型失败”都可以重放:我把同样的 Prompt 直接发到模型服务商的测试台,不带任何工具和编排,看它是否复现。如果复现,模型嫌疑坐实;如果不复现,那就怪你的框架或参数处理,跟模型没关系。

这套“可回放”思路是我排查效率提升最大的一步。以前我要靠回忆和猜,现在我只要把四个原稿拉出来看一遍,大多数问题五分钟内能定位。

4. 四个伪装成“模型失败”的真实案例

4.1 案例一:execution terminated due to error. 是容器资源被杀

现象很常见:Agent 在沙盒里执行一段 Python 代码,刚跑到一半就报 “Agent execution terminated due to error.”,没有任何 Python traceback。团队第一反应是模型生成的代码本身有 bug。但我把容器日志拉出来后,发现进程是被内核杀掉的。

Linux 里最容易被忽略的凶器是 OOM Killer。我用dmesg | grep -i oom一看,果然有内存超限记录,容器 cgroup 限制的内存太小,模型生成的代码要处理的数据量又大,进程直接被清掉了。

这个问题如果你只盯着模型输出看,永远找不到答案,因为模型生成的代码在普通环境里跑得好好的,是执行环境不给力。调整沙盒内存上限后,同类 Agent 任务再没出过这个错。经验是:没有 traceback 的 execution terminated,优先怀疑执行环境而不是模型。

4.2 案例二:422 报错是参数类型没对齐

另一个项目里,Agent 调用一个工具服务,模型服务商稳定返回 422,业务方一口咬定“模型没理解工具参数”。我把模型服务商这侧的请求体原稿调出来,发现模型生成的参数在语义上是完全正确的,但字段命名方式和工具定义对不上:模型按照工具 Schema 里的 camelCase 生成了参数,而工具实际后端代码读的是 snake_case,中间没有转换层。

这个问题的根子出在工具契约:工具定义、Schema、后端实现三者没有统一。模型只是在严格执行一份有瑕疵的地图。修好参数转换层之后,422 立刻消失。

所以我在团队里立了个规矩:遇到 422,先打印请求体原文,再打印工具 Schema,两边逐字段比对。模型输出不合法是最后一种可能,在那之前先确认你自己的契约没有自相矛盾。

4.3 案例三:连接超时是 IP 冲突叠加了网关背锅

最戏剧化的一次来自标题里提到的 IP 冲突。有一段时间,Agent 在特定时段调用外部工具服务频繁连接超时,时好时坏。初步怀疑是模型服务商网络波动,但抓包发现请求没有到达应有的下一跳。

我用ip addr看了网卡,用arp -a查相邻表,再用arping -D -c 3 <ip>做地址冲突检测,发现同一个 IP 被分配给了两个容器。它们在同一个网络命名空间里互相打架,ARP 表不停摇摆,网络包时通时不通。重启其中一个容器后,超时立刻消失。

这种问题很难从模型侧看到任何线索,因为模型请求本身没有错,是网络到达路径已经坏了。排查网络类超时,一定要先确认“地址唯一、路由正确、握手成功”,再谈服务商慢不慢。

4.4 案例四:模型真的很“笨”,但链路日志救了场

也有确实是模型问题的时候。某个多步推理任务里,模型经常漏掉一个关键工具调用,链路五段全部正常,没有网络问题、没有资源问题、没有契约问题,但模型每次生成的 choices 内容就是不完整。

我用同一个 Prompt 在模型服务商测试台单独重放,不带工具定义,复现率大概 80%,这时才敢下结论:问题出在模型能力边界上。后续的修法也不是“骂模型”,而是把任务拆小、增加一步校验重试机制,让模型先生成计划、确认后再逐步执行。这条经验反过来也说明:链路日志齐全的情况下,判断模型问题反而更快,因为你排除了其他所有变量。

4.5 案例复盘:共性线索表

症状粗错误码真正根因确认手段修复动作
沙盒执行中断,无 tracebackexecution terminated due to error.容器 OOM 被杀dmesg | grep -i oom调大内存上限
工具调用被拒HTTP 422参数命名契约不一致对比请求体与 Schema统一契约/加转换层
间歇性超时HTTP 504容器 IP 冲突arping / arp -a重启冲突容器,固定 IP
输出内容不完整无,链路正常模型能力边界测试台重放复现拆任务或加重试约束

共性是:所有案例在一开始都被归因到了模型,但真正用失败链证据说话之后,根因全在别处。

5. Linux 排查工具箱与一条命令拉起失败链

5.1 分层命令清单

没有链路日志的时候,命令就是你最快的观测手段。我按五段拆分了常用命令:

排查段命令作用
DNS 解析dig +short api.example.com、getent hosts api.example.com看解析结果是否唯一、是否被劫持
网络连通ping -c 4 <ip>、mtr -r <host>看丢包与路径节点
TCP 握手nc -vz -w 5 <host> <port>看端口是否通、握手耗时
IP 冲突ip addr、arp -a、arping -D -c 3 <ip>看地址分配与 ARP 冲突
端口监听ss -lntp、lsof -i:8080看服务有没有在监听
容器状态docker ps -a、docker logs --tail 200 <容器>看容器退出码和日志
资源与 OOMfree -m、df -h、dmesg | grep -i oom、docker stats看内存、磁盘、内核杀进程记录
HTTP 时序curl -w "dns:%{time_namelookup} tcp:%{time_connect} ttfb:%{time_starttransfer}" -o /dev/null分段定位 HTTP 请求耗时

这里最容易被忽略的是arping -D,它在排查“网络看起来通但不稳定”时的价值极高。如果一台机器 IP 和别人冲突,ping 可能大部分时间通,但偶尔断,你只看 ping 会以为只是网络抖动。

5.2 一个可直接改用的链路巡检脚本

我把自己日常用的一组检查写成了脚本,挂在告警群里当第一道过滤网,收到失败告警时先看它输出,省掉一半以上盲猜时间。

#!/usr/bin/env bash # check_agent_link.sh - Agent 失败链路巡检脚本 # 用法: bash check_agent_link.sh TARGET_HOST="${1:-api.example.com}" TARGET_PORT="${2:-443}" echo "===== 1) DNS 解析 =====" dig +short "$TARGET_HOST" | head -5 echo "===== 2) TCP 握手 =====" nc -vz -w 5 "$TARGET_HOST" "$TARGET_PORT" 2>&1 echo "===== 3) 本机关键端口监听 =====" ss -lntp | grep -E ':3000|:8080' || echo "no service listening" echo "===== 4) IP 冲突检测 =====" MY_IP=$(hostname -I | awk '{print $1}') if command -v arping >/dev/null 2>&1; then arping -D -c 3 "$MY_IP" 2>&1 | tail -3 else echo "arping not installed, skip" fi echo "===== 5) 容器异常状态 =====" docker ps -a --filter "status=exited" --format "{{.Names}} {{.Status}}" | head -10 echo "===== 6) 资源使用 =====" df -h / | tail -1 free -m | grep Mem echo "===== 7) 内核 OOM 记录 =====" dmesg | grep -i oom | tail -10

脚本思路很简单:按“网络是不是通、服务是不是在、资源是不是够、容器是不是被杀了”的顺序跑一遍,把容易背锅给模型的四个大类问题全部前置暴露。实际执行时可以把脚本挂到 cron,每小时跑一次,结果追加到日志文件,告警来了先看最近一条输出。

5.3 排查顺序的建议

我见过不少人一上来就翻模型响应体,这其实是高成本低回报的做法。推荐的顺序是:

  • 先看最近一次完整链路日志,确认 trace_id 里每一段是否有记录;
  • 没有链路日志就执行上面的巡检脚本,确认网络层、资源层没有致命问题;
  • 确认请求真的到达模型服务商且被正常处理之后,再去翻模型原始输出;
  • 最后才把“模型能力问题”纳入候选。

这个顺序的本质是“由外到内、由基础设施到上层逻辑”。网络和资源问题通常是最便宜的定位对象,命令一敲就有结果;模型问题才是最贵的,因为你需要设计复现实验、控制变量、对比多个模型版本。

6. 什么时候才真的是模型的事

6.1 三条确认模型问题的硬标准

链路日志全部正常、资源网络全部正常,模型才能进入决赛圈。我判断模型问题时只看三条硬标准:

  • 同一 Prompt 直接请求模型服务商(不带工具、不带编排)能稳定复现同样的问题;
  • 链路日志显示模型请求成功发出且返回成功,但输出内容与预期不一致;
  • 更换模型或版本后,相同链路的失败率出现明显变化。

三条里满足两条以上,我才会在复盘里写“根因:模型能力”。否则一律先写“根因待确认”,宁可承认自己还没查透,也不要给模型扣锅。

6.2 模型问题其实也分细类

就算真是模型问题,也要继续细分,否则修复方向会错。我遇到过的模型侧问题大致分四类:

类型典型表现常用修法
上下文过长模型遗忘早期指令,工具参数越到后面越乱压缩上下文、滑动窗口摘要
Schema 复杂工具定义过大时 JSON 输出不稳定、漏字段简化工具 Schema、拆分工具
指令遵循漂移同样 Prompt 不同批次表现不一致加 few-shot、固定输出格式约束
多步规划不足复杂任务漏步骤、顺序错乱拆任务、分阶段校验、允许重试

修模型问题最高效的办法不是我在这里说什么“换更强的模型”,而是让失败链在每一轮重试时都能提供结构化反馈:哪一步没做对、哪个字段缺失,然后把反馈拼回 Prompt 里,让模型有第二次机会自我纠正。这套机制比单纯换模型可靠得多。

6.3 把失败链做成告警资产

我现在收到 Agent 失败告警,第一步不是打开模型聊天框,而是先看链路各段的耗时与状态码,把错误码当线索而不是结论。这里再分享一个小技巧:给团队的错误分级里加一套“粗原因代码”,比如 network_unreachable、ip_conflict、container_oom、schema_mismatch、model_capability,让框架在吞异常时至少留一个「粗原因」,然后自动把对应段的日志拼到告警卡片里。

这样做了三个月之后,团队里的“模型背锅”言论明显少了,因为告警卡片自带链路证据,谁再说“模型不行”,就让他先解释网络段为什么丢包、或系统为什么 OOM。Agent 失败没那么玄学,只要把链路打开看,根因总归是能找到的。模型是最后怀疑对象,而不是第一怀疑对象。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/3 7:42:07

vLLM KV缓存用量26%却调度失败:PagedAttention分块机制与调度器排查调优

1. 这个现象到底在说什么面板上 KV 用量显示 26%&#xff0c;看起来离打满还远得很&#xff0c;但调度器那边一条新请求都塞不进去&#xff0c;全部卡在等待队列里。这个场景做大模型推理服务的人大概率都遇到过&#xff0c;尤其是用 vLLM 部署 Qwen、DeepSeek、GLM 这类模型的…

作者头像 李华
网站建设 2026/11/3 7:42:07

化工行业CRM系统:客户资源管理与企业价值提升

1. 化工行业CRM系统的特殊性与价值化工行业作为典型的B2B领域&#xff0c;其客户关系管理&#xff08;CRM&#xff09;系统与传统快消品行业有着本质区别。我在为多家化工企业实施CRM系统的过程中发现&#xff0c;这个行业的客户生命周期往往长达5-10年&#xff0c;单个客户的价…

作者头像 李华
网站建设 2026/11/3 7:41:40

前端DOM操作实战:微博发布功能实现解析

1. 微博发布功能实现解析这个微博发布案例是一个典型的前端DOM操作练习&#xff0c;通过HTML、CSS和JavaScript的配合&#xff0c;实现了一个简易的微博发布和展示功能。下面我将从技术实现角度详细拆解这个案例。1.1 页面结构与样式设计整个页面采用经典的"上发布区下展示…

作者头像 李华
网站建设 2026/11/3 7:41:15

SpinWait在高并发消息分发中的优化实践

1. 项目背景与核心挑战在即时通讯和客服系统这类高并发场景中&#xff0c;消息分发模块的性能直接决定了整个系统的吞吐量和响应速度。传统客服系统每秒需要处理成千上万条消息&#xff0c;这些消息需要在用户与客服之间快速路由&#xff0c;同时还要支持消息状态同步、已读回执…

作者头像 李华
网站建设 2026/11/3 7:41:15

ADS功放协同仿真:Fast Cosim一次算全ACPR、EVM与PAE

简介&#xff1a;面向射频与通信电路设计者的一份应用笔记&#xff0c;聚焦如何在Keysight ADS中借助Ptolemy协同仿真完成ACPR、EVM与PAE三项指标的评估&#xff0c;适合已具备一定功放设计基础、需要把仿真流程落到实处的工程师与相关专业学习者。文档以EDGE调制信号驱动待测功…

作者头像 李华
网站建设 2026/11/3 7:40:39

modbus_tk实战:RTU主站调试工具的轻量级配置与字节级排错

1. 项目概述&#xff1a;为什么一个MODBUS RTU主站调试工具值得花时间重做一遍你手头有一台PLC、一块温湿度传感器模块、或者一套工业现场的电表采集终端&#xff0c;它们都支持MODBUS RTU协议——这个在工业自动化领域扎根三十多年、至今仍在产线设备里嗡嗡运转的“老派通信协…

作者头像 李华