Saltar al contenido

← Deep Dives

Deep diveArtículoAI AgentFunctionsIntegracionesCanales — WhatsAppContexto ExternoResume

Inyecta contexto desde un sistema externo sin cortar la conversación

Un cliente pide un aumento de límite por WhatsApp. Quien puede aprobarlo no está en ese chat — puede estar en un correo, un CRM o un sistema de pagos. Con Contexto externo, el agente pausa la ejecución y retoma el mismo hilo en cuanto llega la respuesta, sin que la persona tenga que volver a preguntar.

Un cliente escribe por WhatsApp pidiendo un aumento de límite de 10.000 dólares. El Agent reúne los datos — monto, motivo, historial — y arma la solicitud. Pero quien puede aprobarla no está en esa conversación: puede estar revisando un correo, en otro equipo, o simplemente en otro horario.

La conversación llegó a un punto en el que todavía no existe una respuesta. Nada de eso depende del Agent — depende de que alguien, en algún otro sistema, tome una decisión.

Minutos u horas después, la aprobación llega. No importa si fue por correo, por Slack, por la confirmación de un pago o el cierre de un ticket: la misma conversación de WhatsApp continúa exactamente donde había quedado, sin que el cliente haya tenido que escribir de nuevo.

Para el cliente es una sola conversación. Para el Agent, esa conversación puede depender de uno o varios sistemas externos a la vez, cada uno con su propio tiempo de respuesta. Contexto externo es lo que hace posible esa diferencia: separar el momento en que alguien pide algo del momento en que un sistema — o una persona en otro sistema — lo resuelve, sin convertir la espera en un ticket.

El Agent pausa, algo afuera resuelve, POST a Resume. El recuadro del medio es un ejemplo: correo, Slack, un pago o un ticket.
El Agent espera. Algo afuera ocurre. Resume continúa la conversación.

La conversación puede quedar en pausa

En la pestaña Contexto del AI Agent está Agregar contexto externo. Ahí una interacción puede detenerse sin cerrar la ejecución.

AI Agent, pestaña Contexto: Agregar contexto externo con el POST a Resume, el header x-api-key y el cuerpo con executionId.
Pestaña Contexto · Agregar contexto externo. El POST y el executionId están ahí.

Jelou conserva el executionId de esa ejecución. Cuando el sistema externo tenga una respuesta, puede usarlo para continuar exactamente ese hilo.

Eso permite separar dos momentos que no necesariamente ocurren juntos:

  • el usuario hace una solicitud;
  • algo afuera la resuelve.

El usuario no tiene que mantener el chat abierto ni volver a escribir para que el proceso continúe.

Una ejecución pausada puede reanudarse durante 24 horas. Después de ese plazo, el executionId deja de estar disponible para Resume.

Volver requiere una señal

Para continuar la ejecución, el sistema externo hace ese POST.

executionId identifica la conversación que estaba esperando. message le entrega al Agent el resultado que acaba de llegar.

La API key nunca debe viajar en un link, query param o correo. Quien tenga esa clave puede reanudar ejecuciones.

Da igual quién origine la señal. Si puede hacer el POST de Resume con el executionId correcto, puede volver a poner la conversación en marcha.

Un ejemplo: aprobar desde correo

Volvamos al aumento de límite.

El Agent reúne la solicitud, envía un correo al aprobador y pausa la interacción. El correo tiene dos acciones: Aprobar y Rechazar.

Correo de Gmail: solicitud pendiente de aprobación por compra de un auto, 10.000 USD, con links Aprobar y Rechazar.
El correo lleva la decisión y el executionId. La API key queda fuera.

En este ejemplo, el clic llega a una Function. La Function guarda la API key de forma segura y hace la llamada a Resume:

La Function llama a Resume
await fetch("https://gateway.jelou.ai/workflows/v1/skills/resume", {
  method: "POST",
  headers: {
    "x-api-key": apiKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    executionId,
    message: "La solicitud fue aprobada",
    pauseInteraction: false,
  }),
});

La Function no es parte obligatoria del patrón. Está ahí porque un link de correo no debe llevar la API key.

Si la señal viniera de una pasarela de pago, por ejemplo, su webhook podría hacer el mismo POST directamente.

El usuario no tiene que volver

Cuando llega Resume, el Agent recibe el resultado y continúa desde donde quedó.

Mismo hilo de WhatsApp: el usuario pide un aumento de 10.000 USD, el Agent avisa que quedó pendiente y a las 10:10 llega la aprobación sin un mensaje nuevo del usuario.
La respuesta llega al mismo hilo sin un nuevo mensaje del usuario.

En el ejemplo fue un correo. Podría haber sido Slack, un CRM, una aprobación interna, un webhook o la confirmación de un pago.

El sistema externo cambia. La conversación no necesita saberlo: espera una señal y, cuando llega, continúa.

El usuario no debería tener que volver para que el proceso continúe.

¿Quieres este ejemplo en tu Brain?

El patrón ya está. Si quieres el mismo loop en tu cuenta, son dos piezas: el workflow y la Function.

El workflow: usa el template

El template ya trae el AI Agent del ejemplo (solicitudes que requieren aprobación), Gmail para mandar el correo con Aprobar y Rechazar, y Contexto externo para pausar. Lo instalas en tu Brain y conectas tu cuenta de Gmail.

La Function: la creas tú

El clic del correo no puede llevar la API key. Por eso el link apunta a una Function tuya: recibe executionId y decision, y hace el POST a Resume. Créala con el inicio rápido de Functions, déjala pública (un link de Gmail no manda token) y guarda la API key en un secret.

La Function recibe el clic y llama a Resume
import { define, z } from "@jelou/functions";

export default define({
  name: "resume-aprobacion",
  description: "Recibe Aprobar o Rechazar y llama a Resume",
  input: z.object({
    executionId: z.string(),
    decision: z.enum(["approved", "rejected"]),
  }),
  config: {
    public: true,
    methods: ["GET"],
    mcp: false,
  },
  handler: async (input, ctx) => {
    const apiKey = ctx.env.get("JELOU_API_KEY");
    await fetch("https://gateway.jelou.ai/workflows/v1/skills/resume", {
      method: "POST",
      headers: {
        "x-api-key": apiKey,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        executionId: input.executionId,
        message:
          input.decision === "approved"
            ? "La solicitud fue aprobada"
            : "La solicitud fue rechazada",
        pauseInteraction: false,
      }),
    });
    return { ok: true };
  },
});

Despliégala, pon esa URL en los links del correo, y prueba: WhatsApp pide, llega el correo, Aprobar, el mismo hilo continúa.

Soporte

¿Te quedó una duda?

Ábrela en tu cuenta.

Cómo escribirnos