CodeGym /Cursos /ChatGPT Apps /Interacción con ChatGPT: follow-ups y «diálogos alrededor...

Interacción con ChatGPT: follow-ups y «diálogos alrededor del widget»

ChatGPT Apps
Nivel 3 , Lección 3
Disponible

1. Qué son los follow‑ups en ChatGPT App y para qué sirven

Empecemos con una definición en lenguaje humano, no de marketing. Un follow‑up en el contexto de ChatGPT App es un siguiente paso del diálogo iniciado por el programa. Suele ser una sugerencia corta presentada como botón: al pulsarlo se convierte en un nuevo mensaje de texto del usuario en el chat y activa la continuación del escenario de interacción entre la persona y la IA.

Desde el punto de vista del modelo, un follow‑up es simplemente otro mensaje de usuario. No hay magia: cuando el usuario hace clic en tu botón «Mostrar opciones más baratas», al historial del chat llega algo como «Muestra regalos más baratos». El modelo lo ve como una frase normal del usuario, aplica el prompt del sistema y las descripciones de herramientas, decide qué herramienta llamar y, posiblemente, vuelve a renderizar tu widget ya con otros datos.

Por qué importa:

  • El modelo piensa en términos de texto. Si al hacer clic llamas la herramienta directamente (sin mensaje), estás esquivando el «cerebro» principal del sistema y perdiendo parte del contexto. El follow‑up conserva el progreso de la conversación en el historial y ayuda al modelo a entender qué está pasando.
  • El usuario permanece en la paradigma habitual del chat: o escribe mensajes, o pulsa sugerencias. Los follow‑ups son «respuestas rápidas» (quick replies) como en los mensajeros modernos.
  • Es el puente principal entre tu UI y la parte textual de ChatGPT. Sin follow‑ups, el widget se convierte en una isla muda: el usuario hace clics y no tiene claro qué hacer después.

Puedes ver los follow‑ups como un botón de «Siguiente pregunta para la IA», solo que formulada por ti. En adelante, veremos los follow‑ups no como «otra funcionalidad de UI», sino como la forma principal de construir el diálogo alrededor del widget.

2. «Diálogo alrededor del widget»: sándwich conversacional

Para ver con facilidad cómo los follow‑ups ayudan a construir un «diálogo alrededor del widget», es útil imaginar el diálogo como un sándwich de tres capas:

  • arriba, texto de ChatGPT antes del widget (pre‑text),
  • en medio, tu widget (UI),
  • abajo, follow‑ups y mensajes posteriores (post‑interaction).

Esquemáticamente:

sequenceDiagram
    participant U as Usuario
    participant G as ChatGPT
    participant W as Widget

    U->>G: "Busca un regalo para mi hermana de hasta 100$"
    G->>G: Decide invocar la App
    G->>U: Pre-text: "Ahora abriré GiftGenius y buscaré ideas"
    G->>W: Pasa toolOutput para el renderizado
    W-->>U: Tarjetas de regalos + botones de follow-up
    U->>W: Clic en «Mostrar opciones más baratas»
    W->>G: sendFollowUpMessage("Muestra regalos más baratos, hasta 50$")
    G->>G: Nueva pasada del modelo, llamada a tools
    G->>W: Nuevo toolOutput, widget actualizado

El pre‑text normalmente lo genera por completo el modelo en base al prompt del sistema y al contexto: ahí «explica» lo que va a ocurrir («Ahora abriré una aplicación que ayudará a elegir un regalo»). Controlaremos esta capa más adelante, en el módulo sobre instrucciones.

El widget es tu componente de React de siempre: renderiza el toolOutput, usa widgetState, ofrece botones y opciones.

La capa post‑interaction es lo que vemos hoy. Mediante follow‑ups y el envío de mensajes marcas una ruta clara a seguir: «Más caro», «Cambiar presupuesto», «Empezar de cero», «Ir a la compra».

Simplificando, un follow‑up es una réplica de control que cierra el ciclo: UI → texto → nueva UI.

3. Modelo técnico: cómo un clic en un follow‑up se convierte en una nueva llamada a la herramienta (tool‑call)

Veamos con atención la cadena de eventos «bajo el capó». Es cómodo pensarlo como un bucle de interacción híbrido: clic → API → texto en el historial → nueva decisión del modelo → nueva llamada a la herramienta → UI actualizada.

La secuencia aproximada es:

  1. El usuario pulsa un botón en tu widget.
  2. El widget llama al API window.openai.sendFollowUpMessage o, en la capa React, al hook de conveniencia useSendMessage (en los ejemplos de abajo usaremos justo el hook). El argumento es una cadena normal: el texto como si lo hubiera escrito el usuario.
  3. ChatGPT añade ese mensaje al historial como un nuevo user_message.
  4. El modelo realiza una nueva pasada: tiene en cuenta todo el historial, incluido el toolOutput anterior, y decide si llamar una herramienta, cuál y con qué argumentos.
  5. Tu backend/MCP ejecuta el tool‑call y devuelve el toolOutput.
  6. ChatGPT muestra una nueva respuesta: quizá de nuevo el widget (con datos nuevos), quizá texto, quizá una combinación.

Es importante que casi nunca quieras, directamente desde el widget, llamar la misma herramienta que invocó el modelo, saltándote este ciclo. Si no, el modelo «pierde» el paso: en el historial no hay la petición que inició la llamada repetida. Más tarde, en escenarios largos, esto se convierte en un contexto confuso.

Podemos reducirlo a una fórmula corta:

User Click → useSendMessage("...") → ChatGPT (LLM) → Tool Call → New toolOutput → Widget rerender

4. Tipos de follow‑ups y quién los idea

Ya entendimos qué ocurre «bajo el capó» tras un clic en un follow‑up. Ahora veamos qué follow‑ups tiene sentido ofrecer al usuario y qué roles pueden jugar en el escenario.

En una App real existen varias «familias» de follow‑ups. Yo los divido por distintos ejes: estáticos vs dinámicos, por rol (drill‑down, pivot, commit, etc.).

Para la práctica es más cómodo con una tabla.

Tipo Qué hace Ejemplo de texto/botón
Sugerente (Suggestive) Ayuda cuando el usuario no sabe qué pedir a continuación «Mostrar más ideas», «Acotar por intereses»
De precisión (Drill‑down / Parametric) Restringe la petición anterior por parámetros «Más barato», «Solo regalos digitales», «Solo Nike»
Giro (Pivot) Cambia la rama del escenario «Empezar de nuevo», «Mostrar regalos para un niño»
Navegación (Navigation) Lleva a otro paso del proceso «Ir a la compra», «Volver a la selección»
Confirmación (Commit) Confirma una acción «Pedir este regalo», «Guardar la selección»

Desde el punto de vista de la fuente de ideas hay dos grandes grupos.

Primero, los follow‑ups que propone la propia aplicación. Son nuestros botones en el widget, ligados a la lógica de la UI y a los datos: por ejemplo, «Mostrar similares a [Nombre del regalo]» o «Filtrar solo por el interés travel». Estas sugerencias se pueden codificar rígidamente (static) o formarse dinámicamente en función del toolOutput (dynamic).

Segundo, las sugerencias «nativas» de ChatGPT — pequeños chips bajo el mensaje, que el modelo inventa por sí mismo. No las controlas directamente; tómalas como un bonus gratuito, no como un mecanismo fiable. Tu aplicación debe funcionar igual incluso sin ellas.

En esta lección nos interesa más el primer grupo: botones y sugerencias que dibujas en tu componente de React y que, al hacer clic, envían sendFollowUpMessage.

5. Implementación de follow‑ups en React: ejemplo con GiftGenius

Continuemos con nuestra App hipotética GiftGenius, que sugiere regalos. Tras llamar la herramienta get_gift_ideas, el widget recibe un toolOutput con la lista de regalos. En temas anteriores ya hicimos una cuadrícula de tarjetas. Ahora añadiremos una sección de follow‑ups.

Supongamos que en el SDK tenemos los hooks useWidgetProps y useSendMessage. Los nombres aquí son orientativos, pero el concepto coincide con cómo está en la implementación de referencia:

import { useWidgetProps, useSendMessage } from '@/openai-apps';

export const GiftSuggestions: React.FC = () => {
  const { toolOutput } = useWidgetProps();
  const sendMessage = useSendMessage();

  const gifts = toolOutput?.data?.gifts ?? [];

  if (gifts.length === 0) {
    return <div>No se han encontrado regalos. Prueba a cambiar la petición.</div>;
  }

  const handleCheaper = () => {
    sendMessage('Muestra regalos más baratos, hasta 50$');
  };

  const handleDigital = () => {
    sendMessage('Muestra solo regalos digitales: vales, suscripciones, etc.');
  };

  return (
    <div className="flex flex-col gap-4">
      <div className="grid grid-cols-2 gap-2">
        {gifts.map((gift: any) => (
          <GiftCard key={gift.id} item={gift} />
        ))}
      </div>

      <div className="border-t pt-3 text-sm">
        <div className="text-xs text-gray-500 mb-2">¿Qué hacer a continuación?</div>
        <div className="flex flex-wrap gap-2">
          <button
            onClick={handleCheaper}
            className="px-3 py-1 rounded-full bg-gray-100 hover:bg-gray-200"
          >
            Más barato
          </button>
          <button
            onClick={handleDigital}
            className="px-3 py-1 rounded-full bg-gray-100 hover:bg-gray-200"
          >
            Solo digitales
          </button>
        </div>
      </div>
    </div>
  );
};

Aquí hay varios puntos importantes.

Primero, sendMessage recibe una cadena: ese texto aparecerá en el chat como si lo hubiera introducido el usuario. Tu App no debe imitar un protocolo «interno» del sistema; simplemente formula frases para que el modelo las entienda.

Segundo, la sección de follow‑ups está separada visualmente (borde superior, texto pequeño «¿Qué hacer a continuación?») para que el usuario entienda que es más bien la continuación del diálogo que elementos de la propia tarjeta.

Tercero, hay pocas opciones — dos. Las recomendaciones de UX aconsejan mantenerse en un rango de aproximadamente dos a cuatro opciones: suficiente para ayudar, pero sin saturar.

Follow‑up dinámico basado en datos

Supongamos que quieres permitir al usuario profundizar en un regalo concreto: «Mostrar similares a este». Entonces el texto del follow‑up debe mencionar el objeto adecuado, y puedes generar el texto al vuelo.

const handleShowSimilar = (giftTitle: string) => {
  sendMessage(
    `Muestra regalos parecidos a "${giftTitle}", en el mismo presupuesto o un poco más caros`
  );
};

Y en la tarjeta:

<button
  onClick={() => handleShowSimilar(gift.title)}
  className="mt-2 text-xs text-blue-600 underline"
>
  Mostrar parecidos
</button>

Así implementas un follow‑up dinámico enlazado a datos concretos del toolOutput. Justo este tipo de botones hacen el diálogo «inteligente», y no solo un conjunto de «Siguiente / Atrás».

6. Por qué enviamos texto y no llamamos la tool directamente

Un pensamiento típico de un desarrollador frontend: «Si tengo useCallTool, ¿para qué enviar texto? Puedo invocar directamente get_gift_ideas con otros parámetros». A veces realmente hace falta (habrá más en el módulo sobre llamadas a herramientas (tools) desde el widget), pero por defecto es mejor ir por el follow‑up textual. Las razones son bastante prácticas.

Primero, el historial del chat permanece coherente. Desde fuera todo parece como si el usuario hubiera escrito: «Muestra regalos más baratos». Dentro de una semana abrirá el historial y entenderá lo que pasó. Si lo haces todo con llamadas directas a la tool, entre los mensajes del usuario irán apareciendo widgets distintos sin causa visible.

Segundo, el modelo puede tomar decisiones adicionales. Por ejemplo, entender que en lugar de volver a llamar a la misma herramienta, primero conviene aclarar el presupuesto: «¿Seguro que quieres bajarlo a 5$? ¿Y si lo dejamos al menos en 20$?» Estos escenarios flexibles se vuelven imposibles si codificas rígidamente «clic → la misma tool con otros argumentos».

Tercero, el modelo puede llamar a una herramienta completamente diferente. Supón que el usuario pulsa «Contactar con soporte», y tu prompt del sistema enseña al modelo que, en ese caso, hay que llamar a create_support_ticket, y no a get_gift_ideas. Un follow‑up como texto le da al modelo la libertad de cambiar de herramienta.

Por eso, la regla práctica del módulo 3: al hacer clic en la UI, en la mayoría de los casos enviamos un follow‑up textual, no llamamos la tool directamente. Las llamadas directas a tools desde el widget las dejamos para casos específicos en los que seguro no queremos un nuevo paso de usuario en el historial.

7. Vincular follow‑ups y estados: no desincronizar la UI y el texto

Un problema interesante: la UI «vive» su vida y el texto en el chat, la suya. Supón que al hacer clic cambias un filtro dentro del widget y, al mismo tiempo, envías un follow‑up. Si solo actualizaste la UI pero no fijaste el nuevo estado mediante widgetState, en el siguiente render ChatGPT restaurará el widgetState antiguo. Como resultado, el widget volverá a mostrar los filtros antiguos, aunque en el historial ya exista el paso «sobre más barato». Es una experiencia bastante extraña.

Por eso, un buen patrón es: al hacer clic en un follow‑up, a la vez:

  1. actualizar el widgetState,
  2. enviar el mensaje de follow‑up.

Ejemplo:

import { useWidgetState, useSendMessage } from '@/openai-apps';

type GiftWidgetState = {
  priceFilter?: 'any' | 'cheap' | 'premium';
};

export const GiftFollowups: React.FC = () => {
  const [widgetState, setWidgetState] = useWidgetState<GiftWidgetState>();
  const sendMessage = useSendMessage();

  const handleCheaper = () => {
    setWidgetState({ ...widgetState, priceFilter: 'cheap' });
    sendMessage('Muestra regalos más baratos, aproximadamente hasta 50$');
  };

  // ...
};

Ahora tanto ChatGPT como tu UI saben que el filtro cambió. Si el modelo recompone el widget más tarde, verá el widgetState actualizado y podrá, por ejemplo, formar un nuevo pre‑text del tipo «Aquí tienes ideas en un segmento más económico».

8. Diseñar buenos follow‑ups

Un buen follow‑up es la mitad del éxito de UX. No es solo «bonito», ahorra energía mental al usuario.

Hay varios principios prácticos que conviene tener siempre presentes.

Primero, brevedad. Un follow‑up no es lugar para poemas. Una frase corta, comprensible sin el contexto de la UI, suele ser ideal: «Más barato», «Solo premium», «Cambiar destinatario». Si hace falta algo más largo, plantéate si no debería ser texto normal de GPT en vez de un botón.

Segundo, orientación a la acción. Formula de modo que quede claro qué ocurrirá. «Más ideas» está bien. «Más detalles del punto 2» es mejor cambiarlo por «Cuéntame más sobre la segunda opción» (así el modelo entiende de qué se trata incluso sin la UI).

Tercero, continuación del escenario, no su repetición. En lugar de «Volver a seleccionar regalo», mejor «Cambiar presupuesto» o «Cambiar aficiones del destinatario». Un follow‑up debe empujar al usuario hacia delante o hacia un lado, no devolverlo al punto de partida sin necesidad.

Cuarto, cantidad limitada. Dos–cuatro botones al pie del widget suelen ser suficientes. Una banda con diez opciones se convierte en un examen de «elige tu destino»: el usuario se pierde y no pulsa nada.

Por último, cuida el tono. Si toda la aplicación habla de forma cercana, resulta extraño colocar un botón «CONFIRMAR PEDIDO» en mayúsculas. El follow‑up forma parte del mismo diálogo que el texto del modelo; el estilo debe coincidir.

9. «Diálogos alrededor del widget» en general: responsabilidades

Es importante no ver el widget como «el protagonista» y a ChatGPT como «el marco alrededor». Es al revés: el modelo sigue llevando el diálogo, y el widget es solo una de las formas de mostrar y ajustar datos.

Un escenario típico para GiftGenius se ve así:

  1. Usuario: «Necesito un regalo para mi hermana que trabaja en IT, hasta 100$».
  2. Modelo: introducción textual (pre‑text) — explica que ahora abrirá GiftGenius y qué hace.
  3. Widget: muestra una selección de ideas y ofrece follow‑ups.
  4. Usuario: o bien escribe un mensaje, o bien pulsa un botón de follow‑up (por ejemplo, «Mostrar solo regalos digitales»).
  5. Modelo: lo interpreta como texto, llama a la tool necesaria y, si hace falta, comenta el resultado (post‑text) o vuelve a mostrar el widget.
  6. Y así en bucle hasta resolver la tarea — incluso hasta confirmar la elección, el pedido, etc.

Los follow‑ups son el pegamento que conecta cada vuelta de este ciclo. Sin ellos, tras el widget el usuario queda en el aire: todo es bonito, pero «qué sigue» no está claro.

En escenarios más complejos (workflows, agentes), los follow‑ups ayudan a modelar embudos de varios pasos: «Primero elige el destinatario», «Ahora aclara el presupuesto», «Ahora confirmemos la elección». Pero en este módulo lo importante es ver que incluso la App más simple de un solo paso se beneficia mucho de un par de sugerencias bien pensadas.

10. Práctica: qué conviene hacer ahora mismo

Un buen ejercicio para afianzar — mejorar tu widget de práctica actual.

Si ya tienes una lista de resultados (por ejemplo, de regalos, hoteles o documentos), añade debajo un pequeño bloque «¿Qué sigue?» con dos–tres botones. Intenta que estos botones correspondan a los tipos de la tabla anterior: uno debería ser de precisión (drill‑down, por ejemplo, «Más barato»), otro — de giro (pivot, «Cambiar destinatario»), y un tercero — si hace falta, de navegación (navigation, «Ir a la compra»).

Dentro de los controladores de clic, llama a useSendMessage con un texto significativo en lenguaje natural y no olvides, si es necesario, actualizar el widgetState. Luego vuelve a ejecutar el escenario en ChatGPT y observa cómo se ve el diálogo: si ahora queda más claro qué hacer después del widget.

Prueba también a hacer a propósito malos follow‑ups: largos, ambiguos, con una decena de opciones — y compara las sensaciones. Es una manera rápida de notar la diferencia en carne propia.

11. Errores típicos al trabajar con follow‑ups

Error n.º 1: widget «silencioso».
El desarrollador crea una excelente UI, pero no da follow‑ups. El usuario ve tarjetas, piensa «qué bien», y luego debe intuir que puede pedir «Muestra más barato» o «Cambia el destinatario». La mayoría no lo intuye y se va. Al menos una o dos sugerencias de «qué sigue» bajo el widget resuelven este problema.

Error n.º 2: demasiados botones.
El extremo contrario — saturar al usuario con una decena de opciones: «Cambiar presupuesto», «Cambiar intereses», «Cambiar moneda», «Guardar selección», «Compartir con un amigo», «Mostrar similares», «Preguntar a soporte», etc. Se crea un «bufé libre» psicológico del que es difícil elegir. Mejor empezar con las dos–tres acciones más frecuentes y dejar el resto al modelo y al texto normal.

Error n.º 3: la lógica del diálogo solo en el frontend.
A veces se intenta «optimizar» y, en lugar de enviar un follow‑up mediante useSendMessage (o el de bajo nivel sendFollowUpMessage), se llama directamente a la misma tool desde el widget, actualizando la UI. En el historial del chat no hay ni una palabra de lo que pasó. Tras un par de pasos el modelo empieza a confundirse, y tú con él. El camino correcto: mantener la lógica del diálogo en el nivel del texto y las herramientas, y el widget como una capa de UI fina.

Error n.º 4: formulaciones poco claras o ambiguas.
Un botón «Más» sin contexto puede significar cualquier cosa: ¿más regalos, más texto, más dinero? De igual modo, formulaciones como «Recalcular» o «Reconstruir» no son claras ni para el modelo ni para el usuario. Los mejores follow‑ups son concretos: «Mostrar más opciones en este presupuesto», «Mostrar solo regalos digitales».

Error n.º 5: UI y texto desincronizados.
Un clásico: al hacer clic en «Más barato» actualizaste el filtro de la UI, pero no enviaste el follow‑up al chat o no actualizaste el widgetState. Como resultado, en el historial no hay pasos sobre el cambio de presupuesto y, en el siguiente render del widget, el filtro «se revierte». Aparece la sensación de una interfaz «rota». Usa la combinación setWidgetState + sendMessage para que texto y UI vayan al unísono.

Error n.º 6: intentar controlar las sugerencias «nativas» de ChatGPT.
A veces los desarrolladores confían en que ChatGPT generará por sí mismo los chips de follow‑up adecuados bajo el mensaje y no añaden los suyos. Pero esas sugerencias no están garantizadas ni controladas por la aplicación. Trátalas como un bonus agradable, pero ofrece siempre tus propios botones de follow‑up críticos dentro del widget.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION