01.02概念更新于 2026年9月17日

JSON 与 JSON Schema

Tool Calling 的通用语言,以及如何用 Schema 约束数据结构。

01.02 · 课时讲解

JSON 与 JSON Schema

JSON 是交换数据的通用格式,Schema 描述这份 JSON 应该长什么样。

1 / 11

一句话理解:JSON 是系统之间交换数据的通用格式,JSON Schema 是描述“这份 JSON 应该长什么样”的规则;模型通过 Schema 理解工具需要什么参数,程序通过 Schema 检查模型填得对不对。

在 Agent 系统里,JSON 无处不在:API 返回的是 JSON,模型调用工具时输出的是 JSON,工具定义本身也是 JSON,结构化输出要求的还是 JSON。而 JSON Schema 是让这一切“可靠”的关键——它把“请填一个日期”这种模糊的要求,变成程序可以检查的精确规则。

产品经理不需要手写复杂的 Schema,但需要能读懂它,因为 工具定义里的 Schema 就是模型理解工具的唯一说明书,写得好不好直接决定 Agent 会不会用错工具。

JSON:六种值就够了

JSON(JavaScript Object Notation)是一种纯文本数据格式,只有六种值类型:

类型 写法 例子
字符串 string 双引号包裹 "SF1234"
数字 number 直接写 18.5、42
布尔 boolean true / false true
空值 null null null
对象 object 花括号,键值对 {"city": "杭州"}
数组 array 方括号,有序列表 ["饮料", "零食"]

对象和数组可以任意嵌套。一个销售分析工具返回的结果可能是这样:

{
  "region": "华东",
  "period": { "start": "2026-09-07", "end": "2026-09-13" },
  "total_sales": 1284500.0,
  "change_rate": -0.18,
  "is_anomaly": true,
  "top_declines": [
    { "category": "饮料", "change_rate": -0.62 },
    { "category": "日化", "change_rate": -0.05 }
  ],
  "note": null
}

把这份 JSON 展开成一棵树,层级就一目了然:

销售分析结果 JSON 的层级结构:最外层是对象,包含字符串、数字、布尔、空值字段,以及一个嵌套对象和一个对象数组 { } 对象 最外层 region string period object total_sales number change_rate number is_anomaly boolean top_declines array note null { "start": 日期, "end": 日期 } [ 对象, 对象 ] 每个元素:category · change_rate 负数表示下降;单位要看文档
图 1 · 把 JSON 展开成树:先看最外层,再逐层展开

读 JSON 的几个小技巧:

  • 先看最外层是对象还是数组,再逐层展开。
  • 键名通常能说明含义,change_rate 为负数表示下降。
  • 注意单位和格式:-0.18 是 -18% 还是 -0.18%?日期是哪个时区?这些 JSON 本身不会告诉你,要看文档或 Schema 描述。

常见的语法错误:键名没加双引号、字符串用了单引号、最后一个元素后面多了逗号、出现注释。模型偶尔也会犯这些错误,这就是为什么要用程序校验。

JSON Schema:给 JSON 写规则

JSON Schema 本身也是一份 JSON,用来描述另一份 JSON 应该满足的结构。当前版本是 2020-12。看一个“查询销售数据”工具的参数 Schema:

{
  "type": "object",
  "properties": {
    "region": {
      "type": "string",
      "description": "销售大区名称",
      "enum": ["华东", "华南", "华北", "西南"]
    },
    "start_date": {
      "type": "string",
      "description": "开始日期,格式 YYYY-MM-DD,包含当天",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "end_date": {
      "type": "string",
      "description": "结束日期,格式 YYYY-MM-DD,包含当天"
    },
    "group_by": {
      "type": "string",
      "description": "拆分维度;不需要拆分时不要传",
      "enum": ["category", "channel", "sku"]
    },
    "limit": {
      "type": "integer",
      "description": "最多返回的分组数",
      "minimum": 1,
      "maximum": 50,
      "default": 10
    }
  },
  "required": ["region", "start_date", "end_date"],
  "additionalProperties": false
}

常用关键字一览:

关键字 作用 本例中的用法
type 值的类型 object、string、integer
properties 对象有哪些字段 region、start_date 等
required 哪些字段必填 大区和起止日期必填
description 给人和模型看的说明 说明日期格式与是否包含当天
enum 只能取列出的值 大区只能是四个之一
minimum / maximum 数字范围 limit 在 1–50 之间
pattern 字符串需匹配的正则 日期格式
items 数组中每个元素的规则 用于数组类型字段
additionalProperties 是否允许未定义的字段 false 表示不允许多余字段
default 默认值说明 limit 默认 10

还有一个 format 关键字(如 "format": "date"),但在 2020-12 版本中它默认只是注释性的说明,是否真正校验取决于所用的校验库,所以关键格式最好配合 pattern 或程序检查。

Schema 在 Agent 中的三个用途

Schema 在一次工具调用里会出现三次:

JSON Schema 在一次工具调用中的三个用途:告诉模型怎么调用工具、校验模型输出的参数、约束模型的最终输出 告诉模型怎么调用工具 工具定义 = 名称 + 描述 + 参数 Schema 用途 1 模型输出参数 JSON {"region": "华东", "start_date": …} 程序校验模型的输出 不符合 Schema → 把错误信息返回给模型 用途 2 调用真实 API,拿到结果 约束模型的最终输出 结构化输出:按固定字段返回,供下游消费 用途 3 不通过 让模型修正
图 2 · Schema 的三个用途:说明书、检查员、输出契约

用途 1:工具定义。 以 Anthropic 的 Messages API 为例,一个工具由 name、description 和 input_schema 三部分组成,其中 input_schema 就是一份 JSON Schema。其他厂商的字段名略有差异,但结构大同小异:

{
  "name": "query_sales",
  "description": "按大区和日期范围查询销售额,可按品类、渠道或 SKU 拆分。用于分析销售变化原因。只读。",
  "input_schema": {
    "type": "object",
    "properties": {
      "region": { "type": "string", "enum": ["华东", "华南", "华北", "西南"] },
      "start_date": { "type": "string", "description": "YYYY-MM-DD" },
      "end_date": { "type": "string", "description": "YYYY-MM-DD" }
    },
    "required": ["region", "start_date", "end_date"]
  }
}

模型调用时,会输出一个工具调用块,其中的 input 就是按 Schema 填写的参数。工具定义的写法见工具定义三要素。

用途 2:校验。 模型填写参数是概率性的,可能漏字段、填错类型、编造枚举之外的值。程序应该在执行前校验:

from jsonschema import validate, ValidationError

schema = {
    "type": "object",
    "properties": {
        "region": {"type": "string", "enum": ["华东", "华南", "华北", "西南"]},
        "limit": {"type": "integer", "minimum": 1, "maximum": 50},
    },
    "required": ["region"],
    "additionalProperties": False,
}

model_output = {"region": "华中", "limit": 100}

try:
    validate(instance=model_output, schema=schema)
except ValidationError as e:
    # 把可读的错误信息返回给模型,让它修正,而不是直接调用 API
    print("参数不合法:", e.message)

运行后会输出类似 参数不合法: '华中' is not one of ['华东', '华南', '华北', '西南'] 的错误(需要先 pip install jsonschema)。部分模型厂商也提供“严格模式”,在生成阶段就保证输出符合 Schema,例如 Anthropic 的工具定义支持 strict: true,但程序侧的业务校验(例如结束日期不能早于开始日期)仍然需要。

用途 3:结构化输出。 让 Agent 的最终结论按约定字段输出,下游系统才能直接使用,详见结构化输出与输出契约。

好的 Schema 与差的 Schema

同一个“订单查询”工具,对比两种写法:

写法 差的 Schema 好的 Schema
字段名 id order_no
类型 所有字段都是 string 数量用 integer,开关用 boolean
取值范围 status 可以是任意字符串 status 用 enum 列出合法值
描述 没有 description 说明格式、单位、示例、什么时候不需要传
必填 全部可选 只有真正必需的字段放进 required
多余字段 允许任意字段 additionalProperties: false

记住一个原则:模型看不到你的代码和数据库,只能看到 Schema 和描述。 你会对新同事口头解释的每一个细节——“订单号是字母 A 开头”“日期是北京时间”“金额单位是分”——都应该写进描述。

常见误区

  • “Schema 是给程序看的,描述写不写无所谓。” 恰恰相反,description 是模型选择工具、填写参数最主要的依据。
  • “用了严格模式就不需要校验了。” 结构正确不等于业务正确。格式完全合法的 {"refund_amount": 99999} 仍然需要程序检查是否超过订单金额。
  • “字段越多越灵活。” 可选字段过多会让模型困惑、填入不必要的值。只暴露任务真正需要的参数。

产品经理检查清单

评审工具定义或结构化输出方案时:

  • 每个字段的名称是否一眼能看懂?有没有 id、type、data 这类含糊的名字?
  • 有固定取值的字段是否用了 enum?
  • 单位、时区、格式是否写进了描述?
  • 必填字段是否是真正必须的最小集合?
  • 模型输出参数后,程序做了哪些校验?校验失败时模型能看到什么错误信息?
  • 业务规则(金额上限、状态流转)是否由程序检查,而不只依赖 Schema?

练习

用 30–45 分钟完成:

  1. 为订单售后诊断 Agent 的工具 get_order_events 写一份参数 Schema,要求:订单号必填且以字母 A 开头;可选的事件类型只能是“已创建、已支付、已确认、已完成、已取消”之一;可选的最多返回条数在 1–100 之间。
  2. 为每个字段写一句面向模型的 description。
  3. 写出 3 个“不合法”的参数示例,并说明它们分别违反了哪条规则。
  4. 进阶:安装 jsonschema,用上面的 Python 代码验证你的 3 个反例确实会报错。

延伸阅读

下一步

工具要调用真实系统,首先得证明“你是谁、能做什么”。下一课「认证、授权与 OAuth」讲清 Agent 如何安全地拿到访问权限。

试试:上下文、MCP、沙箱、Prompt 注入、外链