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:
- O usuário clica em um botão no seu widget.
- 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.
- O ChatGPT adiciona essa mensagem ao histórico como um novo user_message.
- 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.
- Seu backend/MCP executa o tool‑call e retorna o toolOutput.
- 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:
- atualizar o widgetState,
- 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:
- Usuário: “Preciso de um presente para minha irmã de TI por até US$ 100”.
- Modelo: um texto de introdução (pré‑texto) — explica que abrirá o GiftGenius e o que ele faz.
- Widget: mostra a seleção de ideias e oferece follow‑ups.
- Usuário: ou escreve uma mensagem, ou clica em um botão de follow‑up (por exemplo, “Mostrar apenas presentes digitais”).
- Modelo: interpreta isso como texto, chama o tool necessário, se preciso comenta o resultado (pós‑texto) ou mostra novamente o widget.
- 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.
GO TO FULL VERSION