Guardrails para Agentes de IA: Reglas Que los LLM No Pueden Evadir
<blockquote> <p>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.</p> </blockquote> <p>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. <strong>El prompt engineering por sí solo no puede prevenir estos errores.</strong></p> <p>Este post demuestra cómo la <strong>validación neurosimbólica</strong> — combinando razonamiento del LLM con reglas simbólicas deterministas aplicadas a nivel de framework — bloquea operaciones inválidas antes de que se eje
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.txtgit 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.txtEnter fullscreen mode
Exit fullscreen mode
Implementación: Reglas, Hook y Dos Agentes
Paso 1: Definir Reglas Simbólicas
from dataclasses import dataclass from typing import Callablefrom 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"), ]`
Enter fullscreen mode
Exit fullscreen mode
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)}"`
Enter fullscreen mode
Exit fullscreen mode
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}"`
Enter fullscreen mode
Exit fullscreen mode
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)`
Enter fullscreen mode
Exit fullscreen mode
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. """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.`
Enter fullscreen mode
Exit fullscreen mode
❌ 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)}"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.`
Enter fullscreen mode
Exit fullscreen mode
✅ 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: BeforeToolCallEvent intercepta 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 NeurosymbolicHook valida 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.pygit 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.pyEnter fullscreen mode
Exit fullscreen mode
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
-
Strands Hooks Documentation
-
Strands Model Providers
Código
- Repositorio de Código
Gracias!
🇻🇪🇨🇱 Dev.to Linkedin GitHub Twitter Instagram Youtube Linktr
Dev.to AI
https://dev.to/aws-espanol/guardrails-para-agentes-de-ia-reglas-que-los-llm-no-pueden-evadir-5dmnSign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
llamamodelopen-source
Seedance 2.0 API: A Technical Guide to AI Video Generation with Pricing and Integration Examples
This post covers the Seedance 2.0 API — a unified AI video generation interface from EvoLink.ai that exposes text-to-video, image-to-video, and reference-to-video capabilities through a single consistent API. The focus here is on technical integration patterns, model selection logic, and cost modeling — the parts that matter when you’re building a real system around this. API Design: Unified Async Task Model The central design of Seedance 2.0 is a unified async task pattern across all generation modes. Rather than separate endpoints with different request and response schemas, every generation request follows the same lifecycle: POST /v1/videos/generations — submit task, receive ID immediately GET /v1/tasks/{id} — poll for status and progress Download video from result URL once status == "
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Products

Seedance 2.0 API: A Technical Guide to AI Video Generation with Pricing and Integration Examples
This post covers the Seedance 2.0 API — a unified AI video generation interface from EvoLink.ai that exposes text-to-video, image-to-video, and reference-to-video capabilities through a single consistent API. The focus here is on technical integration patterns, model selection logic, and cost modeling — the parts that matter when you’re building a real system around this. API Design: Unified Async Task Model The central design of Seedance 2.0 is a unified async task pattern across all generation modes. Rather than separate endpoints with different request and response schemas, every generation request follows the same lifecycle: POST /v1/videos/generations — submit task, receive ID immediately GET /v1/tasks/{id} — poll for status and progress Download video from result URL once status == "

Tied Designing a 8 bytes PDAP BINARY based on JSON 404 and TOON 171, T-TOON 130 and A TOKENIZED T-TOON 112 not sure if it works in Real World Applications?
TOTAL: 8 bytes, zero parsing overhead ``` **What we eliminated:** Field names (`“disk”`, `“byte”`, `“value”`) Length prefixes Token tables / dictionaries Schema metadata Repetition & redundancy **What we kept:** Fixed positional meaning (byte 0 = disk0, byte 1 = disk1, etc.) Pre-agreed protocol between sender/receiver Direct memory mapping → CPU can load in 1–2 instructions -– ## Working Code: PDAP Binary Encoder/Decoder (JavaScript) ```javascript // PDAP Binary: 8-byte ultra-compact format class PDAPBinary { // Encode: 32-bit value + 4 disk bytes → 8-byte Buffer static encode(value32, diskBytes) { if (diskBytes.length !== 4) throw new Error(‘Exactly 4 disk bytes required’); const buffer = Buffer.alloc(8); // Bytes 0-3: 32-bit value (big-endian) buffer.writeUInt32BE(value32 >>> 0, 0); // B



Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!