问题现象

在 Hermes Agent 中把模型切换到 claude-opus-4-7 后,请求直接失败:

HTTP 400: custom.input_schema: JSON schema is invalid.
It must match JSON Schema draft 2020-12

同一套工具 schema 在 gpt-5.5 等模型上正常,但在 Claude/Anthropic 兼容接口上报错。

初步判断

报错信息指向:

custom.input_schema

也就是 tool/function 的 input schema 不被 Claude 的工具调用校验器接受。

这类问题通常不是模型本身不可用,而是某个 tool 的 JSON Schema 写法在某些后端比较宽松,在 Anthropic/Claude 兼容后端比较严格。

排查方法

1. 导出当前 Hermes 工具列表

Hermes 的工具定义会经过:

tools/registry.py
model_tools.py
schema_sanitizer.py

最终生成 OpenAI 格式的 tools:

{
  "type": "function",
  "function": {
    "name": "xxx",
    "description": "...",
    "parameters": {
      "type": "object",
      "properties": {}
    }
  }
}

2. 单独测试每一个 tool

把当前工具逐个提交给 claude-opus-4-7,定位到底哪些 schema 会触发 400。

最终发现报错工具包括:

browser_back
browser_console
browser_get_images
browser_snapshot
delegate_task
send_message
session_search
skills_list
todo

这些工具的共同点是:parameters 或嵌套对象里存在 object schema,但没有显式声明 required

例如:

{
  "type": "object",
  "properties": {}
}

或者:

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string"
    }
  }
}

根因

JSON Schema Draft 2020-12 中,required 字段是可以省略的。

也就是说:

{
  "type": "object",
  "properties": {}
}

从标准 JSON Schema 角度看是合法的。

但 Anthropic/Claude 的 tool input schema 校验器更严格,实际要求 object schema 必须显式带上 required 数组。

如果没有必填字段,也要写成:

{
  "type": "object",
  "properties": {},
  "required": []
}

所以问题不是 schema 完全非法,而是 Claude 工具调用接口对 schema 有额外兼容要求。

解决方法

在 Hermes 的 schema sanitizer 里,对所有 object schema 自动补上:

"required": []

前提是该 object schema 有 properties,但没有合法的 required 数组。

修改文件:

tools/schema_sanitizer.py

核心逻辑:

def ensure_object_required_arrays(schema: Any) -> Any:
    """Add required: [] to every object schema missing it."""
    if isinstance(schema, list):
        return [ensure_object_required_arrays(item) for item in schema]
    if not isinstance(schema, dict):
        return schema

    out = dict(schema)
    if out.get("type") == "object" and isinstance(out.get("properties"), dict):
        required = out.get("required")
        if not isinstance(required, list) or not all(isinstance(item, str) for item in required):
            out["required"] = []

    for key, value in list(out.items()):
        if key in {"properties", "$defs", "definitions"} and isinstance(value, dict):
            out[key] = {
                sub_key: ensure_object_required_arrays(sub_value)
                for sub_key, sub_value in value.items()
            }
        elif key in {"items", "additionalProperties"}:
            if not isinstance(value, bool):
                out[key] = ensure_object_required_arrays(value)
        elif key in {"anyOf", "oneOf", "allOf"} and isinstance(value, list):
            out[key] = [ensure_object_required_arrays(item) for item in value]

    return out

然后在 sanitizer 流程中调用:

fn["parameters"] = ensure_object_required_arrays(fn["parameters"])

验证结果

修复前,多个工具单独发送给 claude-opus-4-7 会返回 400。

修复后:

TOOL_COUNT 30
MISSING_REQUIRED_OBJECTS 0
CLAUDE_OPUS_4_7_ALL_TOOLS 200 OK

也就是说,当前 30 个工具一起提交给 claude-opus-4-7 已经可以正常通过。

经验总结

  1. OpenAI/GPT 兼容接口能接受的 schema,不代表 Claude/Anthropic 兼容接口一定接受。
  2. Claude tool schema 对 object 的 required 更敏感。
  3. 即使没有必填字段,也建议显式写:
"required": []
  1. 最稳妥的处理方式是在统一的 schema sanitizer 层修复,而不是逐个 tool 手动改。
  2. 遇到 tool schema 400,优先用“逐个 tool 单独请求”的方式二分/枚举定位。

最终结论

这次 claude-opus-4-7 报错的根因是:Hermes 部分工具 schema 的 object 节点缺少显式 required 数组。

通过在 schema_sanitizer.py 中自动补齐 required: [],即可兼容 Claude/Anthropic 工具调用校验器。

最后修改:2026 年 05 月 17 日
如果觉得我的文章对你有用,请随意赞赏