Colas (queues)
Una cola (queue) es una lista de unidades de trabajo que NORA reparte entre uno o varios robots. En lugar de codificar “qué procesar” dentro del bot, los datos se cargan como items y los robots los consumen uno a uno. Esto permite paralelizar el trabajo, reintentar lo que falla y mantener un registro auditable de cada unidad procesada.

El patrón es productor / consumidor:
- El productor llena la cola con items (desde el panel, desde otro bot, o vía API con
X-API-Key). - El consumidor (un robot ejecutando un job) toma items, los procesa y reporta el resultado.
flowchart TD
P[Productor: panel / API / otro bot] -->|añade items| Q[(Cola)]
Q -->|toma el siguiente item| R[Robot / Job]
R -->|completa o falla| Q
R -.->|envía a revisión| H[Revisor humano]
H -.->|aprueba / rechaza| Q
Anatomía de una cola
Sección titulada «Anatomía de una cola»Una cola pertenece a un workspace (tenant) y su name es único dentro de él. Campos principales (modelo Queue):
| Campo | Descripción |
|---|---|
name | Nombre único en el workspace. El robot lo usa para identificar la cola. |
description | Texto libre opcional. |
max_retries | Reintentos antes de marcar un item como dead_letter. Rango 0–10 (por defecto 3). |
Items y sus estados
Sección titulada «Items y sus estados»Cada item (QueueItem) lleva la carga útil en data (un objeto JSON libre) y avanza por una máquina de estados. Campos relevantes:
| Campo | Descripción |
|---|---|
data | Carga útil JSON definida por el productor. |
priority | 1 = baja, 3 = normal (por defecto), 5 = urgente. |
reference | Clave de negocio opcional fijada por el productor (buscable). |
deadline | SLA opcional; los items con deadline más próximo se despachan primero. |
postpone | El robot omite el item hasta que llegue este instante. |
result | Resultado JSON que escribe el robot al completar. |
retry_count | Número de reintentos consumidos. |
error_message | Motivo del último fallo o rechazo. |
processed_by | id del job que procesó el item. |
reviewed_by / reviewed_at | Usuario y momento de la revisión humana. |
Estados que escribe la plataforma a lo largo del ciclo de vida:
| Estado | Significado |
|---|---|
new | Listo para ser tomado por un robot. |
in_progress | Un robot lo está procesando. |
pending_review | Pausado, esperando aprobación humana. |
completed | Procesado con éxito (lleva result). |
failed | Falló o fue rechazado por un revisor. |
dead_letter | Superó max_retries; ya no se reintenta solo. |
stateDiagram-v2
[*] --> new
new --> in_progress
in_progress --> completed
in_progress --> pending_review
in_progress --> failed
pending_review --> new : aprobado
pending_review --> failed : rechazado
failed --> dead_letter : sin reintentos
failed --> new : reintento
dead_letter --> new : reintento manual
Cargar items (productor)
Sección titulada «Cargar items (productor)»Desde la API pública, el productor añade items a una cola identificándola por nombre, con una API key de scope queues:write. La respuesta va envuelta en { "data": ... } (ver autenticación).
curl -X POST \ "https://nora-api.valisoftconsulting.com/api/v1/queues/by-name/facturas/items" \ -H "X-API-Key: nora_ak_xxx" \ -H "Content-Type: application/json" \ -d '{ "data": {"numero": "F-001", "proveedor": "Acme", "monto": 15420}, "priority": 5, "reference": "F-001" }'{ "success": true, "data": { "id": "…", "queue_id": "…", "status": "new", "priority": 5, "reference": "F-001", "data": {"numero": "F-001", "proveedor": "Acme", "monto": 15420}, "result": null, "retry_count": 0 }}Para carga masiva existe el endpoint .../items/bulk (hasta 1000 items por petición, scope queues:write). Los detalles completos de todos los endpoints están en la referencia de colas en la API.
Consumir items (robot)
Sección titulada «Consumir items (robot)»El robot, dentro de su job, toma el siguiente item disponible y reporta el desenlace mediante el NORA Agent SDK. La selección respeta priority, deadline y postpone.
from nora_agent import sdk
while True: item = sdk.get_queue_item("facturas") # toma el siguiente; None si está vacía if item is None: break try: resultado = procesar(item["data"]) sdk.complete_queue_item("facturas", item["id"], resultado) except Exception as e: # Reintenta hasta max_retries; luego pasa a dead_letter sdk.fail_queue_item("facturas", item["id"], str(e))Aprobación humana (human-in-the-loop)
Sección titulada «Aprobación humana (human-in-the-loop)»Cuando un paso requiere validación, el robot puede pausar el item y esperar la decisión de una persona antes de continuar. El flujo lo expone el SDK y la decisión se toma desde el panel.
sequenceDiagram
participant R as Robot
participant N as NORA
participant H as Revisor
R->>N: send_queue_item_for_review(item)
Note over N: status → pending_review
N-->>H: notificación en el panel
H->>N: Aprobar / Rechazar
R->>N: wait_for_queue_review(item)
N-->>R: "approved" o "rejected"
alt aprobado
R->>N: complete_queue_item(...)
else rechazado
Note over N: status → failed
end
- El robot llama a
send_queue_item_for_review(...); el item pasa apending_reviewy se notifica al panel. - El robot bloquea con
wait_for_queue_review(...)(sondea hasta un timeout configurable). - Un revisor abre la cola, revisa los
datadel item y aprueba (vuelve anewpara que el robot lo procese) o rechaza (quedafailed). - El robot recibe
"approved"o"rejected"y actúa en consecuencia.
Quién puede revisar
Sección titulada «Quién puede revisar»Una cola puede tener revisores asignados (QueueReviewer). Si los tiene, solo esos usuarios reciben la notificación y pueden decidir. Si no tiene ninguno, cualquier admin u operator del workspace puede revisar. Asignar revisores es exclusivo de admin.
| Rol | Crear/editar colas y cargar items | Aprobar/rechazar | Asignar revisores |
|---|---|---|---|
admin | Sí | Sí | Sí |
operator | Sí | Sí (si está asignado o la cola no tiene revisores) | No |
viewer | No (solo lectura) | No | No |
Desde el panel también puedes aplicar acciones masivas sobre varios items a la vez: retry, approve, reject o delete.
La superficie pública completa de la API está documentada en la referencia de la API.