Cómo se usa la IA aquí. Los fragmentos son código real del repositorio.
Usuario a ser usado: admin@empresa.mx (contraseña Demo2026!)
Herramientas que expone a la IA (3):
consultar_usuariopreparar_alta_usuariolistar_usuarios
Ruta base en Nexus: /usuarios-accesos-ms/v1
01 Herramienta de lectura: consulta el servicio y devuelve datos
Herramienta de lectura: consulta el servicio y devuelve datos.
@Tool(name = "consultar_usuario",
description = "Devuelve los datos de un usuario por su identificador UUID: correo y nombre enmascarados, estatus, roles y área.")
public String consultarUsuario(
@ToolParam(description = "Identificador UUID del usuario", required = true) String usuarioId) {
RegistroHerramientasUsadas.registrar("consultar_usuario");
String cuerpo = gateway.get()
.uri(constructor -> constructor.path(RUTA_BASE + "/usuarios/{id}")
.build(UUID.fromString(usuarioId.trim())))
.retrieve()
.body(String.class);
return FiltroDatosSensibles.redactar(cuerpo).texto();
}
Qué hace: Llama al gateway con la ruta del servicio y devuelve el resultado al modelo.
02 Herramienta de escritura: prepara la acción y NO la ejecuta
Herramienta de escritura: prepara la acción y NO la ejecuta.
@Tool(name = "preparar_alta_usuario",
description = "Prepara el alta de un usuario nuevo. No crea el usuario y no pide contraseña: "
+ "devuelve el identificador de la acción y un código de confirmación. "
+ "El administrador completa el alta en la pantalla de altas, donde escribe la contraseña temporal.")
public String prepararAltaUsuario(
@ToolParam(description = "Correo electrónico del usuario nuevo", required = true) String correo,
@ToolParam(description = "Nombre completo del usuario nuevo", required = true) String nombreCompleto,
@ToolParam(description = "Roles separados por coma. Valores: ADMIN, FINANZAS, CONTADOR, VENTAS, COMPRAS, "
+ "ALMACEN, OPERACIONES, CALIDAD, DIRECCION, LEGAL", required = true) String roles) {
RegistroHerramientasUsadas.registrar("preparar_alta_usuario");
String correoLimpio = correo == null ? "" : correo.trim();
String nombreLimpio = nombreCompleto == null ? "" : nombreCompleto.trim();
List<String> rolesLista = roles == null ? List.of()
: Arrays.stream(roles.split(",")).map(String::trim).filter(r -> !r.isEmpty()).toList();
if (!correoLimpio.matches("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$")) {
return "El correo no es válido. Pide el correo completo del usuario.";
}
if (nombreLimpio.isEmpty()) {
return "Falta el nombre completo del usuario.";
}
if (rolesLista.isEmpty() || !ROLES_ALTA.containsAll(rolesLista)) {
return "Roles inválidos. Usa solo: " + String.join(", ", ROLES_ALTA) + ".";
}
String usuario = SecurityContextHolder.getContext().getAuthentication().getName();
String payload = aJson(Map.of("correo", correoLimpio, "nombreCompleto", nombreLimpio, "roles", rolesLista));
AccionPendiente accion = acciones.preparar(usuario, AccionesPendientes.TIPO_USUARIO_ALTA, payload,
"Alta de usuario " + correoLimpio + " con roles " + String.join(", ", rolesLista));
return "Alta preparada: acción " + accion.id() + ", vence " + accion.expiraUtc()
+ ". Código de confirmación: " + codigos.generar(accion.id(), accion.usuario())
+ ". El usuario aún no existe. Completa el alta en /usuarios/altas/" + accion.id()
+ ", donde se escribe la contraseña temporal.";
}
Qué hace: La acción queda pendiente hasta que la persona confirma con el código.
03 Ruta base del servicio dentro de Nexus
Ruta base del servicio dentro de Nexus.
static final String RUTA_BASE = "/usuarios-accesos-ms/v1";
Qué hace: Todas las herramientas de este módulo se construyen sobre esta ruta.
Regla del proyecto: la IA propone o prepara; la persona confirma con el código de 8 dígitos. Ninguna herramienta de escritura cambia datos por sí sola.