La mayoría de los fracasos en implementaciones comerciales con agentes de IA se originan en un error conceptual: asumir que los Modelos de Lenguaje (LLMs) son cerebros autónomos capaces de tomar decisiones críticas mediante prosa conversacional.
Cuando le confías a un LLM la toma de decisiones empresariales mediante instrucciones en lenguaje natural, el resultado es predecible: alucinaciones, olvido de restricciones bajo saturación de contexto y discrepancias sutiles en los datos que terminan corrompiendo tus APIs.
En software de producción, los LLMs deben tratarse como enrutadores semánticos probabilistas. Su función se limita a interpretar la intención del usuario y mapearla hacia argumentos fuertemente tipados; la ejecución y la persistencia deben gobernarse por código 100% determinista.
Te comparto la arquitectura de producción que utilizo para erradicar alucinaciones en agentes de IA.
1. El Principio Fundamental: El LLM como Enrutador Semántico
Entrada del Usuario / Webhook
│
▼
┌────────────────────────┐
│ LLM (Router Semántico)│ ──> Emite llamada a herramienta + argumentos tipados
└────────────────────────┘
│
▼ (Interceptado ANTES de ejecutar)
┌────────────────────────┐
│ Validador Zod/Schema │ ──> Rechaza tipos incorrectos antes de tocar backend
└────────────────────────┘
│
▼ (Si es válido)
┌────────────────────────┐
│ Motor Determinista │ ──> Ejecuta APIs transaccionales con rollbacks
└────────────────────────┘
El modelo nunca escribe directamente en tu base de datos ni despacha peticiones HTTP externas por su cuenta. Solo puede seleccionar una función predefinida y rellenar un esquema JSON estructurado.
2. Definición Estricta de Esquemas con Zod y JSON Schema
Cada herramienta expuesta al modelo debe declarar un esquema de entrada cerrado y tipado:
import { z } from 'zod';
export const ProcessInvoiceToolSchema = z.object({
invoiceNumber: z.string().regex(/^INV-\d{4}-\d{5}$/, 'Formato de factura inválido'),
vendorTaxId: z.string().min(8).max(15),
totalAmountCents: z.number().int().positive(),
currency: z.enum(['USD', 'EUR', 'PEN']),
lineItems: z.array(
z.object({
description: z.string().min(3),
unitPriceCents: z.number().int().positive(),
quantity: z.number().int().positive(),
})
).nonempty(),
action: z.enum(['APPROVE', 'FLAG_FOR_AUDIT', 'REJECT']),
});
export type ProcessInvoiceInput = z.infer<typeof ProcessInvoiceToolSchema>;
Este esquema se transforma en la definición formal consumida por motores como Gemini 3.7 Flash o Claude:
export const ProcessInvoiceToolDefinition = {
name: 'process_invoice',
description: 'Valida y concilia una factura de proveedor frente a órdenes de compra del ERP.',
parameters: zodToJsonSchema(ProcessInvoiceToolSchema),
};
3. Intercepción en Tiempo de Ejecución y Autocorrección
Si el modelo entrega un payload incompleto o viola una restricción de validación, no interrumpas el flujo abruptamente. Intercepta el fallo en la frontera de ejecución y reenvía el detalle exacto al modelo para una corrección en un único turno adicional:
export async function executeToolWithGuardrails(
toolName: string,
rawArgs: unknown,
executor: (args: ProcessInvoiceInput) => Promise<ToolResult>
): Promise<ToolResult> {
const parseResult = ProcessInvoiceToolSchema.safeParse(rawArgs);
if (!parseResult.success) {
const errorDetails = parseResult.error.issues
.map(i => `${i.path.join('.')}: ${i.message}`)
.join('; ');
return {
status: 'VALIDATION_FAILED',
errorMessage: `Validación rechazada: ${errorDetails}. Reextrae los datos cumpliendo estrictamente los tipos requeridos.`,
};
}
try {
return await executor(parseResult.data);
} catch (error) {
return {
status: 'EXECUTION_ERROR',
errorMessage: error instanceof Error ? error.message : 'Fallo de ejecución desconocido',
};
}
}
4. Idempotencia y Transacciones Compensatorias
En flujos automatizados con agentes, las caídas de red o reintentos automáticos son habituales. Cada herramienta ejecutada debe ser estrictamente idempotente:
- Claves de Idempotencia: Genera un hash SHA-256 a partir del ID de sesión, el nombre de la herramienta y los datos parseados:
const idempotencyKey = crypto .createHash('sha256') .update(`${sessionId}:${toolName}:${JSON.stringify(parseResult.data)}`) .digest('hex'); - Two-Phase Commit: Registra una entrada de auditoría con estado
PENDINGantes de contactar sistemas externos (Stripe, ERP, pasarelas de correo). - Acciones de Compensación: Si una llamada posterior falla, ejecuta de forma atómica la reversión correspondiente (anular el borrador creado o cancelar la reserva).
5. Caso de Producción: Motor Autónomo de Agentes de IA
Implementé esta arquitectura en el Motor Autónomo de Agentes de IA, orquestando flujos empresariales integrados con ERPs, webhooks y túneles de Cloudflare:
- 99.8% de precisión en esquemas: El parseo estricto con Zod eliminó escrituras corruptas en bases de datos.
- Cero incidentes por alucinaciones: Dado que las operaciones externas son deterministas y tipadas, el modelo no tiene capacidad de inventar registros ni alterar saldos.
- Reducción del 80% en tiempos de gestión: Las conciliaciones de documentos y altas en el sistema se ejecutan en menos de 3 segundos sin intervención manual.
Conclusión Pragmática
No le pidas a un LLM que opere tu lógica de negocio; utilízalo para estructurar información en esquemas estrictos y deja que el software determinista se encargue del resto.