Los agentes de IA pueden alucinar el éxito de una operación incluso cuando violan reglas de negocio. Confirman reservas sin verificación de pago, aceptan parámetros inválidos como 15 huéspedes cuando el máximo es 10, o ignoran prerrequisitos obligatorios.
El problema central: los agentes pueden confirmar reservas de hotel a pesar de que el pago nunca fue verificado, violar restricciones de capacidad, o saltarse pasos de validación obligatorios. El prompt engineering por sí solo no puede prevenir estos errores.
Este post demuestra cómo la validación neurosimbólica — combinando razonamiento del LLM con reglas simbólicas deterministas aplicadas a nivel de framework — bloquea operaciones inválidas antes de que se ejecuten.
Esta demo utiliza Strands Agents. Patrones similares pueden aplicarse en LangGraph, AutoGen u otros frameworks de agentes.
Resumen de la Serie
Esta es la Parte 3 de una serie sobre cómo detener las hallucinations en agentes de IA:
- RAG vs Graph-RAG — Knowledge graphs para prevenir hallucinations
- Semantic Tool Selection — Filtrado de tools basado en vectores
- AI Agent Guardrails (este post) — Reglas simbólicas que los LLM no pueden evadir
- Runtime Guardrails — Redirigir en lugar de bloquear
- Multi-Agent Validation — Detección de hallucinations basada en equipos
El Problema: Los Prompts Son Sugerencias, No Restricciones
La investigación de ATA: Autonomous Trustworthy Agents (2024) identifica tres patrones de hallucination:
-
Errores de parámetros: El agent llama a
book_hotel(guests=15)a pesar de que el docstring indica un máximo de 10 - Errores de completitud: El agent ejecuta reservas sin la verificación de pago requerida
- Comportamiento de evasión de tools: El agent confirma éxito sin llamar a los tools de validación obligatorios
Causa raíz: Los prompts son texto que el LLM interpreta. Las reglas de negocio embebidas en docstrings se convierten en sugerencias — el modelo decide si las sigue en cada llamada.
La Solución: Validación Neurosimbólica con Strands Hooks
Los hooks a nivel de framework interceptan las llamadas a tools antes de la ejecución. Usando BeforeToolCallEvent en Strands Agents, puedes:
- Validar reglas simbólicas de forma determinista
- Cancelar la ejecución del tool si alguna regla falla
- Enviar un mensaje de cancelación directamente al LLM (no puede ser anulado)
Diferencia arquitectónica clave:
- Prompts: Entrada del LLM (interpretable, anulable)
- Hooks: Interceptores del framework (deterministas, obligatorios)
Prerrequisitos
- Experiencia con Python y uso de tools en agentes LLM
- Familiaridad con Strands Agents
git clone https://github.com/aws-samples/sample-why-agents-fail
cd stop-ai-agent-hallucinations/04-neurosymbolic-demo
uv venv && uv pip install -r requirements.txt
Implementación: Reglas, Hook y Dos Agentes
Paso 1: Definir Reglas Simbólicas
from dataclasses import dataclass
from typing import Callable
@dataclass
class Rule:
name: str
condition: Callable[[dict], bool]
message: str
BOOKING_RULES = [
Rule("max_guests", lambda ctx: ctx.get("guests", 1) <= 10, "Maximum 10 guests per booking"),
Rule("valid_dates", lambda ctx: ctx["check_in"] < ctx["check_out"], "Check-in must be before check-out"),
]
CONFIRMATION_RULES = [
Rule("payment_before_confirm", lambda ctx: ctx.get("payment_verified", False),
"Payment must be verified before confirmation"),
]
Las reglas son funciones Python simples — deterministas, testeables y auditables de forma independiente a cualquier agent.
Paso 2: Crear el Hook de Validación
from strands.hooks import HookProvider, HookRegistry, BeforeToolCallEvent
class NeurosymbolicHook(HookProvider):
def register_hooks(self, registry: HookRegistry) -> None:
registry.add_callback(BeforeToolCallEvent, self.validate)
def validate(self, event: BeforeToolCallEvent) -> None:
tool_name = event.tool_use["name"]
if tool_name not in self.rules:
return
context = self._build_context(tool_name, event.tool_use["input"])
passed, violations = validate(self.rules[tool_name], context)
if not passed:
event.cancel_tool = f"BLOCKED: {', '.join(violations)}"
Cuando se establece event.cancel_tool, Strands reemplaza el resultado del tool con ese mensaje antes de que el LLM lo vea. El tool nunca se ejecuta.
Paso 3: Definir Tools Limpios
from strands import tool
@tool
def book_hotel(hotel: str, check_in: str, check_out: str, guests: int = 1) -> str:
"""Book a hotel room."""
return f"SUCCESS: Booked {hotel} for {guests} guests, {check_in} to {check_out}"
@tool
def process_payment(amount: float, booking_id: str) -> str:
"""Process payment for a booking."""
return f"SUCCESS: Processed ${amount:.2f} for {booking_id}"
@tool
def confirm_booking(booking_id: str) -> str:
"""Confirm a booking."""
return f"SUCCESS: Confirmed {booking_id}"
Los tools contienen solo lógica de negocio — sin validación mezclada.
Paso 4: Crear Ambos Agentes
from strands import Agent
# Using OpenAI-compatible interface via Strands SDK (not direct OpenAI usage)
from strands.models.openai import OpenAIModel
MODEL = OpenAIModel(model_id="gpt-4o-mini")
# Baseline: no hook, no validation
baseline_agent = Agent(tools=[book_hotel, process_payment, confirm_booking], model=MODEL)
# Guarded: hook intercepts every tool call
hook = NeurosymbolicHook(STATE)
guarded_agent = Agent(tools=[book_hotel, process_payment, confirm_booking], hooks=[hook], model=MODEL)
Mismos tools, mismo modelo, mismos prompts. La única diferencia: hooks=[hook]
Resultados de las Pruebas
Prueba 1: Confirmar Reserva Sin Pago
Consulta: "Confirm booking BK001"
| Agent | Resultado |
|---|---|
| Baseline | ❌ Ejecuta — pago nunca verificado, docstring ignorado |
| Guarded | ✅ Bloqueado — el hook evalúa CONFIRMATION_RULES, encuentra payment_verified=False, cancela |
El LLM recibe: BLOCKED: Payment must be verified before confirmation
Prueba 2: Reservar Hotel Excediendo el Límite de Huéspedes
Consulta: "Book Grand Hotel for 15 people from 2026-03-20 to 2026-03-25"
| Agent | Resultado |
|---|---|
| Baseline | ❌ Ejecuta con 15 huéspedes — máximo en docstring ignorado |
| Guarded | ✅ Bloqueado — max_guests_check(15 <= 10) falla, ejecución cancelada |
La validación ocurre antes de la ejecución — no hay reserva que revertir.
Prueba 3: Reserva Válida
Consulta: "Book Grand Hotel for 5 guests from 2026-03-20 to 2026-03-25"
| Agent | Resultado |
|---|---|
| Baseline | ✅ Ejecuta |
| Guarded | ✅ Ejecuta — todas las reglas pasan, el hook no agrega fricción |
Resumen de Escenarios
| Escenario | Baseline | Guarded |
|---|---|---|
| Confirmar sin pago | ❌ Ejecuta — hallucination | ✅ Bloqueado antes de la ejecución |
| Reservar 15 huéspedes (máx. 10) | ❌ Ejecuta — regla violada | ✅ Bloqueado antes de la ejecución |
| Reserva válida (5 huéspedes) | ✅ Ejecuta | ✅ Ejecuta |
Punto Clave: Dónde Se Aplica la Validación
Prompt Engineering (Insuficiente)
system_prompt = """
IMPORTANT: Never confirm bookings without payment verification.
CRITICAL: Maximum 10 guests per booking.
"""
# The LLM reads this as context. It can hallucinate compliance.
❌ El LLM decide si sigue estas instrucciones en cada llamada.
Aplicación Basada en Hooks (Suficiente)
def validate(self, event: BeforeToolCallEvent) -> None:
passed, violations = validate(self.rules[tool_name], context)
if not passed:
event.cancel_tool = f"BLOCKED: {', '.join(violations)}"
# Tool never executes. LLM receives the cancellation.
# There is no path to override this.
✅ El hook se ejecuta fuera del LLM. La decisión no depende del LLM.
Diferencia arquitectónica: Los prompts son entrada del LLM (interpretable). Los hooks son interceptores del framework (deterministas).
Consideraciones para Producción
Ventajas
- Restricciones verificables: Las reglas son código, no instrucciones
- Centralizadas: Un solo hook valida todos los tools
- Testeables de forma independiente: Las reglas funcionan fuera de cualquier agent o contexto de LLM
- Auditables: Las violaciones de reglas producen eventos explícitos con nombre del tool, parámetros y razón
Desafíos
- Las reglas deben definirse explícitamente para cada operación protegida
- No maneja lógica difusa o probabilística — las reglas son booleanas
- Los casos límite requieren manejo explícito en las condiciones
- Las reglas necesitan mantenimiento a medida que evoluciona la lógica de negocio
Mejores Prácticas
- Define hooks para operaciones críticas: reservas, pagos, cancelaciones
- Registra todas las violaciones de reglas con nombre del tool, parámetros y razón
- Testea las reglas de forma independiente y exhaustiva
- Combina con semantic tool selection (Parte 2) y multi-agent validation (Parte 5) para protección en capas
Siguiente Paso
Los guardrails simbólicos bloquean violaciones de reglas a nivel de tool. Pero bloquear detiene el flujo de trabajo — el usuario debe intervenir.
Parte 4: Runtime Guardrails muestra cómo Agent Control redirige a los agentes para que se autocorrijan en lugar de bloquearlos, completando flujos de trabajo sin intervención humana.
Conclusiones Clave
- Los prompts son sugerencias: El LLM interpreta docstrings; puede alucinar cumplimiento con cualquier instrucción
-
Los hooks son aplicación forzada:
BeforeToolCallEventintercepta antes de la ejecución a nivel de framework — el LLM no puede anular un tool cancelado - Todas las operaciones inválidas bloqueadas: Cero cambios en tools, cero cambios en prompts, un hook agregado
- Separación limpia: Los tools manejan operaciones; los hooks manejan la aplicación de restricciones
- Auditable por diseño: Las violaciones de reglas son condiciones Python explícitas — testeables, registrables, trazables
-
Un hook, todos los tools: Un solo
NeurosymbolicHookvalida cada llamada a tool de forma centralizada
Ejecútalo Tú Mismo
git clone https://github.com/aws-samples/sample-why-agents-fail
cd stop-ai-agent-hallucinations/04-neurosymbolic-demo
uv venv && uv pip install -r requirements.txt
uv run test_neurosymbolic_hooks.py
Puedes cambiar a cualquier proveedor soportado por Strands — consulta Strands Model Providers para la configuración.
Referencias
Investigación
- ATA: Autonomous Trustworthy Agents (2024)
- Enhancing LLMs through Neuro-Symbolic Integration
- Mitigating LLM Hallucinations: Meta-Analysis
Strands Agents
Código
Gracias!
🇻🇪🇨🇱 Dev.to Linkedin GitHub Twitter Instagram Youtube
Linktr
Top comments (0)