# Tipos de workers

> Tipos de workers

Source: https://docs.plazbot.com/kb/tipos-de-workers

Hay cinco tipos de workers y cada uno se activa de una forma distinta. **El tipo lo define la función que usas en el código**:

Tipo

Función

Cuándo se ejecuta

`run` recibe

Tool

`defineTool`

Tu agente de IA la usa cuando la necesita

`payload, plz`

Webhook

`defineWebhook`

Otro sistema hace un POST a su URL

`payload, plz`

Schedule

`defineSchedule`

Corre solo, según un horario (cron)

`plz`

Sync

`defineSync`

Por horario, y recuerda hasta dónde llegó

`plz`

Worker

`defineWorker`

La acción **Ejecutar Worker** del agente o la API

`payload, plz`

**Importante:** `plz.contacts`, `plz.whatsapp` y las demás llamadas a datos de Plazbot necesitan los secrets `PLZ_API_KEY` y `PLZ_ZONE` (ver **Secrets**). `plz.fetch`, `plz.log`, `plz.kv` y `plz.env` funcionan sin ellos.

[Watch the video on YouTube](https://www.youtube.com/watch?v=e_dFJZ50ZFk)

## Tool: una herramienta para tu agente

```ts
import { defineTool } from 'plz/workers'

export default defineTool({
  name: 'consultar-pedido',
  reference: 'Consulta el estado de un pedido cuando el cliente da su numero',
  agents: ['agt_1x8r3w'],
  parameters: [
    { name: 'numeroPedido', type: 'string', description: 'Numero de pedido', example: 'Cual es tu pedido?' }
  ],

  async run(payload, plz) {
    const { numeroPedido, contactId } = payload
    plz.log.info('Consultando pedido', { numeroPedido, contactId })
    const res = await plz.fetch(`https://api.tutienda.com/pedidos/${numeroPedido}`)
    if (!res.ok) return { result: `No encontre el pedido ${numeroPedido}` }
    const pedido = await res.json()
    return { result: `Pedido ${numeroPedido}: ${pedido.estado}` }
  }
})
```

- `agents`: los IDs de los agentes que pueden usar la herramienta.
- `parameters`: los datos que el agente debe conseguir del cliente. **Cada parámetro va en una sola línea**, con `name`, `type`, `description` y, opcionalmente, `example` (la pregunta que el agente le hará al cliente).

### Así lo usa el agente

1. El cliente pregunta por su pedido. El agente ve la herramienta `worker_consultar-pedido` con tu **Referencia** y decide usarla.
2. Si le falta el número de pedido, lo pregunta.
3. Llama al worker. El `payload` trae los parámetros más `contactId`, `agentId`, `workspaceId` y `workerName`.
4. Responde con lo que devuelve `result`. **El agente solo lee** `result`: el resto de lo que devuelvas no le llega.

## Webhook: recibe datos de otros sistemas

```ts
import { defineWebhook } from 'plz/workers'

export default defineWebhook({
  name: 'nuevo-lead',
  reference: 'Recibe leads del formulario web',

  async run(payload, plz) {
    const { email, nombre } = payload
    plz.log.info('Lead recibido')
    if (!email) return { ok: false, motivo: 'email requerido' }
    await plz.kv.set(`lead:${email}`, { nombre, recibido: new Date().toISOString() }, { ttl: 86400 })
    return { ok: true, email }
  }
})
```

El cuerpo JSON de la petición llega en `payload`. `plz.kv.set` guarda datos con vencimiento (`ttl` en segundos: 86400 = 1 día).

Al desplegarlo, Plazbot crea una **URL única** que ves en la cabecera del worker (botón **Ver cURL**):

```bash
curl -X POST 'https://api.plazbot.com/api/worker/webhook/nuevo-lead?workspace=wok_8f2kQxLm4Tz9' \
  -H 'Content-Type: application/json' \
  -d '{"email":"ana@tuempresa.com","nombre":"Ana"}'
```

Respuesta:

```json
{
  "success": true,
  "result": { "ok": true, "email": "ana@tuempresa.com" },
  "duration": 184,
  "logs": [ ... ]
}
```

- Acepta **solo POST** y es **pública**: no pide token.
- La respuesta incluye los **logs**. **Nunca escribas datos sensibles en los logs de un webhook.**

## Schedule: una tarea programada

```ts
import { defineSchedule } from 'plz/workers'

export default defineSchedule({
  name: 'contar-pendientes',
  reference: 'Cuenta los chats pendientes',
  cron: '*/5 * * * *',
  timezone: 'America/Lima',

  async run(plz) {
    const pendientes = await plz.contacts.list({ filter: { isSolved: false }, limit: 1000 })
    plz.log.info(`Chats pendientes: ${pendientes.length}`)
    return { pendientes: pendientes.length }
  }
})
```

- `cron`: cinco campos (minuto, hora, día, mes, día de la semana). Lo más frecuente es cada minuto.

cron

Significa

`*/5 * * * *`

Cada 5 minutos

`0 9 * * 1-5`

A las 9:00, de lunes a viernes

- `timezone`: tu zona horaria. Sin ella, el horario es **UTC**.
- `run(plz)` no recibe payload: nadie lo llama, corre solo.

## Sync: sincroniza solo lo nuevo

```ts
import { defineSync } from 'plz/workers'

export default defineSync({
  name: 'sync-productos',
  reference: 'Trae los productos nuevos de la tienda',
  cron: '*/30 * * * *',

  async run(plz) {
    const desde = Number(plz.cursor ?? '0')
    const res = await plz.fetch(`https://api.tutienda.com/productos?desde=${desde}&limite=50`)
    const items = await res.json()
    for (const item of items) await plz.kv.set(`producto:${item.id}`, { nombre: item.nombre })
    plz.setCursor(String(desde + items.length))
    plz.log.info(`Sincronizados ${items.length} desde ${desde}`)
    return { synced: items.length }
  }
})
```

Un Sync es un Schedule con memoria: `plz.cursor` es donde quedaste en la ejecución anterior (la primera vez está vacío) y `plz.setCursor()` guarda el nuevo punto.

**Ojo:** probarlo con **Test** también guarda el cursor.

## Worker: lo ejecutas cuando lo necesitas

```ts
import { defineWorker } from 'plz/workers'

export default defineWorker({
  name: 'marcar-derivado',
  reference: 'Etiqueta y avisa cuando el agente deriva al contacto',

  async run(payload, plz) {
    const { contactId, contact } = payload
    if (!contactId) return { ok: false, motivo: 'contactId requerido' }
    await plz.contacts.addTag(contactId, 'derivado')
    if (contact?.phoneNumber) {
      await plz.whatsapp.send({ to: contact.phoneNumber, message: 'Un asesor te atendera en breve' })
    }
    return { ok: true }
  }
})
```

Aunque el selector de tipo dice **«Worker - Escuchar eventos»**, hoy un Worker **no se activa solo con eventos**. Se ejecuta de dos formas:

**Desde tu agente:** en una acción, agrega **Ejecutar Worker** y elige el worker en **Seleccionar worker...**. El ícono de ayuda muestra el payload que recibe:

```json
{
  "contactId": "ctc_f7g8h9j0",
  "agentId": "agt_1x8r3w",
  "workspaceId": "wok_8f2kQxLm4Tz9",
  "workerName": "marcar-derivado",
  "contact": {
    "name": "Juan", "phoneNumber": "+521234567890",
    "tags": [ … ], "variables": [ … ]
  }
}
```

**Desde tus sistemas:**

```bash
curl -X POST 'https://api.plazbot.com/api/worker/execute' \
  -H 'Content-Type: application/json' \
  -H 'x-workspace-id: wok_8f2kQxLm4Tz9' \
  -H 'x-api-key: TU_TOKEN_DE_API' \
  -d '{
    "workerName": "marcar-derivado",
    "type": "worker",
    "payload": { "contactId": "ctc_f7g8h9j0" },
    "triggerSource": "api"
  }'
```

`x-api-key` es tu token de API de **Configuración › Developer**.
