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.
01plazbot workers deploy [archivo] [options]
Parámetros
| Parámetro | Flag | Requerido | Descripción |
|---|---|---|---|
| Archivo | [archivo] | No | Ruta 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> | No | Nombre del worker; reemplaza el name del archivo. Solo con un archivo. |
| Descripción | --description <text> | No | Descripción del worker; reemplaza la reference del archivo. Solo con un archivo. |
| JSON | --json | No | Imprime el resultado de cada archivo como un arreglo JSON. |
Ejemplos
01# Desplegar un solo archivo02plazbot workers deploy ./workers/get-stock.ts0304# Desplegar todos los *.ts de ./workers05plazbot workers deploy0607# Desplegar con nombre y descripción propios08plazbot workers deploy ./workers/cron.ts -n "daily-report" --description "Genera los KPIs del día"0910# Desplegar todo y obtener el resultado por archivo en JSON (CI)11plazbot workers deploy --json
Qué sucede al desplegar
- 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 deplazbot/workers. - El servidor de Plazbot detecta el tipo por la función
define*usada, extraename,reference,cron,timezone,methody los parámetros, y compila el TypeScript a JavaScript. - Se crea o actualiza el worker (por nombre) y se guarda una versión.
- 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
01 Deploying 2 workers02 ────────────────────────────────────────03✔ daily-report.ts → daily-report (schedule)04✔ get-stock.ts → get-stock (tool)0506 2 workers deployed07┌─────────────────┬──────────────┬──────────┬────────┬───────────┐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:
01✖ broken.ts: Codigo no permitido: Uso de eval() no permitido02...03 1 of 3 workers failed to deploy04 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.
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
| Mensaje | Causa | Solució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ón | Tipo | Se ejecuta cuando... |
|---|---|---|
defineTool | tool | Un agente IA decide usarlo durante una conversación. |
defineWorker | worker | Ocurre un evento de la plataforma (mensaje, contacto, conversación). |
defineSchedule | schedule | Se cumple su expresión cron. |
defineSync | sync | Se cumple su cron; trae registros externos y los aplica a contactos. |
defineWebhook | webhook | Llega 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? }.
01import { defineTool } from 'plazbot/workers'0203export 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.
01import { defineWorker } from 'plazbot/workers'0203export 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.data09 if (!contact) return10 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.
01import { defineSchedule } from 'plazbot/workers'0203export 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.
01import { defineSync } from 'plazbot/workers'0203export 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.
01import { defineWebhook } from 'plazbot/workers'0203export default defineWebhook({04 name: 'payments',05 reference: 'Recibe pagos confirmados',06 method: 'POST',07 async handler(request, plz) {08 const body = request.body as any09 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.