Un agente LLM puede elegir una herramienta correcta y aun así producir un sistema frágil. El problema suele estar en el contrato: argumentos ambiguos, respuestas sin estado y reintentos que repiten efectos secundarios.
En flujos que tocan cuentas, correo o despliegues, una tool debe parecerse menos a una función cómoda y más a una pequeña API pública. La pregunta no es solo “¿puede el modelo llamarla?”, sino “¿podemos explicar qué ocurrió cuando la llamada fue incompleta, lenta o repetida?”.
El problema: una tool no es una función aislada
Un modelo trabaja con probabilidades. Un backend trabaja con invariantes. Entre ambos hay una frontera que conviene diseñar de forma explicita (sí, explicita): nombres claros, entradas limitadas y resultados que indiquen el estado real.
Piensa en este flujo:
modelo -> contrato JSON -> validador -> servicio -> evento -> respuesta normalizada
Si el modelo pide email: "temp gamil com", el validador debe rechazarlo con una razón útil. Si una integración devuelve un timeout después de crear el recurso, el sistema no debería fingir que falló sin más. Esa diferencia cambia por completo el siguiente paso del agente.
Para escenarios de prueba también conviene separar un mejor correo desechable de una identidad apta para producción. Un agente no debería decidir esa política por inferencia; debe recibir una capacidad explícita, con límites y propósito.
Diseñar el contrato
Un contrato práctico tiene cuatro capas:
-
Entrada tipada. Cada campo tiene formato, longitud máxima y enumeración cuando sea posible.
purposepuede serqa,previewoproduction; no un texto libre de veinte palabras. -
Precondiciones. Declara qué debe existir antes de actuar. Por ejemplo, un
request_idúnico para deduplicar una operación. -
Resultado con estado. Devuelve
accepted,completed,rejectedounknown, junto con un identificador de operación. -
Errores accionables. Incluye
code,retryableynext_action. Un mensaje genérico como “tool error” no ayuda al modelo ni al operador.
La salida podría tener esta forma:
{
"status": "rejected",
"operation_id": "op_123",
"error": {"code": "INVALID_INPUT", "retryable": false},
"next_action": "corregir email"
}
El campo next_action reduce conjeturas. También evita que el agente intente tres variantes de la misma llamada solo porque no entendió el fallo.
Fallos, reintentos y evidencia
Los reintentos deben estar definidos por contrato, no improvisados en el prompt. Una operación de lectura puede repetirce con seguridad; una creación necesita una clave de idempotencia. Si el proveedor externo no permite consultar el estado, registra la llamada como unknown y manda la decisión a una cola de revisión.
En ese punto, la observabilidad es parte de la interfaz. Guarda el request_id, versión del contrato, argumentos saneados, latencia y resultado. No guardes secretos ni el contenido completo de correos si no hace falta. Los runbooks SRE para correos de guardia ayudan a convertir esa evidencia en una respuesta operativa repetible.
Para trabajos lentos, devuelve un job_id y un estado consultable. Una cola visible permite distinguir “todavía procesando” de “falló”; hay más detalle práctico en estas colas visibles para trabajos de email largos. Esta separación agrega una pequeña complejidad, pero evita que el LLM rellene el vacio con una afirmación inventada.
Implementación por checkpoints
Empieza con una sola tool y mide cuatro cosas: porcentaje de argumentos rechazados, reintentos por operación, estados unknown y tiempo hasta resolución. Luego añade checkpoints:
- Antes de ejecutar: valida esquema, permisos y propósito.
-
Durante: emite un evento con el mismo
request_id. - Después: persiste resultado y duración.
- En recuperación: permite consultar el estado sin repetir el efecto.
No hace falta construir un framework de agentes para esto. Un adaptador pequeño alrededor del servicio suele ser suficiente. El diseño más sencillo gana si mantiene las garantías visibles para el modelo y para quien mantiene el sistema.
Checklist final
- ¿Cada tool tiene entradas con límites verificables?
- ¿El modelo recibe estados distintos para rechazo, éxito y timeout?
- ¿Las operaciones con efectos secundarios son idempotentes?
- ¿Un operador puede reconstruir la secuencia con
request_id? - ¿Los errores indican si conviene reintentar?
- ¿Se distingue una dirección de correo desechable de una identidad de producción?
Los contratos de tools no eliminan la incertidumbre de un LLM. La hacen observable y acotada. Ese es el objetivo real: que un agente pueda avanzar cuando todo funciona, y que falle de manera explicable cuando no.
Top comments (0)