Structured Output con tool_use y JSON Schemas
Structured Output con tool_use y JSON Schemas
Anterior: Criterios y Few-Shot · Índice · Siguiente: Validación y Retry
tool_use como mecanismo de structured output
El approach más confiable para obtener output estructurado de Claude es tool_use con JSON schemas. En lugar de pedir “responde en JSON”, defines una herramienta cuyo input schema es exactamente la estructura que necesitas, y Claude la “invoca” con datos conformes al schema.
Esto no es un hack — es el mecanismo diseñado por Anthropic para structured output garantizado.
Ventaja sobre pedir JSON en texto
| Approach | Syntax errors | Campos faltantes | Tipos incorrectos |
|---|---|---|---|
| ”Respond in JSON” | Frecuentes | Comunes | Comunes |
| tool_use + schema | Eliminados | Eliminados | Eliminados |
Clave para el examen: tool_use con JSON schemas elimina errores de sintaxis pero NO errores semánticos (valores incorrectos, datos inventados, sumas que no cuadran).
tool_choice: controlando cuándo y qué tool usar
El parámetro tool_choice controla el comportamiento de selección de herramientas:
tool_choice: “auto” (default)
Claude decide si usar una herramienta o responder en texto. Apropiado cuando:
- No siempre se necesita output estructurado
- Claude puede necesitar clarificación antes de actuar
- Hay conversación mixta (texto + acciones)
tool_choice: “any”
Claude debe usar alguna de las herramientas disponibles, pero elige cuál. Ideal para:
- Múltiples schemas y el tipo de documento es desconocido
- Routing: cada tool representa un tipo de output diferente
- Garantizar que siempre haya output estructurado
tool_choice forzado (tool específico)
Claude debe usar exactamente la herramienta nombrada. Usar cuando:
- Se necesita garantizar que la extracción corra antes de cualquier enrichment
- Solo hay un schema posible para la tarea
- Se quiere eliminar toda ambigüedad de selección
{
"tool_choice": {
"type": "tool",
"name": "extract_invoice"
}
}
Diseño de JSON Schemas efectivos
required vs optional fields
No todos los campos deben ser required. Si el source document puede no contener cierta información, hacer el campo required fuerza a Claude a inventar un valor.
Patrón correcto: Campos que siempre existen en el source como required, campos que pueden faltar como nullable.
{
"type": "object",
"required": ["vendor_name", "total_amount", "date"],
"properties": {
"vendor_name": { "type": "string" },
"total_amount": { "type": "number" },
"date": { "type": "string", "format": "date" },
"tax_id": { "type": ["string", "null"] },
"purchase_order": { "type": ["string", "null"] }
}
}
Enum con “other” + detail string
Para campos categóricos donde no puedes anticipar todas las opciones:
{
"document_type": {
"type": "string",
"enum": ["invoice", "receipt", "purchase_order", "other"]
},
"document_type_detail": {
"type": ["string", "null"],
"description": "If document_type is 'other', describe the type"
}
}
Este patrón evita que Claude fuerce documentos raros en categorías incorrectas.
Format normalization en prompts
Strict schemas garantizan estructura pero no formato. Si necesitas que las fechas sean YYYY-MM-DD y los montos tengan 2 decimales, debes especificarlo en el prompt:
Format rules:
- Dates: YYYY-MM-DD format
- Amounts: numeric with exactly 2 decimal places
- Phone numbers: E.164 format (+1234567890)
- Names: Title Case
Estas reglas van en el prompt, no en el schema (JSON Schema tiene format pero Claude no siempre lo respeta para normalización).
Extraction tools con JSON schemas
Para tareas de extracción de datos, defines “herramientas” que son realmente schemas de output:
{
"name": "extract_invoice_data",
"description": "Extract structured data from invoice",
"input_schema": {
"type": "object",
"required": ["vendor", "line_items", "total"],
"properties": {
"vendor": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"address": { "type": ["string", "null"] }
}
},
"line_items": {
"type": "array",
"items": {
"type": "object",
"required": ["description", "amount"],
"properties": {
"description": { "type": "string" },
"quantity": { "type": ["number", "null"] },
"amount": { "type": "number" }
}
}
},
"total": { "type": "number" }
}
}
}
La herramienta nunca se “ejecuta” realmente — solo sirve como schema de output.
tool_choice: “any” con múltiples schemas
Cuando el tipo de documento es desconocido, defines múltiples extraction tools y usas tool_choice: "any":
{
"tools": [
{ "name": "extract_invoice", "input_schema": { ... } },
{ "name": "extract_receipt", "input_schema": { ... } },
{ "name": "extract_po", "input_schema": { ... } }
],
"tool_choice": { "type": "any" }
}
Claude analiza el documento, determina el tipo, y elige el schema apropiado. Esto es más efectivo que un solo schema genérico con muchos campos opcionales.
Forced tool para pipelines secuenciales
En pipelines donde la extracción debe completarse antes del enrichment:
- Paso 1:
tool_choice: { type: "tool", name: "extract_raw" }— garantiza extracción - Paso 2: Tomar output, validar, pasar al siguiente step
- Paso 3:
tool_choice: { type: "tool", name: "enrich_data" }— enrichment con datos validados
Sin forced tool, Claude podría intentar hacer extracción y enrichment en un solo paso, perdiendo la oportunidad de validar entre medio.
Errores semánticos: lo que schemas NO resuelven
Strict schemas eliminan:
- JSON mal formado
- Campos faltantes
- Tipos incorrectos (string donde debería ser number)
Pero NO eliminan:
- Valores extraídos incorrectamente
- Datos inventados (alucinaciones)
- Sumas que no cuadran (total ≠ sum of line items)
- Datos colocados en el campo equivocado
Para errores semánticos, necesitas validación post-extracción (siguiente capítulo).
Resumen
- tool_use + JSON schema es el approach más confiable para structured output
tool_choice: "auto"para flexibilidad,"any"para routing, forzado para pipelines- Campos nullable cuando el source puede no tener la información
- Enum con “other” + detail string para categorías abiertas
- Format normalization va en el prompt, no en el schema
- Schemas eliminan errores de sintaxis pero no semánticos
Anterior: Criterios y Few-Shot · Índice · Siguiente: Validación y Retry