# Una tarea que pide aprobación humana

Hay pasos que no quieres automatizar del todo: aplicar un descuento, mandar un contrato,
emitir una nota crédito. Una **tarea** puede hacer todo el trabajo previo y **detenerse**
justo antes de ese paso, esperando a una persona.

Esta receta conecta esa pausa con tu propio sistema, para que la decisión se tome donde ya
trabaja tu equipo en vez de en un panel más.

## Antes de empezar

Tu key necesita `tasks:read` y `tasks:write`.

## Las dos pausas, que no son la misma

| | quién hace el trabajo | cómo se destraba |
|---|---|---|
| **Aprobación** | el Met, y pide permiso para seguir | `approveStep` / `rejectStep` |
| **Paso humano** | la persona | `completeHumanStep` |

Confundirlas es el error más común: si el trabajo lo hizo el Met y tú llamas
`completeHumanStep`, la ejecución avanza sin que nadie haya aprobado nada.

## 1. Dispara la tarea

```ts
import Met from '@meteor.ia/sdk';

const met = new Met(process.env.MET_API_KEY!, {
  workspaceId: Number(process.env.MET_WORKSPACE_ID),
});

const ejecucion = await met.tasks.execute('tsk_123');
// → { id: 'tex_…', status: 'running', … }
```

## 2. Detecta que se detuvo y en qué paso

El detalle de la ejecución trae el resultado de cada paso de esa corrida en
`task_step_executions`:

```ts
const estado = await met.tasks.execution(ejecucion.id);

const pendiente = estado.task_step_executions.find(
  (p) => p.status === 'waiting_for_approval' || p.status === 'waiting_for_human',
);

if (pendiente) {
  await avisarleATuEquipo({
    ejecucion: ejecucion.id,
    paso: pendiente.step_id,     // ← el del paso, no el de su corrida
    tipo: pendiente.status,
    loQueHizoElMet: pendiente.output,
  });
}
```

Un paso de ejecución pasa por `pending`, `running`, `completed`, `failed`,
`waiting_for_approval`, `waiting_for_human`, `approved` y `rejected`.

> Cada fila tiene **dos** identificadores: `id` es el de esa corrida del paso y `step_id`
> es el del paso dentro de la receta. Aprobar y rechazar piden el **`step_id`**. Con el
> otro, la respuesta es un 404 que parece decir que el paso no existe.

Sondear está bien para empezar, pero para producción es mejor enterarse: suscríbete a
`task.completed` con [webhooks firmados](receta-webhooks-firmados.html) y deja de
preguntar.

## 3. Deja que tu equipo decida desde donde ya trabaja

```ts
const stepId = pendiente.step_id;

// Aprobar: la ejecución sigue al paso siguiente, de forma asíncrona.
await met.tasks.approveStep(ejecucion.id, stepId, 'Va, los montos cuadran');

// Rechazar: esa rama se detiene.
await met.tasks.rejectStep(ejecucion.id, stepId, 'El descuento no está autorizado');

// Paso humano: lo hizo tu sistema, no el Met.
await met.tasks.completeHumanStep(ejecucion.id, stepId, 'Contrato firmado y archivado');
```

El comentario que mandas queda guardado en `approval_comment` del paso, junto con quién
decidió y cuándo. Es lo que después explica una corrida rara sin tener que reconstruirla.

> Las tres operan sobre el **id de la ejecución**, no el de la tarea. El paso pertenece a
> la receta, pero la pausa pertenece a la corrida: usar el id de la tarea es el error que
> más tiempo cuesta aquí.

## 4. Cortar una corrida

```ts
await met.tasks.cancelExecution(ejecucion.id);
```

Distinto de pausar la tarea con `met.tasks.setStatus(tarea.id, 'paused')`: eso impide que
nazcan ejecuciones nuevas y **no detiene las que están corriendo**.

## Lo que hay que decidir antes de poner esto en producción

Una ejecución detenida se queda detenida. Si nadie aprueba, ahí sigue — no hay tiempo
límite que la resuelva por ti. Decide desde el principio qué pasa con una aprobación que
nadie miró en 48 horas: recordar, escalar, o cancelar y rehacer. Es una decisión de
producto, y la respuesta "ya la mirará alguien" termina siempre en la misma llamada de un
cliente preguntando por algo que quedó a medias.

Y por lo mismo, una tarea con pausas humanas no va en CI: el job se queda esperando hasta
el tiempo límite. Para lo desatendido, mira
[ejecutar un Met desde GitHub Actions](receta-github-actions.html).

## Y después

- Pasos, disparadores y el modelo completo: [Tareas](tareas.html).
- Enterarte del final sin sondear: [Eventos en vivo](eventos.html).
