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:
- RAG vs Graph-RAG — Los grafos de conocimiento previenen agregaciones alucinadas
- Semantic Tool Selection — El filtrado vectorial reduce las elecciones incorrectas de herramientas
- AI Agent Guardrails — Reglas simbólicas que el LLM no puede eludir
- 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"
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:
- Las reglas residen en un servidor — se modifican vía API o dashboard sin tocar el código del agent
-
Los steer controls devuelven
Guide()en lugar de bloquear — el agent reintenta con instrucciones correctivas
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:
- El LLM genera: "I will book Grand Hotel for 15 guests from May 1 to May 3"
- Agent Control evalúa la salida del LLM → el regex coincide con "15 guest"
- El steer control se activa → devuelve
Guide("reduce to 10, inform the user") - El LLM reintenta con la guía → llama a
book_hotel(guests=10) - La reserva se completa → se informa al usuario sobre el ajuste
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}"
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")
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
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."
}
}
}
}
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")
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
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(...)])
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
Puedes cambiar a cualquier proveedor compatible con Strands — consulta Strands Model Providers para la configuración.
Referencias
Investigación
- ATA: Autonomous Trustworthy Agents (2024) — Patrones de fallo en guardrails
- Enhancing LLMs through Neuro-Symbolic Integration — Razonamiento neural + simbólico
Strands Agents
- Strands Agents with Agent Control — Anuncio en blog
- Agent Control Plugin — Documentación de integración
-
Strands Hooks —
BeforeToolCallEvent,cancel_tool -
Strands Steering —
Guide,Proceed,SteeringHandler - Strands Model Providers — Cambiar a Amazon Bedrock, Anthropic, Ollama
Agent Control
- Agent Control GitHub — Código abierto, Apache 2.0
- Agent Control Docs — Configuración del servidor y referencia de API


Top comments (0)