Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://docs.jelou.ai/llms.txt

Use this file to discover all available pages before exploring further.

Validación de entrada

Cuando defines un esquema input, cada petición se valida antes de ejecutar el handler. Si la validación falla, el handler no se ejecuta y se retorna un 400:
{
  "error": "Validation failed",
  "details": [
    {
      "path": ["email"],
      "message": "Invalid email",
      "code": "invalid_string"
    }
  ]
}

Ejemplo con esquema completo

index.ts
import { define, z } from "@jelou/functions";

export default define({
  name: "crear-ticket",
  description: "Crea un ticket de soporte desde WhatsApp",
  input: z.object({
    nombre: z.string().min(1).describe("Nombre del cliente"),
    email: z.string().email().describe("Email de contacto"),
    asunto: z.string().max(200).describe("Asunto del ticket"),
    prioridad: z.enum(["baja", "media", "alta"]).default("media"),
  }),
  output: z.object({
    ticketId: z.string(),
    estado: z.string(),
  }),
  handler: async (input, ctx) => {
    ctx.log("Creando ticket", { cliente: input.nombre, prioridad: input.prioridad });
    return { ticketId: "TKT-2024-0042", estado: "abierto" };
  },
});

Tipos soportados

Puedes usar cualquier tipo de Zod dentro de z.object():
input: z.object({
  nombre: z.string().min(1),
  edad: z.number().int().positive(),
  email: z.string().email(),
  activo: z.boolean().default(true),
  rol: z.enum(["admin", "usuario", "invitado"]),
  tags: z.array(z.string()).optional(),
  metadata: z.record(z.string(), z.unknown()).optional(),
})

Coerción en peticiones GET

Para peticiones GET, los query parameters son strings. Usa z.coerce para convertir tipos automáticamente:
index.ts
import { define, z } from "@jelou/functions";

export default define({
  name: "buscar-pedidos",
  description: "Busca pedidos por estado",
  input: z.object({
    q: z.string(),
    limit: z.coerce.number().default(10),
    pagina: z.coerce.number().default(1),
    activo: z.coerce.boolean().default(true),
  }),
  handler: async (input, ctx) => {
    ctx.log("Buscando", { q: input.q, limit: input.limit });
    return { resultados: [], total: 0 };
  },
});
curl "https://buscar-pedidos.fn.jelou.ai/?q=pendiente&limit=5&pagina=2"

Anotaciones .describe()

Usa .describe() en cada campo para documentar los parámetros. Estas descripciones aparecen automáticamente en el esquema MCP, lo que ayuda a los agentes IA a entender cómo usar tu función:
input: z.object({
  telefono: z.string().min(10).describe("Número de teléfono con código de país, ej: 593987654321"),
  incluirHistorial: z.boolean().default(false).describe("Si incluir el historial de conversaciones"),
})

Validación de salida

Cuando defines un esquema output, el valor retornado por el handler se valida después de la ejecución. Si no coincide:
  • Se registra una advertencia en los logs
  • La respuesta se envía normalmente con status 200
La validación de output nunca bloquea la respuesta. Es una herramienta de desarrollo para detectar inconsistencias.
output: z.object({
  nombre: z.string(),
  saldo: z.number(),
})
Si el handler retorna { nombre: "María", saldo: "150" } (saldo como string), verás una advertencia en los logs pero el cliente recibe la respuesta sin cambios.

Formato de errores de validación

Cada error en el array details contiene:
CampoTipoDescripción
pathstring[]Ruta al campo con error, ej: ["email"] o ["direccion", "ciudad"]
messagestringMensaje legible del error
codestringCódigo de error de Zod (ej: invalid_string, too_small, invalid_enum_value)
{
  "error": "Validation failed",
  "details": [
    {
      "path": ["nombre"],
      "message": "String must contain at least 1 character(s)",
      "code": "too_small"
    },
    {
      "path": ["prioridad"],
      "message": "Invalid enum value. Expected 'baja' | 'media' | 'alta', received 'urgente'",
      "code": "invalid_enum_value"
    }
  ]
}