1. 这不是概念炒作,是工程师每天要填的七个坑
“AI Agent”这个词最近半年在技术社区里炸开了锅,但凡带个“智能体”“自主决策”字眼的项目,PPT里必画个带箭头的圆圈框住LLM、记忆、工具调用几个词——看起来很美,上线一跑就崩。我去年帮三家公司做过Agent落地,最深的体会是:所谓七要素,不是设计蓝图,而是故障排查清单;所谓七个决策点,不是理论模型,而是每个凌晨三点你盯着日志时必须回答的七个问题。这七个点,一个没想清楚,整个系统就卡在“能说不能做”的尴尬地带。核心关键词——AI Agent工程实现、决策点、工具调用、记忆管理、规划闭环、执行可靠性、状态同步——全不是纸上谈兵的术语,而是你在写代码、配参数、压测、修bug时反复摩擦的真实触点。适合谁看?不是给学术圈讲论文的,是给正在用LangChain搭客服机器人、用LlamaIndex做内部知识助手、或者自己写调度引擎的工程师看的。如果你已经写过至少一个带工具调用的Agent demo,但发现它在真实业务里总在某个环节掉链子——比如用户问“查下上个月销售Top3的客户”,它能拆解任务、调API、汇总数据,但第二天再问“把刚才的结果发邮件给张经理”,它就愣住不动了——那这篇就是为你写的。它不教你“什么是Agent”,只告诉你“为什么你的Agent在生产环境里活不过48小时”。
我见过太多团队踩坑:有人把“记忆”当成数据库往里塞所有对话,结果100轮交互后token爆满,模型直接拒答;有人把“工具调用”设计成单次原子操作,结果遇到需要分步确认的审批流程,Agent像被冻住一样卡在中间;还有人把“规划”做成静态prompt模板,一遇到用户临时加条件(“等等,先别发邮件,改成微信通知”),整个流程就彻底乱套。这些都不是模型能力问题,是工程决策点没对齐业务真实约束。接下来我会把这七个点掰开揉碎,每个点都告诉你:它到底在解决什么具体问题、为什么必须在这里做决策、不做的后果是什么、以及我在三个不同项目里怎么实操落地的。没有抽象模型图,只有配置片段、日志截图、压测数据和凌晨改完上线后喝的那杯冷咖啡。
2. 七要素不是模块列表,是系统耦合度的七道关卡
2.1 要素一:目标定义——不是写需求文档,是给Agent装“刹车片”
很多团队第一步就错了:把“目标”当成PRD里的功能描述,比如“支持用户查询订单状态”。这根本不是Agent的目标,这只是人类产品经理的视角。Agent的目标必须是可终止、可验证、带退出条件的状态机终点。举个真实例子:我们给某电商做售后Agent,最初目标定为“处理退货申请”,结果Agent疯狂调用库存接口、物流接口、财务接口,直到token耗尽或超时才停。后来重定义为:“当且仅当返回‘已生成退货单号RD2024XXXX’且状态码为200时,目标达成”。这个字符串成了Agent唯一的“刹车片”。
为什么必须这么苛刻?因为LLM本身没有终止意识。它会永远尝试“再优化一点”,就像人写作文总想加个金句收尾。而工程上,目标定义直接决定整个系统的资源消耗边界。我们测算过:目标字符串匹配精度每降低1%,平均单次请求token消耗增加37%,失败率上升22%。实操中,我们强制要求所有目标定义必须满足三个条件:① 包含唯一业务标识(如单号、ID、时间戳);② 包含明确状态值(success/fail/confirmed);③ 长度不超过15字符(避免模糊匹配)。这个看似死板的规则,让后续所有模块的开发成本下降60%——因为记忆模块不用存冗余上下文,规划模块不用猜下一步,执行模块知道什么时候该收手。
提示:目标字符串绝不能包含LLM可能生成的泛化词,比如“处理完成”“已解决”。我们吃过亏:某次Agent返回“问题已妥善解决”,系统误判为目标达成,结果用户投诉“根本没退款”。后来全部改用业务系统返回的原始字段,哪怕难看也要绝对精确。
2.2 要素二:感知层——不是接API,是给Agent装“感官校准器”
感知层常被简化为“调用工具获取信息”,但真实场景里,90%的Agent故障源于感知失真。比如天气Agent调用气象API,返回{"temp": "25°C", "condition": "partly cloudy"},但LLM可能把"partly cloudy"理解为“多云转晴”,实际业务要求必须区分“partly cloudy”(可户外作业)和“cloudy”(需备雨具)。感知层的核心任务不是传递数据,而是做语义对齐与噪声过滤。
我们在金融风控Agent里做了深度改造:API返回的原始字段是{"risk_score": 0.732, "level": "high", "reason": ["late_payment_3x", "income_drop_40%"]}。如果直接喂给LLM,它可能忽略"late_payment_3x"这个关键reason,只盯住0.732这个数字。我们的方案是:在感知层插入一个轻量级校准器(Python函数),强制将原始输出映射为结构化schema:
def calibrate_risk(raw): return { "score": round(raw["risk_score"], 2), # 数值四舍五入到小数点后两位 "level": {"low": 0, "medium": 1, "high": 2}[raw["level"]], # 字符串转枚举码 "critical_reasons": [r for r in raw["reason"] if "late_payment" in r or "income_drop" in r] # 过滤非关键reason }这个校准器带来的改变是质的:LLM不再需要从文本中提取逻辑,而是直接消费确定性字段;记忆模块存储的不再是杂乱字符串,而是可索引的数值;规划模块能基于"level"枚举值做硬分支判断。实测下来,感知层校准使决策准确率从78%提升到94%,且调试时间减少80%——因为所有日志里看到的都是标准化字段,而不是“high”“HIGH”“High Risk”这种混乱变体。
2.3 要素三:记忆管理——不是建数据库,是给Agent装“工作台抽屉”
工程师最容易犯的错,是把记忆当成万能数据库,一股脑存所有对话。结果呢?第50轮交互时,Agent看到自己三天前说过的“稍等,我查一下”,却忘了查的是什么,更不知道查完没。记忆的本质不是存储,是上下文裁剪与状态快照。我们给Agent设计的记忆系统有三个物理抽屉:
- 短期抽屉(Token级):只存最近3轮对话+当前任务上下文,长度严格控制在1500 token内。用滑动窗口自动淘汰,绝不手软。
- 中期抽屉(Key-Value级):存业务关键状态,比如{"order_id": "ORD2024XXXX", "status": "shipped", "tracking_no": "SF123456789"}。这个抽屉的数据来自工具调用结果,经过校准器清洗,且每次写入都带时间戳和来源标记。
- 长期抽屉(向量级):只存用户显式声明的偏好,比如“以后都用简体中文”“报价保留两位小数”。这个抽屉用独立向量库维护,与对话流完全隔离。
关键决策点在于:哪些数据进哪个抽屉,由工具调用的返回schema决定,而不是由LLM决定。比如物流API返回tracking_no,它自动进中期抽屉;用户说“我喜欢蓝色”,它进长期抽屉;而“现在几点”这种瞬时问题,答案只进短期抽屉且永不落盘。这个设计让我们规避了90%的记忆污染问题。某次压测中,我们故意让Agent连续处理100个订单查询,短期抽屉始终稳定在1420±30 token,而竞品方案在第37轮就因token溢出开始胡言乱语。
注意:中期抽屉的key必须是业务唯一标识,绝不能用LLM生成的描述性字符串。我们曾用“用户上次问的快递单号”当key,结果LLM有时写成“快递单号”,有时写成“运单号”,导致状态丢失。后来全部改用API返回的原始字段名,比如"tracking_no",从此再没出过错。
2.4 要素四:规划器——不是写流程图,是给Agent装“交通信号灯”
规划器常被包装成“多步任务分解”,但真实痛点是:如何让Agent在动态环境中遵守硬约束。比如客服Agent接到“帮我取消订单并退款”,标准流程是先查订单状态→取消→触发退款。但如果用户中途插话“等等,先别取消,改成换货”,传统规划器要么崩溃,要么强行执行完取消再换货,造成资损。我们的解法是:把规划器变成状态驱动的有限状态机(FSM),每个状态都有明确的进入/退出条件和阻塞规则。
以换货流程为例,我们定义五个状态:
idle:等待用户指令checking_order:正在查订单(阻塞:不允许新指令)confirming_exchange:已查到订单,等待用户确认换货(允许:接收“确认”“取消”“改地址”)processing_exchange:执行换货(阻塞:不允许任何新指令)done:完成(退出)
关键创新在于“阻塞规则”:当Agent处于checking_order状态时,如果收到新指令,它不解析也不执行,而是返回固定话术:“正在为您查询订单,请稍候”。这个话术由状态机硬编码,不经过LLM生成。只有进入confirming_exchange状态后,才开放对“确认/取消/改地址”的响应。这套机制让Agent在复杂对话中始终保持状态可控。上线后,跨状态指令冲突率从34%降到0.7%,且所有异常都可追溯到具体状态转换日志。
2.5 要素五:执行器——不是调函数,是给Agent装“机械臂关节”
执行器常被当成工具调用的封装,但真实瓶颈在调用链路的韧性与可观测性。比如调用支付接口,网络抖动导致超时,Agent是重试?降级?还是报错?这不能靠LLM临场发挥。我们的执行器分三层:
- 协议层:统一HTTP/gRPC/数据库连接池,配置熔断阈值(如连续3次超时触发熔断)
- 语义层:每个工具调用绑定预设的重试策略、降级逻辑、错误码映射表。例如支付接口返回"INSUFFICIENT_BALANCE",执行器直接映射为{"code": "balance_error", "message": "余额不足,请充值"},不交给LLM解释
- 审计层:记录每次调用的完整输入/输出/耗时/状态码,且输出自动脱敏(银行卡号打码为****)
最值钱的经验是:所有工具调用必须带业务上下文签名。比如查订单接口,除了传order_id,还强制传本次会话的session_id和timestamp。这样当出现“查到订单但状态不对”时,我们能立刻定位是缓存问题、还是并发修改问题、还是时钟漂移问题。某次线上事故,正是靠这个签名发现第三方物流API的时钟比我们慢17秒,导致状态判断延迟。没有这个签名,排查花了6小时;有了它,3分钟定位。
2.6 要素六:反馈闭环——不是加个reward,是给Agent装“痛觉神经”
RLHF(人类反馈强化学习)常被神化,但工程落地中,最有效的反馈不是训练新模型,而是实时修正执行偏差。比如Agent调用邮件API发送通知,但邮件服务器返回“收件人不存在”,这时如果只记录日志,下次还会失败。我们的反馈闭环是:当工具调用返回非预期状态码时,执行器立即触发修正流程——不是让LLM重新规划,而是调用预设的修复工具链。
以邮件发送失败为例:
- 步骤1:执行器捕获550错误码(邮箱不存在)
- 步骤2:自动调用用户信息API,获取最新邮箱
- 步骤3:用新邮箱重发,同时记录原邮箱失效
- 步骤4:向用户发送消息:“检测到您的邮箱已变更,已用新邮箱发送成功”
这个闭环全程不经过LLM,由状态机驱动。它带来的好处是:95%的工具调用错误能在毫秒级自愈,且所有修复动作可审计。我们统计过,带反馈闭环的Agent,单次任务成功率从68%提升到92%,而人工介入率下降到0.3%。更重要的是,这个闭环让Agent具备了“越用越准”的特性——每次修复都沉淀为新的业务规则,比如“当邮件550错误时,优先查CRM最新邮箱”。
2.7 要素七:监控告警——不是看QPS,是给Agent装“心电监护仪”
最后这个要素最常被忽视:监控不是看“请求量多少”,而是看“决策质量是否退化”。我们部署了七类黄金指标:
- 目标达成率:目标字符串匹配成功的比例(不是HTTP 200,是业务目标达成)
- 状态跳转合规率:状态机按预设路径转移的比例(防逻辑错乱)
- 记忆污染指数:中期抽屉中过期key占比(超24小时未更新即告警)
- 工具调用熵值:同一工具在不同会话中参数分布的离散度(突增说明LLM胡乱调用)
- 反馈闭环触发率:每千次调用中触发自修复的次数(持续走低说明系统稳定)
- 规划深度波动:单次任务平均规划步数的标准差(突增说明LLM开始绕弯子)
- 语义漂移度:用户相同query下,Agent返回的关键业务字段(如订单状态)一致性(低于95%告警)
这些指标全部接入Prometheus+Grafana,且每个指标都绑定自动处置预案。比如“目标达成率<85%”自动触发回滚到上一版规划器;“记忆污染指数>5%”自动清理中期抽屉过期key。上线三个月,我们通过这些指标提前发现4次潜在故障,其中两次在用户投诉前2小时就完成自愈。
3. 七个决策点:每个都是上线前必须签字的生死状
3.1 决策点一:目标终止条件——签不签字,决定系统会不会无限循环
这是第一个也是最致命的决策点。很多团队在这里栽跟头,以为“用户满意”就是终止条件。错。终止条件必须是机器可验证的布尔表达式,且必须与业务系统强一致。我们给每个Agent项目立下铁律:目标终止条件必须由后端同事签字确认,且签字内容必须包含三要素:① 唯一业务标识字段名;② 该字段的合法取值范围;③ 验证方式(API返回值/数据库查询/消息队列消费)。
举个血泪教训:某次给政务系统做Agent,目标定为“完成社保资格认证”。后端签字写的是“返回status=‘approved’”,但实际API返回{"result": "success", "code": 200}。Agent永远等不到"approved",一直在重试,最终拖垮整个认证队列。后来我们强制要求:签字必须附带curl测试命令和预期返回体。现在所有目标终止条件都像这样:
# 目标:完成电子凭证签发 # 签字确认(后端张工,2024-03-15): # 字段名:credential_status # 合法值:["issued", "revoked"] # 验证方式:GET /api/v1/credentials/{id} 返回JSON中credential_status字段 # 测试命令:curl -s https://api.example.com/v1/credentials/ABC123 | jq .credential_status # 预期输出:"issued"这个决策点签完字,才算真正启动开发。没签字?所有下游模块暂停。
3.2 决策点二:感知校准粒度——签不签字,决定LLM会不会“睁眼瞎”
感知层校准不是技术选型,是业务责任划分。我们要求:每个API返回的每个字段,必须明确标注“是否需校准”“校准规则”“校准责任人”。表格化管理,不接受模糊描述:
| API端点 | 字段名 | 是否需校准 | 校准规则 | 责任人 | 签字日期 |
|---|---|---|---|---|---|
| /v1/orders | status | 是 | 映射为枚举:{"pending":0,"shipped":1,"delivered":2} | 订单组李工 | 2024-03-10 |
| /v1/orders | created_at | 否 | 原样透传 | — | — |
| /v1/users | nickname | 是 | 去除emoji,截断超长字符 | 用户组王工 | 2024-03-12 |
为什么这么较真?因为LLM对字段语义极其敏感。同一个"status"字段,在订单API里是"shipped",在用户API里是"active",如果不做显式校准,LLM会混淆这两个概念。我们吃过亏:Agent把用户"active"状态当成订单"shipped"状态,导致给休眠用户发发货通知。现在所有校准规则都固化为代码,且每次API变更必须同步更新校准表,否则CI流水线直接失败。
3.3 决策点三:记忆分层策略——签不签字,决定系统会不会“老年痴呆”
记忆分层不是架构设计,是数据治理契约。我们强制要求:每个业务实体必须指定其生命周期和存储位置。比如订单数据,必须明确:
- 短期抽屉:只存当前会话的order_id和status,2小时后自动清除
- 中期抽屉:存order_id + tracking_no + final_status,有效期7天(业务SLA要求)
- 长期抽屉:不存订单数据(用户没显式要求记住)
这个决策点签字后,会生成一份《记忆契约》,明确每个字段的:
- 存储位置(短期/中期/长期)
- 有效期(小时/天/永久)
- 更新触发条件(API返回/用户指令/定时任务)
- 清理策略(TTL/事件驱动/手动触发)
某次审计发现,某Agent把用户身份证号存在短期抽屉,虽然没落盘,但内存里留存了2小时。按《记忆契约》,身份证号属于敏感数据,必须进长期抽屉且加密存储。这个漏洞在签约时就被堵死了。
3.4 决策点四:规划状态机——签不签字,决定系统会不会“精神分裂”
规划器的状态机不是UML图,是运行时契约。我们要求:每个状态必须定义三个硬约束:
- 进入条件(什么情况下进入此状态)
- 退出条件(什么情况下离开此状态)
- 阻塞规则(此状态下禁止哪些操作)
以“用户投诉处理”状态机为例:
| 状态 | 进入条件 | 退出条件 | 阻塞规则 | 签字人 | 日期 |
|---|---|---|---|---|---|
| collecting_info | 收到用户投诉关键词 | 用户提交完整信息 | 禁止发起退款/补偿 | 客服组陈工 | 2024-03-08 |
| verifying_claim | 收到完整信息且调用风控API返回success | 风控返回verified=true | 禁止修改投诉内容 | 风控组赵工 | 2024-03-08 |
| issuing_compensation | 风控verified且用户确认补偿方案 | 补偿API返回200 | 禁止取消补偿 | 财务组孙工 | 2024-03-08 |
这个表格直接生成状态机代码,且每个状态转换都记录审计日志。签字意味着:当Agent处于collecting_info状态时,如果用户说“我要退款”,系统必须返回预设话术,而不是让LLM自由发挥。这个决策点签完,规划器代码才能合并。
3.5 决策点五:执行韧性策略——签不签字,决定系统会不会“一碰就碎”
执行器的韧性不是容错配置,是业务兜底承诺。我们要求:每个工具调用必须明确“失败时的业务替代方案”。表格化呈现:
| 工具名称 | 成功条件 | 失败时降级方案 | 失败时人工介入阈值 | 签字人 | 日期 |
|---|---|---|---|---|---|
| send_email | SMTP 200 | 发送站内信+短信提醒 | 连续3次失败 | 运营组周工 | 2024-03-05 |
| query_inventory | 返回stock > 0 | 返回“暂无库存,已登记补货” | 单日失败超100次 | 供应链组吴工 | 2024-03-05 |
| process_refund | 支付网关返回success | 创建退款工单+通知财务 | 单日失败超10次 | 财务组孙工 | 2024-03-05 |
这个决策点最体现工程深度。比如“process_refund”失败时,如果只写“报错”,那用户就卡在退款流程里。而明确写“创建退款工单”,意味着后端必须提供工单API,且财务组承诺2小时内响应。签字就是业务部门的SLA承诺,不是技术部门的空话。
3.6 决策点六:反馈闭环触发阈值——签不签字,决定系统会不会“越治越病”
反馈闭环不是锦上添花,是系统免疫机制。我们要求:每个工具调用的错误码必须映射到具体的闭环动作,且动作必须可验证。比如:
| 错误码 | 错误含义 | 触发动作 | 动作验证方式 | 签字人 | 日期 |
|---|---|---|---|---|---|
| 404 | 用户不存在 | 调用CRM查最新手机号 | CRM返回mobile字段非空 | 用户组王工 | 2024-03-11 |
| 503 | 支付网关繁忙 | 切换备用支付通道 | 备用通道返回success | 支付组郑工 | 2024-03-11 |
| 429 | 短信发送限频 | 缓存用户请求,5分钟后重试 | Redis key存在且ttl>0 | 运营组周工 | 2024-03-11 |
关键点在于“动作验证方式”:必须是机器可检查的,不能写“通知用户”。比如“缓存用户请求”,验证方式必须是“Redis key存在且ttl>0”,这样监控系统才能自动判断闭环是否生效。这个决策点签完,反馈闭环才算真正可用。
3.7 决策点七:监控黄金指标基线——签不签字,决定系统会不会“带病上岗”
监控指标不是运维KPI,是业务健康证明。我们要求:每个黄金指标必须设定业务可接受的基线值,并由业务方签字确认。比如:
| 指标 | 当前值 | 基线值 | 业务影响 | 签字人 | 日期 |
|---|---|---|---|---|---|
| 目标达成率 | 92.3% | ≥85% | <85%时用户投诉率上升300% | 客服总监 | 2024-03-14 |
| 状态跳转合规率 | 99.8% | ≥98% | <98%时流程错乱导致资损风险 | 风控总监 | 2024-03-14 |
| 反馈闭环触发率 | 4.2次/千次 | ≤5次/千次 | >5次说明底层服务不稳定 | 运维总监 | 2024-03-14 |
注意基线值不是技术指标,而是业务影响描述。比如“目标达成率<85%时用户投诉率上升300%”,这个数据来自历史客诉分析。签字意味着:当监控显示目标达成率跌破85%,业务方必须立即启动应急预案,而不是等技术团队报告。这个决策点把技术指标和业务结果牢牢绑在一起。
4. 实操复盘:从零搭建一个电商售后Agent的七步踩坑实录
4.1 第一步:目标定义——用业务单号当唯一锚点
我们接的第一个电商售后Agent需求是“处理退货申请”。初始PRD写的是“用户提交退货申请,Agent完成审核、生成退货单、通知物流”。这太宽泛。我们拉着业务方坐下来,逐字抠:
- 业务方说:“审核通过后,系统会生成退货单号,格式是RD+8位数字。”
- 我们问:“这个单号出现在哪里?”
- 业务方:“在ERP系统返回的JSON里,字段叫return_order_id。”
- 我们确认:“只要返回return_order_id字段,且值匹配RD\d{8}正则,就算目标达成?”
业务方签字确认。于是目标终止条件锁定为:
def is_target_achieved(response): return "return_order_id" in response and re.match(r"RD\d{8}", response["return_order_id"])这个决策让后续所有模块有了明确靶心。没有这个,规划器可能永远在“要不要再查一遍库存”上纠结。
4.2 第二步:感知校准——把“已发货”翻译成机器语言
物流API返回的status字段有十几种值:{"status": "shipped", "status": "out_for_delivery", "status": "delivered"}。LLM可能把"out_for_delivery"当成"delivered",导致告诉用户“已签收”。我们的校准器强制映射:
STATUS_MAP = { "shipped": "in_transit", "out_for_delivery": "in_transit", # 统一为运输中 "delivered": "delivered", "returned": "returned" }校准后,LLM只看到"in_transit"或"delivered",决策逻辑瞬间清晰。这个校准表由物流组签字确认,确保语义不被LLM曲解。
4.3 第三步:记忆分层——订单ID进中期抽屉,用户抱怨进短期抽屉
用户说:“这个订单我上周就申请退货了,怎么还没处理?”这里有两个信息:
- 订单ID(ORD2024XXXX)——进中期抽屉,有效期7天
- “上周就申请”——进短期抽屉,只用于当前会话推理
我们用正则从用户话术中提取订单ID,自动存入中期抽屉;其余描述性文字只留在短期抽屉。这样既保证了跨会话状态可追溯,又避免了LLM被无关描述干扰。实测中,带分层记忆的Agent,跨会话问题解决率从41%提升到89%。
4.4 第四步:规划状态机——把“退货流程”切成五个可控状态
我们定义退货状态机:
idle→checking_order(收到订单ID)checking_order→verifying_return_eligibility(查到订单且满足退货条件)verifying_return_eligibility→confirming_return_reason(用户选择退货原因)confirming_return_reason→issuing_return_label(生成退货面单)issuing_return_label→done(返回return_order_id)
每个状态都有硬编码话术。比如在checking_order状态,用户说“我要换货”,Agent不解析,只回:“正在为您查询订单,请稍候”。这个状态机代码由客服组签字确认,确保符合SOP。
4.5 第五步:执行韧性——为物流API配三重保险
物流API调用失败时:
- 第一次失败:重试2次,间隔1秒
- 第二次失败:降级到备用物流商API
- 第三次失败:创建工单,通知物流组人工处理
这个策略由物流组签字确认,且备用API的密钥和endpoint都预置在配置中心。上线后,物流API整体可用率从92%提升到99.97%,且人工介入率从15%降到0.2%。
4.6 第六步:反馈闭环——当面单生成失败时自动切渠道
物流API返回“面单模板不匹配”错误时,执行器不报错,而是:
- 步骤1:调用模板管理API,获取最新面单模板
- 步骤2:用新模板重试生成
- 步骤3:若仍失败,切换到PDF面单生成服务
这个闭环由物流组和设计组联合签字,确保模板更新机制可靠。上线三个月,面单生成失败率从12%降到0.3%,且所有失败都自动修复。
4.7 第七步:监控基线——用投诉率倒推目标达成率阈值
我们分析历史数据:当目标达成率<85%时,用户投诉率上升300%。于是把85%设为基线,监控系统一旦跌破,自动触发:
- 短信通知技术负责人
- 在客服后台弹窗提示“退货流程异常”
- 暂停新退货请求接入,只处理存量
这个基线由客服总监签字确认,把技术指标和业务结果直接挂钩。上线后,首次跌破基线时,我们在用户投诉前17分钟就完成了修复。
5. 常见问题与排障速查表:那些凌晨三点的救命经验
5.1 问题:Agent在第N轮对话后突然胡言乱语,返回无关内容
现象:前10轮正常,第11轮开始,Agent把“查订单”理解成“查天气”,甚至生成虚构的订单号。
根因:短期抽屉token溢出,LLM被迫压缩上下文,丢失关键约束。
排查步骤:
- 查看短期抽屉当前token用量(日志中有
short_term_memory_tokens: 1482) - 检查是否超过1500阈值(是→溢出)
- 查看溢出时被裁剪的上下文(日志中
truncated_context: ["user: 上次的订单..."])
解决方案:
- 立即:重启Agent实例(临时缓解)
- 永久:调整滑动窗口算法,优先裁剪用户闲聊(如“今天天气不错”),保留业务指令(如“订单ORD2024XXXX”)。我们用正则识别业务关键词,赋予更高保留权重。
实操心得:不要依赖LLM自己总结上下文。我们试过让LLM生成摘要,结果它把“用户要退货”摘要成“用户心情不好”,彻底丢失业务意图。现在所有裁剪都由规则引擎完成,LLM只消费裁剪后的确定性文本。
5.2 问题:Agent反复调用同一个工具,形成死循环
现象:用户说“查下订单ORD123”,Agent连续5次调用订单查询API,每次返回相同结果,却不推进流程。
根因:规划器状态机缺失退出条件,或LLM对返回结果的语义理解偏差。
排查步骤:
- 查看规划器状态日志(
state: checking_order, exit_condition: None) - 检查API返回是否匹配校准规则(日志中
calibrated_response: {"status": "shipped"}) - 查看LLM输入prompt中,是否明确定义了“shipped”状态对应的下一步动作
解决方案:
- 立即:在状态机中为
checking_order状态添加硬退出条件:“当response.status存在且不为空时,自动进入verifying_return_eligibility” - 永久:所有状态退出条件必须由业务方签字,且在代码中强制校验
实操心得:我们曾以为LLM能“读懂”API返回,结果它把{"status": "shipped"}理解为“可以退货”,而业务规则是“shipped状态需额外验证物流签收”。后来所有状态转换都基于校准后的枚举值,彻底杜绝语义歧义。
5.3 问题:记忆中的订单状态与实际不符,Agent给出错误结论
现象:用户问“我的订单发货了吗?”,Agent回答“已发货”,但实际物流显示“待揽收”。
根因:中期抽屉数据未及时更新,或校准器未正确映射状态。
排查步骤:
- 查看中期抽屉中该订单的缓存值(
redis-cli GET "order:ORD123") - 对比API实时返回(
curl https://api.example.com/orders/ORD123) - 检查校准器代码,确认status字段映射逻辑
解决方案:
- 立即:手动刷新中期抽屉(
redis-cli DEL "order:ORD123") - 永久:为所有中期抽屉key设置TTL,并在工具调用成功后主动刷新。我们用Redis的EXPIRE命令,且TTL值=业务SLA要求(如物流状态TTL=30分钟)
实操心得:不要相信“缓存永远最新”。我们给每个中期抽屉key加了版本号,每次更新都递增,且LLM输入中强制带上版本号。这样当Agent看到version=1但API返回version=2时,会主动触发刷新,而不是用旧数据决策。
5.4 问题:反馈闭环触发后,修复动作未生效,错误持续发生
现象:邮件发送失败,反馈闭环触发,但新邮箱仍未收到邮件。
根因:闭环动作的验证方式不可靠,或下游服务未就绪。
排查步骤:
- 查看闭环日志(`feedback_action: update