Ir al contenido

Procesos y paquetes

En NORA, lo que ejecuta un robot se modela en tres niveles. Entenderlos evita confusiones al subir código y al lanzar jobs.

Listado de procesos en NORA, con carpeta, etiquetas, paquete y versión, timeout, reintentos y SLA de cada proceso.

ConceptoQué esCambia con
Paquete (Package)El robot como producto: un nombre y una descripción. Agrupa todas sus versiones.Casi nunca (es la identidad del robot).
Release (versión)El código del robot empaquetado en un ZIP, con su versión, su entry point y el hash del archivo.Cada vez que cambias el código (subes una versión nueva).
Proceso (Process)Lo que se ejecuta: apunta a un Release y añade la configuración de ejecución (parámetros, timeout, reintentos, assets requeridos, carpeta…).Cuando ajustas configuración o promueves/haces rollback a otra versión.
flowchart TD
    P[Paquete: facturacion] --> R1[Release 1.0.0]
    P --> R2[Release 1.0.1]
    P --> R3[Release 1.1.0]
    PR[Proceso: Facturacion mensual] -->|release_id activo| R3
    PR -.->|rollback| R2

Un Paquete tiene muchos Releases (la versión es única por paquete). Un Proceso fija un Release como activo mediante release_id; cambiarlo permite promover una versión nueva o volver a una anterior sin tocar el robot.

Un robot es una carpeta con, como mínimo, un entry point (por defecto main.py) y, normalmente, un requirements.txt. Ejemplo real del directorio examples/rpa-challenge/:

rpa-challenge/
├── main.py # entry point (orquesta el flujo)
├── requirements.txt # dependencias (playwright>=1.40)
├── rpa_challenge/ # módulos del robot
├── data/
└── nora.json # manifiesto (lo crea/actualiza `nora package`)

El entry point usa el SDK nora_agent para registrar logs, leer assets, consumir colas y reportar progreso. Si falta requirements.txt, el agente no instalará dependencias (la CLI te avisa).

La CLI nora (paquete nora_agent) construye el ZIP de forma segura. Desde la carpeta del robot:

Ventana de terminal
# Vista previa: lista qué se incluiría, sin escribir nada
nora package --list
# Construye el ZIP en dist/<nombre>-<version>.zip
nora package

nora package hace tres cosas:

  1. Resuelve la versión desde el manifiesto nora.json. El primer paquete usa 1.0.0; los siguientes auto-incrementan (--bump patch|minor|major|none, por defecto patch). Puedes fijarla con --version 2.0.0.
  2. Escribe nora.json con name, version y entry_point (se incluye en el ZIP y sirve de fuente de la versión para la próxima vez).
  3. Escanea en busca de secretos (claves privadas, nora_ak_…, tokens, claves AWS). Si encuentra algo, aborta antes de escribir el ZIP; usa --allow-secrets solo si es un falso positivo.

Opciones útiles: --entry workflow.py (otro entry point), --exclude '*.csv' (excluir más archivos, repetible), --gitignore (honrar también .gitignore).

Con la sesión iniciada (nora login), sube el ZIP como Release. release push es solo para administradores y crea el paquete si no existe:

Ventana de terminal
nora login
nora package
nora release push # sube dist/<nombre>-<version>.zip

Otros subcomandos: nora release list, nora release delete <version> y nora release download <version>.

Listado de paquetes en NORA, con la última versión publicada, el número de releases y los procesos asociados a cada paquete.

La CLI llama a estos endpoints (base de producción https://nora-api.valisoftconsulting.com, prefijo /api/v1, autenticación con sesión Bearer). La subida es multipart/form-data:

POST /api/v1/releases
Content-Type: multipart/form-data
package_id=<uuid>&version=1.0.1&entry_point=main.py
file=@rpa-challenge-1.0.1.zip

El backend valida que el ZIP sea válido, sin rutas con .. ni absolutas, con tope de 50 MB subidos y 500 MB descomprimidos, y calcula file_hash (SHA-256). La respuesta va envuelta en {"success": true, "data": …}:

{
"success": true,
"data": {
"id": "",
"package_id": "",
"version": "1.0.1",
"file_hash": "",
"file_size": 20480,
"entry_point": "main.py",
"is_active": true,
"uploaded_by": ""
}
}

La descarga (GET /api/v1/releases/{release_id}/download) devuelve el ZIP y expone la cabecera X-Release-Hash para verificar integridad.

Un Release es solo código; para ejecutarlo, crea un Proceso que lo apunte. POST /api/v1/processes (rol admin) recibe, entre otros campos:

  • name, description, release_id (obligatorio), folder_id.
  • input_schema: esquema de los parámetros de entrada del job. Normalmente lo declaras una vez en nora.json (inputs) y NORA lo deriva solo; con él, el panel de Ejecutar muestra un formulario precargado en lugar de un JSON crudo. Detalle completo en Argumentos de entrada/salida.
  • timeout_seconds (0 = sin límite), max_retries, auto_retry, retry_delay_seconds.
  • sla_deadline_minutes, on_success_trigger_process_id (encadenar procesos), tags.
  • required_assets: lista de assets que el robot puede leer en tiempo de ejecución. Si no está vacía, el token por job se limita exactamente a esos nombres (un robot comprometido no puede leer el resto de la bóveda del tenant).

Formulario de parámetros de entrada que NORA genera al ejecutar un proceso, derivado de su input_schema: campos "mes", "reintentos" y "enviar_correo" con sus tipos y descripciones.

Para cambiar la versión activa (promover o hacer rollback) sin recrear el proceso, usa PATCH /api/v1/processes/{process_id}/active-release con {"release_id": "…"}. Activar/desactivar un proceso: PATCH /api/v1/processes/{process_id}/toggle.

Para integraciones externas, NORA expone un endpoint con API key (cabecera X-API-Key: nora_ak_…), que requiere el scope processes:read y está limitado a 60 peticiones/minuto:

Ventana de terminal
curl https://nora-api.valisoftconsulting.com/api/v1/processes/list \
-H "X-API-Key: nora_ak_tu_clave_aqui"

Devuelve solo procesos activos, paginado (page, limit, folder_id opcionales) y con la envoltura habitual:

{
"success": true,
"data": [
{ "id": "", "name": "Facturacion mensual", "release_id": "", "is_active": true }
],
"meta": { "page": 1, "limit": 20, "total": 1, "pages": 1 }
}

Con el id del proceso ya puedes dispararlo desde la API. Consulta jobs y autenticación.