【导航台账】制造业数据与AI践行者老蒋的技术博客全系列文章汇总(持续更新)
📌 文章摘要
LangChain ReAct Agent 调用多参数工具时,反复报 Field required 错误,排查发现完整 JSON 被嵌套塞进第一个参数字段。本文深入剖析 ReAct Agent 参数打包机制,提供 args_schema=None 绕过 Pydantic 自动校验、手动解析参数的完整落地方案,彻底终结嵌套 JSON 问题。
问题现象
兄弟们,我在Case03多工具协同Agent的开发中,被同一个问题折磨了好几天。
明明代码逻辑没问题,工具定义也写清楚了,但Agent一调用 generate_work_order 就报错:
bash
❌ 错误: 3 validation errors for WorkOrderInput
fault_code
Field required [type=missing, input_value={'line_name': '{"line_nam...gned_shift": "白班"}'}, input_type=dict]
solution
Field required [type=missing, input_value={'line_name': '{"line_nam...gned_shift": "白班"}'}, input_type=dict]
spare_parts_status
Field required [type=missing, input_value={'line_name': '{"line_nam...gned_shift": "白班"}'}, input_type=dict]
我当时的第一反应是:这不科学啊......
Agent生成的 Action Input 明明包含了所有参数:
bash
{
"line_name": "交互屏组装A线",
"fault_code": "E401",
"solution": "重启工控机并检查USB连接线",
"spare_parts_status": "充足",
"assigned_shift": "白班"
}
但Pydantic告诉我 fault_code、solution、spare_parts_status 这三个字段缺失。
仔细一看报错信息里的 input_value ------ 整个JSON被嵌套( ReAct Agent 嵌套 JSON**)塞进了 line_name 字段**:
bash
input_value={'line_name': '{"line_name": "交互屏组装A线", "fault_code": "E401", ...}'}
根因分析
说实话,Field required 报错原因让我翻来覆去查了好几天。不是代码写错了,而是 LangChain ReAct Agent 的"出厂设置"就是这样的。
第一层:ReAct Agent 不支持多参数工具
LangChain 官方文档里其实藏着一句话:create_react_agent 创建的工具不支持多参数-。
ReAct Agent 在处理工具调用时,会把所有参数打包成一个JSON字符串 ,然后整个塞进第一个字段里-。这就是为什么 line_name 收到的不是字符串,而是一个完整的JSON对象。
第二层:Pydantic在校验之前就已经"阵亡"了
BaseTool 的 args_schema 在 _run 方法执行之前就会对输入参数进行校验-。
当Agent把嵌套JSON传给工具时,Pydantic看到的是:
python
{"line_name": '{"line_name": "交互屏组装A线", "fault_code": "E401", ...}'}
它只认识 line_name 这个字段,其他字段全被埋在了字符串内部,根本解析不到。于是报错 Field required。
你在 _run 里面加再多的解析逻辑,都没用。因为Pydantic在校验阶段就把路堵死了。
第三层:这是一个社区公认的"老大难"问题
这个问题在LangChain社区里被反复讨论-。
有开发者尝试过把所有字段都设为 Optional,然后在 _run 里手动处理-。也有人尝试用正则表达式自己解析。但这些方案要么不彻底,要么治标不治本。
解决方案
别慌,一招搞定它。
核心思路:绕过Pydantic自动校验
把 args_schema 设为 None,让 _run 方法自己说了算。
python
class GenerateWorkOrderTool(BaseTool):
name: str = "generate_work_order"
description: str = "生成智联工坊标准维修工单..."
args_schema: Optional[Type[BaseModel]] = None # 👈 关键:关闭自动校验
然后修改 _run 方法,手动解析Agent传入的所有参数:
python
def _run(self, *args, **kwargs) -> str:
# 收集所有可能的输入
raw_input = None
if args and len(args) > 0:
raw_input = args[0]
if not raw_input:
raw_input = kwargs.get("line_name") or kwargs.get("input")
# 解析嵌套JSON
if isinstance(raw_input, str) and raw_input.strip().startswith('{'):
try:
import json, re
cleaned = re.sub(r'^```json\s*', '', raw_input.strip())
cleaned = re.sub(r'\s*```$', '', cleaned)
data = json.loads(cleaned)
# 从解析结果中提取所有字段
line_name = data.get("line_name")
fault_code = data.get("fault_code")
solution = data.get("solution")
spare_parts_status = data.get("spare_parts_status")
assigned_shift = data.get("assigned_shift", "待分配")
except json.JSONDecodeError:
pass
# 兜底默认值
fault_code = fault_code or "未知"
solution = solution or "请参考维修手册"
# ... 生成工单逻辑
为什么这样做有效?
| 对比项 | Pydantic校验(args_schema定义) |
手动解析(args_schema=None) |
|---|---|---|
| 校验时机 | _run执行之前 |
_run执行之中 |
| 嵌套JSON处理 | ❌ 直接报错 | ✅ 可以解析后再提取 |
| 容错能力 | 低(严格匹配字段) | 高(可以处理各种格式) |
| 灵活性 | 低(字段必须一一对应) | 高(可以从各种来源提取参数) |
验证结果
修改之后,Agent的调用不再报错:
python
Action: generate_work_order
Action Input: {"line_name": "交互屏组装A线", "fault_code": "E401", ...}
Observation: {
"order_id": "WO-20260804-4164",
"status": "待执行",
"line": "交互屏组装A线",
"fault_code": "E401",
...
}
工单成功生成,嵌套JSON噩梦终于终结了。
经验总结
怕你忘了,我再啰嗦一遍😀😀😀create_react_agent 不支持多参数工具,它会把所有参数打包成嵌套JSON塞进第一个字段。与其跟Pydantic死磕,不如直接绕过它。
落到具体操作上就是三条:
-
args_schema=None是解药,不是毒药 。官方文档推荐用Pydantic做参数校验,但在ReAct Agent的多参数场景下,这套机制反而成了阻碍。关闭自动校验,在_run里手动解析,是更健壮的做法。 -
手动解析要足够"皮实"。Agent可能传入纯净JSON、带Markdown代码块的JSON、甚至夹杂多余文字的JSON。你的解析逻辑要能覆盖这些情况,而不是只处理理想格式。
-
兜底默认值很重要 。即使解析失败,也要让工具有合理的默认值,而不是直接崩溃。工具应该"尽量工作",而不是"完美地失败"。
说白了就是一句话:工具是给Agent用的,不是给Pydantic看的。让工具适配Agent的行为,比让Agent适配工具的校验规则更靠谱。
bash
【注意】本方案针对 ReAct Agent 多参数工具嵌套 JSON 场景,并非所有场景都要关闭 Pydantic 校验。
单参数工具:仍推荐使用 args_schema 做类型校验,类型安全更有保障;
支持结构化输出的 Agent(如 OpenAI Functions Agent):原生支持多参数调用,无需此处理;
手动解析时必须增加异常捕获与兜底逻辑,避免非法输入导致工具崩溃。
系列导航
- 本文属于《数据与AI工程排坑笔记》系列
-
下一篇:《不要让你的Agent"吊死"在一棵树上:工具返回"未找到"时的容错设计》(即将发布)
本文问题源自 :《智联工坊实战:多工具协同Agent》实战过程,完整源码及深度教程见该文:链接
💡 建议收藏 :下次遇到 Field required 报错时,可以先检查是否是嵌套JSON导致的问题。
互动与交流
你在使用LangChain ReAct Agent时,有没有遇到过类似的"嵌套JSON"问题?你是怎么解决的?欢迎评论区吐槽,咱们互相交流一下------说实话,这个问题我前前后后折腾了好几天才搞明白。
关于作者
制造业数据与AI践行者老蒋,23年IT老兵。聚焦制造业数据架构与AI融合落地。全流程实战,全源码开源。
