Producto
CLI

Desplegar workers

Despliega un archivo de worker, o todos los de ./workers, en tu workspace.

Desplegar workers

Sube uno o varios archivos TypeScript de worker a tu workspace. Si no indicas un archivo, despliega todos los *.ts de la carpeta ./workers. Si ya existe un worker con el mismo nombre, se actualiza y se guarda una versión nueva.

bash
01plazbot workers deploy [archivo] [options]

Parámetros

ParámetroFlagRequeridoDescripción
Archivo[archivo]NoRuta al archivo .ts del worker. Si se omite, se despliegan todos los *.ts de ./workers (se ignoran los *.d.ts), en orden alfabético.
Nombre-n, --name <name>NoNombre del worker; reemplaza el name del archivo. Solo con un archivo.
Descripción--description <text>NoDescripción del worker; reemplaza la reference del archivo. Solo con un archivo.
JSON--jsonNoImprime el resultado de cada archivo como un arreglo JSON.

Ejemplos

bash
01# Desplegar un solo archivo
02plazbot workers deploy ./workers/get-stock.ts
03 
04# Desplegar todos los *.ts de ./workers
05plazbot workers deploy
06 
07# Desplegar con nombre y descripción propios
08plazbot workers deploy ./workers/cron.ts -n "daily-report" --description "Genera los KPIs del día"
09 
10# Desplegar todo y obtener el resultado por archivo en JSON (CI)
11plazbot workers deploy --json

Qué sucede al desplegar

  1. El CLI lee cada archivo y envía solo ese código fuente. No se empaquetan imports relativos (./utils) ni dependencias de npm: todo el worker debe vivir en un único archivo que importe solo de plazbot/workers.
  2. El servidor de Plazbot detecta el tipo por la función define* usada, extrae name, reference, cron, timezone, method y los parámetros, y compila el TypeScript a JavaScript.
  3. Se crea o actualiza el worker (por nombre) y se guarda una versión.
  4. Si es un webhook, se genera su URL pública y el CLI la muestra.

name, reference y cron se leen del código como texto literal: escríbelos como strings (name: 'get-stock'), no como variables. El servidor rechaza código que use eval(), new Function(), require(), import() dinámico, process.env o Deno.*; para secretos usa plz.env. El compilador del servidor quita anotaciones de tipo simples (: string, as any); evita genéricos explícitos (defineSync<...>) y aserciones con tipos objeto (as { ... }).

Resultado

text
01 Deploying 2 workers
02 ────────────────────────────────────────
03✔ daily-report.ts → daily-report (schedule)
04✔ get-stock.ts → get-stock (tool)
05 
06 2 workers deployed
07┌─────────────────┬──────────────┬──────────┬────────┬───────────┐
08│ File │ Name │ Type │ Status │ URL/Cron │
09├─────────────────┼──────────────┼──────────┼────────┼───────────┤
10│ daily-report.ts │ daily-report │ schedule │ active │ 0 8 * * * │
11├─────────────────┼──────────────┼──────────┼────────┼───────────┤
12│ get-stock.ts │ get-stock │ tool │ active │ — │
13└─────────────────┴──────────────┴──────────┴────────┴───────────┘

Para webhooks se añade una sección Webhook URLs con la URL de cada uno. Si algún archivo falla, los demás se despliegan igual y al final se listan los fallidos:

text
01✖ broken.ts: Codigo no permitido: Uso de eval() no permitido
02...
03 1 of 3 workers failed to deploy
04 broken.ts: Codigo no permitido: Uso de eval() no permitido

El comando termina con código 1 si al menos un archivo falla.

Salida JSON

Un arreglo con un objeto por archivo. Los campos vacíos se omiten.

json
01[
02 {
03 "file": "get-stock.ts",
04 "name": "get-stock",
05 "type": "tool",
06 "status": "deployed",
07 "workerStatus": "active"
08 },
09 {
10 "file": "stripe-payments.ts",
11 "name": "stripe-payments",
12 "type": "webhook",
13 "status": "deployed",
14 "workerStatus": "active",
15 "webhookUrl": "https://..."
16 },
17 {
18 "file": "broken.ts",
19 "status": "failed",
20 "error": "Codigo no permitido: Uso de eval() no permitido"
21 }
22]

Errores comunes

MensajeCausaSolución
No worker files found to deploy.No pasaste archivo y ./workers no existe o no tiene *.ts.Pasa la ruta del archivo o crea los workers en ./workers.
File not found: <archivo>.La ruta indicada no es un archivo.Revisa la ruta.
--name and --description only apply to a single file, but N files were found in ./workers.Usaste -n o --description sin indicar un archivo.Despliega un archivo a la vez: plazbot workers deploy ./workers/my-tool.ts -n "my-tool".
No se detecto un define* valido (...)El archivo no usa ninguna función define*.Exporta el worker con defineTool, defineWorker, defineSync, defineSchedule o defineWebhook.
El worker debe tener un nombre (...)No hay name literal en el archivo.Agrega name: 'mi-worker' o usa --name.
Codigo no permitido: ...El código usa una API bloqueada.Reemplázala por el SDK (plz.fetch, plz.env).
You are not signed in.No hay sesión.Ejecuta plazbot login.

Tipos de worker

El archivo debe exportar por defecto el resultado de una función define* del paquete plazbot/workers (incluido en el SDK plazbot). Cada handler recibe el contexto plz con la API del workspace (plz.contacts, plz.whatsapp, plz.fetch, plz.log, plz.env, etc.; ver Runtime: Contactos).

FunciónTipoSe ejecuta cuando...
defineTooltoolUn agente IA decide usarlo durante una conversación.
defineWorkerworkerOcurre un evento de la plataforma (mensaje, contacto, conversación).
defineSchedulescheduleSe cumple su expresión cron.
defineSyncsyncSe cumple su cron; trae registros externos y los aplica a contactos.
defineWebhookwebhookLlega una petición HTTP a su URL pública.

defineTool

Herramienta que un agente IA ejecuta. El agente usa reference para decidir cuándo invocarla y extrae los parameters de la conversación. Tipos de parámetro: string, number, boolean, date, email, phone. El handler devuelve { result, data?, actions? }.

typescript
01import { defineTool } from 'plazbot/workers'
02 
03export default defineTool({
04 name: 'get-stock',
05 reference: 'Consulta el stock de un producto',
06 parameters: {
07 product: { type: 'string', description: 'Nombre del producto', required: true },
08 },
09 async handler(input, plz) {
10 const res = await plz.fetch(`https://api.example.com/stock?q=${input.product}`, {
11 headers: { Authorization: `Bearer ${plz.env.INVENTORY_API_KEY}` },
12 })
13 const data = await res.json()
14 return {
15 result: `Hay ${data.quantity} unidades de ${input.product}`,
16 actions: [{ type: 'tag', value: 'consulto-stock' }],
17 }
18 },
19})

Acciones disponibles en actions: tag, removeTag, setVariable (con code), setStage, setSegmentation, assignAgent, resolve.

defineWorker

Escucha eventos de la plataforma. Requiere al menos un evento en events: message.received, message.image.received, message.audio.received, message.document.received, contact.created, contact.existing, contact.deleted, contact.blocked, contact.from.ad, conversation.assigned, conversation.resolved, conversation.reopened.

typescript
01import { defineWorker } from 'plazbot/workers'
02 
03export default defineWorker({
04 name: 'welcome',
05 reference: 'Etiqueta a los contactos nuevos',
06 events: ['contact.created'],
07 async handler(event, plz) {
08 const { contact } = event.data
09 if (!contact) return
10 await plz.contacts.addTag(contact.id, 'nuevo')
11 },
12})

defineSchedule

Tarea periódica con una expresión cron de 5 campos y timezone IANA opcional. El handler recibe solo plz.

typescript
01import { defineSchedule } from 'plazbot/workers'
02 
03export default defineSchedule({
04 name: 'daily-report',
05 reference: 'Cuenta los chats pendientes cada mañana',
06 cron: '0 8 * * *',
07 timezone: 'America/Lima',
08 async handler(plz) {
09 const pending = await plz.contacts.list({ filter: { isSolved: false }, limit: 1000 })
10 plz.log.info(`Chats pendientes: ${pending.length}`)
11 },
12})

defineSync

Sincroniza datos externos con contactos: fetch trae los registros, map convierte cada uno en { match, variables?, contact? } (o null para omitirlo) y Plazbot crea o actualiza el contacto. Usa schedule (cron) y source (nombre del sistema origen). En fetch, plz.cursor y plz.setCursor() guardan el punto de la última sincronización.

typescript
01import { defineSync } from 'plazbot/workers'
02 
03export default defineSync({
04 name: 'crm-customers',
05 reference: 'Sincroniza el plan de los clientes del CRM',
06 source: 'CRM',
07 schedule: '0 * * * *',
08 async fetch(plz) {
09 const res = await plz.fetch('https://api.example.com/customers')
10 return res.json()
11 },
12 map(customer: any) {
13 return {
14 match: { email: customer.email },
15 variables: { crm_plan: customer.plan },
16 }
17 },
18})

defineWebhook

Endpoint HTTP público para recibir eventos de otras apps. method es GET, POST, PUT, PATCH o DELETE. El handler recibe request (method, headers, query, body, url) y devuelve { status, headers?, body? }. La URL se muestra al desplegar y en plazbot workers list --json.

typescript
01import { defineWebhook } from 'plazbot/workers'
02 
03export default defineWebhook({
04 name: 'payments',
05 reference: 'Recibe pagos confirmados',
06 method: 'POST',
07 async handler(request, plz) {
08 const body = request.body as any
09 if (body.email) {
10 const [contact] = await plz.contacts.search({ email: body.email })
11 if (contact) await plz.contacts.addTag(contact.id, 'cliente-pago')
12 }
13 return { status: 200, body: { received: true } }
14 },
15})

Si el worker usa secretos (plz.env.MI_SECRET), configúralos antes con plazbot workers secret set MI_SECRET. Después de desplegar, pruébalo con plazbot workers test.

¿Quieres probar la API en vivo? Abre el Playground.