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.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.
  • 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).

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.