错误分类:根据原因选择下一步
正在读取学习记录…
1. 把“出错了”拆成具体原因
一次Agent任务会经过输入、模型、工具、网络和业务服务。出错的位置不同,下一步也不同:参数少了字段,先补参数;读取请求超时,可以有限重试;权限不足,需要核对访问范围;写入结果未知,先查询回执。
错误分类就是给错误一个稳定的类别,让程序按类别处理。像医院分诊,先知道是哪个环节需要处理,才容易找到正确入口。错误消息供人理解,类别供程序分流;两者可以同时返回。
常见的四个位置可以这样区分:模型输出缺少字段属于输出格式问题;工具参数不合法属于输入问题;网络超时属于环境问题;计划依赖的资料从未取得属于规划问题。一个位置也可能有多种原因,例如工具返回失败,既可能是权限不足,也可能是后端暂时不可用。
2. 运行一个错误到动作的映射
先在 PowerShell 创建并进入学习目录:
mkdir "F:\学习\l3-errors" -Force
cd "F:\学习\l3-errors"保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。
在新目录创建 errors.py:
先在 PowerShell 创建并进入学习目录:
mkdir "F:\学习\l3-errors" -Force
cd "F:\学习\l3-errors"保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。
"""根据错误类型选择下一步处理方式。"""
import json
POLICY = {
"timeout": ("network", "retry_read"),
"bad_argument": ("input", "fix_argument"),
"denied": ("permission", "request_access"),
"write_unknown": ("uncertain_result", "query_receipt"),
"missing_evidence": ("data", "try_other_source"),
}
def classify(error):
# 返回结构化的类别和动作,调用方可据此分流。
category, action = POLICY.get(error, ("unknown", "human"))
return {"category": category, "action": action}
if __name__ == "__main__":
for error in ("timeout", "bad_argument", "denied", "write_unknown"):
print(json.dumps({"error": error, **classify(error)}))ls
python errors.py输出:
{"error": "timeout", "category": "network", "action": "retry_read"}
{"error": "bad_argument", "category": "input", "action": "fix_argument"}
{"error": "denied", "category": "permission", "action": "request_access"}
{"error": "write_unknown", "category": "uncertain_result", "action": "query_receipt"}POLICY 是分类表,每个错误码对应类别和处理动作。classify 查表,将二元组拆成两个字段。调用方可以根据 action 进入后续分支。
这些英文值对应:network 网络,input 输入,permission 权限,uncertain_result 结果待确认;retry_read 重试读取,fix_argument 修正参数,request_access 核对权限,query_receipt 查询操作回执。
3. 加一个新错误,观察默认处理
把主程序最后一个错误换成 "new_error",会得到 category: unknown 和 action: human。这给未识别错误保留了人工入口。再在表中增加:
"model_format": ("output", "regenerate_with_schema"),把主程序相应项改为 "model_format",保存后运行 python errors.py,得到output类别与regenerate_with_schema动作。模型输出格式错误可以反馈具体缺失字段,再生成一次,同时限制尝试次数。观察结束后恢复原四项错误输入并删去新增表项,再运行核对原结果。
4. 用测试保存判断规则
在同目录创建 test_errors.py:
下面的测试检查不同错误类别是否选择相应的下一步处理方式。
测试代码:test_errors.py
"""检查errors示例的正常路径和边界结果。"""
import unittest
from errors import classify
class Tests(unittest.TestCase):
def test_types(self):
self.assertEqual(classify("timeout"),{"category":"network","action":"retry_read"})
self.assertEqual(classify("denied")["action"],"request_access")
self.assertEqual(classify("write_unknown")["action"],"query_receipt")
def test_unknown(self): self.assertEqual(classify("new_error")["action"],"human")
if __name__ == "__main__":
unittest.main()python -m unittest test_errors -v正常路径与改动后的边界都在测试中检查。若结果不同,先定位失败的断言,再回到对应的字段与分支。
5. 让分类真正影响执行
分类后的下一步还需要参数:重试几次、等多久、使用同一请求编号还是创建新操作。读请求的有限重试与写请求的结果确认要分别设计。
| 问题 | 优先查看 | 处理方向 |
|---|---|---|
| 模型返回字段缺失 | 原输出与Schema检查结果 | 反馈缺失字段,有限重生成 |
| 工具参数错误 | 字段名、类型和值 | 修正具体参数 |
| 网络暂时失败 | 超时与HTTP状态 | 有限重试读取 |
| 资源权限不足 | 可信身份和目标资源 | 核对权限或换允许资源 |
| 写入后没收到响应 | 请求编号与回执 | 先查结果 |
| 计划依赖未完成 | 计划与完成记录 | 补前置资料或修订计划 |
工具返回的错误文本可以作为观察传给模型,但对用户和模型只提供必要字段。凭据、完整堆栈和敏感正文放在受控日志中。Python 的 异常教程介绍捕获特定异常的方法;先按具体类型处理,比一个大范围捕获更容易保留原因。
偶发网络失败、参数缺失和权限拒绝,也有不同的重试效果。等待并重试可能改善暂时网络问题;同一份错误参数重发通常仍然失败。排查时优先查看首次失败的类别,后面的连锁错误常是它造成的。
从症状走到原因,再决定下一动作
假设Agent查询订单失败。日志显示参数中order_id为空,属于输入错误。它需要补订单编号。若参数正确、服务5秒未响应,属于等待超时,可以有限重试读取。若服务返回权限拒绝,下一步核对身份和订单归属。
| 用户看到的症状 | 程序已知的信息 | 下一轮提供什么 |
|---|---|---|
| 没有查到订单 | 查询成功但列表为空 | 当前来源和条件,可尝试其他条件 |
| 查询失败 | 连接超时 | 错误类别和已用次数 |
| 无法访问 | 身份或资源范围不足 | 目标资源与需要核对的权限 |
| 提交结果待确认 | 已发送写请求但无响应 | 原操作编号与回执查询方式 |
分类表应由可信的服务结果生成。模型可以建议原因,应用仍需对照实际HTTP状态、异常类型或业务错误码。保存错误码和适当的用户提示,方便界面展示与程序分支各取所需。
重试之前先判断操作性质。读取资料可有限重试,写入结果未知则先查询前次操作。两者都可能表现为超时,但后续风险不同。将动作类型纳入策略,比只看一个timeout字符串更接近实际工作。
回顾与下一步
保留类别、原始操作编号和下一步动作。接下来 上下文构建决定下一轮该给模型哪些信息。
课后练习展开习题收起习题
正在读取本地记录…
不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。
选择题 · 先判断边界
关于“模型、工具、环境与规划错误分类”,哪种做法更稳妥?
对应知识点:L3-errors
简答题 · 解释失败
写出一个失败输入并说明记录字段。
对应知识点:L3-errors
代码题 · 边界测试
补充正常、边界、失败三组输入和预期结果。
对应知识点:L3-errors
场景题 · 结果未知
证据不足时如何设计状态和人工接管?
对应知识点:L3-errors
描述会发送给本站维护者,用于修订文章,保存90天。请只填写文章问题,省略个人信息、密钥和内部资料。