Califica prospectos, muestra inventario real, agenda citas y toma pedidos — 24/7, en español e inglés. Un mismo motor; cambias un archivo de configuración y es un giro nuevo.
No es un chatbot de árbol de opciones. Es un agente que razona, usa herramientas y ejecuta acciones reales con cada cliente.
Número real vía WhatsApp Cloud API. El cliente escribe como a cualquier persona; el agente contesta al instante.
Detecta y responde en español o inglés. El mismo agente atiende a tu cliente local y a un inversionista extranjero.
Precios, inventario y totales salen SOLO de las herramientas. El modelo nunca inventa un dato.
Inmobiliaria hoy, restaurante mañana. Cambias el config-pack, no el código. Tú lo revendes a tus clientes.
En cada turno el modelo decide si necesita una herramienta, cuál y con qué datos. El servidor la ejecuta, le devuelve el resultado, y el ciclo se repite hasta que el agente tiene una respuesta. Los planes (calificar → buscar → agendar → entregar el lead) emergen del bucle, no de un flujo programado a mano.
Llega el mensaje del cliente (texto libre, ES/EN).
El modelo elige una herramienta y extrae los argumentos.
El servidor ejecuta la herramienta (busca, agenda, registra).
Le devuelve el resultado real; repite o responde.
Node puro. Las herramientas se exponen al modelo como funciones con esquema JSON; el modelo las llama de forma nativa. Este es el código real que corre en producción.
// Herramientas expuestas al modelo como funciones tipadas (JSON Schema)
const tools = config.tools.map(n => ({
name: n,
description: TOOLS[n].description,
input_schema: { type: "object", properties: SCHEMAS[n], required: REQUIRED[n] },
}));
// El bucle agéntico — hasta 8 saltos perceive→act→observe
for (let i = 0; i < 8; i++) {
const r = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: { "x-api-key": KEY, "anthropic-version": "2023-06-01" },
body: JSON.stringify({ model, system: config.systemPrompt, tools, messages: session.api }),
});
const data = await r.json();
if (data.error) throw new Error(data.error.message); // falla en voz alta
session.api.push({ role: "assistant", content: data.content });
const uses = data.content.filter(b => b.type === "tool_use"); // ¿llamó a una tool?
if (uses.length) {
session.api.push({ role: "user", content: uses.map(u => ({
type: "tool_result", tool_use_id: u.id,
content: JSON.stringify(execTool(u.name, u.input, session)), // la ejecutamos de verdad
})) });
continue; // observa → repite
}
final = data.content.filter(b => b.type === "text").map(b => b.text).join("");
break; // el modelo terminó
}
export function search_listings({ colonia, max_precio, recamaras }) {
// Solo devuelve inmuebles reales que cumplen los filtros.
let r = LISTINGS.filter(l =>
(!max_precio || l.precio <= +max_precio) &&
(!recamaras || l.recamaras >= +recamaras) &&
(!colonia || norm(l.colonia).includes(norm(colonia))));
r = r.sort((a, b) => a.precio - b.precio).slice(0, 3);
return { count: r.length, listings: r, source: SOURCE }; // p.ej. "MLS en vivo"
}
function execTool(name, args, session) {
const def = TOOLS[name];
if (!def) return { error: `unknown_tool:${name}` };
const result = def.handler(args, session.id); // determinista, dueño de los cálculos
session._actions.push({ tool: name, args, result }); // rastro completo → UI / dashboard
return result;
}
real_estate: {
brand: { name: "Casa Nova Inmobiliaria", color: "#0F766E" },
tools: ["search_listings", "get_listing", "book_viewing", "create_lead"],
systemPrompt: `Eres el asistente de "Casa Nova Inmobiliaria" en CDMX.
Califica al prospecto, muéstrale propiedades REALES del inventario,
agenda una visita y entrega el lead al asesor humano.
Nunca inventes inventario, precios ni disponibilidad.`,
},
restaurant: {
brand: { name: "Taquería El Agave", color: "#B91C1C" },
tools: ["get_menu", "add_to_order", "create_order"],
systemPrompt: `Toma el pedido, sugiere UN complemento, confirma el
total (lo calcula la herramienta) y cierra con un ticket para cocina.`,
},
// WhatsApp Cloud API: mensaje entrante → agente → respuesta
async function handleWhatsApp(payload) {
const msg = payload.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
if (!msg || msg.type !== "text") return; // ignora estados
const session = getSession("wa-" + msg.from, DEFAULT_VERTICAL);
const out = await respond(config, session, msg.text.body); // corre el agente
await sendWhatsApp(msg.from, out.reply); // responde vía Graph API
}
Cada lead, cita y pedido es un registro real. El agente escribe a sistemas reales, no a un archivo de mentira.
El teléfono de arriba está corriendo esta conversación. Cambia el giro y observa cómo se re-marca por completo — misma lógica, otro negocio.
Abre el demo, escribe como cliente y mira al agente calificar, buscar inventario real y agendar. Cambia a inglés con un toque.
▶ Abrir el demo en vivo