Cómo se usa la IA aquí. Los fragmentos son código real del repositorio.
Usuario a ser usado: direccion@demo.empresa.mx (contraseña Demo2026!)
Herramientas que expone a la IA (3):
consultar_indicadoresconsultar_reporteregistrar_indicador
Ruta base en Nexus: /reportes-ejecutivos-ms/v1
01 Herramienta de lectura: consulta el servicio y devuelve datos
Herramienta de lectura: consulta el servicio y devuelve datos.
@Tool(name = "consultar_indicadores",
description = "Devuelve los indicadores consolidados de un periodo. El periodo es AAAA-MM, AAAA-Qn o AAAA.")
public String consultarIndicadores(
@ToolParam(description = "Periodo: AAAA-MM, AAAA-Q1..Q4 o AAAA", required = true) String periodo,
@ToolParam(description = "Área opcional. Valores válidos: VENTAS_ATENCION_CLIENTES, FINANZAS_CONTABILIDAD, OPERACIONES, COMPRAS_PROVEEDORES, ADMINISTRACION_LEGAL, DIRECCION_GENERAL. Vacío para todas.",
required = false) String area) {
RegistroHerramientasUsadas.registrar("consultar_indicadores");
String cuerpo = gateway.get()
.uri(constructor -> {
var uri = constructor.path(RUTA_BASE + "/indicadores").queryParam("periodo", periodo);
if (area != null && !area.isBlank()) {
uri.queryParam("area", area.trim().toUpperCase());
}
return uri.build();
})
.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 = "registrar_indicador",
description = "Prepara el registro de un indicador de un área para un periodo. NO lo registra: devuelve "
+ "un resumen y un accion_id. El usuario debe confirmarlo en la aplicación. Solo DIRECCION puede usarla.")
public String registrarIndicador(
@ToolParam(description = "Área. Valores válidos: VENTAS_ATENCION_CLIENTES, FINANZAS_CONTABILIDAD, OPERACIONES, COMPRAS_PROVEEDORES, ADMINISTRACION_LEGAL, DIRECCION_GENERAL",
required = true) String area,
@ToolParam(description = "Nombre del indicador", required = true) String nombre,
@ToolParam(description = "Periodo: AAAA-MM, AAAA-Q1..Q4 o AAAA", required = true) String periodo,
@ToolParam(description = "Valor numérico del indicador", required = true) String valor,
@ToolParam(description = "Momento en que se actualizó la fuente, en ISO-8601 UTC, por ejemplo 2026-11-08T00:00:00Z",
required = true) String fuenteActualizadaUtc) {
RegistroHerramientasUsadas.registrar("registrar_indicador");
if (acciones == null) {
return NO_DISPONIBLE;
}
String areaLimpia = area == null ? "" : area.trim().toUpperCase();
if (!AREAS.contains(areaLimpia)) {
return "El área no es válida. Valores: " + String.join(", ", AREAS) + ".";
}
if (nombre == null || nombre.isBlank()) {
return "El nombre del indicador es obligatorio.";
}
String periodoLimpio = periodo == null ? "" : periodo.trim();
if (!PERIODO.matcher(periodoLimpio).matches()) {
return "El periodo debe ser AAAA-MM, AAAA-Qn o AAAA.";
}
BigDecimal numero;
try {
numero = new BigDecimal(valor.trim());
} catch (NumberFormatException | NullPointerException e) {
return "El valor debe ser numérico.";
}
Instant fuente;
try {
fuente = Instant.parse(fuenteActualizadaUtc.trim());
} catch (DateTimeParseException | NullPointerException e) {
return "La fecha de actualización debe estar en ISO-8601 UTC, por ejemplo 2026-11-08T00:00:00Z.";
}
Map<String, Object> cuerpo = new LinkedHashMap<>();
cuerpo.put("area", areaLimpia);
cuerpo.put("nombre", nombre.trim());
cuerpo.put("periodo", periodoLimpio);
cuerpo.put("valor", numero);
cuerpo.put("fuenteActualizadaUtc", fuente.toString());
String resumen = "Registrar indicador " + nombre.trim() + " de " + areaLimpia + " (" + periodoLimpio
+ ") = " + numero.toPlainString();
AccionPendiente accion = acciones.preparar(usuarioActual(), AccionesPendientes.TIPO_INDICADOR_REGISTRAR,
aJson(cuerpo), resumen);
return FiltroDatosSensibles.redactar("Registro preparado, no ejecutado. " + resumen
+ ". accion_id: " + accion.id() + ". Vence en 10 minutos; el usuario debe confirmarlo en la aplicación.")
.texto();
}
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 = "/reportes-ejecutivos-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.