从智能体获取结构化输出
使用 JSON Schema、Zod 或 Pydantic 从智能体工作流返回验证的 JSON。在多轮工具使用后获取类型安全的结构化数据。
结构化输出让你定义从智能体返回的数据的确切形状。智能体可以使用任何需要的工具来完成任务,最后你仍然会获得与你的 schema 匹配的验证 JSON。定义一个 JSON Schema 来描述你需要的结构,SDK 会根据它验证输出,在不匹配时重新提示。如果验证在重试限制内没有成功,结果将是一个错误而不是结构化数据;请参阅 错误处理。
为了获得完整的类型安全,使用 Zod(TypeScript)或 Pydantic(Python)来定义你的 schema 并获取强类型对象。
为什么使用结构化输出?
智能体默认返回自由格式的文本,这适用于聊天但不适用于需要以编程方式使用输出的情况。结构化输出为你提供类型化数据,你可以直接传递给应用逻辑、数据库或 UI 组件。
考虑一个食谱应用,其中智能体搜索网络并返回食谱。没有结构化输出,你会得到需要自己解析的自由格式文本。有了结构化输出,你定义你想要的形状并获得可以直接在应用中使用的类型化数据。
这是一个经典的巧克力芯片饼干食谱!
**巧克力芯片饼干**
准备时间:15 分钟 | 烹饪时间:10 分钟
材料:
- 2 1/4 杯通用面粉
- 1 杯黄油,软化
...
要在你的应用中使用这个,你需要解析出标题,将"15 分钟"转换为数字,将材料与说明分开,并处理响应中的不一致格式。
{
"name": "Chocolate Chip Cookies",
"prep_time_minutes": 15,
"cook_time_minutes": 10,
"ingredients": [
{ "item": "all-purpose flour", "amount": 2.25, "unit": "cups" },
{ "item": "butter, softened", "amount": 1, "unit": "cup" }
// ...
],
"steps": ["Preheat oven to 375°F", "Cream butter and sugar" /* ... */]
}
你可以直接在 UI 中使用的类型化数据。
快速开始
要使用结构化输出,定义一个 JSON Schema 来描述你想要的数据形状,然后通过 outputFormat 选项(TypeScript)或 output_format 选项(Python)将其传递给 query()。当智能体完成时,结果消息包含一个 structured_output 字段,其中包含与你的 schema 匹配的验证数据。
下面的示例要求智能体研究 Anthropic 并返回公司名称、成立年份和总部作为结构化输出。
import { query } from "@anthropic-ai/claude-agent-sdk";
// 定义你想要返回的数据形状
const schema = {
type: "object",
properties: {
company_name: { type: "string" },
founded_year: { type: "number" },
headquarters: { type: "string" }
},
required: ["company_name"]
};
for await (const message of query({
prompt: "Research Anthropic and provide key company information",
options: {
outputFormat: {
type: "json_schema",
schema: schema
}
}
})) {
// 结果消息包含带有验证数据的 structured_output
if (message.type === "result" && message.subtype === "success" && message.structured_output) {
console.log(message.structured_output);
// { company_name: "Anthropic", founded_year: 2021, headquarters: "San Francisco, CA" }
}
}
使用 Zod 和 Pydantic 的类型安全 schema
与其手动编写 JSON Schema,你可以使用 Zod(TypeScript)或 Pydantic(Python)来定义你的 schema。这些库为你生成 JSON Schema,并让你将响应解析为完全类型化的对象,你可以在整个代码库中使用,具有自动完成和类型检查。
下面的示例定义了一个功能实现计划的 schema,包括摘要、步骤列表(每个步骤都有复杂度级别)和潜在风险。智能体规划功能并返回一个类型化的 FeaturePlan 对象。然后你可以访问 plan.summary 等属性,并使用完整的类型安全遍历 plan.steps。
import { z } from "zod";
import { query } from "@anthropic-ai/claude-agent-sdk";
// 使用 Zod 定义 schema
const FeaturePlan = z.object({
feature_name: z.string(),
summary: z.string(),
steps: z.array(
z.object({
step_number: z.number(),
description: z.string(),
estimated_complexity: z.enum(["low", "medium", "high"])
})
),
risks: z.array(z.string())
});
type FeaturePlan = z.infer<typeof FeaturePlan>;
// 转换为 JSON Schema
const schema = z.toJSONSchema(FeaturePlan);
// 在查询中使用
for await (const message of query({
prompt:
"Plan how to add dark mode support to a React app. Break it into implementation steps.",
options: {
outputFormat: {
type: "json_schema",
schema: schema
}
}
})) {
if (message.type === "result" && message.subtype === "success" && message.structured_output) {
// 验证并获取完全类型化的结果
const parsed = FeaturePlan.safeParse(message.structured_output);
if (parsed.success) {
const plan: FeaturePlan = parsed.data;
console.log(`Feature: ${plan.feature_name}`);
console.log(`Summary: ${plan.summary}`);
plan.steps.forEach((step) => {
console.log(`${step.step_number}. [${step.estimated_complexity}] ${step.description}`);
});
}
}
}
优势:
- 完整的类型推断(TypeScript)和类型提示(Python)
- 使用
safeParse() 或 model_validate() 进行运行时验证
- 更好的错误消息
- 可组合、可重用的 schema
输出格式配置
outputFormat(TypeScript)或 output_format(Python)选项接受一个对象,包含:
type:设置为 "json_schema" 以获得结构化输出
schema:一个 JSON Schema 对象,定义你的输出结构。你可以使用 z.toJSONSchema() 从 Zod schema 生成它,或使用 .model_json_schema() 从 Pydantic 模型生成它
SDK 支持标准 JSON Schema 功能,包括所有基本类型(object、array、string、number、boolean、null)、enum、const、required、嵌套对象和 $ref 定义。有关支持的功能和限制的完整列表,请参阅 JSON Schema 限制。
不是有效 JSON Schema 的 schema 在启动时会导致运行失败,并显示一条错误消息,说明问题所在。在 v2.1.205 之前,无效的 schema 会被静默忽略,智能体会返回非结构化文本。
format 关键字,例如 "format": "email",被接受为注释,SDK 的验证器不会强制执行它。在 v2.1.205 之前,任何包含 format 的 schema 都被视为无效。
示例:TODO 跟踪智能体
此示例演示了结构化输出如何与多步工具使用配合工作。智能体需要在代码库中查找 TODO 注释,然后为每个注释查找 git blame 信息。它自主决定使用哪些工具(Grep 搜索、Bash 运行 git 命令)并将结果合并为单个结构化响应。
schema 包括可选字段(author 和 date),因为 git blame 信息可能不适用于所有文件。智能体填充它能找到的内容并省略其余部分。
import { query } from "@anthropic-ai/claude-agent-sdk";
// 定义 TODO 提取的结构
const todoSchema = {
type: "object",
properties: {
todos: {
type: "array",
items: {
type: "object",
properties: {
text: { type: "string" },
file: { type: "string" },
line: { type: "number" },
author: { type: "string" },
date: { type: "string" }
},
required: ["text", "file", "line"]
}
},
total_count: { type: "number" }
},
required: ["todos", "total_count"]
};
// 智能体使用 Grep 查找 TODO,使用 Bash 获取 git blame 信息
for await (const message of query({
prompt: "Find all TODO comments in this codebase and identify who added them",
options: {
outputFormat: {
type: "json_schema",
schema: todoSchema
}
}
})) {
if (message.type === "result" && message.subtype === "success" && message.structured_output) {
const data = message.structured_output as { total_count: number; todos: Array<{ file: string; line: number; text: string; author?: string; date?: string }> };
console.log(`Found ${data.total_count} TODOs`);
data.todos.forEach((todo) => {
console.log(`${todo.file}:${todo.line} - ${todo.text}`);
if (todo.author) {
console.log(` Added by ${todo.author} on ${todo.date}`);
}
});
}
}
错误处理
结构化输出生成可能会失败,当智能体无法生成与你的 schema 匹配的有效 JSON 时。这通常发生在 schema 对于任务来说太复杂、任务本身不明确或智能体在尝试修复验证错误时达到重试限制时。它也可能在没有任何验证失败的情况下发生:模型回退可以在流中途收回已完成的输出,如果没有重试替换它,运行将以相同的错误结束。在调试你的 schema 之前,检查结果消息上的 errors 字段以区分这两个原因。
发生错误时,结果消息有一个 subtype 指示出了什么问题:
下面的示例检查 subtype 字段以确定输出是否成功生成或你是否需要处理失败:
for await (const msg of query({
prompt: "Extract contact info from the document",
options: {
outputFormat: {
type: "json_schema",
schema: contactSchema
}
}
})) {
if (msg.type === "result") {
if (msg.subtype === "success" && msg.structured_output) {
// 使用验证的输出
console.log(msg.structured_output);
} else if (msg.subtype === "error_max_structured_output_retries") {
// 处理失败 - 使用更简单的提示重试、回退到非结构化等
console.error("Could not produce valid output");
}
}
}
避免错误的提示:
- 保持 schema 专注。 具有许多必需字段的深层嵌套 schema 更难满足。从简单开始,根据需要添加复杂性。
- 匹配 schema 到任务。 如果任务可能没有你的 schema 要求的所有信息,请将这些字段设为可选。
- 使用清晰的提示。 模糊的提示使智能体更难知道要生成什么输出。
相关资源
- JSON Schema 文档:学习 JSON Schema 语法以定义具有嵌套对象、数组、枚举和验证约束的复杂 schema
- API 结构化输出:直接使用 Claude API 的结构化输出进行单轮请求,无需工具使用
- 自定义工具:在返回结构化输出之前,在执行期间给你的智能体自定义工具来调用