结构化输出
使用 JSON Schema 约束 Messages 接口的最终结果,并正确处理非流式和流式响应。
结构化输出让 Agent 在完成工具调用和多轮处理后,返回经过 JSON Schema 校验的数据。它适合把结果直接交给业务代码、数据库或 UI,避免再从自然语言中提取字段。
该能力仅适用于 POST /openapi/v1/messages,大多数用在非流式的一次性任务中。如果在多轮对话场景,需要结构化结果的每一轮都必须携带 output_format;复用会话时,上一轮的 Schema 不会自动沿用。
请求参数
| 参数 | 类型 | 必填条件 | 说明 |
|---|---|---|---|
model | string | 是 | 协议兼容和响应回显字段;实际模型由 API Key 配置决定 |
messages | array | 是 | 至少一条消息;当前使用最后一条 user 消息作为本轮输入 |
stream | boolean | 否,默认 false | false 返回完整 JSON;true 返回 SSE |
output_format | object | 需要结构化输出时 | 结构化输出配置 |
output_format.type | "json_schema" | 是 | 固定值,表示使用 JSON Schema 约束结果 |
output_format.schema | object | 是 | JSON Schema Draft-07 Schema,描述 structured_output 的类型与规则 |
metadata.session_id | UUID string | 否 | 续聊当前用户有权访问且绑定 Key 匹配的会话 |
background | boolean | 否,默认 false | true 时以后台任务提交;必须同时使用 stream=false |
background_payload | Base64 string | 否 | 后台任务业务透传数据,最长 8192 个字符 |
idempotency_key | string | 后台任务必填 | 最长 128 个字符;重试同一业务请求时复用 |
Schema 只约束最终结果,不会阻止 Agent 在生成结果前使用工具、读取附件或进行多轮处理。
JSON Schema 常用字段
接口使用 JSON Schema Draft-07。常用字段如下:
| 字段 | 作用 |
|---|---|
type | 值类型,支持 object、array、string、integer、number、boolean、null |
properties | 定义对象允许包含的字段,以及每个字段自己的 Schema |
required | 指定对象中必须出现的字段;未列出的字段是可选字段 |
additionalProperties | 是否允许 properties 之外的字段;固定数据契约建议设为 false |
items | 定义数组中每一项的 Schema;Draft-07 不支持 prefixItems |
minItems、maxItems | 限制数组最少和最多包含多少项 |
enum | 将结果限制为候选值之一 |
const | 要求结果等于固定值,适合版本号或类型标识 |
definitions、$ref | 定义并复用嵌套 Schema |
description | 说明字段的业务含义,帮助 Agent 理解应填写什么 |
format | 仅作为注解,例如 email 不会由 Agent SDK 强制校验 |
“可选”和“可空”不是同一件事:
- 可选字段:不要把字段名放进
required。 - 可空字段:使用
"type": ["string", "null"]等联合类型。 - 不要使用 OpenAPI 扩展
"nullable": true代替联合类型。
使用 Zod 生成 Schema 时,需要明确指定 Draft-07:
const jsonSchema = z.toJSONSchema(schema, { target: "draft-7" });Zod 默认生成的 Draft 2020-12 Schema 不能直接用于本接口。
非流式请求
下面的 Schema 要求结果包含摘要、待办事项和状态,并禁止返回未定义字段:
{
"model": "poco-agent",
"stream": false,
"messages": [
{
"role": "user",
"content": "分析下面的任务并返回摘要与待办事项:完成季度经营复盘,整理收入变化并安排后续负责人。"
}
],
"output_format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"summary": {
"type": "string",
"description": "季度经营复盘的核心结论"
},
"action_items": {
"type": "array",
"description": "需要继续推进的工作",
"items": { "type": "string" },
"minItems": 1
},
"status": {
"type": "string",
"enum": ["completed", "needs_follow_up"]
}
},
"required": ["summary", "action_items", "status"],
"additionalProperties": false
}
}
}成功时返回 HTTP 200。业务方应读取 structured_output,不要解析 content 中可能存在的过程文本:
{
"id": "msg_123456",
"type": "message",
"role": "assistant",
"content": [],
"model": "poco-agent",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 123,
"output_tokens": 456,
"cache_creation_input_tokens": null,
"cache_read_input_tokens": null
},
"structured_output": {
"summary": "完成季度经营复盘并明确收入变化原因。",
"action_items": ["整理季度收入变化数据", "为每项后续工作指定负责人"],
"status": "needs_follow_up"
}
}X-Session-Id 是会话 ID,后续可通过 metadata.session_id 继续会话;X-Run-Id 是本轮运行 ID,可用于查询本轮产物。
后台结构化输出
结构化输出可以与 background=true 直接组合,不需要新的接口或 Schema。请求继续携带完整 output_format,并设置 stream=false、唯一的 idempotency_key:
{
"model": "poco-agent",
"stream": false,
"background": true,
"idempotency_key": "quarter-review-2026-q3",
"messages": [{ "role": "user", "content": "返回季度复盘结果" }],
"output_format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"summary": { "type": "string" },
"action_items": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["summary", "action_items"],
"additionalProperties": false
}
}
}首次 HTTP 202 提交响应尚未完成时 structured_output 为 null;后台幂等重放仍返回 202,原 Run 已完成时可直接带最终结果。调用方按 background_results.result_url 查询;状态为 completed 时,最终 structured_output 保持 Schema 定义的原始 JSON 类型。若运行结束但没有同步到有效结构化结果,状态为 incomplete,不会把未校验数据伪装成成功结果。
流式请求与响应
流式请求使用相同的 output_format,只需把 stream 设为 true:
{
"model": "poco-agent",
"stream": true,
"messages": [
{
"role": "user",
"content": "返回本次季度复盘的摘要与待办事项。"
}
],
"output_format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"summary": { "type": "string" },
"action_items": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["summary", "action_items"],
"additionalProperties": false
}
}
}执行期间可能先返回 message_start、content_block_* 和 message_delta 等事件。成功完成时,最终结构化数据通过 result 事件返回,之后发送 message_stop:
event: result
data: {"type":"result","subtype":"success","structured_output":{"summary":"完成季度经营复盘并明确收入变化原因。","action_items":["整理季度收入变化数据","为每项后续工作指定负责人"]}}
event: message_stop
data: {"type":"message_stop"}流式客户端必须遵循以下规则:
- 持续读取 SSE,不能在收到普通文本事件后提前结束。
- 以
event: result中的structured_output作为最终结果。 - 收到
event: message_stop表示事件流正常结束。 - 收到
event: error表示本轮失败,不应继续等待result。
非对象根类型
Schema 根节点不必是对象。structured_output 会保持 Schema 定义的原始 JSON 类型,不会额外包裹对象。
数组 Schema:
{
"output_format": {
"type": "json_schema",
"schema": {
"type": "array",
"items": { "type": "string" }
}
}
}对应结果:
{
"structured_output": ["整理收入数据", "指定后续负责人"]
}基础类型同样保持原始类型:
| 根 Schema | structured_output 示例 |
|---|---|
{"type":"string","enum":["ok","failed"]} | "ok" |
{"type":"integer","const":3} | 3 |
{"type":"number","const":3.5} | 3.5 |
{"type":"boolean"} | true |
{"type":"null"} | null |
因此业务代码不能假设结构化结果永远是对象,应按自己提交的根 Schema 解析。
复用 Schema 定义
复杂结构可通过 Draft-07 的 definitions 和本地 $ref 复用:
{
"$ref": "#/definitions/result",
"definitions": {
"result": {
"type": "array",
"items": { "$ref": "#/definitions/task" }
},
"task": {
"type": "object",
"properties": {
"title": { "type": "string" },
"done": { "type": "boolean" }
},
"required": ["title", "done"],
"additionalProperties": false
}
}
}只使用当前 Schema 内的本地引用。业务代码提交前应先用 Draft-07 Validator 验证 Schema 本身有效。
错误处理
Agent SDK 会校验最终输出,并在单次运行内部尝试纠正不符合 Schema 的结果。如果最终仍未生成有效数据,接口不会把未经校验的结果作为成功响应返回。
| 场景 | 非流式请求 | 流式请求 |
|---|---|---|
| API Key 缺失或无效 | HTTP 401 | 建立事件流前返回 HTTP 401 |
请求字段或 output_format.type 无效 | HTTP 422 | 建立事件流前返回 HTTP 422 |
metadata.session_id 不存在或无权访问 | 不存在 404,归属或绑定 Key 不符 403 | 建立事件流前返回对应 HTTP 状态 |
| 最终结果不符合 Schema | HTTP 500,error.type=api_error | 发送 event: error 后结束 |
| 非流式 HTTP 等待超时 | HTTP 504,并返回 Retry-After: 5 | 不适用;事件流保持连接直到结束或客户端取消 |
流式错误示例:
event: error
data: {"type":"error","error":{"type":"api_error","message":"未收到有效结构化结果,请稍后重试"}}Schema 编写建议
- 只定义业务真正需要的字段;嵌套层级和必填字段过多会增加生成失败概率。
required应与任务实际能获得的信息一致;不确定能否获得的字段设为可选或可空。- 为含义不直观的字段添加
description,并在用户指令中说明数据来源和判断标准。 - 需要固定字段集合时设置
additionalProperties: false。 - 不要把 Draft 2020-12 的
prefixItems、$dynamicRef等关键字直接传入。 - 业务代码仍应根据自己的 Schema 对
structured_output做本地类型校验,以便尽早发现契约变化。