Structured Output con tool_use y JSON Schemas

Por: Artiko
claudecertificacionstructured-outputtool-usejson-schema

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

ApproachSyntax errorsCampos faltantesTipos incorrectos
”Respond in JSON”FrecuentesComunesComunes
tool_use + schemaEliminadosEliminadosEliminados

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:

tool_choice: “any”

Claude debe usar alguna de las herramientas disponibles, pero elige cuál. Ideal para:

tool_choice forzado (tool específico)

Claude debe usar exactamente la herramienta nombrada. Usar cuando:

{
  "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:

  1. Paso 1: tool_choice: { type: "tool", name: "extract_raw" } — garantiza extracción
  2. Paso 2: Tomar output, validar, pasar al siguiente step
  3. 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:

Pero NO eliminan:

Para errores semánticos, necesitas validación post-extracción (siguiente capítulo).


Resumen


Anterior: Criterios y Few-Shot · Índice · Siguiente: Validación y Retry