Cómo estructurar tools/functions para que el modelo las use bien

By Carlos Montiel | Especialista en IA Empresarial
Publicado: 2026-07-28 | Por: Carlos Montiel | Lectura: ~5 minutos

La causa más común de que un agente "no use bien las herramientas" no es el modelo — es que la herramienta está mal descrita, mal nombrada, o el set de herramientas es demasiado grande para que el modelo elija con precisión.

El nombre y la descripción son la interfaz real

El modelo no ve tu código — ve el nombre, la descripción, y el schema de la herramienta. Todo lo que sabe sobre cuándo y cómo usarla viene de ese texto. Un nombre genérico como `procesar` o una descripción de una línea que solo dice qué hace la función, sin decir *cuándo* usarla, deja al modelo adivinando.

# Mal: describe QUÉ hace, no CUÁNDO usarla { "name": "buscar", "description": "Busca información.", ... } # Bien: nombre específico + descripción con criterio de activación { "name": "buscar_precio_producto", "description": ( "Busca el precio actual de un producto específico en el " "catálogo. Úsala cuando el usuario pregunte por precios, " "costos o disponibilidad de un producto por nombre o SKU. " "No la uses para preguntas generales sobre categorías " "de productos — para eso usa listar_categoria." ), ... }

En modelos recientes, que tienden a ser más conservadores al invocar herramientas, ser explícito sobre el criterio de activación en la descripción (no solo en el system prompt general) da una mejora medible en la tasa de invocación correcta.

El schema debe reflejar restricciones reales, no solo tipos

Un schema que solo dice `"type": "string"` para un campo que en realidad solo acepta 5 valores posibles deja demasiado espacio para que el modelo invente variantes. Usa `enum` siempre que el conjunto de valores válidos sea finito y conocido.

{ "name": "actualizar_estado_ticket", "description": "Actualiza el estado de un ticket de soporte existente.", "input_schema": { "type": "object", "properties": { "ticket_id": { "type": "string", "description": "ID del ticket, formato TICK-XXXXX", }, "nuevo_estado": { "type": "string", "enum": ["abierto", "en_progreso", "esperando_cliente", "resuelto", "cerrado"], }, "razon": { "type": "string", "description": "Explicación breve del cambio de estado", }, }, "required": ["ticket_id", "nuevo_estado", "razon"], "additionalProperties": False, }, }

Marcar `required` con precisión importa tanto como el `enum`: si un campo es opcional pero lo marcas como requerido, el modelo va a inventar un valor cuando no lo tenga, en vez de omitirlo correctamente.

Usa modo estricto cuando la validación exacta importa

Para herramientas donde un parámetro mal formado tiene consecuencias reales (una transacción, un cambio de configuración), el modo estricto garantiza que el `input` del modelo valide exactamente contra tu schema — sin campos extra, sin tipos incorrectos.

{ "name": "ejecutar_pago", "description": "Ejecuta un pago a un proveedor registrado.", "strict": True, "input_schema": { "type": "object", "properties": { "proveedor_id": {"type": "string"}, "monto_centavos": {"type": "integer"}, "moneda": {"type": "string", "enum": ["GTQ", "USD"]}, }, "required": ["proveedor_id", "monto_centavos", "moneda"], "additionalProperties": False, }, }

El modo estricto (`strict: true` en la definición de la herramienta, no en `tool_choice`) exige `additionalProperties: false` y una lista `required` explícita, pero a cambio te garantiza que nunca vas a recibir un input malformado que tu código de ejecución tenga que validar de nuevo defensivamente.

No satures el set de herramientas

Un set de 30+ herramientas disponibles en cada llamada degrada la precisión de selección — el modelo tiene que discriminar entre demasiadas opciones similares, y la probabilidad de elegir la herramienta equivocada (o ninguna, cuando debería usar una) sube. Si tu agente necesita un catálogo grande de herramientas, la solución no es meterlas todas siempre — es usar un mecanismo de descubrimiento dinámico que solo cargue las definiciones relevantes al contexto actual de la tarea, mientras el resto queda diferido hasta que realmente se necesiten.

Como regla práctica: si un agente tiene más de 15-20 herramientas activas simultáneamente y ves errores de selección, la primera intervención no es reescribir las descripciones — es reducir cuántas están disponibles a la vez.

Maneja errores de herramienta como parte del contrato, no como excepción

Cuando la ejecución de una herramienta falla (API caída, timeout, validación fallida en tu backend), el resultado debe volver al modelo marcado explícitamente como error, no como si fuera un resultado exitoso con contenido raro. Esto le permite al modelo decidir razonadamente si reintentar, informar al usuario, o intentar un camino alterno — en vez de interpretar un mensaje de error como dato válido.

tool_result = { "type": "tool_result", "tool_use_id": tool_use_id, "content": "Error: el proveedor con ID 'PROV-9981' no existe en el sistema.", "is_error": True, }

Un patrón que rompe agentes con frecuencia: devolver el error como texto plano sin `is_error: true`. El modelo entonces trata el mensaje de error como si fuera el resultado legítimo de la operación, y puede reportarle al usuario que la acción se completó cuando en realidad falló.

Múltiples llamadas paralelas: junta todos los resultados en un solo turno

Cuando el modelo pide varias herramientas en una sola respuesta (comportamiento por defecto en la mayoría de los modelos actuales), ejecuta todas y regresa todos los `tool_result` juntos en un único mensaje — no los separes en múltiples mensajes de usuario. Separarlos entrena implícitamente al modelo a dejar de pedir llamadas paralelas, lo cual reintroduce la latencia secuencial que el paralelismo estaba evitando.

# Correcto: todos los tool_results en un solo mensaje de usuario tool_results = [ {"type": "tool_result", "tool_use_id": tu.id, "content": ejecutar(tu.name, tu.input)} for tu in tool_use_blocks ] messages.append({"role": "user", "content": tool_results})

Da ejemplos de uso correcto directamente en la definición cuando el schema es complejo

Para herramientas con parámetros anidados o formatos no obvios (fechas en un formato específico, estructuras de filtro complejas), un ejemplo de invocación correcta dentro de la descripción reduce errores de formato más que cualquier cantidad de detalle en el schema JSON puro.

{ "name": "filtrar_transacciones", "description": ( "Filtra transacciones por rango de fecha y categoría. " "Ejemplo de uso correcto: para 'transacciones de marzo en " "la categoría viáticos', el input sería " '{"fecha_inicio": "2026-03-01", "fecha_fin": "2026-03-31", ' '"categoria": "viaticos"}. Las fechas siempre en formato ' "ISO 8601 (YYYY-MM-DD)." ), ... }

Diseñar bien el set de herramientas no es un detalle secundario del sistema de agentes — es, junto con el context engineering, la parte de la arquitectura que más determina si el agente es confiable en producción o si termina generando llamadas erráticas que hay que parchear caso por caso.

Carlos Montiel
Arquitecto de Soluciones IA Empresarial
Especialista en LLMs, Agentes y Orquestación
guatemalia.com/#contacto · info@guatemalia.com

¿Necesitas implementar IA en tu empresa?

Carlos Montiel es arquitecto de soluciones IA empresarial. Implementa LLMs, Agentes, RAG y orquestadores en empresas de Guatemala y Latinoamérica. Contáctalo para una consultoría.

Contactar a Carlos Montiel

info@guatemalia.com