8 min de lectura

Aprovisionamiento reversible de usuarios SaaS con agentes de IA

Diseña un aprovisionamiento reversible de usuarios SaaS con agentes de IA separando invitaciones, roles y grupos, con reintentos y auditoría.

Aprovisionamiento reversible de usuarios SaaS con agentes de IA

Un agente de IA nunca debería aprovisionar a un usuario de SaaS con una instrucción opaca como «añade a Priya a la cuenta de la empresa con el acceso normal de ingeniería». Esa frase esconde al menos tres cambios de estado: crear o invitar una identidad, asignar un rol en la cuenta y añadir pertenencias a grupos. Cada cambio tiene un riesgo, una condición de finalización y una operación de deshacer diferentes.

El aprovisionamiento reversible de usuarios SaaS empieza por conservar esos límites. El agente propone una secuencia, ejecuta una llamada cada vez, registra los identificadores devueltos y se detiene cuando el estado observado no coincide con el esperado. Requiere algunas llamadas más a la API. A cambio, el operador no tiene que reconstruir una concesión de acceso a medias tras un tiempo de espera agotado, una dirección de correo errónea o una asignación de grupo demasiado amplia.

Invitación, rol y pertenencia son estados distintos

Una invitación pendiente no es un usuario, un usuario no es un rol y un rol no es la pertenencia a un grupo. Los sistemas de aprovisionamiento suelen mezclar estos objetos porque las consolas de los proveedores los presentan en un solo formulario. La API subyacente suele exponer recursos u operaciones de ciclo de vida diferentes, y esa diferencia determina si un agente puede recuperarse con seguridad.

Una invitación suele representar una intención y un proceso de entrega o canje. El destinatario puede tener que aceptarla, usar una identidad distinta de la prevista o no responder nunca. Microsoft Graph lo documenta de forma explícita para usuarios externos: crear una invitación devuelve un objeto de invitación, mientras la persona invitada completa un flujo interactivo de canje. En GitHub, la pertenencia a una organización también sigue pendiente hasta que la persona acepta. Un agente que registra «usuario creado» justo después de cualquiera de esas invitaciones ha anotado un deseo, no un hecho.

Un rol cambia la autoridad en la cuenta o la organización. Puede convertir a una persona en propietaria, responsable de facturación, administradora, invitada o miembro normal. La pertenencia a un grupo suele conceder acceso indirecto a proyectos, repositorios, canales, aplicaciones o datos compartidos. Quitar el grupo puede revocar ese acceso indirecto sin cambiar el rol de la cuenta. Rebajar el rol puede dejar intactos los privilegios derivados de grupos.

Modela los estados por separado, incluso cuando el proveedor ofrezca un endpoint cómodo que acepte los tres en un único POST. Un registro interno razonable tiene esta forma:

{
  "subject": "[email protected]",
  "invitation": {"state": "pending", "id": "inv_8421"},
  "role": {"desired": "member", "observed": null},
  "groups": {
    "desired": ["engineering", "on-call-readers"],
    "observed": []
  }
}

La separación responde a la pregunta operativa incómoda: ¿qué hay que deshacer exactamente? Si existe la invitación pero la cuenta no se ha canjeado, cancela la invitación. Si la cuenta existe con un rol equivocado, restaura el rol anterior. Si se añadió un grupo y falló la llamada siguiente, elimina solo la pertenencia creada por esa ejecución. Borrar al usuario completo suele ser un sustituto temerario de saber qué estado cambió.

La primera regla de diseño es sencilla: una acción registrada debe corresponder a una transición de estado observable en el sistema remoto. La llamada puede producir efectos secundarios del proveedor, como un correo electrónico, pero el agente y el operador deben poder nombrar la transición principal sin añadir «y también hizo…».

El plan de aprovisionamiento debe ser datos, no prosa

El agente debe compilar una petición humana en un plan tipado antes de llamar al proveedor. Un plan hace visibles las suposiciones ambiguas y entrega entradas estables al ejecutor. El razonamiento libre pertenece a la fase previa; el límite de ejecución debe recibir datos aburridos y precisos.

Como mínimo, el plan necesita un identificador del sujeto, el tenant de destino, el modo de invitación, el rol y los grupos solicitados, las precondiciones y un identificador de operación. También debe indicar si la acción puede enviar correo. La entrega de una invitación es un efecto externo que la cancelación no puede retirar, por lo que esconderla detrás de un valor predeterminado es una mala práctica.

{
  "operation_id": "prov_2026_07_24_0187",
  "tenant": "acme-production",
  "subject": {"email": "[email protected]"},
  "steps": [
    {"kind": "invite", "send_email": false},
    {"kind": "wait_for_acceptance"},
    {"kind": "set_role", "role": "member"},
    {"kind": "add_group", "group": "engineering"},
    {"kind": "add_group", "group": "on-call-readers"}
  ],
  "preconditions": {
    "account_absent": true,
    "allowed_email_domain": "example.test"
  }
}

Conserva cada alta de grupo como un paso separado, en vez de pasar una matriz a un endpoint amplio. Así el ejecutor puede aprobar, reintentar y compensar cada pertenencia por separado. El plan también muestra el orden. Si el proveedor no permite asignar el rol hasta la aceptación, wait_for_acceptance es una barrera real de estado, no una instrucción de espera por tiempo.

Valida el plan con restricciones locales antes de exponer una credencial o hacer una llamada de red. Comprueba que el tenant sea un identificador exacto y conocido, normaliza el dominio del correo sin reescribir la parte local, resuelve los nombres legibles de grupos a identificadores inmutables del proveedor y rechaza un rol de propietario o administrador salvo que la petición lo nombre expresamente. No permitas que el agente descubra tenants buscando en todas las cuentas accesibles para un token potente.

Las lecturas preliminares deben capturar el estado existente. Busca al sujeto por el atributo único que documente el proveedor y consulta después los registros directos de rol y pertenencia. Distingue «no encontrado» de «falló la lectura». Un 403, un tiempo agotado o una página truncada no prueban que algo no exista. Si la búsqueda tiene consistencia eventual o paginación, registra esa limitación y exige una consulta más fuerte antes de crear nada.

Congela el plan después de aprobarlo. Si el agente cambia un correo, rol, identificador de grupo o indicador de entrega, genera otro identificador de operación y solicita una decisión nueva. De lo contrario, la frase aprobada y las llamadas ejecutadas pueden divergir en silencio.

Prepara la invitación antes de conceder acceso

Crea o envía primero la invitación y detente hasta que el servicio demuestre qué ocurrió. No empaquetes roles privilegiados y grupos sensibles en la invitación solo porque el endpoint lo permita. El argumento popular a favor de agruparlos es la eficiencia: una petición parece atómica y envía una sola notificación. En la práctica, la mayoría de las API SaaS no prometen una transacción entre creación de identidad, asignación de rol, notificación y propagación de grupos.

El endpoint de invitaciones a organizaciones de GitHub muestra bien la tentación. La petición puede incluir un rol y varios identificadores de equipo. Resulta cómodo para un propietario que usa la consola, pero un ejecutor autónomo pierde puntos de control útiles al enviarlo todo junto. Un error de validación puede rechazarlo todo, mientras una respuesta perdida después de la aceptación deja al ejecutor sin saber qué efectos ocurrieron. Además, una persona puede aceptar mucho después de terminar la ejecución y activar entonces el acceso.

Prefiere la invitación con menos autoridad que admita el proveedor. Si debe incluir un rol, usa el rol de miembro ordinario y aplaza la elevación. Si debe incluir un grupo o canal, elige uno de recepción sin recursos sensibles y añade las pertenencias previstas cuando la identidad alcance el estado esperado. Algunas API limitan esta estrategia. Por ejemplo, el método documentado por Slack para invitar en Enterprise Grid exige al menos un identificador de canal. Eso justifica definir un canal de llegada con poco acceso, no adjuntar todos los canales de trabajo a la primera llamada.

Registra si el proveedor envió correo y captura el identificador, estado, hora de creación y sujeto canónico que devuelva el servicio. No guardes una URL de canje en un diario amplio porque puede funcionar como capacidad al portador. Si la API devuelve una para entregarla por separado, pásala por el componente de confianza más pequeño y ocúltala de los resultados visibles para el agente.

Una invitación preparada necesita una condición terminal explícita. Usa accepted, expired, cancelled y pending cuando el proveedor los exponga. Si no lo hace, deriva el estado de campos documentados del usuario o la pertenencia e indica que el valor es derivado. Nunca interpretes «el POST de invitación devolvió 201» como «el destinatario ya puede acceder a datos de producción».

Define una fecha límite en el registro local de la operación. Cuando venza, consulta el estado y cancela la invitación si sigue pendiente y la petición empresarial ya no es válida. No programes una cancelación ciega: la persona puede haber aceptado justo antes de dispararse el temporizador. Lee, compara y actúa.

Cancelar una invitación solo es reversible en un sentido limitado. Puede impedir una aceptación posterior cuando el servicio lo permite, pero no puede retirar un correo ni borrar el conocimiento de la organización. Escribe ese límite en la tarjeta de aprobación. Los operadores deciden mejor cuando «reversible» describe el estado de autorización remoto en vez de fingir que todas las consecuencias se pueden borrar.

Asigna roles solo cuando la identidad esté fijada

La asignación de rol debe esperar hasta que el agente pueda vincular la petición a un identificador remoto estable. Los correos sirven para buscar, pero son malos identificadores duraderos. Las direcciones cambian, los alias chocan y algunos invitados canjean la invitación con una cuenta existente. El identificador devuelto por el proveedor debe convertirse en sujeto de las llamadas posteriores.

Antes de cambiar un rol, lee el rol actual y guárdalo como valor de compensación. Si el valor deseado ya coincide, registra una operación sin cambios en lugar de emitir otra escritura. Ese registro es evidencia útil: demuestra que el ejecutor comprobó la condición y no se atribuyó un cambio que ya había hecho otro actor.

Trata la elevación de modo distinto a la pertenencia ordinaria. Un agente puede asignar un rol normal bajo autorización de sesión, mientras los roles de propietario, administrador o facturación requieren aprobación por llamada. El límite de control debe seguir la consecuencia del uso de la credencial, no el método HTTP. PATCH /users/123 puede ser rutinario o desastroso según un solo campo.

Usa controles de comparación y escritura cuando la API los ofrezca. Un ETag con If-Match, un campo de versión o una revisión propia del proveedor evita que el agente sobrescriba un cambio humano posterior a la lectura preliminar. Si el servicio devuelve un conflicto, vuelve a leer y detente para revisión. No leas el valor nuevo y fuerces inmediatamente el plan original; el cambio concurrente puede ser justo el hecho que el operador necesita ver.

La entrada del rol debe incluir el valor anterior, el solicitado, el observado, el identificador remoto del sujeto, el estado de respuesta y cualquier token de concurrencia. No debe incluir el token portador de la llamada. Un registro mínimo de éxito puede ser:

{
  "operation_id": "prov_2026_07_24_0187",
  "step": 3,
  "action": "role.set",
  "subject_id": "usr_1938",
  "before": "guest",
  "requested": "member",
  "observed": "member",
  "http_status": 200,
  "undo": {"action": "role.set", "value": "guest"}
}

No des por terminado un cambio de rol solo porque la actualización devolvió éxito. Consulta el recurso de usuario o pertenencia y confirma el valor efectivo. Las API pueden devolver 202 Accepted, aplicar cambios de forma asíncrona o exponer registros pendientes y activos por separado. El diario debe decir requested hasta que una lectura pruebe observed.

Cuando la degradación sea la compensación, considera si también necesita aprobación. Restaurar guest tras una concesión accidental de propietario suele ser más seguro que esperar, pero la reversión automática puede chocar con una corrección humana. Define la regla antes: solo se permite compensar automáticamente mientras la versión guardada coincida con la creada por esta operación. En otro caso, detente y muestra la divergencia.

Añade cada grupo con su propia llamada

Detén una ejecución parcial
Revoca la sesión antes de que un plan parcialmente fallido realice su siguiente llamada.

Cada pertenencia a grupo debe tener su propio paso, identificador remoto, resultado e instrucción de deshacer. Los grupos suelen ocultar accesos amplios. Un nombre como engineering puede controlar repositorios, consolas de despliegue, canales de incidencias y asignaciones sincronizadas a otras aplicaciones. El agente no debe inferir ese alcance a partir del nombre amable.

Resuelve los grupos desde un catálogo permitido que se mantenga fuera del prompt. Debe asociar el nombre visible a un identificador inmutable limitado al tenant e indicar si la pertenencia es directa, anidada, dinámica o sincronizada. Si dos grupos comparten nombre, falla de forma segura. Si un grupo está gestionado por reglas, no combatas la regla con escrituras directas repetidas.

La API Directory del Admin SDK de Google hace tangible ese límite. Expone un endpoint para añadir miembros, otro para actualizar la pertenencia y uno DELETE para eliminarla. Su documentación avisa de que la pertenencia anidada puede tardar en aparecer y rechaza ciclos. Esos detalles exigen comprobaciones de estado observado, no un bucle que suponga consistencia inmediata.

SCIM aporta otro comportamiento útil. El ejemplo PATCH de RFC 7644 para añadir un miembro indica que si el usuario ya pertenece al grupo, el servidor no debería cambiar nada y debería devolver éxito. Es cómodo para los reintentos, pero no supongas que todas las implementaciones de SCIM siguen el ejemplo a la perfección. Prueba el proveedor y conserva una consulta de conciliación.

Un paso de grupo debe distinguir cuatro resultados: added, already_present, rejected y unknown. Already_present no debe crear una acción de deshacer, porque eliminar esa pertenencia durante la reversión borraría un acceso anterior a la operación. Unknown significa que la escritura pudo tener éxito pero se perdió la respuesta o falló la verificación. Exige conciliación, no un reintento optimista.

Procesa los grupos de menor a mayor privilegio. Añade el grupo básico de colaboración antes del grupo de administración de producción. No elimina el daño de un fallo, pero deja al sujeto con menos acceso si la ejecución se detiene. Exige una aprobación nueva al cruzar cualquier límite marcado como sensible, aunque los grupos ordinarios ya se hayan añadido.

No paralelices las escrituras solo para ahorrar latencia. Las llamadas paralelas desordenan la evidencia, complican los límites de tasa y pueden activar sistemas posteriores en un orden impredecible. Unas llamadas secuenciales cuestan poco frente a investigar por qué una identidad recibió una licencia antes de que se registrara su acuerdo de datos restringidos.

Tras cada alta, lee el recurso de pertenencia directa, no una vista aplanada del acceso efectivo. La pertenencia efectiva puede proceder de un grupo padre y seguir siendo cierta tras borrar el vínculo directo. El recibo de reversión debe nombrar el vínculo creado por esta operación.

Los reintentos seguros empiezan por observar el estado

Una política de reintentos no convierte cualquier POST en una operación segura. RFC 9110 define PUT, DELETE y los métodos seguros como idempotentes por su efecto previsto. También indica que un cliente no debería reintentar automáticamente una petición no idempotente salvo que conozca su semántica idempotente o pueda saber que la petición original nunca se aplicó. El código de aprovisionamiento debe tomar esa advertencia al pie de la letra.

El caso peligroso es un tiempo agotado tras enviar un POST de invitación. El servidor puede haber creado la invitación y enviado el correo antes de fallar la conexión. Repetirlo puede crear otra invitación u otra notificación. La siguiente acción correcta es leer por sujeto y tenant, y después adoptar el objeto remoto coincidente, reintentar solo si se demuestra la ausencia o detenerse si el resultado es ambiguo.

Usa una clave de idempotencia cuando la API la documente. Derívala del identificador inmutable de operación y del número de paso, guárdala y reutilízala para el mismo intento lógico. Nunca generes otra solo porque la petición agotó el tiempo. Una clave nueva indica al servidor que se trata de otra acción.

Sin clave de idempotencia, crea una función de conciliación para cada escritura antes de ponerla en manos de un agente. Debe encontrar el objeto creado sin coincidencias difusas. Correo más tenant puede identificar una invitación pendiente; usuario más grupo identifica un vínculo. Si la API no admite una consulta exacta, clasifica el resultado incierto como necesitado de confirmación humana.

Los reintentos también necesitan un presupuesto. Respeta Retry-After, aplica una espera incremental limitada a errores transitorios y detente ante errores de validación, permiso o conflicto. Un 403 no es un 200 lento. Repetir la misma llamada denegada también acostumbra a los operadores a aprobar sin leer.

Un ejecutor fiable usa esta tabla:

ResultadoAcción siguiente
Éxito definido y estado verificadoConfirmar el recibo del paso
Fallo definido sin cambio de estadoRegistrar el fallo y detenerse
Tiempo agotado después del envíoConciliar antes de reintentar
Respuesta correcta pero verificación distintaRegistrar divergencia y detenerse
Límite de tasa con instruccionesEsperar dentro del presupuesto

Separa los intentos de transporte de los pasos lógicos. Cinco intentos HTTP pueden corresponder a una sola alta de grupo. El diario principal debe mostrar el resultado lógico y los registros enlazados deben conservar códigos y tiempos. De otro modo, quien audite puede confundir reintentos con concesiones repetidas.

Revertir es compensar, no viajar atrás

Verifica el rastro sin conexión
sp audit verify comprueba la cadena cifrada sin abrir los registros de aprovisionamiento.

El aprovisionamiento SaaS rara vez ofrece una transacción distribuida, así que revertir significa aplicar compensaciones en orden inverso. Elimina las pertenencias creadas por la ejecución, restaura el rol anterior y cancela la invitación si sigue pendiente. Cada compensación es otra llamada real que puede fallar, requerir aprobación o encontrar ediciones concurrentes.

Construye la pila de compensaciones a partir de cambios confirmados, no de pasos planeados. Si el grupo ya estaba presente, no hay nada que quitar. Si la actualización de rol nunca llegó, no hay nada que restaurar. Cuando la verificación es desconocida, no adivines: concilia antes de añadir una compensación.

Un recibo útil guarda datos suficientes para intentar y limitar la operación inversa:

{
  "action": "group.add",
  "target": {"user_id": "usr_1938", "group_id": "grp_77"},
  "result": "added",
  "remote_version_after": "W/\"9012\"",
  "compensation": {
    "action": "group.remove",
    "only_if_direct_membership_matches": true
  }
}

La protección de versión importa. Supón que el agente añade a Priya y luego un responsable confirma la pertenencia de forma independiente en la consola. Una reversión ciega puede eliminar una decisión que ahora tiene otro dueño. Algunos servicios no permiten expresar la condición en DELETE. En ese caso, consulta el vínculo y sus metadatos, muestra el conflicto y pide una decisión humana.

No todos los efectos tienen compensación. El correo no se puede retirar, un evento de auditoría no debe borrarse, una licencia puede afectar a la facturación aunque se elimine después y un proveedor de identidad posterior puede propagar el grupo tras desaparecer el vínculo de origen. Marca estos efectos residuales en el resultado en vez de declarar una reversión completa sin matices.

La reversión necesita plazo y ruta de escalado. Las credenciales caducan, el servicio puede caer y el proceso original puede terminar. Conserva los recibos fuera del contexto del agente para que otro ejecutor de confianza continúe. El operador necesita ver rollback_pending, no un mensaje alegre oculto en una transcripción.

Prueba la compensación en un tenant no productivo con comportamiento real. Crea una invitación, cancélala y verifica que el enlace falle. Añade y elimina un vínculo directo y revisa el acceso efectivo. Cambia un rol de bajo riesgo y restáuralo ante un conflicto de concurrencia. La documentación describe la intención; estas pruebas revelan lo que el servicio expone.

El diario debe demostrar causa y efecto

Un diario útil responde quién pidió el cambio, qué proceso lo ejecutó, qué límite de credencial lo autorizó, qué objeto remoto cambió y cómo se verificó. Una transcripción de herramientas no basta. La narración del agente puede ser errónea y los cuerpos HTTP pueden contener datos sensibles o ser demasiado grandes.

Asigna identificadores estables a operaciones y pasos. Registra el hash del plan, tenant exacto, sujeto normalizado, identificadores remotos, decisión de aprobación, huella de la petición, estado de respuesta, lectura de verificación y compensación. Guarda extractos redactados solo cuando expliquen el resultado. Un hash de la respuesta permite comparar después sin copiar datos personales.

Separa afirmaciones de observaciones. requested_role: member expresa intención. response_status: 200 observa el transporte. observed_role: member es estado remoto verificado. Meter los tres en un booleano success destruye la evidencia necesaria en un incidente.

La vista de línea de comandos debe mostrar con claridad una finalización parcial:

$ provision status prov_2026_07_24_0187
STEP  ACTION                 RESULT            UNDO
1     invitation.create      accepted          unavailable
2     acceptance.wait        observed          n/a
3     role.set               changed           ready: guest
4     group.add engineering  added             ready
5     group.add on-call      denied            none
STATE partial_failure

La salida indica que existe la cuenta, cambió el rol, se añadió un grupo y falló el último. No reduce todo a «falló el aprovisionamiento». La distinción orienta tanto la reversión como la decisión de continuar tras corregir la autorización.

Protege el diario del agente que realiza las acciones. Si puede reescribir su propia evidencia, el registro vale poco. Sallyport mantiene las sesiones y las llamadas individuales como dos vistas de un único registro cifrado y encadenado por hashes; sp audit verify comprueba la cadena sin conexión sobre el texto cifrado y sin clave. No sustituye los registros del proveedor, pero ofrece al operador una secuencia local independiente.

Correlaciona identificadores locales con los de petición del proveedor. En un caso de soporte, el identificador remoto localiza trazas del servidor y el registro local explica intención y aprobación. Conserva marcas de tiempo, pero ordena por una secuencia local monotónica porque los relojes y los eventos asíncronos pueden discrepar.

La retención requiere una política deliberada. La evidencia puede contener correos, nombres de grupos e historial de roles. Guarda el mínimo necesario, cífralo, limita lectores y, si la política lo permite, caduca los datos auxiliares antes que el registro principal.

La aprobación pertenece a los límites de consecuencia

Revisa reintentos como llamadas
Cada intento repetido queda visible como una entrada individual del diario Activity.

La aprobación humana funciona cuando la tarjeta describe una consecuencia concreta. «Permitir aprovisionamiento» es demasiado amplio. «Invitar a [email protected] a acme-production sin enviar correo» se puede revisar. «Cambiar usr_1938 de guest a member» y «añadir usr_1938 a production-deployers» merecen decisiones separadas si difiere su riesgo.

Muestra identificadores resueltos y estado actual, no solo las palabras del agente. La tarjeta debe enseñar tenant, sujeto canónico, acción, valores anterior y posterior, y si existe compensación automática. En una invitación pendiente, indica si se enviará correo; para grupos, enseña el identificador inmutable junto al nombre.

La autorización de sesión puede cubrir llamadas repetitivas de bajo riesgo, mientras credenciales o acciones sensibles exigen aprobación en cada uso. La escalera fija de Sallyport permite esa separación: la bóveda debe estar desbloqueada, cada proceso nuevo recibe por defecto autorización de sesión y una marca por clave puede exigir aprobación en cada llamada. Coloca la credencial privilegiada en el límite estricto, en lugar de pedir al modelo que controle su propio comportamiento.

La aprobación no corrige una ejecución débil. Una persona puede aprobar el grupo correcto y sufrir un POST duplicado tras un tiempo agotado. El ejecutor sigue siendo responsable de idempotencia, verificación y compensación. Del mismo modo, un diario perfecto no vuelve segura una credencial excesiva.

Reduce la fatiga quitando avisos que no contienen una decisión. Las lecturas con metadatos limitados pueden caber en la sesión. Las operaciones sin cambio deben registrarse sin pedir aprobar algo que no ocurrirá. Agrupa pertenencias idénticas de bajo riesgo solo si la interfaz muestra todos los destinos y el motor conserva recibos separados.

Revocar debe detener los pasos futuros sin fingir que deshace los completados. Si el operador revoca la sesión después del paso cuatro, el ejecutor debe cancelar llamadas en cola, marcar la operación como interrumpida y ofrecer el plan de compensación. No debe usar otra credencial ni abrir otra sesión a escondidas.

Una ejecución fallida debe seguir siendo comprensible

Imagina que un agente debe incorporar a una contratista con cuenta normal y dos grupos. La lectura previa no encuentra cuenta. La invitación agota el tiempo después del envío, la conciliación encuentra una invitación pendiente y el ejecutor adopta su identificador. La contratista acepta. El rol se actualiza, se añade el primer grupo y el segundo devuelve 403 porque el token carece de autoridad.

Es un resultado parcial, no un error indistinto. Hay una cuenta activa y una pertenencia directa. El agente debe detenerse, mostrar el paso denegado y ofrecer dos opciones válidas: conservar el estado confirmado mientras se consigue autoridad para el grupo restante, o compensar la primera pertenencia y restaurar el rol anterior antes de tratar la cuenta.

No debe borrar al usuario. Borrar puede eliminar datos, invalidar una identidad aceptada o chocar con sistemas posteriores. Tampoco debe reintentar el 403, afirmar que el correo entregado se puede revertir ni sustituir el grupo denegado por otro más amplio.

El diario permite continuar con seguridad. Otro ejecutor carga el plan inmutable y los recibos, lee el estado remoto y confirma que cuenta, rol y primer grupo siguen coincidiendo. Si es así, pide aprobación solo para la pertenencia restante. Si un responsable cambió el rol, el plan está obsoleto y requiere una decisión nueva.

El patrón se extiende más allá del alta. La baja debe separar revocación de sesiones, eliminación de grupos, cambio de rol, suspensión y borrado porque difieren en urgencia y reversibilidad. La asignación de licencias debe separarse del grupo cuando el proveedor la expone aparte. La regla no cambia: conserva en el plan y la evidencia los límites de estado significativos del sistema remoto.

Las llamadas extra son fricción deliberada. Crean puntos para verificar identidad, limitar autoridad, detenerse ante divergencias y deshacer solo lo que cambió esta operación. Un agente autónomo merece más libertad cuando su trabajo puede inspeccionarse en esos límites. Si una API obliga a juntar consecuencias en una llamada irreversible, clasifícala con honestidad y pon a una persona delante.

FAQ

¿Debe un agente crear al usuario SaaS y asignar acceso en una sola llamada?

Normalmente no. Separa invitación o creación, cambio de rol y cada grupo para verificarlos y deshacerlos de forma independiente. Usa un endpoint combinado solo si sus efectos acoplados se entienden y aprueban como una unidad irreversible.

¿Qué ocurre si la API de invitación agota el tiempo?

No repitas el POST de inmediato. Busca la invitación exacta por tenant y sujeto, adopta un resultado inequívoco y reintenta solo tras demostrar que la primera petición no cambió nada.

¿Borrar al usuario es una reversión segura?

Casi nunca, porque puede eliminar datos e interferir con una identidad que ya aceptó. Compensa solo cambios confirmados de la ejecución, como vínculos directos y el rol anterior.

¿Cómo se trata una pertenencia que ya existía?

Registra already_present y no añadas una acción de deshacer. Eliminarla durante la reversión borraría acceso anterior a la operación.

¿Cuándo es reversible una acción de aprovisionamiento?

Cuando hay una compensación que restaura el estado observado anterior y existen identificadores suficientes para aplicarla con seguridad. El correo, la facturación y la propagación pueden persistir.

¿Qué debe guardar una entrada de auditoría?

Identificadores de operación y paso, tenant, objetos remotos, valores anterior y solicitado, aprobación, respuesta, verificación y compensación. Excluye credenciales y enlaces de canje.

¿Puede el agente reintentar PUT y DELETE automáticamente?

HTTP los define como idempotentes por su efecto previsto, pero aún hay que respetar la semántica del proveedor y los cambios concurrentes. Usa condiciones de versión y verifica después.

¿Conviene añadir grupos en paralelo?

Las escrituras secuenciales son más seguras para acceso privilegiado. Conservan el orden, aclaran la evidencia, simplifican los límites y dejan un recibo preciso por pertenencia.

¿Cómo debe ser una tarjeta de aprobación?

Debe mostrar una consecuencia, tenant, sujeto canónico, identificador inmutable, estado anterior y posterior, efectos de entrega y compensación. «Permitir alta» oculta demasiado.

¿Qué debe hacer el agente tras un 403?

Detenerse y comunicar el estado parcial exacto. No debe reintentar ni sustituir por un acceso mayor; debe esperar una autorización corregida u ofrecer compensación.

Sallyport

Sallyport ejecuta llamadas de API y comandos SSH por tu agente de IA. Las claves se quedan en una bóveda local de tu Mac; tú apruebas cada ejecución y cada acción queda en un registro sellado.

© 2026 Sallyport · Código abierto bajo Apache-2.0 · Oleg Sotnikov