🛡️ ARK 智能体诊断报告

langchain-ai/langchain#39099 · args_schema 不完整时工具静默以「零参数」暴露给模型 · 2026-07-28 · W32 诊断 2/5

📋

问题摘要

🔴

当工具参数类型图里存在不可解析的前向引用(如嵌套 Pydantic 模型引用了装饰时尚未定义的类), langchain-core 不报错、不告警,而是把工具 以「零参数」schema 静默递交给模型{"properties": {}, "type": "object"}。 模型据此发起空参数调用,随后在校验层爆出 ValidationError —— 对外宣称的 schema 与实际校验的 schema 互相矛盾。 issue 报告者披露:一个模块 13 个工具中 12 个受影响,数月无人察觉

契约不一致 · advertised ≠ enforced 静默降级 · 零日志零异常 ARK 实机完全复现 ✅

影响范围

langchain-core 0.3.29 → 1.5.1 · Python 3.10-3.13 · LangGraph InjectedState 高发

框架现状

⚠️ open · bug/core 标签 · 已有贡献者认领

ARK 方案

✅ InputGuard schema 完整性门禁

🔍

根因定位(P2 Probe)

失效链共四级,每一级单独看都"合理",串起来就是静默灾难:

  1. 嵌套模型含未解析前向引用 → Pydantic 标记 __pydantic_complete__ = False(不抛错,合法中间态)
  2. 不完整模型使 inspect.signature() 退化为 (**data: Any)
  3. get_all_basemodel_annotations() 因此返回空字典 {}
  4. tool_call_schema 把「schema 无法解析」误读为「该工具没有参数」→ 空 schema 递交模型

不一致性是核心:同样的错误若直接出现在工具签名一级, create_schema_from_function 会立刻抛 NameError(硬错误);嵌套一层后,同一错误变成零参数静默降级。 开发者被上层的硬错误训练出「写错会立刻炸」的预期,恰恰因此更难怀疑到这里。

🧪

ARK 实机验证(2026-07-28 · langchain-core 1.5.1 / pydantic 2.13 / Python 3.11)

issue 提供的最小复现在 ARK 验证环境逐项完全复现(5/5)

pydantic_complete: False ← schema 明知不完整 args: [] ← 工具对外宣称零参数 openai_tool params: {"properties": {}, "type": "object"} ← 空 schema 递交模型 invoke({}) → ValidationError: real_arg / container Field required ← 校验层却要求全部参数 对照组(签名一级同错误)→ NameError: name 'RowX' is not defined ← 上一层是硬错误

与 #39087(部分复现、诚实披露)不同,本例为确定性缺陷:任何版本、任何平台、100% 触发。危险性不在概率,而在零信号——没有任何日志、警告或异常提示 schema 已降级。

🛡️

ARK Trust Layer 如何拦截(P3 Prescribe)

① InputGuard · schema 完整性门禁(注册时)
工具注册进 ARK 时强制断言:__pydantic_complete__ == True 且 「函数签名参数数 == 对外 schema 参数数」。任何一条不满足即拒绝注册并报错——把静默降级变回硬错误,恢复框架在上一层本就有的行为。

② OutputValidator · 契约一致性不变式(运行时)
不变式:advertised schema ⊇ enforced schema。模型按对外 schema 生成的合法调用,必须能通过实际校验。 校验失败但调用符合对外 schema 时,判定为「工具契约自相矛盾」而非「模型幻觉」——错误归因直接改变排障方向。

③ OTel 留痕
每个工具注册时记录 schema 指纹(参数名/类型哈希)。12/13 个工具空参数这类批量异常,在可观测面板上一眼可见,而非数月潜伏。

📚

缺陷模式索引归档(P4 Publish)

归入 F3 · 静默失败 / 失败伪装成功(第 4 例)。 本例把该族从「运行时失败被吞」扩展到「构建时降级被吞」:schema 构建失败不是运行时异常, 而是被静默折叠成一个语义完全不同的合法值(空 schema)。同族前例:#39039(失败流事件被丢)、#38892(空流误判失败)、#38893(不可重试异常被吞成 AIMessage)。

ARK — Agent Reliability Kit · github.com/wzg0911/ark

诊断方法论:4P Framework(Pinpoint → Probe → Prescribe → Publish)· 所有结论基于实机验证,复现与未复现均如实披露

生成时间:2026-07-28 09:35 CST · W32 诊断报告 2/5