CodeGym /Cursos /ChatGPT Apps /Interação com o ChatGPT: follow-ups e “diálogos em torno ...

Interação com o ChatGPT: follow-ups e “diálogos em torno do widget”

ChatGPT Apps
Nível 3 , Lição 3
Disponível

1. O que são follow‑ups no ChatGPT App e para que servem

Vamos começar com uma definição em linguagem humana, não de marketing. Um follow‑up no contexto do ChatGPT App é um próximo passo no diálogo iniciado por código. Geralmente é uma dica curta apresentada como botão: ao clicar, ela se transforma em uma nova mensagem de texto do usuário no chat e aciona a continuação do fluxo de conversa entre a pessoa e a IA.

Do ponto de vista do modelo, um follow‑up é simplesmente mais uma mensagem do usuário. Nada de mágico: quando o usuário clica no seu botão “Mostrar opções mais baratas”, algo como “Mostre presentes mais baratos” entra no histórico do chat. O modelo vê isso como uma frase normal do usuário, aplica o system prompt e as descrições dos tools, decide qual ferramenta chamar e, possivelmente, renderiza novamente seu widget com outros dados.

Por que isso é importante:

  • O modelo pensa em termos de texto. Se, no clique, você apenas chama um tool diretamente (sem mensagem), você contorna o “cérebro” principal do sistema e perde parte do contexto. O follow‑up preserva o progresso da conversa no histórico e ajuda o modelo a entender o que exatamente está acontecendo.
  • O usuário permanece na paradigmática familiar de chat: ele escreve mensagens ou toca em sugestões. Os follow‑ups são “respostas rápidas” (quick replies), como nos mensageiros modernos.
  • É a principal ponte entre seu UI e a parte textual do ChatGPT. Sem follow‑ups, o widget vira uma ilha silenciosa: o usuário clica e não entende bem o que fazer depois.

Você pode encarar follow‑ups como um botão “Próxima pergunta para a IA”, só que formulada por você. A seguir, veremos follow‑ups não como “mais um recurso de UI”, mas como a maneira principal de estruturar o diálogo em torno do widget.

2. “Diálogo em torno do widget”: conversational sandwich

Para enxergar como os follow‑ups ajudam a construir o “diálogo em torno do widget”, é útil imaginar o diálogo como um sanduíche de três camadas:

  • em cima, o texto do ChatGPT antes do widget (pré‑texto),
  • no meio, o seu widget (UI),
  • embaixo, os follow‑ups e mensagens subsequentes (pós‑interação).

Esquematicamente:

sequenceDiagram
    participant U as Usuário
    participant G as ChatGPT
    participant W as Widget

    U->>G: "Encontre um presente para minha irmã por até US$ 100"
    G->>G: Decide chamar o App
    G->>U: Pre-text: "Vou abrir o GiftGenius e encontrar algumas ideias"
    G->>W: Envia toolOutput para renderização
    W-->>U: Cards de presentes + botões de follow-up
    U->>W: Clique em "Mostrar opções mais baratas"
    W->>G: sendFollowUpMessage("Mostre presentes mais baratos, até US$ 50")
    G->>G: Novo ciclo do modelo, chamada de tools
    G->>W: Novo toolOutput, widget atualizado

O pré‑texto geralmente é totalmente gerado pelo modelo com base no prompt do sistema e no contexto: ali ele “explica” o que vai acontecer (“Vou abrir um app que ajuda a escolher presentes”). Vamos controlar essa camada depois, no módulo sobre instruções.

O widget é seu componente React habitual: renderiza o toolOutput, usa o widgetState, oferece botões e escolhas.

A camada de pós‑interação é o que tratamos hoje. Por meio dos follow‑ups e do envio de mensagens, você define a próxima rota clara: “Mostrar mais caro”, “Alterar orçamento”, “Recomeçar a seleção”, “Ir para a finalização”.

Simplificando, um follow‑up é uma fala de controle que fecha o ciclo: UI → texto → novo UI.

3. Modelo técnico: como o clique em um follow‑up vira um novo tool‑call

Vamos olhar com atenção a cadeia de eventos “por baixo do capô”. É útil pensar nisso como um ciclo de interação híbrido: clique → API → texto no histórico → nova decisão do modelo → nova chamada de ferramenta → UI atualizado.

A sequência é mais ou menos assim:

  1. O usuário clica em um botão no seu widget.
  2. O widget chama a API window.openai.sendFollowUpMessage ou, na camada React, um hook de conveniência useSendMessage (nos exemplos abaixo usaremos esse hook). O argumento é uma string comum: o texto que parece ter sido escrito pelo usuário.
  3. O ChatGPT adiciona essa mensagem ao histórico como um novo user_message.
  4. O modelo faz uma nova passagem: considera todo o histórico, incluindo o toolOutput anterior, e decide se deve chamar um tool, qual e com quais argumentos.
  5. Seu backend/MCP executa o tool‑call e retorna o toolOutput.
  6. O ChatGPT exibe a nova resposta: pode ser novamente o widget (com novos dados), pode ser texto, pode ser uma combinação.

É importante notar que você quase nunca vai querer, a partir do widget, chamar diretamente o mesmo tool que o modelo chamou, contornando esse ciclo. Caso contrário, o modelo “perde” um passo: não há no histórico o pedido que iniciou a chamada repetida. Em cenários longos, isso cobra seu preço com um contexto confuso.

Isso pode ser resumido numa fórmula curta:

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

4. Tipos de follow‑ups e quem os cria

Já entendemos o que acontece “por baixo do capô” depois do clique em um follow‑up. Agora vamos ver que tipos de follow‑ups fazem sentido oferecer ao usuário e quais papéis eles podem cumprir no fluxo.

Em um App real, existem várias “famílias” de follow‑ups. Eu as classifico por diferentes eixos: estáticos vs. dinâmicos, por papel (drill‑down, pivot, commit etc.).

Para a prática, é mais conveniente uma tabela.

Tipo O que faz Exemplo de texto/botão
Sugestivo (Suggestive) Ajuda quando o usuário não sabe o que pedir em seguida “Mostrar mais ideias”, “Restringir por interesses”
De esclarecimento (Drill-down / Parametric) Restringe a solicitação anterior por parâmetros “Mais barato”, “Apenas presentes digitais”, “Apenas Nike”
De pivô (Pivot) Muda o ramo do fluxo “Recomeçar a seleção”, “Mostrar presentes para criança”
Navegação (Navigation) Leva a outra etapa do processo “Ir para a finalização”, “Voltar à escolha”
De confirmação (Commit) Confirma uma ação “Pedir este presente”, “Salvar seleção”

Do ponto de vista da origem das ideias, há dois grandes grupos.

Primeiro, follow‑ups propostos pelo próprio aplicativo. São nossos botões no widget, atrelados à lógica do UI e aos dados: por exemplo, “Mostrar semelhantes a [Nome do presente]” ou “Filtrar apenas por interesse travel”. Tais sugestões podem ser codificadas rigidamente (static) ou geradas dinamicamente com base no toolOutput (dynamic).

Segundo, as sugestões “nativas” do ChatGPT — pequenos chips sob a mensagem que o modelo inventa sozinho. Você não as controla diretamente; trate-as como um bônus gratuito, não como um mecanismo confiável. Seu aplicativo deve funcionar mesmo sem elas.

Nesta aula, nos interessa mais o primeiro grupo: botões e sugestões que você desenha no seu componente React e, ao clicar, enviam sendFollowUpMessage.

5. Implementando follow‑ups em React: GiftGenius como exemplo

Vamos continuar com nosso App hipotético GiftGenius, que sugere presentes. Após chamar o tool get_gift_ideas, o widget recebe um toolOutput com a lista de presentes. Em tópicos anteriores, já fizemos uma grade de cards. Agora vamos adicionar a seção de follow‑ups.

Suponha que o SDK tenha os hooks useWidgetProps e useSendMessage. Os nomes aqui são ilustrativos, mas o conceito coincide com a implementação de referência:

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>Nenhum presente encontrado. Tente alterar a consulta.</div>;
  }

  const handleCheaper = () => {
    sendMessage('Mostre presentes mais baratos, até US$ 50');
  };

  const handleDigital = () => {
    sendMessage('Mostre apenas presentes digitais: vales, assinaturas 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">O que fazer a seguir?</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"
          >
            Mais barato
          </button>
          <button
            onClick={handleDigital}
            className="px-3 py-1 rounded-full bg-gray-100 hover:bg-gray-200"
          >
            Apenas digitais
          </button>
        </div>
      </div>
    </div>
  );
};

Aqui, alguns pontos são importantes.

Primeiro, sendMessage recebe uma string — esse texto aparecerá no chat como se tivesse sido digitado pelo usuário. Seu App não deve imitar um protocolo “interno” do sistema; apenas formule as frases de forma que o modelo entenda.

Segundo, a seção de follow‑ups é visualmente separada (borda superior, texto menor “O que fazer a seguir?”), para que o usuário entenda: isso é mais a continuação do diálogo do que elementos do próprio card.

Terceiro, poucos botões — dois. Recomendações de UX sugerem ficar no intervalo de aproximadamente duas a quatro opções: é suficiente para ajudar, mas sem sobrecarregar.

Follow‑up dinâmico com base em dados

Suponha que você queira permitir que o usuário aprofunde um presente específico: “Mostrar semelhantes a este”. Então o texto do follow‑up deve mencionar o objeto correto, e você pode gerar o texto em tempo real.

const handleShowSimilar = (giftTitle: string) => {
  sendMessage(
    `Mostre presentes parecidos com "${giftTitle}", no mesmo orçamento ou um pouco mais caro`
  );
};

E no card:

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

Assim, você implementa um follow‑up dinâmico, ligado a dados específicos do toolOutput. São exatamente esses botões que tornam o diálogo “inteligente”, e não apenas um conjunto de “Avançar / Voltar”.

6. Por que enviamos texto em vez de chamar o tool diretamente

Um pensamento típico de desenvolvedor front-end: “Se eu tenho useCallTool, por que enviar texto? Posso chamar get_gift_ideas com outros parâmetros direto.” Às vezes isso realmente é necessário (falaremos mais sobre chamadas de tools a partir do widget em outro módulo), mas, por padrão, é melhor seguir com o follow‑up textual. Os motivos são bem práticos.

Primeiro, o histórico do chat permanece coeso. Externamente, parece que o próprio usuário escreveu: “Mostre presentes mais baratos”. Daqui a uma semana ele abre o histórico e entende o que aconteceu. Se você fez tudo via chamadas diretas de tool, entre mensagens do usuário surgirão widgets diferentes sem razões aparentes.

Segundo, o modelo pode tomar decisões adicionais. Por exemplo, entender que, em vez de chamar o mesmo tool novamente, é melhor primeiro esclarecer o orçamento: “Você tem certeza de que quer reduzir o orçamento para US$ 5? Talvez deixar pelo menos US$ 20?” Esses cenários flexíveis ficam impossíveis se você codifica rigidamente “clique → o mesmo tool com outros argumentos”.

Terceiro, o modelo pode chamar um tool totalmente diferente. Suponha que o usuário tocou em “Falar com o suporte”, e seu system prompt instrui o modelo que, nesse caso, deve chamar create_support_ticket, e não get_gift_ideas. O follow‑up como texto dá ao modelo liberdade para alternar para outra ferramenta.

Portanto, a regra prática do módulo 3 é: ao clicar no UI, na maioria dos casos enviamos um follow‑up textual, e não um tool diretamente. Chamadas diretas de tool a partir do widget ficam para casos específicos em que definitivamente não precisamos de um novo passo do usuário no histórico.

7. Ligando follow‑ups e estados: não dessincronize UI e texto

Um problema interessante: o UI “vive” sua vida, e o texto no chat — a dele. Suponha que você, no clique, altere um filtro dentro do widget e, ao mesmo tempo, envie um follow‑up. Se você atualizar apenas o UI, mas não registrar o novo estado via widgetState, no próximo render o ChatGPT restaurará o widgetState antigo. Como resultado, o widget mostrará de novo os filtros antigos, embora o histórico do chat já tenha um passo “sobre mais barato”. É uma experiência estranha.

Portanto, um bom padrão: ao clicar em um follow‑up, simultaneamente:

  1. atualizar o widgetState,
  2. enviar a mensagem de follow‑up.

Exemplo:

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('Mostre presentes mais baratos, aproximadamente até US$ 50');
  };

  // ...
};

Agora, tanto o ChatGPT quanto seu UI sabem que o filtro mudou. Se o modelo reconstruir o widget depois, ele verá o widgetState atualizado e poderá, por exemplo, formar um novo pré‑texto como “Aqui estão ideias em uma faixa mais econômica”.

8. Projetando bons follow‑ups

Um bom follow‑up é metade do sucesso de UX. Ele não é apenas “bonito”; ele economiza a energia mental do usuário.

Há alguns princípios práticos que valem ficar à vista no monitor.

Primeiro, concisão. Follow‑up não é lugar para poesias. Uma frase curta, compreensível sem o contexto do UI, costuma ser ideal: “Mais barato”, “Apenas premium”, “Alterar destinatário”. Se precisar de algo mais longo, pense se isso não deveria ser texto normal do GPT, e não um botão.

Segundo, orientação à ação. Formule de forma que fique claro o que ocorrerá. “Mais ideias” — ok. “Mais detalhes sobre o item 2” — melhor trocar por “Explique melhor a segunda opção” (assim o modelo entende do que se trata, mesmo sem o UI).

Terceiro, continuação do fluxo, não repetição. Em vez de “Selecionar presente novamente”, prefira “Alterar orçamento” ou “Trocar o hobby do destinatário”. O follow‑up deve mover o usuário para frente ou para o lado, e não voltar ao ponto inicial sem necessidade.

Quarto, quantidade limitada. Duas a quatro opções no rodapé do widget — quase sempre o suficiente. Uma faixa com dez opções vira um “vestibular” de escolhas: o usuário se perde e não clica em nada.

Por fim, considere a tonalidade. Se todo o app se comunica de forma amigável, é estranho colocar um botão “CONFIRMAR PEDIDO” em caixa alta. O follow‑up faz parte do mesmo diálogo que o texto do modelo; o estilo deve coincidir.

9. “Diálogos em torno do widget” no geral: quem faz o quê

É importante não encarar o widget como “protagonista” e o ChatGPT como “moldura ao redor”. É o contrário: o modelo continua conduzindo o diálogo, e o widget é apenas uma das formas de exibir e ajustar dados.

Um fluxo típico para o GiftGenius é assim:

  1. Usuário: “Preciso de um presente para minha irmã de TI por até US$ 100”.
  2. Modelo: um texto de introdução (pré‑texto) — explica que abrirá o GiftGenius e o que ele faz.
  3. Widget: mostra a seleção de ideias e oferece follow‑ups.
  4. Usuário: ou escreve uma mensagem, ou clica em um botão de follow‑up (por exemplo, “Mostrar apenas presentes digitais”).
  5. Modelo: interpreta isso como texto, chama o tool necessário, se preciso comenta o resultado (pós‑texto) ou mostra novamente o widget.
  6. E assim por diante, até a tarefa ser concluída — até a confirmação da escolha, pedido etc.

Os follow‑ups aqui são a cola que liga cada volta desse ciclo. Sem eles, o usuário, após o widget, fica em suspenso: tudo está bonito, mas “e agora?” — não está claro.

Em cenários mais complexos (workflows, agentes), os follow‑ups ajudam a modelar funis de múltiplas etapas: “Primeiro escolha o destinatário”, “Agora ajuste o orçamento”, “Agora confirme a escolha”. Mas, neste módulo, o importante é ver que até o App mais simples de uma etapa ganha muito com algumas sugestões bem pensadas.

10. Prática: o que vale fazer agora

Um bom exercício de fixação é aprimorar seu widget de estudos atual.

Se você já tem uma lista de resultados (por exemplo, presentes, hotéis ou documentos), adicione abaixo dela um pequeno bloco “O que fazer a seguir?” com dois ou três botões. Tente fazer com que esses botões correspondam aos tipos da tabela acima: um deve ser de esclarecimento (drill‑down, por exemplo, “Mais barato”), outro — um pivô (pivot, “Alterar destinatário”), o terceiro —, se necessário, de navegação (navigation, “Ir para a finalização”).

Dentro dos handlers de clique, chame useSendMessage com um texto significativo em linguagem natural; não se esqueça de atualizar o widgetState se necessário. Em seguida, execute novamente o fluxo no ChatGPT e veja como o diálogo fica: ficou mais claro o que fazer após o widget?

Tente também, de propósito, criar follow‑ups ruins: longos, vagos, com dezenas de opções — e compare a sensação. É uma forma rápida de perceber a diferença na prática.

11. Erros comuns ao trabalhar com follow‑ups

Erro nº 1: widget “silencioso”.
O desenvolvedor cria um ótimo UI, mas não oferece follow‑ups. O usuário vê os cards, pensa “legal”, e depois precisa adivinhar que pode, por exemplo, pedir: “Mostrar mais barato” ou “Trocar o destinatário”. A maioria das pessoas simplesmente não adivinha e vai embora. Pelo menos uma ou duas sugestões de “o que vem depois” abaixo do widget resolvem esse problema.

Erro nº 2: botões demais.
O extremo oposto é lotar o usuário com dezenas de opções: “Alterar orçamento”, “Alterar interesses”, “Trocar moeda”, “Salvar seleção”, “Compartilhar com um amigo”, “Mostrar semelhantes”, “Perguntar ao suporte” e assim por diante. Vira um “buffet” psicológico em que escolher é difícil. É melhor começar com duas ou três ações mais frequentes e deixar o restante para o modelo e para o texto normal.

Erro nº 3: lógica do diálogo apenas no front-end.
Às vezes tentam “otimizar” e, em vez de enviar o follow‑up via useSendMessage (ou o sendFollowUpMessage de baixo nível), chamam diretamente o mesmo tool a partir do widget, atualizando o UI. No histórico do chat, não há uma palavra sobre o que aconteceu. Após algumas etapas, o modelo começa a se confundir — e você também. O caminho certo: manter a lógica do diálogo no nível do texto e dos tools, e o widget como uma camada de UI fina.

Erro nº 4: formulações pouco claras ou ambíguas.
Um botão “Mais” fora de contexto pode significar qualquer coisa: mais presentes, mais texto, mais dinheiro? Da mesma forma, formulações como “Recalcular” ou “Reconstruir” são pouco claras tanto para o modelo quanto para o usuário. Os melhores follow‑ups são específicos: “Mostrar mais opções neste orçamento”, “Mostrar apenas presentes digitais”.

Erro nº 5: UI e texto dessincronizados.
Clássico: ao clicar em “Mais barato”, você atualiza o filtro do UI, mas não envia um follow‑up no chat ou não atualiza o widgetState. Como resultado, não há passos no histórico sobre a mudança de orçamento, e, no próximo render do widget, o filtro “volta” ao estado anterior. Surge a sensação de um UI “quebrado”. Use a combinação setWidgetState + sendMessage para que texto e UI caminhem juntos.

Erro nº 6: tentar controlar as sugestões “nativas” do ChatGPT.
Às vezes, desenvolvedores contam que o ChatGPT vai gerar sozinho os chips certos de follow‑up sob a mensagem e não adicionam os seus. Mas essas sugestões não são garantidas e não são controladas pelo aplicativo. Trate-as como um bônus agradável, mas sempre ofereça seus próprios botões de follow‑up críticos no widget.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION