langchain-ai/langchain#39100 · ChatAnthropic system 块 id 原样透传导致 400 · 2026-07-28 · W32 诊断 5/5
LangChain v1 标准内容块 API create_text_block()
会给每个块铸造一个 id(形如 lc_<uuid4>)。
langchain_anthropic._format_messages()
对 human/assistant 文本块做了字段收窄(只保留 Anthropic 接受的键),
但 system 分支把块原样透传——lc_ id 直达 Anthropic API,
换回 400 "system.0.id: Extra inputs are not permitted"。
同一路径也被 get_num_tokens_from_messages() 复用,token 计数同样失败。
影响范围
langchain-anthropic 1.5.2 · 所有用 v1 content_blocks 构造 SystemMessage 的用户
框架现状
⚠️ open · 2 位贡献者认领 · 修复方向共识(system 块套用同一收窄逻辑)
ARK 方案
✅ OutputValidator 出站 payload 契约 + OTel 字段级留痕
缺陷是「同一函数内的不对称清洗」——出站边界只对一半的消息角色执行契约:
create_text_block()(langchain-core v1 标准内容块)默认给块铸造 id="lc_<uuid4>"——这是 LangChain 内部的溯源元数据,不属于任何 provider 的 wire 协议_format_messages()(langchain_anthropic/chat_models.py)对 human/assistant 的 dict 文本块收窄到 Anthropic 接受的字段(type/text/cache_control/citations)system 字段get_num_tokens_from_messages() 复用同一 formatted payload → token 计数同样 400结构性观察: 这是「框架自铸元数据 → 泄漏到出站协议」的典型样本。v1 内容块把 id 设计为一等公民(用于溯源/去重), 意味着每个 provider 适配器的每个消息角色分支都必须显式过滤,漏掉任何一个分支就是 400 或静默行为差异。 越是「推荐的新 API」(v1 content_blocks + create_text_block 正是官方迁移方向),越先踩中——与 #39047 的「官方指引即陷阱」同构。
ARK 采用离线确定性验证:不打真实 API,直接检视 _format_messages() 产出的出站 payload,同批消息同时覆盖 system / human / assistant 三个角色,证明不对称清洗:
验证强度说明:离线检视出站 payload 比打真实 API 更强——它把根因钉死在 langchain-anthropic 的格式化层(而非网络/账号/模型版本),且完全确定性、可在 CI 中回归。复现脚本:scripts/repros/repro_39100_system_block_id_leak.py。
① OutputValidator · 出站 payload 契约(发送前)
对每个 provider 声明 wire schema 白名单(Anthropic system 块只接受 type/text/cache_control/citations)。
ARK 在 HTTP 请求发出前对最终 payload 做 schema 对账,lc_ id 在出站边界被拦截并指明来源块,
而非让用户面对一个看似「Anthropic 侧」的 400。
② InputGuard · 内部元数据标记
框架自铸字段(lc_ 前缀 id、内部溯源键)在进入适配层前统一打上 internal 标记;
任何 internal 字段出现在出站 payload 即为契约违规——把「每个适配器每个分支都要记得过滤」的 N×M 人工纪律,
收敛为单点自动强制。
③ OTel 留痕
请求 span 记录 block_source(create_text_block) → formatter(system 分支) → rejected_field(id) 链路。
「为什么 SystemMessage 会 400 而 HumanMessage 不会」从翻源码对比分支,变成 trace 上一眼可见的字段级差异。
新设 F9 · 出站契约不对称 / 内部元数据泄漏到 wire 协议(首例)。 与 F2(内部状态泄漏到后续请求)互为镜像:F2 泄漏的是时间维度(本次参数污染下次调用), F9 泄漏的是层级维度(框架内部元数据穿透到 provider 协议层)。 共性根因都是「边界上缺一道强制清洗」,且都随分支/适配器数量线性放大遗漏概率。 与 #39047 共享「官方推荐路径先崩」的传播叙事:v1 content_blocks 正是 LangChain 力推的标准化方向。
ARK — Agent Reliability Kit · github.com/wzg0911/ark
诊断方法论:4P Framework(Pinpoint → Probe → Prescribe → Publish)· 所有结论基于实机验证,复现与未复现均如实披露
生成时间:2026-07-28 15:38 CST · W32 诊断报告 5/5(本周诊断目标达成)