DEV Community

Cover image for Guardrails para Agentes de IA que se Autocorrigen en Lugar de Bloquear
Elizabeth Fuentes L for AWS Español

Posted on

Guardrails para Agentes de IA que se Autocorrigen en Lugar de Bloquear

La mayoría de los guardrails para agentes hacen una sola cosa: bloquear. El agent choca con una regla, el flujo se detiene y el usuario tiene que intervenir. Agent Control añade una segunda opción: steer — el agent recibe instrucciones correctivas, se autocorrige y completa la tarea sin intervención humana.

Los guardrails para agentes hoy son binarios: permitir o denegar. Cuando un agent viola una política, la respuesta típica es bloquear la acción y mostrar un error. Esto funciona para restricciones estrictas (cumplimiento PCI, bloqueos regulatorios), pero genera fricción en reglas donde el agent podría resolver el problema por sí mismo: ajustar un parámetro, redactar datos sensibles o reformatear una salida.

Agent Control es un plano de control en tiempo de ejecución de código abierto que introduce steer controls junto con los bloqueos tradicionales. Los steer controls devuelven instrucciones correctivas mediante Guide() — el agent reintenta con la corrección aplicada y completa la tarea. Las reglas residen en un servidor, no en el código — se actualizan vía API o dashboard sin necesidad de redesplegar el agent.

Este artículo muestra cómo funciona Agent Control usando una demo de reservas construida con Strands Agents. Comparamos dos enfoques sobre el mismo escenario: hooks que bloquean vs Agent Control que corrige. Hooks y Agent Control son complementarios — usa hooks para bloqueos estrictos, steer para correcciones.


Resumen de la Serie

Este es un artículo adicional en la serie sobre cómo detener las alucinaciones de agentes de IA — añadido tras el lanzamiento de Agent Control:

  1. RAG vs Graph-RAG — Los grafos de conocimiento previenen agregaciones alucinadas
  2. Semantic Tool Selection — El filtrado vectorial reduce las elecciones incorrectas de herramientas
  3. AI Agent Guardrails — Reglas simbólicas que el LLM no puede eludir
  4. Bonus: Agent Control (este artículo) — Steer en lugar de block

El Problema: Bloquear Detiene el Flujo

Los Strands Hooks aplican reglas a nivel de tool. Cuando el agent llama a book_hotel(guests=15) y el máximo es 10, el hook establece cancel_tool y el agent recibe un mensaje de bloqueo:

class MaxGuestsHook(HookProvider):
    def check(self, event: BeforeToolCallEvent) -> None:
        guests = event.tool_use["input"].get("guests", 1)
        if guests > 10:
            event.cancel_tool = f"BLOCKED: {guests} guests exceeds maximum of 10"
Enter fullscreen mode Exit fullscreen mode

El agent entonces le dice al usuario:

"El Grand Hotel tiene una capacidad máxima de 10 huéspedes. ¿Le gustaría ajustar el número de huéspedes?"

El flujo se detiene. El usuario debe responder. Para un asistente de reservas que maneja cientos de solicitudes, cada operación bloqueada es un punto de fricción.


La Solución: Steer en Lugar de Block

Agent Control es un plano de control en tiempo de ejecución de código abierto que evalúa las entradas y salidas del agent contra políticas gestionadas en el servidor. Se integra con Strands como un Plugin — el mismo punto de extensión que los Hooks, pero con dos diferencias clave:

  1. Las reglas residen en un servidor — se modifican vía API o dashboard sin tocar el código del agent
  2. Los steer controls devuelven Guide() en lugar de bloquear — el agent reintenta con instrucciones correctivas

Hooks (Block) vs Agent Control (Self-Correct) comparison

Cómo Funciona Steer

Cuando el LLM genera una salida que menciona "15 guests", el AgentControlSteeringHandler la evalúa contra los controls definidos en el servidor:

  1. El LLM genera: "I will book Grand Hotel for 15 guests from May 1 to May 3"
  2. Agent Control evalúa la salida del LLM → el regex coincide con "15 guest"
  3. El steer control se activa → devuelve Guide("reduce to 10, inform the user")
  4. El LLM reintenta con la guía → llama a book_hotel(guests=10)
  5. La reserva se completa → se informa al usuario sobre el ajuste

Agent Control steer flow: User Request → LLM → Agent Control server evaluates → Self-Correct → Final Response

El agent responde:

"La capacidad máxima del Grand Hotel es de 10 huéspedes, así que he ajustado la reserva en consecuencia. ID de reserva: BK002."

Sin intervención del usuario. Sin reintentos manuales. El flujo se completó.


Implementación: Misma Consulta, Dos Enfoques

Las tools son idénticas — funciones de reserva limpias sin lógica de validación:

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: Booking {booking_id}{hotel}, {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

Las tools NO aplican la regla de máximo de huéspedes. Eso es responsabilidad de la capa de guardrails.

Test 1 — Hooks (Block)

from strands import Agent
from strands.hooks import HookProvider, HookRegistry, BeforeToolCallEvent

class MaxGuestsHook(HookProvider):
    def __init__(self):
        self.blocked = 0
    def register_hooks(self, registry: HookRegistry) -> None:
        registry.add_callback(BeforeToolCallEvent, self.check)
    def check(self, event: BeforeToolCallEvent) -> None:
        if event.tool_use["name"] != "book_hotel":
            return
        guests = event.tool_use["input"].get("guests", 1)
        if guests > 10:
            self.blocked += 1
            event.cancel_tool = f"BLOCKED: {guests} guests exceeds maximum of 10"

agent = Agent(model=MODEL, tools=[book_hotel, process_payment, confirm_booking],
              hooks=[MaxGuestsHook()])
agent("Book Grand Hotel for 15 guests from 2026-05-01 to 2026-05-03")
Enter fullscreen mode Exit fullscreen mode

Resultado:

Hook blocked: 1 call(s)
Agent: "The Grand Hotel has a maximum capacity of 10 guests.
        Would you like to adjust?"
Outcome: BLOCKED — user must intervene
Enter fullscreen mode Exit fullscreen mode

Test 2 — Agent Control (Steer)

Los controls se definen en el servidor de Agent Control — no en el código:

# setup_controls.py — run once
control = {
    "name": "steer-max-guests",
    "definition": {
        "scope": {"step_types": ["llm"], "stages": ["post"]},
        "selector": {"path": "output"},
        "evaluator": {"name": "regex", "config": {"pattern": r"(1[1-9]|[2-9]\d)\s*guest"}},
        "action": {
            "decision": "steer",
            "message": "Guest count exceeds maximum of 10",
            "steering_context": {
                "message": "Reduce the guest count to 10, retry the booking, "
                           "and inform the user that the maximum capacity is 10."
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

El agent usa AgentControlPlugin + AgentControlSteeringHandler — ambos como Plugins de Strands:

from agent_control.integrations.strands import AgentControlPlugin, AgentControlSteeringHandler
import agent_control

agent_control.init(agent_name="booking-guardrails-demo")

plugin = AgentControlPlugin(agent_name="booking-guardrails-demo",
                            event_control_list=[BeforeToolCallEvent, AfterToolCallEvent])
steering = AgentControlSteeringHandler(agent_name="booking-guardrails-demo")

agent = Agent(model=MODEL, tools=[book_hotel, process_payment, confirm_booking],
              plugins=[plugin, steering])
agent("Book Grand Hotel for 15 guests from 2026-05-01 to 2026-05-03")
Enter fullscreen mode Exit fullscreen mode

Resultado:

Steered: 1 time(s)
Agent: "The maximum capacity for the Grand Hotel is 10 guests,
        so I have adjusted the booking accordingly. Booking ID: BK002."
Outcome: SELF-CORRECTED — booking completed
Enter fullscreen mode Exit fullscreen mode

Resultados

Misma consulta. Mismas tools. Mismo modelo. Solo cambia el guardrail.

Enfoque Tiempo Resultado
Test 1 — Hooks (cancel_tool) ~4s BLOCKED — el agent pide al usuario que ajuste
Test 2 — Agent Control (steer) ~6s Autocorregido — reserva completada con 10 huéspedes

Ambos aplican la misma regla. La diferencia es lo que ocurre cuando la regla se viola — no qué enfoque es "mejor". Los hooks son más rápidos y sencillos (Python puro, sin servidor). Agent Control añade latencia (steer → reintento) pero completa el flujo sin intervención del usuario. Elige según la regla, no según la tecnología.


Cuándo Usar Cada Enfoque

Enfoque Mejor para
Hooks (block) Reglas que DEBEN bloquear estrictamente — sin alternativa posible (p. ej., pago antes de confirmación, cumplimiento PCI)
Agent Control (steer) Reglas donde el agent PUEDE autocorregirse — ajustar parámetros, redactar PII, corregir formato
Agent Control (deny) Igual que hooks pero gestionado en un servidor — cambiar reglas sin redesplegar código

Son complementarios, no competidores. Los hooks son más sencillos (Python puro, sin servidor, sin sobrecarga de latencia). Agent Control es más flexible (gestionado en servidor, steer + deny, actualizaciones en tiempo de ejecución sin redespliegue). Muchos sistemas en producción usan ambos:

  • Hooks para reglas de cumplimiento que nunca deben eludirse — verificación de pagos, bloqueos regulatorios, PII en parámetros de tools
  • Agent Control (deny) para los mismos bloqueos estrictos pero gestionados centralmente en múltiples agents — actualización vía dashboard, sin redespliegue
  • Agent Control (steer) para reglas flexibles donde la autocorrección es preferible — ajustes de capacidad, redacción de PII en salidas, formato de fechas

Dos Formas de Definir Controls

Modo Mejor para
Server (esta demo) Equipos, producción, gestión vía dashboard — los controls residen en el servidor de Agent Control
Local YAML Prototipado rápido — controls definidos en controls.yaml, sin necesidad de servidor

Consulta la documentación de Agent Control para más detalles sobre ambos modos.


Por Qué Strands lo Hace Sencillo

Tanto Hooks como Agent Control se integran con un solo cambio de línea:

# Hooks — block violations (existing Strands API):
agent = Agent(tools=[...], hooks=[MaxGuestsHook()])

# Agent Control — steer violations (plugin API):
agent = Agent(tools=[...], plugins=[AgentControlPlugin(...), AgentControlSteeringHandler(...)])
Enter fullscreen mode Exit fullscreen mode

Sin orquestación personalizada. Sin lógica de reintentos. Strands gestiona el ciclo de vida — los hooks interceptan antes de las llamadas a tools, el steering evalúa después de la salida del modelo, y Guide() activa el reintento automático con instrucciones correctivas.

Strands Hooks Documentation
Strands Steering Documentation
Agent Control Plugin for Strands


Puntos Clave

  • Los hooks bloquean violaciones — efectivo pero detiene el flujo y requiere intervención del usuario
  • Agent Control redirige las violaciones — el agent se autocorrige y completa la tarea
  • Los steer controls devuelven Guide() con instrucciones correctivas — el LLM reintenta con la corrección aplicada
  • Los controls residen en un servidor — se actualizan las reglas vía API o dashboard sin tocar el código del agent
  • Ambos enfoques aplican la misma regla (máximo 10 huéspedes) — la diferencia es lo que ocurre cuando la regla se viola
  • Hooks para bloqueos estrictos, Agent Control para autocorrección — usa ambos cuando sea necesario

Ejecútalo Tú Mismo

git clone https://github.com/aws-samples/sample-why-agents-fail
cd stop-ai-agent-hallucinations/05-agent-control-demo

# Start Agent Control server (see setup instructions)
# https://github.com/agentcontrol/agent-control

# Install and run
uv venv && uv pip install -r requirements.txt
uv run setup_controls.py
uv run test_hooks_vs_control.py
Enter fullscreen mode Exit fullscreen mode

Puedes cambiar a cualquier proveedor compatible con Strands — consulta Strands Model Providers para la configuración.


Referencias

Investigación

Strands Agents

Agent Control

Código

Top comments (0)