Definición de un JSON Schema para output_config.format
output_config.format solo garantiza una respuesta válida según el schema si el schema que le proporcionas está bien formado.
Esta página cubre exactamente cómo escribir ese schema: los dos campos que cada objeto necesita, cómo construirlo manualmente frente a generarlo a partir de un modelo Pydantic, y cómo encajan el anidamiento, los arrays y los enums.
Resumen
El schema que pasas a output_config.format es un JSON Schema estándar, con dos convenciones que la API de Claude requiere en cada objeto: un array required que lista cada propiedad, y additionalProperties: false.
Acertar con estos dos en cada objeto anidado es la fuente más común de errores de schema.
Puedes escribir el schema como un diccionario Python plano, o generarlo automáticamente a partir de un BaseModel de Pydantic con .model_json_schema().
Ambos enfoques producen el mismo formato de transmisión; Pydantic simplemente te ahorra tener que mantener un diccionario y un tipo analizado sincronizados manualmente.
No todas las palabras clave de JSON Schema son compatibles, por lo que un schema que parece razonable aún puede ser rechazado o ignorado silenciosamente en algunas partes; consulta la referencia de tipos de campo y restricciones para ver la lista completa.
Receta
Tarjeta de receta de referencia rápida, lista para copiar y pegar.
from anthropic import Anthropic
client = Anthropic()
schema = {
"type": "object",
"properties": {
"title": {"type": "string"},
"priority": {"type": "string", "enum": ["low", "medium", "high"]},
},
"required": ["title", "priority"],
"additionalProperties": False,
}
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
output_config={"format": {"type": "json_schema", "schema": schema}},
messages=[{"role": "user", "content": "Resume este informe de error como un ticket."}],
)Cuándo usar esto:
- Cualquier vez que el código posterior analice la respuesta de Claude como datos en lugar de mostrarla como texto.
- Extrayendo un conjunto fijo de campos de una entrada no estructurada (correos electrónicos, tickets, texto de formularios).
- Tareas de clasificación donde la respuesta debe ser una de un conjunto conocido de etiquetas.
- Siempre que actualmente confíes en la redacción del prompt "por favor, devuelve solo JSON".
Ejemplo de Trabajo
from pydantic import BaseModel, Field
from anthropic import Anthropic
class BugReport(BaseModel):
title: str = Field(description="Un resumen corto y de una línea del error")
priority: str = Field(description="Uno de: low, medium, high")
steps_to_reproduce: list[str] = Field(description="Lista ordenada de pasos de reproducción")
affected_component: str
client = Anthropic()
response = client.messages.parse(
model="claude-sonnet-5",
max_tokens=1024,
output_config={
"format": {"type": "json_schema", "schema": BugReport.model_json_schema()}
},
messages=[{
"role": "user",
"content": (
"Convierte esto en un informe de error: La página de pago falla cuando un usuario "
"aplica un código de descuento con caracteres especiales. Ocurre cada vez "
"en el módulo de pagos. Inicia sesión, añade un artículo al carrito, aplica un código como "
"'SAVE#10', haz clic en pagar. Esto bloquea todas las compras, por lo que es de alta prioridad."
),
}],
)
report: BugReport = response.parsed_output
print(report.title)
print(report.priority)
for step in report.steps_to_reproduce:
print("-", step)Lo que esto demuestra:
Field(description=...)en un modelo Pydantic se convierte en ladescriptiondel JSON Schema que el modelo lee al decidir qué poner en cada campo.list[str]se convierte automáticamente en unarrayde elementosstring; no se necesita un schema de array manual.response.parsed_outputdevuelve una instancia real deBugReport, no un diccionario, por lo que el acceso a atributos y los verificadores de tipos funcionan.- El schema y el tipo en tiempo de ejecución se definen exactamente una vez, en una sola clase.
Inmersión Profunda
Cómo Funciona
output_config.formattoma un envoltoriotype: "json_schema"alrededor de tu objetoschema; el schema en sí es un documento JSON Schema estándar.- La API restringe la generación de tokens para que la respuesta solo pueda ser texto que valide contra el schema que proporcionaste; no está validando después del hecho, está restringiendo durante la generación.
requiredle dice a la API que cada propiedad listada debe estar presente en la respuesta; omitir una propiedad derequiredla hace opcional, lo cual rara vez es lo que quieres para una tarea de extracción fija.additionalProperties: falsecierra el objeto; sin él, la API (y cualquier validador estricto que superpongas) no puede garantizar que el modelo no agregará campos adicionales no solicitados.- Tanto
requiredcomoadditionalProperties: falsese necesitan en cada objeto del schema, incluidos los objetos anidados; establecerlos solo en el nivel superior no se propaga hacia abajo.
Construcción del Schema Manualmente vs. con Pydantic
| Enfoque | Lo que escribes | Lo que obtienes |
|---|---|---|
| Diccionario escrito a mano | Un dict Python plano que coincide con la sintaxis de JSON Schema | Control total, pero mantienes el schema y cualquier tipo posterior por separado |
Pydantic model_json_schema() | Una subclase de BaseModel con campos tipados | Schema generado automáticamente; response.parsed_output devuelve una instancia de tu modelo |
Los schemas escritos a mano son útiles para formas muy simples y únicas, o cuando no quieres una dependencia de Pydantic. Para cualquier cosa con más de dos o tres campos, un modelo Pydantic evita que el schema y el tipo de datos de tu aplicación se separen a medida que la forma evoluciona.
Objetos Anidados y Arrays
from pydantic import BaseModel
class LineItem(BaseModel):
sku: str
quantity: int
class Order(BaseModel):
customer_name: str
items: list[LineItem]
# Order.model_json_schema() produce un objeto de nivel superior con una propiedad de array "items"
# cuya palabra clave "items" apunta al schema del objeto LineItem anidado;
# cada nivel aún necesita su propio required + additionalProperties: false, que
# Pydantic genera automáticamente para ti.- El anidamiento es compatible a través de la composición ordinaria de JSON Schema (
properties,items,$ref/$def), que es exactamente lo que Pydantic emite para modelos anidados. - Mantén el anidamiento superficial. Dos o tres niveles de profundidad son confiables; las estructuras muy profundas o recursivas no son compatibles; consulta la referencia de tipos de campo.
- Cada objeto en cada nivel todavía necesita su propia lista
requiredyadditionalProperties: false; Pydantic maneja esto correctamente por sí solo, pero si escribes schemas anidados a mano, agrega ambos a cada objeto anidado tú mismo.
Notas de Python
from pydantic import BaseModel
class Ticket(BaseModel):
subject: str
urgency: str
schema = Ticket.model_json_schema()
print(schema["required"]) # ['subject', 'urgency']
print(schema["additionalProperties"]) # Falsemodel_json_schema()de Pydantic establecerequiredyadditionalProperties: falseautomáticamente para unBaseModelestándar sin campos opcionales; esta es una razón para preferirlo sobre escribir el diccionario a mano.- Un campo tipado como
Optional[str]o al que se le asigna un valor predeterminado se excluye derequiredpor Pydantic; si deseas que todos los campos sean obligatorios en la respuesta, evita los valores predeterminados yOptionalen los campos que importan. response.parsed_outputdeclient.messages.parse(...)está tipado como una instancia del modelo que pasaste, por lo que los IDE y los verificadores de tipos entienden la forma sin anotaciones adicionales.
Parámetros y Valores de Retorno
| Campo | Tipo | Descripción |
|---|---|---|
output_config.format.type | str | Siempre "json_schema" para esta característica. |
output_config.format.schema | dict | El documento JSON Schema que describe la forma de respuesta requerida. |
schema.required | list[str] | Cada nombre de propiedad que debe estar presente en la respuesta, por objeto. |
schema.additionalProperties | bool | Debe ser False en cada objeto del schema. |
Trampas Comunes
- Olvidar
additionalProperties: falseen un objeto anidado. Establecerlo solo en el nivel superior deja los objetos internos abiertos. Solución: verifica que cada objeto anidado en el schema también lleveadditionalProperties: false; si escribes schemas a mano, es fácil pasarlo por alto en un campo profundamente anidado. - Listar un campo en
propertiespero no enrequired. El campo se vuelve opcional, por lo que el modelo puede omitirlo y tu código debe verificar defensivamente su presencia. Solución: incluye cada campo que realmente necesitas enrequired, y solo haz que los campos sean opcionales cuando la respuesta genuinamente pueda no tenerlos. - Asumir que cada palabra clave de JSON Schema funciona. Cosas como las restricciones de rango numérico o ciertas palabras clave de composición complejas no son aplicadas por la API. Solución: consulta la referencia de tipos de campo y restricciones antes de diseñar un schema más allá de los tipos básicos,
enumy anidamiento simple. - Reutilizar un modelo Pydantic con campos
Optionalpara una tarea de extracción "debe tener todo". Los campos opcionales/con valor predeterminado se eliminan automáticamente derequired, lo que debilita la garantía que realmente querías. Solución: mantén los campos no opcionales sin valor predeterminado cuando cada valor deba estar presente en la respuesta. - Tratar una respuesta válida según el schema como datos garantizados correctos. El schema impone la forma, no la precisión; un campo
priority: "high"aún puede ser válido según el schema y ser factualmente incorrecto. Solución: mantén tu propio paso de validación o revisión posterior para la corrección, independientemente de la conformidad del schema. - Escribir un schema excesivamente profundo o recursivo. Los schemas recursivos (un objeto que se referencia a sí mismo) no son compatibles, y el anidamiento muy profundo aumenta la posibilidad de que se introduzca una construcción no compatible. Solución: aplana la forma siempre que sea posible, o divide una extracción profundamente anidada en dos llamadas secuenciales.
Alternativas
| Alternativa | Úsala Cuando | No la uses Cuando |
|---|---|---|
| Diccionario de schema escrito a mano | La forma es pequeña, fija y no quieres una dependencia de Pydantic | La forma tiene más de unos pocos campos o evoluciona con frecuencia |
Pydantic model_json_schema() | Ya tienes (o quieres) una clase Python tipada para los datos | Necesitas el schema en un contexto no Python y no puedes compartir el modelo |
input_schema estricto (strict: true) | Quieres restringir los parámetros de una llamada a herramienta en lugar de la respuesta final del mensaje | Estás restringiendo la respuesta de texto general del asistente, no una invocación de herramienta |
| Solo instrucciones JSON basadas en prompt | Prototipado rápido donde la salida ocasionalmente mal formada es aceptable | Cualquier pipeline de producción que analice la respuesta programáticamente |
Preguntas Frecuentes
¿Tengo que escribir required y additionalProperties a mano cada vez?
- No si usas Pydantic;
model_json_schema()establece ambos automáticamente para unBaseModelsin campos opcionales. - Si escribes el schema a mano como un diccionario, sí, debes agregar ambos explícitamente a cada objeto, incluidos los anidados.
¿Qué sucede si olvido additionalProperties: false?
- El objeto queda "abierto", lo que significa que la garantía de aplicación sobre exactamente qué campos pueden aparecer es más débil de lo previsto.
- Siempre establécelo explícitamente en
Falseen cada objeto del schema.
¿Puede un campo ser opcional en mi schema?
- Sí, simplemente omítelo de
requiredy el modelo puede incluirlo o no. - Para tareas de extracción donde realmente necesitas que todos los campos estén poblados, mantén todo en
requireden lugar de hacer los campos opcionales por costumbre.
¿Cómo expreso "uno de estos valores fijos" en el schema?
{"type": "string", "enum": ["low", "medium", "high"]}enumes una construcción bien soportada y es la forma estándar de restringir un campo a un conjunto fijo de valores.
¿Puedo anidar objetos y arrays dentro del schema?
- Sí;
propertiespara objetos anidados yitemspara arrays funcionan, y Pydantic genera esto automáticamente para modelos anidados y camposlist[...]. - Mantén el anidamiento superficial (dos o tres niveles); las estructuras muy profundas o recursivas no son compatibles.
¿Funciona model_json_schema() con campos que tienen valores predeterminados?
- Sí, pero un campo con un valor predeterminado (o tipado como
Optional) es excluido derequiredpor Pydantic. - Si necesitas que todos los campos estén garantizados presentes, evita los valores predeterminados y el tipado
Optionalen esos campos.
¿Es un JSON Schema para output_config.format lo mismo que un schema para uso de herramientas?
- Utilizan la misma sintaxis de JSON Schema y la misma convención
required/additionalProperties: false. - La diferencia es lo que restringen:
output_config.formatrestringe toda la respuesta del mensaje; elinput_schemade una herramienta (constrict: true) restringe los parámetros de una sola llamada a herramienta.
¿Causará un error una palabra clave de schema no compatible?
- El comportamiento varía según la construcción; algunas restricciones no compatibles simplemente no se aplican en lugar de ser rechazadas directamente.
- Consulta la referencia de tipos de campo y restricciones en lugar de asumir que una palabra clave funciona porque es un JSON Schema válido en general.
¿Debo validar la respuesta analizada nuevamente después de recibirla?
- El schema impone la forma, no la corrección factual, por lo que si los valores en sí mismos importan (no solo su forma), mantén tu propio paso de validación o revisión para la corrección.
- Esto es independiente de, y no reemplaza, la garantía de forma de la API.
¿Cuál es el schema válido mínimo que puedo pasar a output_config.format?
{
"type": "object",
"properties": {"answer": {"type": "string"}},
"required": ["answer"],
"additionalProperties": False,
}- Esta es la forma válida más pequeña: un objeto, una propiedad de cadena requerida, cerrada a extras.
¿Puedo generar el schema a partir de una dataclass en lugar de Pydantic?
BaseModelde Pydantic es la ruta de conveniencia común porque.model_json_schema()produce el schema directamente.- Una
dataclasssimple no tiene esto incorporado; escribirías el schema de diccionario tú mismo si no quieres una dependencia de Pydantic.
Relacionados
- Conceptos Básicos de Salidas Estructuradas - solicita una respuesta de JSON schema y analízala con client.messages.parse.
- Validación y Análisis de Respuestas Estructuradas en Python - qué sucede con este schema una vez que solicitas una respuesta con él.
- Referencia de Tipos de Campo y Restricciones de Salida Estructurada - la lista completa de construcciones de schema compatibles e incompatibles referenciadas en toda esta página.
- Manejo de Salidas JSON Malformadas o Truncadas - qué hacer cuando un schema bien formado aún regresa incompleto.
Versiones de Stack: Escrito contra la línea de modelos Claude actual a partir de ~junio de 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (el predeterminado) y Claude Haiku 4.5 - y el SDK oficial de Python
anthropic(última versión 0.x). Los nombres de modelos, versiones de SDK y precios cambian rápidamente; verifica los detalles actuales en platform.claude.com/docs antes de confiar en ellos.