Un botón de aprobación no demuestra que un agente esperó. La tool pudo ejecutarse antes de la decisión, el executor pudo usar otros argumentos o una reanudación pudo repetir el efecto.

La prueba debe separar dos preguntas: qué decisión registró la política y qué ocurrió en el sistema externo. La guía sobre cuándo debe pedir aprobación humana un agente de IA explica el diseño del gate. Este artículo se centra en demostrar que funciona con aprobación, rechazo, cambios y reinicios.

Flujo dibujado muestra una propuesta de tool rechazada o aprobada antes de una única ejecución.

Respuesta corta

  • Una llamada pendiente no puede producir efectos antes de la decisión.
  • El rechazo o la expiración deben dejar el contador de efectos en cero.
  • Aprobar debe ejecutar una vez el mismo payload que vio la persona.
  • Cambiar el objetivo, los argumentos o la versión de la política debe exigir una nueva decisión.

¿Qué debe demostrar la prueba?

La guía de human-in-the-loop de OpenAI Agents SDK describe un flujo en el que una llamada que requiere aprobación no se ejecuta, el run devuelve una interrupción y el estado puede reanudarse después. Ese es el contrato mínimo: pendiente antes del efecto, decisión explícita y reanudación del mismo run.

No pruebes solo que la interfaz mostró una pregunta. Registra la llamada propuesta, la decisión, el payload normalizado y el estado del recurso que podría cambiar. Una prueba verde debe decir si la política decidió correctamente y si el executor respetó esa decisión.

Una matriz pequeña ya encuentra fallos importantes:

Caso Decisión esperada Efecto esperado
Acción de bajo riesgo permitida por la política allow Una ejecución válida
Acción que requiere revisión pending Ningún efecto mientras espera
La persona rechaza deny Ningún efecto
Se aprueba el payload original allow Un efecto con los mismos argumentos
El payload cambia después de aprobar deny o nueva pendiente Ningún efecto con el payload cambiado
La reanudación se repite decisión ya consumida Como máximo un efecto

¿Cómo probar la decisión sin llamar al servicio real?

Empieza con un executor falso. La prueba no necesita enviar un correo, cambiar un CRM o borrar un registro para demostrar que la política bloquea la acción. Necesita recibir la misma llamada que recibiría el executor real y dejar una evidencia sencilla cuando se alcanzaría.

La guía de pruebas de OpenAI Agents SDK recomienda utilidades deterministas para probar workflows sin solicitudes al proveedor. Esa frontera importa: un modelo puede proponer una llamada en una prueba de integración, pero la regla de aprobación y el executor necesitan pruebas previsibles.

Este es un esqueleto ilustrativo de una fixture. Una aplicación real debe persistir el estado y definir su propia identidad de revisor.

type Action = { tool: string; target: string; body: string };
type Pending = { id: string; action: Action; status: "pending" | "used" | "rejected" };

const effects: Action[] = [];
const pending = new Map<string, Pending>();

function propose(action: Action): Pending {
  const item = { id: "approval-1", action, status: "pending" as const };
  pending.set(item.id, item);
  return item;
}

function resume(id: string, decision: "approve" | "reject", action: Action) {
  const item = pending.get(id);
  if (!item || item.status !== "pending") throw new Error("stale approval");
  if (JSON.stringify(item.action) !== JSON.stringify(action)) {
    throw new Error("payload changed");
  }
  if (decision === "reject") {
    item.status = "rejected";
    return;
  }
  item.status = "used";
  effects.push(action);
}

La idea no es usar JSON.stringify en producción. La idea es hacer explícita la relación entre el ID pendiente, el payload aprobado y el consumo único. Usa una comparación canónica, una versión de la política y una transacción o clave idempotente adecuada para tu almacenamiento.

¿Cómo demostrar que el rechazo bloquea el efecto?

Envía una llamada que normalmente escribiría en un adapter falso. Antes de reanudar, comprueba que el estado es pending y que el adapter no se llamó. Después rechaza la llamada y comprueba ambos lados: la decisión registrada es negativa y el estado externo no cambió.

Esa separación evita un falso verde. Un log puede decir denied mientras otro camino usa la misma credencial y realiza la operación. El método de WorkOS para probar políticas de autorización de agentes recomienda comprobar por separado el veredicto y el estado producido por el servicio. La recomendación sirve aunque el servicio no sea un correo.

Incluye como mínimo estos casos:

  • rechazo explícito antes del executor;
  • expiración o timeout sin liberación automática;
  • error en la pantalla de aprobación sin fallback a la ejecución;
  • camino alternativo que intenta llamar a la misma tool sin pasar por el gate.

Si algún caso cambia el contador, el outbox o el registro de prueba, la aprobación existe solo en la interfaz. El gate debe estar en la frontera del executor, donde cada llamada mutante pasa antes del efecto.

¿Cómo probar una aprobación con el payload cambiado?

La aprobación pertenece a una acción concreta, no a una intención vaga. Aprueba un payload y cambia un campo antes de reanudar: destinatario, importe, registro, mensaje o alcance. El executor debe rechazar la llamada o crear una nueva aprobación pendiente.

Es fácil ocultar este fallo. El revisor ve "enviar el resumen al equipo", pero el runtime obtiene datos nuevos y reconstruye el cuerpo después del clic. Una prueba que compara solo el texto de la interfaz no detectará el cambio.

Guarda lo que la persona aprobó realmente:

  • nombre y versión de la tool;
  • identidad del agente y del usuario;
  • objetivo y argumentos normalizados;
  • versión de la política;
  • vencimiento de la decisión;
  • un ID que conecte propuesta, aprobación y efecto.

Cuando la aplicación cambie un campo protegido, invalida la aprobación. No conserves la decisión porque el cambio parezca pequeño. La prueba debe hacer visible la regla, y la política puede decidir si la nueva revisión es automática u obligatoria.

¿Cómo probar la reanudación, el reinicio y la ejecución única?

Una aprobación que vive solo en la memoria del worker desaparece al reiniciar. El SDK muestra cómo reanudar desde el mismo estado del run y recomienda mantener el estado en el servidor cuando la aprobación puede tardar. La prueba debe simular ese intervalo, no aprobar dentro de la misma función que creó la pendiente.

Ejecuta la secuencia por etapas:

  1. Crea la pendiente y persiste una representación serializable.
  2. Detén el proceso o descarta el objeto en memoria.
  3. Lee el estado en un nuevo contexto de ejecución.
  4. Aprueba o rechaza con la identidad esperada.
  5. Reanuda dos veces y comprueba que el efecto aparece como máximo una vez.

El último paso importa porque la respuesta de una API puede desaparecer después de que ocurra el efecto externo. La reanudación necesita una clave idempotente, una reserva consumible o una consulta de estado que reconcilie el resultado antes de volver a intentar. Un retry no debe convertir una aprobación válida en dos cobros, mensajes o cambios.

¿Qué fallos deben entrar en la regresión?

Convierte cada hallazgo en un caso fijo con entrada, estado inicial, decisión esperada, efecto prohibido y evidencia final. La guía para probar la trayectoria de un agente puede comprobar el orden de las llamadas y las intervenciones. Este artículo añade la condición de autorización y el estado fuera del agente.

Incluye escenarios que cambien una variable cada vez:

  • la tool correcta no está en el catálogo;
  • el agente pide aprobación para una lectura aunque la política la permita;
  • el rechazo vuelve al modelo y este intenta otro camino;
  • el revisor no tiene autoridad para el objetivo;
  • los argumentos cambian mientras la pendiente está abierta;
  • la política cambia antes de reanudar;
  • el primer envío termina en timeout después de llegar al servicio;
  • dos workers consumen la misma aprobación pendiente.

Usa la validación de tool calls en TypeScript para formato, identidad y argumentos. Usa la prueba de aprobación para la decisión y el consumo. Usa una prueba de integración para el adapter y el servicio externo. Mezclar todo en una prueba lenta hace más difícil descubrir qué frontera se rompió.

Lista de comprobación antes de liberar el agente

  • ¿La pendiente se crea antes de cualquier efecto mutante?
  • ¿La prueba comprueba por separado la decisión y el estado externo?
  • ¿El rechazo, el timeout y los errores de reanudación dejan cero efectos?
  • ¿La aprobación está ligada al payload, el objetivo y la versión de la política?
  • ¿Un cambio después del clic exige una nueva decisión?
  • ¿El estado sobrevive al reinicio del worker?
  • ¿Dos workers pueden consumir la misma pendiente?
  • ¿La prueba usa un adapter falso antes de un sandbox real?
  • ¿La suite demuestra un camino permitido, no solo rechazos?
  • ¿El límite de la prueba está escrito para que nadie la interprete como certificación de seguridad?

El resultado buscado no es "el agente mostró una pantalla". Es una traza corta que conecta propuesta, decisión, ejecución y estado final. Cuando la prueba falle, el equipo debe saber si la política decidió mal, el executor ignoró la decisión o el servicio externo produjo un resultado incierto.

¿Qué no demuestra esta prueba?

Una suite de aprobación no demuestra que el modelo entienda todas las peticiones, que la política cubra todos los recursos o que una integración externa responda siempre bien. Demuestra solo los casos y las autoridades descritos en las fixtures.

Tampoco sustituye autenticación, autorización en el servicio final, aislamiento de credenciales, logs, recuperación ni revisión operativa. Si el agente puede alcanzar el endpoint por otra ruta, la prueba del botón no protege esa ruta. La aprobación debe ser una barrera del runtime, no una promesa del prompt.

Preguntas rápidas

¿Debo usar el modelo real?

Para política, estado pendiente, rechazo y executor, empieza con respuestas controladas. Un modelo real sirve para probar selección y variación de comportamiento, pero no debe decidir si su propia suite pasó. Mantén las expectativas del efecto en código determinista.

¿Toda aprobación de una tool debe bloquearla?

No. La política puede permitir una lectura o una acción reversible sin intervención. La prueba debe demostrar la clasificación elegida: las llamadas permitidas avanzan, las pendientes esperan y las rechazadas nunca llegan al efecto.

¿Qué debe conservar el informe?

Conserva identidad, versión de política, llamada propuesta, decisión, payload ejecutado y estado anterior y posterior. No guardes secretos solo para facilitar la depuración. Un identificador sintético suele bastar para conectar la evidencia.

Cómo se produjo este artículo

Samuel Fajreldines es el autor responsable. La investigación comparó la documentación actual de OpenAI Agents SDK para human-in-the-loop y pruebas deterministas con el método de WorkOS para probar políticas de autorización. Las conversaciones públicas recientes se usaron solo para lenguaje y fallos recurrentes. La fixture de aprobación se ejecutó localmente con un contador de efectos en memoria. No llamó a un modelo, una cuenta real ni un servicio externo.

Uso RemoteCode como herramienta del autor para mantener el contexto entre sesiones. Apoyó la organización del trabajo, pero no ejecutó la fixture ni demostró la seguridad del flujo.

Fuentes consultadas