博客 • AI / JSON Schema
AI Agent 为什么需要 JSON Schema?从 Tool Calling 到 Structured Output 完整解析
你在接 LLM API 做 Agent,文档里同时出现tools[].function.parameters、response_format.json_schema和 MCP 的inputSchema——它们看起来都是 JSON,但各自约束什么、保证什么?
JSON Schema是描述 JSON 数据结构的标准(当前主流版本2020-12)。在 AI Agent 开发里,它不是「可选的文档格式」,而是模型与外部世界之间的契约语言:Tool Calling 用它描述工具参数,Structured Output 用它约束最终回答,MCP 用它定义工具输入输出。
本文将说明:
- JSON Schema 在 Agent 栈的哪几层出现
- Tool Calling 如何用 schema 约束
arguments - Structured Output 三条路径(JSON Mode / Function Calling / Strict Schema)的差异
- MCP 2020-12 工具契约怎么写
- 一份可复制的 tool schema 示例与校验工作流
先记住这一点:模型「输出 JSON」和「输出符合 schema 的 JSON」是两回事。JSON Schema 定义的是后者——字段名、类型、必填项、枚举值。下面按「为什么需要 → Tool Calling → Structured Output → MCP → 怎么写 → 怎么校验」拆开。
Agent 为什么离不开 JSON Schema
Agent 的核心循环是:模型推理 → 决定调用工具或给出结构化回答 → 执行 → 把结果回填 → 继续推理。这个循环里每一步的 I/O 都应该是机器可解析、可校验、可审计的。
纯自然语言输出有两个致命问题:
- 不可编程消费:下游代码无法可靠提取字段,只能靠正则或二次 LLM 解析
- 不可回归测试:同一 prompt 两次输出格式可能不同,无法做 fixture 对比
JSON Schema 解决的是「格式契约」问题:在模型生成之前,你就声明了「输出必须有哪些字段、什么类型、哪些必填」。这让 Agent 从 demo 变成生产系统的关键基础设施。
2026 年的 Agent 栈已经高度对齐:OpenAI Function Calling、Anthropic Tool Use、DeepSeek Function Calling、MCP Tools——全部用 JSON Schema 描述工具参数。
Schema 出现在 Agent 栈的哪几层
一张表看清 JSON Schema 在 Agent 开发中的位置:
| 层级 | Schema 字段 | 约束什么 | 谁负责校验 |
|---|---|---|---|
| LLM API — Tool Calling | tools[].function.parameters |
模型生成的tool_calls[].function.arguments |
模型(软约束)+ 你的代码(硬校验) |
| LLM API — Structured Output | response_format.json_schema |
模型最终回答的 JSON 结构 | 模型(Strict 模式硬约束)+ 你的代码 |
| MCP Server | inputSchema / outputSchema |
工具调用参数 / Server 返回的 structuredContent | Client SDK + 你的代码 |
| 业务层 | 自定义 schema 文件 | 入库前、API 响应前的最终 gate | ajv / jsonschema / 你的 validate 函数 |
关键洞察:API 层的 schema 是「引导模型生成」,业务层的 schema 是「拒绝不合格数据」。两层都需要,不能互相替代。
Tool Calling:parameters 就是 JSON Schema
以 OpenAI 兼容 API 为例,你在请求里声明tools数组,每个工具的function.parameters就是 JSON Schema object:
{
"model": "deepseek-v4-pro",
"messages": [
{ "role": "user", "content": "查一下北京今天天气" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. Beijing"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"default": "celsius"
}
},
"required": ["city"],
"additionalProperties": false
}
}
}
]
}
模型返回的tool_calls里,function.arguments是一个 JSON字符串,不是已解析的对象:
{
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"Beijing\", \"unit\": \"celsius\"}"
}
}
]
}
这意味着你必须在业务层做两件事:
-
1
JSON.parse + try/except
arguments可能语法损坏(缺引号、尾随逗号),先保证是合法 JSON。 -
2
JSON Schema validate
用你声明的
parametersschema 校验解析后的对象——字段是否齐全、类型是否正确、enum 是否合法。
完整的工具循环:请求带 schema → 模型选工具并生成 arguments → 你解析并校验 → 执行工具 → 把结果作为 tool message 回填 → 模型继续推理。schema 质量直接影响模型能不能一次生成正确的 arguments。
Structured Output 三条路径对比
除了 Tool Calling,你还可以让模型直接输出结构化 JSON 作为最终回答。三条常见路径:
| 路径 | API 配置 | 保证什么 | 适用场景 |
|---|---|---|---|
| JSON Mode | response_format: { "type": "json_object" } |
输出是合法 JSON 对象 | 自由格式提取、简单分类、字段结构简单 |
| Function Calling | tools+ 模型返回 tool_calls |
arguments 尽量符合 parameters schema | Agent 工具调用、与 MCP 组合 |
| Strict Schema | response_format.json_schema + strict: true |
输出严格 conform 到给定 schema | 生产环境、schema 复杂、字段类型严格 |
Strict Schema 示例(OpenAI / DeepSeek 兼容格式):
{
"model": "deepseek-v4-pro",
"messages": [
{ "role": "user", "content": "分析这段用户反馈的情感和关键问题" }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "sentiment_analysis",
"strict": true,
"schema": {
"type": "object",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positive", "neutral", "negative"]
},
"issues": {
"type": "array",
"items": { "type": "string" }
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": ["sentiment", "issues", "confidence"],
"additionalProperties": false
}
}
}
}
最佳实践是多层防御:API 层选 Strict 或 Function Calling → 业务层用 JSON Schema validate → 调试层用 JSONNote 本地 format / diff / schema check。详见DeepSeek V4-Pro 完整解析中的 JSON 输出章节。
MCP 与 JSON Schema 2020-12
Model Context Protocol (MCP)是 Agent 与外部服务之间的标准协议。2026-07-28 规范把工具的inputSchema和outputSchema升级到完整 JSON Schema 2020-12,支持oneOf、anyOf、$ref等组合特性。
{
"name": "search_docs",
"description": "Search documentation by keyword",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"query": { "type": "string", "minLength": 1 },
"limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 }
},
"required": ["query"]
},
"outputSchema": {
"type": "object",
"properties": {
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": { "type": "string" },
"url": { "type": "string", "format": "uri" }
},
"required": ["title", "url"]
}
}
},
"required": ["results"]
}
}
Server 返回的structuredContent必须 conform 到outputSchema(如果定义了)。这和 LLM API 里 parsetool_calls.arguments是同一类工程问题——只是数据来源从模型变成了 MCP Server。更多 MCP 背景见AI Conference 2026 热点梳理。
怎么写一份好用的 tool schema
schema 质量直接影响模型 tool calling 的成功率。以下是经过生产验证的写法要点:
-
1
每个 property 都写 description
模型读 description 决定怎么填值。
city写成「City name, e.g. Beijing, Shanghai」比裸字段名准确率高很多。 -
2
用 enum 限制选项,不要靠 description 暗示
"enum": ["low", "medium", "high"]比 description 里写「可选 low/medium/high」可靠。 -
3
设 additionalProperties: false
防止模型「创造性」添加未声明字段。Strict Schema 模式通常强制此选项。
-
4
复杂参数用 oneOf / $ref,不要扁平化所有组合
例如「按 ID 查」和「按名称查」是两种参数结构,用 oneOf 分开比一个大 object 更清晰。
-
5
工具 description 写清楚「什么时候该调、什么时候不该调」
模型靠 description 做 tool selection。写「Only call when user explicitly asks about weather」能减少误触发。
校验工作流:从 API 到业务层
推荐的 Agent JSON 校验流水线:
import json
from jsonschema import validate, ValidationError
TOOL_SCHEMA = {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"],
"additionalProperties": False
}
def parse_tool_arguments(raw: str) -> dict:
try:
data = json.loads(raw)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON in arguments: {e}") from e
try:
validate(instance=data, schema=TOOL_SCHEMA)
except ValidationError as e:
raise ValueError(f"Schema validation failed: {e.message}") from e
return data
# 用法
args = parse_tool_arguments(tool_call["function"]["arguments"])
weather = get_weather(args["city"], args.get("unit", "celsius"))
无论数据来自模型arguments还是 MCPstructuredContent,都走同一套 parse → validate → 业务逻辑。开发阶段把 schema 和实际输出贴进 JSONNote 做可视化校验,比 print 调试快得多。
用 JSONNote 调试 schema 与模型输出
Agent 开发里最耗时的往往不是写 prompt,而是 debug 模型返回的 JSON。JSONNote 在浏览器本地运行,适合处理 API 响应和 MCP 消息:
-
1
格式化模型输出
把
tool_calls[].function.arguments贴进JSON 格式化,立刻看到语法错误和缩进问题。 -
2
校验 tool schema
把 tool 定义和模型返回的 arguments 贴进JSON Schema页面做 validate。
-
3
对比两次调用
用JSON Diff对比 prompt 迭代前后的 structured output 差异,做回归检查。
-
4
分享调试现场
用URL Hash 分享把某次 tool call 的 JSON 写进链接,同事打开即可复现——数据不经过服务器。
常见问题
JSON Schema 和 Function Calling 是什么关系?
Function Calling 的tools[].function.parameters就是 JSON Schema。模型根据 schema 生成 arguments JSON 字符串;你的代码负责解析并校验是否符合 schema。两者不是并列概念,而是「调用机制」与「参数契约」的关系。
JSON Mode 和 Strict Schema 有什么区别?
JSON Mode 只保证输出是合法 JSON 对象,不保证字段和类型符合你的 schema。Strict Schema 在推理阶段约束 token 生成,使输出严格 conform 到给定 schema。简单提取用 JSON Mode;生产环境复杂结构用 Strict Schema。
MCP 工具的 inputSchema 用什么版本?
MCP 2026-07-28 规范要求 inputSchema 和 outputSchema 使用 JSON Schema 2020-12,支持 oneOf、anyOf、$ref 等完整特性。outputSchema 描述 Server 返回的 structuredContent 结构。
模型已经返回 JSON 了,还需要手动校验吗?
需要。即使开了 Strict Schema,生产环境仍建议 try/except 解析 + JSON Schema validate。tool_calls.arguments 可能缺字段、类型错误或语法损坏——校验是业务层的责任,不是模型的保证。
JSON Schema 和 OpenAPI 有什么区别?
OpenAPI 是 REST API 的完整描述规范(路径、方法、认证、响应码等),其 request/response body 部分用 JSON Schema 描述。Agent Tool Calling 只需要「单个函数的参数 schema」,直接用 JSON Schema 即可,不必套整个 OpenAPI 文档。
总结
AI Agent 开发的核心信号可以概括为:
Agent I/O JSON 化、工具契约 Schema 化、校验多层化。
JSON Schema 贯穿 Tool Calling 的 parameters、Structured Output 的 response_format、MCP 的 inputSchema/outputSchema——它是模型与外部世界之间的通用契约语言。写好 schema、加上业务层 validate、用 JSONNote 本地调试,是从 demo 到生产的必经之路。