Structured Outputs en la API de Claude: cómo garantizar que la respuesta siempre cumpla tu esquema JSON, con código real
La función combina dos piezas independientes, salida JSON y uso estricto de herramientas, compilando tu esquema en una gramática que restringe token a token lo que Claude puede generar. Está en beta pública y solo en un grupo concreto de modelos.
Un esquema que deja de ser una esperanza para convertirse en una garantía
Cualquiera que haya construido una integración seria con la API de Claude conoce el problema: por muy bien redactado que esté el prompt pidiendo JSON, de vez en cuando llega una respuesta con una coma de más, una clave inventada o un tipo de dato equivocado, y hay que envolver todo en manejo de errores y reintentos. Structured Outputs ataca ese problema desde la raíz, no desde el prompt: en lugar de pedirle a Claude que produzca JSON válido y confiar en que lo haga, la API compila el esquema JSON que se proporciona en una gramática que restringe, token a token, lo que el modelo puede generar. El resultado es una respuesta que cumple el esquema por construcción, no por suerte.
Dos piezas independientes que resuelven problemas distintos
Structured Outputs no es una única función, sino dos capacidades complementarias que se pueden usar por separado o juntas en la misma solicitud. La primera, salida JSON mediante el parámetro output_config.format, restringe la respuesta de texto de Claude a un objeto JSON que cumple el esquema indicado; es la opción adecuada cuando la tarea es extraer datos estructurados de un texto, generar un informe con una forma fija, o dar formato a una respuesta que otro sistema va a consumir directamente. La segunda, uso estricto de herramientas mediante el campo strict: true en la definición de una herramienta, garantiza que los argumentos con los que Claude llama a esa herramienta coinciden exactamente con su esquema de entrada; es la pieza que interesa en flujos agénticos con herramientas complejas, donde una llamada con un parámetro mal formado puede romper todo el flujo. Ambas piezas resuelven problemas distintos —qué dice Claude frente a cómo llama a las funciones— y se pueden combinar en la misma solicitud cuando se necesitan las dos garantías a la vez.
El esquema real, con sus límites, no la versión idealizada
Un ejemplo mínimo de salida JSON en Python define primero el esquema —un objeto con propiedades tipadas, una lista de campos obligatorios en required, y additionalProperties puesto explícitamente en false para impedir que Claude añada campos no declarados—, y lo pasa dentro de output_config.format en la llamada a client.messages.create, junto al modelo y los mensajes habituales. Para uso estricto de herramientas, el cambio es más pequeño: basta con añadir strict: true a la definición de la herramienta ya existente, junto a su name, description e input_schema, sin tocar el resto de la lógica de la integración.
Aquí está el matiz que separa a quien usa esta función en producción de quien se lleva una sorpresa en el primer despliegue real: Structured Outputs soporta JSON Schema estándar, pero con limitaciones concretas que conviene conocer antes de diseñar un esquema complejo. No soporta restricciones numéricas ni de longitud de cadena de texto directamente en el esquema; la forma recomendada de manejarlas es mantener esas restricciones fuera del esquema que se envía a Claude, describirlas en el campo description de la propiedad correspondiente —por ejemplo, indicando «Debe ser como mínimo 100» en lugar de una restricción de esquema formal—, y validar el resultado contra la restricción real en el propio código después de recibir la respuesta. Los esquemas más complejos generan gramáticas más grandes que tardan más en compilarse, así que la API impone límites de complejidad —número de parámetros combinados entre todas las herramientas estrictas de una misma solicitud, por ejemplo— que conviene tener en cuenta si se combinan varias herramientas estrictas con muchos parámetros opcionales cada una: los límites se aplican al total combinado de la solicitud, no herramienta por herramienta.
Incompatibilidades y matices antes de activarlo en producción
Structured Outputs es incompatible con dos funciones que muchas integraciones ya usan. Con las Citas, porque esa función necesita intercalar bloques de cita con texto libre, algo que entra en conflicto directo con las restricciones de un esquema JSON estricto; combinar ambas devuelve un error 400. Y con el precompletado del turno del asistente (prefill), que en los modelos donde sigue soportado no puede usarse junto a una salida JSON. Hay además un matiz de cumplimiento normativo que rara vez se menciona: la API compila los esquemas JSON en gramáticas que se almacenan en caché por separado del contenido de los mensajes, y esas gramáticas cacheadas no reciben las mismas protecciones de información de salud (PHI) que sí tienen los prompts y las respuestas bajo HIPAA; por tanto, cualquier información de salud protegida debe ir siempre en el contenido del mensaje, nunca en los nombres de propiedades, valores de enumeración o patrones de expresión regular del propio esquema.
Por ahora, la función está disponible como beta pública, activándose con la cabecera beta structured-outputs-2025-11-13, y limitada a un grupo concreto de modelos: Claude Sonnet 4.5 y Claude Opus 4.1 desde su lanzamiento, con soporte añadido para Claude Haiku 4.5 el 4 de diciembre de 2025. Antes de planificar una migración completa de un sistema de validación manual a Structured Outputs, conviene comprobar que el modelo que se está usando en producción está en esa lista, porque intentarlo en un modelo no compatible no ofrece la misma garantía de cumplimiento de esquema.
Por qué importa hoy
Para cualquier equipo que extraiga datos estructurados de texto libre, genere informes con un formato fijo, o dependa de llamadas a herramientas con parámetros complejos en un flujo agéntico, sustituir el manejo manual de errores de parseo por Structured Outputs elimina una categoría entera de fallos en producción sin cambiar el prompt. El primer paso práctico no es reescribir toda la integración, sino identificar el endpoint con más reintentos por errores de formato en los registros actuales, y probar ahí primero si el modelo en uso ya está entre los compatibles con esta función.