El botón de «Aceptar» que nadie lee
Un agente que pide confirmación antes de cada acción parece prudente. En la práctica ocurre otra cosa: a la décima petición, la persona pulsa «Aceptar» sin leer. La aprobación sigue ahí, pero ya no protege nada. Es una fatiga de alertas con otro nombre.
El extremo contrario tampoco funciona. Un agente con permiso para todo acaba ejecutando, tarde o temprano, la acción que nadie quería. La pregunta útil no es si debe haber un humano en el bucle, sino en qué puntos exactos y con qué información delante.
Reversibilidad antes que riesgo percibido
Clasificar las acciones por «lo peligrosas que parecen» da malos resultados, porque es subjetivo. Un criterio más estable es la reversibilidad: ¿se puede deshacer, y a qué coste?
| Tipo de acción | Ejemplo | Política |
|---|---|---|
| Lectura | Consultar un pedido, buscar en el índice | Automática |
| Escritura reversible | Crear un borrador, mover a una carpeta | Automática, con registro |
| Escritura costosa de revertir | Modificar un registro de cliente | Aprobación o ventana de deshacer |
| Irreversible o externa | Enviar un correo, borrar datos, pagar | Aprobación explícita |
La última fila es la que importa. Todo lo que sale de tu sistema (un mensaje, un pago, una publicación) no tiene botón de deshacer. Ahí el humano no es un trámite: es el único control real.
Qué debe ver quien aprueba
Una aprobación solo vale lo que valga la información que la acompaña. «¿Permitir send_email?» no dice nada. Una buena petición contiene tres cosas:
- La acción concreta, con sus argumentos finales: destinatario, asunto y cuerpo, no el nombre de la herramienta.
- El porqué, en una frase: qué intentaba conseguir el agente.
- El efecto: qué cambia y si se puede revertir.
Y un detalle fácil de olvidar: lo que se muestra debe ser exactamente lo que se ejecutará. Si apruebas un texto y el agente lo reescribe después, la aprobación no significa nada. Aprueba el argumento, y ejecuta ese argumento, byte a byte.
Pausar sin perder el estado
El agente no puede quedarse bloqueado en memoria esperando que alguien vuelva de comer. La aprobación puede tardar minutos u horas, así que el flujo debe poder suspenderse y reanudarse. El patrón es guardar el estado, emitir una petición pendiente y retomar cuando llegue la respuesta.
from dataclasses import dataclass
from enum import Enum
class Decision(str, Enum):
PENDING = "pending"
APPROVED = "approved"
REJECTED = "rejected"
@dataclass
class PendingAction:
id: str
tool: str
args: dict # argumentos finales, congelados
reason: str # por qué lo pide el agente
reversible: bool
decision: Decision = Decision.PENDING
def run_step(state, call, tools, store):
spec = tools[call.name]
# Lecturas y escrituras reversibles: sin fricción
if spec.reversible or spec.read_only:
return spec.run(**call.args)
# Acción costosa: se suspende y se guarda la petición
pending = PendingAction(
id=new_id(), tool=call.name, args=call.args,
reason=call.reason, reversible=False,
)
store.save(state, pending) # persistir ANTES de avisar
notify_reviewer(pending)
return Suspended(pending.id)
def resume(pending_id, store, tools):
state, pending = store.load(pending_id)
if pending.decision is not Decision.APPROVED:
return rejected_result(pending) # el agente sabe que se denegó
# Ejecuta los argumentos aprobados, no una versión regenerada
return tools[pending.tool].run(**pending.args)
Dos matices. Persistir antes de notificar evita perder la petición si algo falla entre medias. Y devolver al agente un resultado claro cuando se rechaza le permite replantear el plan en lugar de reintentar lo mismo en bucle. Si la acción puede ejecutarse dos veces por un reintento, conviene combinarlo con idempotencia en las herramientas.
Reducir peticiones sin bajar la guardia
Lo que de verdad evita la fatiga es pedir menos y pedir mejor. Algunas palancas:
- Aprobación por lote: un plan con diez pasos se aprueba una vez, no diez, siempre que los pasos estén acotados.
- Permisos con alcance: «puede enviar correos a
@miempresa.comhoy» en lugar de «puede enviar correos». - Umbrales: pagos por debajo de cierto importe pasan solos; por encima, no.
- Ventana de deshacer: ejecutar con retraso de unos minutos y permitir cancelar, para acciones que se pueden retener.
Cada una afloja una restricción concreta y deja el resto igual. No son atajos: son decisiones de diseño que conviene dejar por escrito.
Cómo saber si tu freno funciona
Mide dos cosas. La primera es la tasa de aprobación: si el 99 % de las peticiones se aprueban, probablemente sobran, o llegan tan mal explicadas que nadie las examina. La segunda es el tiempo de decisión: respuestas en un par de segundos indican clic automático.
Una prueba incómoda pero útil: cada cierto tiempo, introduce una petición deliberadamente defectuosa y comprueba si alguien la rechaza. Si pasa, el freno es decorativo.
Por dónde empezar
- Lista las herramientas de tu agente y marca cuáles son irreversibles o salen de tu sistema.
- Pon aprobación solo en esas, con la acción final, el motivo y el efecto a la vista.
- Haz que la petición se persista y que el flujo pueda reanudarse.
- Revisa a las dos semanas la tasa de aprobación y retira los controles que nunca rechazan nada.
El humano en el bucle no es un seguro contra todo. Es un recurso escaso, y rinde más cuando se reserva para las decisiones que no tienen vuelta atrás.