Functions
Tu agente no es un formulario.Es un archivo de tu repo.
Declara el agente y las herramientas que puede llamar en TypeScript. Despliega el directorio. Zavu lo construye, guarda los secretos, lo ejecuta con tus eventos o en horario, y reconcilia el agente en vivo con lo que dice el archivo.
- Runtime
- nodejs24
- Se fija en el primer deploy y se mantiene, así ningún deploy posterior lo mueve por debajo.
- Timeout
- 1–180 s
- Por defecto 30. Qué techo manda depende del trigger.
- Memoria
- 128 · 256 · 512 · 1024
- MB por invocación. La mayoría de los handlers cabe en el más pequeño.
- Código
- 200 archivos · 900.000 bytes
- Los paquetes npm se declaran, no se suben.
01 — Escríbelo
Un directorio, un entrypoint y lo que importe.
El deploy arranca en el entrypoint y sigue los imports relativos. Lo que alcanza se sube; lo que nadie importa se queda en tu máquina.
Qué se sube de verdad
Elige un archivo. El panel dice si viaja con el deploy, y por qué.
import { defineAgent, defineTool } from "@zavudev/functions"
import { formatOrder, lookupOrder } from "./lib/orders"
import { HOST_PROMPT } from "./prompts/host"
defineAgent({
senderId: process.env.SENDER_ID!,
name: "Bella",
provider: "zavu",
model: "openai/gpt-4o-mini",
prompt: HOST_PROMPT,
})
defineTool({
name: "lookup_order",
description: "Get current status of an order. Use when the customer asks about one.",
parameters: {
type: "object",
properties: { orderId: { type: "string" } },
required: ["orderId"],
},
handler: async ({ orderId }, ctx) => {
ctx.log("lookup", orderId)
return formatOrder(await lookupOrder(orderId))
},
})El entrypoint. El deploy lo lee primero y desde aquí recorre sus imports relativos. Por defecto es index.ts — usa entrypoint por REST, o --source en la CLI, para nombrar otro.
Rutas rechazadas
La CLI y la API son la misma superficie.
Usa la que encaje con tu forma de trabajar. Nada de esto existe solo en una de las dos.
import { defineAgent, defineTool } from "@zavudev/functions"
defineAgent({
senderId: process.env.SENDER_ID!,
name: "Bella",
provider: "zavu",
model: "openai/gpt-4o-mini",
prompt: "You are Bella, host at the restaurant. Be brief.",
})
defineTool({
name: "check_availability",
description: "Get free reservation slots for a date.",
parameters: {
type: "object",
properties: { date: { type: "string" }, partySize: { type: "number" } },
required: ["date", "partySize"],
},
handler: async ({ date, partySize }) => {
return { available: true, slots: ["19:00", "21:00"] }
},
})02 — Despliégalo
Un deploy es un registro que puedes mirar, y al que puedes volver.
Desplegar responde de inmediato con un id. Tú lo consultas. Cada versión se conserva, con la salida del build que la explica.
Ciclo de vida del deployment
Avanza paso a paso, o déjalo correr. Rompe un import para tomar el otro camino.
superseded — en lo que se convierte una versión cuando otra más nueva toma su lugar. Sigue legible, y volver a ella es una sola llamada.
{
"id": "fnd_8c21ab5f",
"functionId": "fn_4kq2m9x",
"version": 7,
"status": "pending",
"sourceCodeBytes": 18432,
"bundleBytes": null,
"errorMessage": null,
"deployedAt": null,
"createdAt": "2026-03-14T09:41:12.000Z"
}Consulta hasta que status sea active o failed. Ambos son terminales.
Rollback
Vuelves atrás nombrando un id de deployment. Su código, sus dependencias y su runtime se copian al draft y se despliegan de nuevo como una versión más, así que el historial solo crece. Los secretos no vuelven atrás: son actuales, no versionados.
Deploy desde GitHub
Enlaza un repositorio y un push a la rama lo despliega. Cómo se autentica el enlace lo decide el servidor, no tú: con la GitHub App de Zavu instalada, los repos privados funcionan y no hay nada que agregar al repositorio. Sin ella obtienes un enlace manual, y su secreto de webhook se imprime exactamente una vez. Enlazar no verifica el repositorio contra GitHub — un owner/repo que la instalación no puede ver se acepta y falla en el primer deploy.
- connection
- app o manual — lo elige el servidor
- branch
- solo los pushes aquí despliegan
- rootDir
- el subdirectorio, para monorepos
- autoDeploy
- en false conserva el enlace e ignora los pushes
- lastStatus
- deploying, deployed o failed
- lastError
- por qué no aterrizó el último push
03 — Ejecútalo
Con tus eventos, o con el reloj.
Un trigger suscribe la función a un tipo de evento, para un sender o para todos. El tipo especial cron la ejecuta en horario.
Constructor de triggers
Elige tipos de evento y senders. El request y los triggers que crea aparecen a la derecha, y una expresión cron se resuelve a sus próximas ejecuciones en UTC.
Tipos de evento
Senders
Agrega el tipo de evento cron arriba para ejecutar la función en horario en vez de suscribirla a un mensaje. Toma una expresión de cinco campos en UTC, y una función puede tener varias con horarios distintos.
{
"eventTypes": [
"message.inbound"
],
"senderIds": [
null
]
}{
"added": 1,
"skipped": 0,
"triggers": [
{
"id": "fnt_0001",
"eventType": "message.inbound",
"senderId": null,
"active": true
}
]
}Un trigger por tipo de evento × sender. Un trigger cron ignora el eje de senders, así que cuenta una vez sin importar cuántos elijas. Los duplicados vuelven como skipped, no se crean dos veces.
Vale la pena saberlo
El timeout que fijas no siempre es el techo que manda.
Ejecuciones por evento y por cron
Asíncronas. Nadie espera la respuesta, así que un timeout largo solo acota lo que te cuesta una ejecución atascada.
Una herramienta en plena conversación
Síncrona. La respuesta al cliente espera a tu handler, así que mantenlos bien por debajo del límite, no pegados a él.
Una función expuesta por HTTP
Además la acota el tope de respuesta HTTP de la plataforma. Subir timeoutSec no sube ese.
04 — Opéralo
Secretos, logs y un endpoint cuando lo quieras.
Los secretos entran y no vuelven
Listarlos devuelve cada clave y los últimos cuatro caracteres de su valor, nunca el valor. Las claves van en mayúsculas estilo variable de entorno, y los prefijos AWS_ y LAMBDA_ están reservados. Definir uno marca la función como desincronizada en vez de reiniciarla por debajo; el siguiente deploy lo aplica.
Una API key que no tuviste que cablear
Crear una función aprovisiona una key de Zavu con alcance acotado y la inyecta como ZAVU_API_KEY, así un handler llama de vuelta a la API sin que administres credenciales. Para más alcance, crea tu propia key y ponla como secreto.
Logs, filtrados y paginados
Trae los logs de invocación acotados por ventana de tiempo o filtrados por patrón, y págilos con nextToken. La misma salida se sigue en vivo desde la CLI mientras trabajas.
Un endpoint HTTPS, con interruptor
Encender la URL pública aplica a la función ya desplegada — sin redeploy. Apagada, la URL guardada deja de servir y ya no se devuelve, así que publicUrl viene en null en vez de quedar obsoleta.
Escríbelo, despliégalo, mira los logs.
Empieza gratis, sin tarjeta. La CLI habla con la misma API que usará tu código.