CodeGym /Kurse /ChatGPT Apps /Interaktion mit ChatGPT: Follow-ups und „Dialoge rund um ...

Interaktion mit ChatGPT: Follow-ups und „Dialoge rund um das Widget“

ChatGPT Apps
Level 3 , Lektion 3
Verfügbar

1. Was sind follow‑ups in der ChatGPT App und wozu braucht man sie

Beginnen wir mit einer Definition in verständlicher, nicht marketinggetriebener Sprache. Follow‑up im Kontext der ChatGPT App ist ein programmatisch initiierter nächster Schritt im Dialog. Meist ist es ein kurzer Hinweis in Form eines Buttons: Beim Klicken wird er zu einer neuen Textnachricht vom Benutzer im Chat und startet die Fortsetzung der Unterhaltung zwischen Mensch und KI.

Aus Sicht des Modells ist ein follow‑up einfach eine weitere Benutzernachricht. Keine Magie: Wenn der Benutzer auf euren Button „Günstigere Varianten anzeigen“ klickt, landet im Chatverlauf etwas wie „Zeige günstigere Geschenke“. Das Modell sieht das als gewöhnliche Benutzeräußerung, wendet den System‑Prompt und Tool‑Beschreibungen an, entscheidet, welches Tool aufzurufen ist, und rendert möglicherweise euer Widget erneut – mit anderen Daten.

Warum das wichtig ist:

  • Das Modell denkt in Text. Wenn ihr beim Klick einfach direkt ein Tool aufruft (ohne Nachricht), umgeht ihr das „Gehirn“ des Systems und verliert einen Teil des Kontexts. Ein Follow‑up bewahrt den Gesprächsfortschritt im Verlauf und hilft dem Modell zu verstehen, was genau passiert.
  • Der Benutzer bleibt in der gewohnten Chat‑Parade: Er schreibt entweder Nachrichten oder tippt auf Vorschläge. Follow‑ups sind dieselben „Quick Replies“ wie in modernen Messengern.
  • Das ist die wichtigste Brücke zwischen eurem UI und dem Textteil von ChatGPT. Ohne follow‑ups wird das Widget zur stummen Insel: Der Benutzer klickt herum und weiß nicht so recht, wie es weitergeht.

Man kann auf follow‑ups schauen wie auf einen Button „Nächste Frage an die KI“, nur von euch formuliert. Im Weiteren betrachten wir follow‑ups nicht als „noch ein UI‑Feature“, sondern als den zentralen Weg, den Dialog rund um das Widget zu gestalten.

2. „Dialog rund um das Widget“: conversational sandwich

Um leichter zu sehen, wie follow‑ups helfen, den „Dialog rund um das Widget“ zu bauen, ist es nützlich, den Dialog als Sandwich aus drei Schichten zu sehen:

  • oben der Text von ChatGPT vor dem Widget (pre‑text),
  • in der Mitte euer Widget (UI),
  • unten die follow‑ups und nachfolgende Nachrichten (post‑interaction).

Schematisch:

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

    U->>G: "Finde ein Geschenk für meine Schwester bis 100$"
    G->>G: Entscheidet, die App aufzurufen
    G->>U: Pre-text: "Ich öffne jetzt GiftGenius und stelle Ideen zusammen"
    G->>W: Übergibt toolOutput zum Rendern
    W-->>U: Geschenk-Karten + Follow-up-Buttons
    U->>W: Klick auf "Günstigere Varianten anzeigen"
    W->>G: sendFollowUpMessage("Zeige günstigere Geschenke, bis 50$")
    G->>G: Neuer Model-Durchlauf, Tools-Aufruf
    G->>W: Neues toolOutput, aktualisiertes Widget

Pre‑text wird gewöhnlich vollständig vom Modell aus System‑Prompt und Kontext generiert: Dort „erklärt“ es, was jetzt passiert („Ich öffne eine App, die beim Geschenkefinden hilft“). Steuern werden wir diese Ebene später, im Modul zu Instruktionen.

Das Widget ist euer vertrauter React‑Komponent: Es rendert toolOutput, nutzt widgetState, bietet Buttons und Auswahlmöglichkeiten.

Die Post‑interaction‑Schicht ist das, worum wir uns heute kümmern. Über follow‑ups und das Senden von Nachrichten weist ihr den weiteren, verständlichen Pfad: „Teurer anzeigen“, „Budget ändern“, „Auswahl neu starten“, „Zur Kasse gehen“.

Vereinfacht ist ein follow‑up eine steuernde Replik, die den Kreis schließt: UI → Text → neues UI.

3. Technisches Modell: wie ein Klick auf follow‑up in einen neuen Tool‑Call übergeht

Schauen wir aufmerksam auf die Ereigniskette „unter der Haube“. Man kann das als hybriden Interaktionszyklus betrachten: Klick → API → Text im Verlauf → neue Modellentscheidung → neuer Tool‑Aufruf → aktualisiertes UI.

Ablauf ungefähr so:

  1. Der Benutzer klickt einen Button in eurem Widget.
  2. Das Widget ruft die API window.openai.sendFollowUpMessage oder, in der React‑Ebene, den bequemen Hook‑Wrapper useSendMessage auf (in den Beispielen unten verwenden wir den Hook). Das Argument ist ein normaler String: Text, den so wirken soll, als hätte ihn der Benutzer geschrieben.
  3. ChatGPT fügt diese Nachricht als neues user_message in den Verlauf ein.
  4. Das Modell führt einen neuen Durchlauf aus: Es berücksichtigt die gesamte Historie, einschließlich des vorherigen toolOutput, und entscheidet, ob ein Tool aufgerufen wird, welches und mit welchen Argumenten.
  5. Euer Backend/MCP führt den Tool‑Call aus und gibt toolOutput zurück.
  6. ChatGPT zeigt die neue Antwort an: möglicherweise wieder ein Widget (mit neuen Daten), eventuell Text oder eine Kombination.

Wichtig: Ihr wollt fast nie direkt aus dem Widget dasselbe Tool aufrufen, das das Modell aufgerufen hat, und dabei diesen Zyklus umgehen. Andernfalls „verliert“ das Modell einen Schritt: Im Verlauf fehlt die Anfrage, die den erneuten Aufruf ausgelöst hat. Später in längeren Szenarien rächt sich das mit verwirrendem Kontext.

Man kann es auf eine kurze Formel bringen:

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

4. Arten von follow‑ups und wer sie entwirft

Wir haben verstanden, was „unter der Haube“ nach einem Klick auf ein follow‑up passiert. Jetzt schauen wir, welche follow‑ups dem Benutzer sinnvoll angeboten werden und welche Rollen sie im Szenario spielen können.

In einer realen App gibt es mehrere „Familien“ von follow‑ups. Ich teile sie entlang verschiedener Achsen: statisch vs. dynamisch, nach Rolle (drill‑down, pivot, commit usw.).

Für die Praxis ist eine Tabelle bequemer.

Typ Was es macht Beispieltext/Schaltfläche
Hinweisend (Suggestive) Hilft, wenn der Benutzer nicht weiß, was er als Nächstes fragen soll „Weitere Ideen anzeigen“, „Nach Interessen eingrenzen“
Präzisierend (Drill-down / Parametric) Schränkt die vorherige Anfrage nach Parametern ein „Günstiger“, „Nur digitale Geschenke“, „Nur Nike“
Schwenk (Pivot) Wechselt den Pfad im Szenario „Auswahl neu starten“, „Geschenke für ein Kind anzeigen“
Navigation Wechselt zu einem anderen Schritt im Prozess „Zur Kasse gehen“, „Zur Auswahl zurückkehren“
Abschließend (Commit) Bestätigt eine Aktion „Dieses Geschenk bestellen“, „Auswahl speichern“

Aus Sicht der Ideengewinnung gibt es zwei große Gruppen.

Erstens follow‑ups, die die App selbst vorschlägt. Das sind unsere Buttons im Widget, die an UI‑Logik und Daten hängen: etwa „Ähnliche anzeigen zu [Geschenkname]“ oder „Nur nach Interesse travel filtern“. Solche Hinweise kann man fest codieren (static) oder dynamisch auf Basis des toolOutput erzeugen (dynamic).

Zweitens die „nativen“ Vorschläge von ChatGPT – kleine Chips unter der Nachricht, die das Modell selbst erfindet. Ihr steuert sie nicht direkt; betrachtet sie als kostenlosen Bonus, nicht als verlässlichen Mechanismus. Eure App muss auch ohne sie funktionieren.

In dieser Lektion interessiert uns vor allem die erste Gruppe: Buttons und Hinweise, die ihr in eurem React‑Komponent zeichnet und beim Klick über sendFollowUpMessage sendet.

5. Implementierung von follow‑ups in React: GiftGenius als Beispiel

Wir machen weiter mit unserer fiktiven App GiftGenius, die Geschenke findet. Nach dem Aufruf des Tools get_gift_ideas erhält das Widget ein toolOutput mit einer Geschenkeliste. In den vorherigen Themen haben wir bereits ein Grid aus Karten gebaut. Jetzt fügen wir den Bereich für follow‑ups hinzu.

Angenommen, im SDK gibt es die Hooks useWidgetProps und useSendMessage. Die Namen sind hier beispielhaft, aber das Konzept entspricht der Referenzimplementierung:

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>Keine Geschenke gefunden. Versuche, die Anfrage zu ändern.</div>;
  }

  const handleCheaper = () => {
    sendMessage('Zeige günstigere Geschenke, bis 50$');
  };

  const handleDigital = () => {
    sendMessage('Zeige nur digitale Geschenke: Gutscheine, Abos usw.');
  };

  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">Wie geht es weiter?</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"
          >
            Günstiger
          </button>
          <button
            onClick={handleDigital}
            className="px-3 py-1 rounded-full bg-gray-100 hover:bg-gray-200"
          >
            Nur digital
          </button>
        </div>
      </div>
    </div>
  );
};

Hier sind einige Punkte wichtig.

Erstens bekommt sendMessage einen String – dieser Text erscheint im Chat, als hätte ihn der Benutzer eingegeben. Eure App sollte kein „internes“ Systemprotokoll imitieren; formuliert die Sätze einfach so, dass das Modell sie versteht.

Zweitens ist der Bereich der follow‑ups visuell abgesetzt (Border oben, kleiner Text „Wie geht es weiter?“), damit der Benutzer versteht: Das ist eher die Fortsetzung des Dialogs als Elemente der Karte selbst.

Drittens gibt es nur wenige Buttons – zwei. UX‑Empfehlungen raten zu etwa zwei bis vier Optionen: genug, um zu helfen, aber nicht zu überfrachten.

Dynamisches follow‑up auf Basis der Daten

Angenommen, ihr wollt dem Benutzer erlauben, in ein konkretes Geschenk hineinzuzoomen: „Ähnliche anzeigen wie dieses“. Dann sollte der follow‑up‑Text das betreffende Objekt erwähnen, und ihr könnt den Text on the fly generieren.

const handleShowSimilar = (giftTitle: string) => {
  sendMessage(
    `Zeige ähnliche Geschenke wie "${giftTitle}", gern im gleichen Budget oder etwas teurer`
  );
};

Und in der Karte:

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

So implementiert ihr ein dynamisches follow‑up, das an konkrete Daten aus dem toolOutput gebunden ist. Gerade solche Buttons machen den Dialog „smart“ – nicht nur zu einer Sammlung generischer „Weiter / Zurück“.

6. Warum wir Text senden und nicht das Tool direkt aufrufen

Der typische Gedanke eines Frontend‑Entwicklers: „Wenn ich useCallTool habe, warum sollte ich Text senden? Ich kann doch direkt get_gift_ideas mit anderen Parametern aufrufen.“ Manchmal ist das tatsächlich nötig (mehr dazu im Modul zum Aufruf von Tools aus dem Widget), aber standardmäßig ist der Weg über das textuelle follow‑up besser. Die Gründe sind pragmatisch.

Erstens bleibt der Chatverlauf konsistent. Von außen sieht alles so aus, als hätte der Benutzer selbst geschrieben: „Zeige günstigere Geschenke.“ In einer Woche öffnet er den Verlauf und versteht, was passiert ist. Wenn ihr alles über direkte Tool‑Aufrufe macht, tauchen zwischen Benutzer‑Nachrichten plötzlich verschiedene Widgets ohne erkennbare Ursache auf.

Zweitens kann das Modell zusätzliche Entscheidungen treffen. Zum Beispiel erkennen, dass statt eines erneuten Aufrufs desselben Tools zuerst das Budget präzisiert werden sollte: „Sind Sie sicher, dass Sie das Budget auf 5$ senken wollen? Vielleicht lassen wir wenigstens 20$?“ Solche flexiblen Szenarien sind unmöglich, wenn ihr hart „Klick → dasselbe Tool mit anderen Argumenten“ codiert.

Drittens kann das Modell ein ganz anderes Tool aufrufen. Angenommen, der Benutzer tippt auf „Support kontaktieren“, und euer System‑Prompt bringt dem Modell bei, in diesem Fall create_support_ticket statt get_gift_ideas aufzurufen. Das follow‑up als Text gibt dem Modell die Freiheit, auf ein anderes Tool umzuschalten.

Daher die praktische Regel in Modul 3: Beim Klick im UI senden wir in den meisten Fällen ein textuelles follow‑up – nicht direkt das Tool. Direkte Tool‑Aufrufe aus dem Widget bleiben für Spezialfälle, in denen wir sicher keinen neuen Benutzerschritt im Verlauf brauchen.

7. Verknüpfung von follow‑ups und Zuständen: UI und Text nicht desynchronisieren

Ein interessantes Problem: Das UI „lebt“ sein eigenes Leben, der Text im Chat sein eigenes. Angenommen, ihr ändert beim Klick einen Filter im Widget und sendet gleichzeitig ein follow‑up. Wenn ihr nur das UI aktualisiert, aber den neuen Zustand nicht im widgetState festhaltet, stellt ChatGPT beim nächsten Rendern den alten widgetState wieder her. Das Widget zeigt dann wieder die alten Filter, obwohl es im Verlauf bereits den Schritt „günstiger“ gibt. Das ist eine seltsame Erfahrung.

Daher ein gutes Muster: Beim Klick auf ein follow‑up gleichzeitig:

  1. widgetState aktualisieren,
  2. die follow‑up‑Nachricht senden.

Beispiel:

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('Zeige günstigere Geschenke, etwa bis 50$');
  };

  // ...
};

Jetzt wissen sowohl ChatGPT als auch euer UI, dass der Filter gewechselt wurde. Wenn das Modell das Widget später neu aufbaut, sieht es den aktualisierten widgetState und kann z. B. einen neuen Pre‑text formulieren wie „Hier sind Ideen im budgetfreundlicheren Segment“.

8. Gute follow‑ups gestalten

Ein gutes follow‑up ist die halbe Miete beim UX‑Erfolg. Es ist nicht nur „schön“, sondern spart dem Benutzer Denkarbeit.

Es gibt einige praktische Prinzipien, die man sich am Monitor anpinnen könnte.

Erstens: Kürze. Ein follow‑up ist kein Ort für Epen. Ein kurzer Satz, der auch ohne UI‑Kontext verständlich ist, ist meist ideal: „Günstiger“, „Nur Premium“, „Empfänger ändern“. Wenn es länger sein muss, überlegt, ob das nicht regulärer GPT‑Text statt eines Buttons sein sollte.

Zweitens: Handlungsorientierung. Formuliert so, dass klar ist, was passieren wird. „Weitere Ideen“ – ok. „Mehr zu Punkt 2“ – besser ersetzen durch „Erzähle mehr zur zweiten Option“ (so versteht das Modell es auch ohne UI).

Drittens: Fortsetzung des Szenarios, nicht dessen Wiederholung. Statt „Geschenk erneut auswählen“ lieber „Budget ändern“ oder „Hobby des Empfängers wechseln“. Ein follow‑up sollte den Benutzer voran- oder seitwärts bewegen, nicht grundlos an den Ausgangspunkt zurückwerfen.

Viertens: Begrenzte Anzahl. Zwei bis vier Buttons unten im Widget reichen fast immer. Eine Tafel mit zehn Optionen wird zur Prüfung des Schicksals: Benutzer sind überfordert und tippen gar nichts.

Und schließlich: Tonalität beachten. Wenn die gesamte App freundlich kommuniziert, wirkt ein Button „BESTELLUNG BESTÄTIGEN“ in Versalien deplatziert. Ein follow‑up ist Teil desselben Dialogs wie der Modelltext; der Stil sollte passen.

9. „Dialoge rund um das Widget“ insgesamt: wer wofür verantwortlich ist

Wichtig ist, das Widget nicht als „Hauptdarsteller“ und ChatGPT nicht als „Rahmen darum“ zu sehen. Eher umgekehrt: Das Modell führt den Dialog fort, und das Widget ist nur eine der Arten, Daten anzuzeigen und zu justieren.

Ein typisches Szenario für GiftGenius sieht so aus:

  1. Benutzer: „Ich brauche ein Geschenk für meine Schwester (IT) bis 100$“.
  2. Modell: Textliches Intro (pre‑text) – erklärt, dass es GiftGenius öffnet und was es macht.
  3. Widget: zeigt eine Ideenauswahl und bietet follow‑ups.
  4. Benutzer: schreibt entweder selbst eine Nachricht oder tippt auf einen follow‑up‑Button (z. B. „Nur digitale Geschenke anzeigen“).
  5. Modell: interpretiert es als Text, ruft das passende Tool auf, kommentiert bei Bedarf das Ergebnis (post‑text) oder zeigt erneut ein Widget.
  6. Und so weiter im Kreis, bis die Aufgabe gelöst ist – bis hin zur Bestätigung der Auswahl, Bestellung usw.

Follow‑ups sind hier der Klebstoff, der jede Drehung dieses Zyklus zusammenhält. Ohne sie bleibt der Benutzer nach dem Widget in der Luft: Alles hübsch, aber „wie weiter?“ bleibt unklar.

In komplexeren Szenarien (Workflows, Agenten) helfen follow‑ups, mehrstufige Funnels zu modellieren: „Wähle zuerst den Empfänger“, „Jetzt das Budget präzisieren“, „Jetzt die Auswahl bestätigen“. In diesem Modul ist wichtig zu sehen: Selbst die einfachste Einstufen‑App profitiert stark von ein paar durchdachten Hinweisen.

10. Praxis: Was sich jetzt sofort umsetzen lässt

Eine gute Übung zum Festigen – erweitert euer aktuelles Übungs‑Widget.

Wenn ihr bereits eine Ergebnisliste habt (z. B. Geschenke, Hotels oder Dokumente), fügt darunter einen kleinen Block „Wie geht es weiter?“ mit zwei bis drei Buttons hinzu. Achtet darauf, dass diese Buttons den Typen aus der Tabelle oben entsprechen: einer präzisierend (drill‑down, z. B. „Günstiger“), einer als Schwenk (pivot, „Empfänger ändern“), ein dritter – falls nötig – navigierend (navigation, „Zur Kasse gehen“).

Ruft in den Klick‑Handlern useSendMessage mit sinnvollem Text in natürlicher Sprache auf, vergesst bei Bedarf die Aktualisierung des widgetState nicht. Startet das Szenario dann in ChatGPT neu und schaut, wie der Dialog wirkt: Wie klar ist, was nach dem Widget zu tun ist?

Versucht außerdem absichtlich schlechte follow‑ups zu bauen: lang, vage, mit einem Dutzend Optionen – und vergleicht das Gefühl. Das ist ein schneller Weg, den Unterschied selbst zu spüren.

11. Typische Fehler im Umgang mit follow‑ups

Fehler Nr. 1: „Stummes“ Widget.
Ein Entwickler baut ein tolles UI, bietet aber überhaupt keine follow‑ups an. Der Benutzer sieht Karten, denkt „ganz nett“, und muss dann selbst raten, dass man z. B. „Günstiger anzeigen“ oder „Empfänger wechseln“ bitten kann. Die meisten kommen nicht darauf und springen ab. Mindestens ein bis zwei Hinweise „wie weiter“ unter dem Widget lösen das Problem.

Fehler Nr. 2: Zu viele Schaltflächen.
Die Gegenextrem: den Benutzer mit einem Dutzend Optionen zuspammen – „Budget ändern“, „Interessen ändern“, „Währung wechseln“, „Auswahl speichern“, „Mit einem Freund teilen“, „Ähnliche anzeigen“, „Support fragen“ usw. Es entsteht ein psychologisches „All‑you‑can‑eat‑Buffet“, auf dem die Wahl schwerfällt. Startet lieber mit zwei bis drei häufigsten Aktionen und überlasst den Rest dem Modell und normalem Text.

Fehler Nr. 3: Dialoglogik nur im Frontend.
Man versucht manchmal „zu optimieren“ und ruft statt des Sendens eines follow‑ups über useSendMessage (oder das Low‑Level‑sendFollowUpMessage) direkt dasselbe Tool aus dem Widget auf und aktualisiert das UI. Im Chatverlauf steht dann kein Wort darüber, was passiert ist. Nach ein paar Schritten fängt das Modell an, sich zu verirren – und ihr mit ihm. Der richtige Weg: Dialoglogik auf Ebene von Text und Tools halten, das Widget als dünne UI‑Schicht verwenden.

Fehler Nr. 4: Unklare oder doppeldeutige Formulierungen.
Ein Button „Mehr“ kann ohne Kontext alles bedeuten: mehr Geschenke, mehr Text, mehr Geld? Genauso sind Formulierungen wie „Neu berechnen“ oder „Neu bauen“ sowohl für Modell als auch Benutzer unklar. Die besten follow‑ups sind konkret: „Mehr Varianten in diesem Budget anzeigen“, „Nur digitale Geschenke anzeigen“.

Fehler Nr. 5: Nicht synchronisierter UI und Text.
Klassiker: Beim Klick auf „Günstiger“ habt ihr den UI‑Filter aktualisiert, aber kein follow‑up gesendet oder den widgetState nicht aktualisiert. Im Verlauf fehlen dann die Schritte zur Budgetänderung, und beim nächsten Rendern „springt“ der Filter zurück. Das fühlt sich „kaputt“ an. Nutzt die Kombination setWidgetState + sendMessage, damit Text und UI im Gleichschritt gehen.

Fehler Nr. 6: Versuch, die „nativen“ ChatGPT‑Vorschläge zu steuern.
Manchmal verlassen sich Entwickler darauf, dass ChatGPT die passenden follow‑up‑Chips unter der Nachricht selbst generiert, und fügen keine eigenen hinzu. Aber diese Vorschläge sind nicht garantiert und werden nicht von der App gesteuert. Betrachtet sie als netten Bonus, gebt aber immer eure eigenen, kritischen follow‑up‑Buttons im Widget.

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