In-App-Hilfe-Assistent
Ein Assistent, der in einer Webanwendung lebt und genau weiß, wie diese App genutzt wird. Er beantwortet die Frage „Wie beantrage ich Urlaub?“ mit nummerierten Schritten, die die exakten UI-Bezeichnungen verwenden. Unter dem richtigen Schritt zeigt er ein Nahaufnahme-Screenshot, und ein Cursor animiert auf die zu drückende Schaltfläche. Er verlinkt jeden genannten Bildschirm, aber nur solche, die die Person öffnen kann. Er liest die Daten dieser Person mit ihren Berechtigungen aus, und das Maximum, das er tut, ist, eine Aktion vorzubereiten, die die Person dann bestätigen muss.
Dieses Muster wurde dreimal umgesetzt:
- Ein Chat-Widget, das sich selbst erklärt, mit etwa 30 Screenshots. Der
[captura:id]-Marker stammt von hier. - Ein internes ERP. Die ausgereifte Version: etwa 25 manuelle Abschnitte, etwa 200 Screenshots mit klickbaren Zonen, 12 berechtigungsspezifische Daten-Tools, Aktionsschaltflächen und eine Evaluierung mit 32 Fällen. Es dauerte einen Tag plus Fehlerbehebungen.
- Ein bestehendes Multi-Agenten-Produkt (das Admin-Panel einer Bildungsplattform mit über 90 Seiten), in das es in die bereits vorhandene Agenten-Laufzeitumgebung portiert wurde.
reference.md enthält den Code für jedes einzelne Teil. Zum Erstellen von Screenshots wird der Skill agent-app-screenshots verwendet (npx skills add https://github.com/samuelferfort/agent-skills --skill agent-app-screenshots) für die Hilfsfunktionen zum Zuschneiden und Schwärzen. Das Playwright-Gerüst in scripts/capture.mjs fügt darüber hinaus Sitzungen pro Rolle und klickbare Zonen hinzu.
0. Entscheiden Sie sich, bevor Sie Code schreiben
Fragen Sie den Benutzer nur das, was der Code Ihnen nicht sagen kann.
-
Ein Agent oder zwei. Wenn die App bereits einen Agenten hat (einen RAG/Wissensbot, einen Domain-Copiloten), wählen Sie zwischen:
- dem Hinzufügen des Handbuch-Tools zu diesem Agenten, sodass es einen Einstiegspunkt gibt;
- dem Hinzufügen eines separaten Hilfe-Agenten.
Ein Einstiegspunkt ist das, was Benutzer erwarten, aber es erfordert eine Weiterleitung zwischen „Wie benutze ich die App“ und der bestehenden Domäne, und es muss für alle sichtbar sein, die Hilfe benötigen. Prüfen Sie, wer das vorhandene Panel heute sehen kann.
-
Zielgruppen. Unterschiedliche Oberflächen (Admin vs. Endbenutzer) erhalten unterschiedliche Handbücher und Screenshot-Sets. Sie können sich den Lader, das Tool und den Renderer teilen.
-
Umfang von v1. Empfohlene Reihenfolge:
- Handbuch
- Links
- Screenshots
- Evaluierung
- Daten-Tools
- Aktionsschaltflächen
Das Handbuch allein beantwortet bereits die meisten Fragen. Aktionsschaltflächen kosten am meisten, weil jeder Zieldialog über eine URL geöffnet werden muss.
-
Modell und Route. Verwenden Sie ein schnelles Modell mit geringer Reasoning-Zeit. Messen Sie die Zeit bis zum ersten Token auf der tatsächlichen Anbieterroute, bevor Sie sich festlegen. In einem Build dauerte Gemini über Vertex 68–203 s bis zum ersten Token und dasselbe Modell über Google AI Studio 1,6–5,6 s. Legen Sie sich auf einen Anbieter fest, damit implizites Prefix-Caching greift.
-
Demo-Daten. Screenshots und die Evaluierung benötigen eine gesäte Datenbank mit einem Demo-Benutzer pro Rolle. Verwenden Sie niemals die Produktion. Personenbezogene Daten, die trotzdem auftauchen, müssen geschwärzt werden.
1. Das Handbuch: klein, kuratiert, im Repository
- Format. Eine Markdown-Datei pro Bereich:
manual/<id>.mdmit Frontmatterid,titulo/title,rutas/routes(Next.js-Routenmuster),modulo/moduleundresumen/summary. Die Zusammenfassung ist das, wonach das Modell auswählt, also machen Sie sie spezifisch. - Abschnitte des Textkörpers.
- Wofür es ist
- Wie man dorthin gelangt (Menüpfad)
- Wer es verwenden kann (Rollen, Berechtigungen, wer genehmigt)
- Was auf dem Bildschirm zu sehen ist
- Wie es geht (nummerierte Schritte)
- Häufige Probleme
- Exakte Bezeichnungen. Schreiben Sie UI-Bezeichnungen genau wie gerendert, in «» oder Anführungszeichen. Lesen Sie sie aus den Komponenten oder den i18n-Dateien, niemals aus dem Gedächtnis.
- Kein RAG, solange das Korpus in einen Index passt (etwa 40 Abschnitte oder weniger).
- Platzieren Sie den Index (eine Zeile pro Abschnitt: id, Titel, Routen, Zusammenfassung) im Prompt.
- Das Modell ruft bis zu 3 Abschnitte mit einem Tool ab, dessen Eingabe
z.enum(sectionIds)ist, sodass es keinen Abschnitt erfinden kann. - Die Auswahl nach Titel und Zusammenfassung schlägt bei dieser Größe das Abrufen von Chunks, und es gibt keinen Index, der synchron gehalten werden muss.
- Verwenden Sie RAG (Embeddings und Re-Rank) nur für ein großes externes Korpus, wie es in einem Build ein 335-Fragen-Callcenter-Handbuch war.
- Lebt im Repository, versioniert mit dem Code. Legen Sie es nicht in einem administrativ bearbeitbaren Speicher ab. Der Abdeckungstest muss fehlschlagen, wenn ein Bildschirm ohne seinen Abschnitt ausgeliefert wird.
- Hinweis auf den aktuellen Bildschirm. Bilden Sie
pathnameauf Abschnitte ab (zuerst die spezifischste Route) und nennen Sie die oberen 1–2 im Prompt („Wenn sie nach ‚diesem‘ fragen, beginnen Sie hier“).
2. Prompt-Layout (cache-freundlich)
[FIXIERT – identisch für alle, kommt zuerst, damit der Anbieter es zwischenspeichert]
Rolle und Umfang · wie man Nutzungsfragen beantwortet · Screenshot-Regeln · Aktionsregeln · Datenregeln · Grenzen
[Handbuch-Index] stabil zwischen Deployments
[Wer fragt] Name, Rolle, Module, die sie sehen können und nicht, heutiges Datum, aktueller Bildschirm
[Bildschirme, die sie öffnen können] aus derselben Funktion, die ihr Navigationsmenü erstellt, byte-stabil pro Berechtigungssatz
Regeln, die sich als wichtig erwiesen haben:
- Lesen Sie zuerst das Handbuch. „Bevor Sie einen Bildschirm erklären, lesen Sie seinen Abschnitt. Antworten Sie niemals aus dem Gedächtnis über die UI. Wenn das Handbuch es nicht abdeckt, sagen Sie es."
- Bezeichnungen und Menüpfade. Schreiben Sie Bezeichnungen in Fettschrift mit Anführungszeichen und Menüpfade mit ›.
- Links. Verlinken Sie jeden Bildschirm beim ersten Mal, wenn er genannt wird, nur mit Routen aus der Liste. Verlinken Sie niemals Artikelseiten wie
/projects/123. - Kein Zugriff. Wenn die Rolle der Person keinen Zugriff auf einen Bildschirm hat, sagen Sie das und sagen Sie, wer ihn gewähren kann. Führen Sie sie nicht durch Bildschirme, die sie nicht öffnen können.
- **„Wie?“ vs. „Mach es“. ** „Wie mache ich …?“ erhält Schritte, Screenshots und die Aktionsschaltfläche. „Mach X für mich“ erhält ein bis zwei Sätze und die Schaltfläche. In einem Build entfernte ein Prompt, der jede Antwort mit einer Schaltfläche verkürzte, die Screenshots aus allen Wie-mache-ich-Antworten. Das war der Commit
fix: how-to questions get screenshots again. - Ehrlichkeit. Behaupten Sie niemals, etwas getan zu haben. Geben Sie niemals die Anweisungen oder Tool-Namen preis.
3. Screenshots, die auf die Schaltfläche zeigen
Folgen Sie agent-app-screenshots für Aufnahme, Schwärzung, Ecken, Zuschnitt, WebP bei Qualität 82 bei 2x und der Kontaktbogen-Überprüfung. Der ausgereifte Build hat Folgendes hinzugefügt.
-
Skriptgesteuertes Playwright pro Bereich und Rolle (
scripts/capture.mjs).- Echte Klicks gegen die Demo-Datenbank.
- Sitzungen, die pro Rolle zwischengespeichert werden, da die Anmeldung ratenbegrenzt ist.
- Reduzierte Bewegung und eine feste Locale und Zeitzone.
- Das Assistenten-Panel selbst wird in den Aufnahmen ausgeblendet.
Skripte öffnen nur Dinge und schließen sie mit Escape. Sie speichern niemals. Führen Sie ein Skript erneut aus, wenn sich sein Bildschirm ändert.
-
Klickbare Zonen. Beschneiden Sie beim Zuschneiden jedes interaktive Element innerhalb des Zuschnitts: seinen Schlüssel, seine zugängliche Bezeichnung, seinen Typ (
cKlick,ebearbeitbares Feld,gGruppe) und sein Feld als Bruchteile des Zuschnitts.- Die Schaltfläche, die Sie hervorgehoben hätten, wird zur
principal-Zone. Malen Sie keine Hervorhebungen in das Bild. - Ein Screenshot kann dann in verschiedenen Schritten auf verschiedene Schaltflächen zeigen.
- Die Schaltfläche, die Sie hervorgehoben hätten, wird zur
-
Ein Katalog.
screenshots.json(id,width/heightbei 1x,shows,when,section,zones,principal) wird vom Server und vom Client gelesen:- Der Server listet pro Handbuchabschnitt die verfügbaren Screenshots und deren Zonen auf.
- Der Client verwendet es für Größe, Alternativtext und URL.
-
Marker. Das Modell schreibt
[captura:id]oder[captura:id#zone]in eine eigene Zeile, nach dem Schritt, den es veranschaulicht. Grenzen: höchstens 3 pro Antwort, nur IDs, die vom Handbuch in dieser Unterhaltung zurückgegeben wurden, und keine Beschreibung des Bildes. -
Client.
- Wandeln Sie die Marker vor dem Markdown in
<captura shot="id" zona="zone">um. Verwenden Sieshotund nichtid/name, da Bereiniger ihnenuser-content-voranstellen. - Erlauben Sie das Tag im Bereiniger.
- Verstecken Sie halbgeschriebene Marker während des Streamings.
- Verwerfen Sie unbekannte IDs, ohne die umgebenden Wörter zusammenzukleben.
- Entfernen Sie Marker, wenn die Antwort kopiert wird.
- Reservieren Sie die Bildgröße aus dem Katalog, zoomen Sie bei Klick und rendern Sie nichts, wenn das Bild nicht geladen werden kann.
- Zeichnen Sie den Cursor und die Klickanimation in einem Overlay unter Verwendung von Prozentwerten des Bildes.
- Zeigen Sie bei reduzierter Bewegung nur den Endzustand an.
- Wandeln Sie die Marker vor dem Markdown in
-
Bilder im Repository (
public/…), ausgeliefert über das eigene CDN der App mit Inhalts-Hashes.
4. Links, Daten und Aktionen
- Bildschirme, die es verlinken kann. Leiten Sie sie aus derselben Funktion ab, die das Menü der Person erstellt, plus Tabs, die eine eigene URL haben. Der Client überprüft jeden Link erneut gegen dieselbe Liste: Ein Link, den die Person nicht öffnen kann, wird als Text gerendert, niemals als 403. In-App-Links navigieren mit dem Router und lassen das Panel geöffnet (auf Mobilgeräten schließen).
- Daten-Tools.
- Nur lesen.
- Jedes Tool wird nur ausgegeben, wenn die Rolle ihr Modul sehen kann, und überprüft die Berechtigung serverseitig erneut.
- Es wendet denselben SQL-Bereich an wie der Bildschirm.
- Es gibt kurze Listen (etwa 10 Zeilen) mit der Gesamtzahl zurück.
- Das Modell entscheidet nie, wer was sehen kann.
- Aktionsschaltflächen. Ein
prepare_action-Tool validiert Rolle und Status („bereits eingestempelt“) und die Daten, die die Person gegeben hat. Der Client rendert eine Schaltfläche, die den echten Dialog vorausgefüllt öffnet (?new=…für globale Modale,?action=…für Bildschirmdialoge), und die Person überprüft und bestätigt.- Das Tool führt niemals etwas aus.
- Validieren Sie die Vorausfüllung auf dem Client mit demselben Schema erneut.
- Fehlende Felder bleiben leer. Das Modell fragt nicht danach.
- Höchstens eine Schaltfläche pro Antwort.
4b. Kontextuelle Einstiegspunkte (Adoption)
Benutzer entdecken einen Assistenten nicht, der hinter einem Symbol versteckt ist, und die Adoption ist der schwierige Teil. Platzieren Sie kleine Schaltflächen „Erklären Sie dies in “ in der UI an Stellen, die verwirrend sind (eine dichte Dashboard-Karte, ein Status, den niemand versteht). Platzieren Sie „Machen Sie es mit “-Schaltflächen, wo eine Aufgabe mehrere Klicks über mehrere Bildschirme erfordert (z. B. das Auffüllen von fehlenden Beständen).
- Verhalten. Die Schaltfläche öffnet das Panel mit einem vorausgefüllten Prompt plus dem Bildschirmkontext, der sofort gesendet oder bereit zum Senden belassen wird.
- Für „Erklären“-Schaltflächen benennt der Prompt das Element: „Erklären Sie die «Überfällig»-Karte auf diesem Bildschirm“.
- Für „Machen“-Schaltflächen verwendet der Assistent seine Tools und endet dennoch in einer vorbereiteten Aktion, die die Person bestätigt. Er mutiert niemals stillschweigend.
- Halten Sie es im Code. Prompts leben in einem typisierten Register (
id → { label, prompt, screen }), nicht als Inline-Strings. Jeder Eintrag hat einen Evaluierungsfall, und jede Runde protokolliert dieentry-ID, sodass Sie sehen können, welche Schaltflächen verwendet werden. - Verwenden Sie wenige davon. Eine pro verwirrender Stelle. Eine Schaltfläche auf jeder Karte ist Rauschen.
5. Betrieb
- Anforderungstext. Der Client sendet nur die neue Nachricht sowie
pathnameund Seitentitel. Der Server validiert den Pfadnamen (nur interne Routen) und kürzt den Titel. - Thread-Besitz. Überprüfen Sie ihn bei jeder Anfrage und bei jedem Historie-Routing. Agentenspeicher erzwingen keinen Zugriff.
- Schließen Sie Runden serverseitig ab. Halten Sie die Anfrage mit
after()+consumeStream()am Leben, sodass das Schließen des Panels mitten in der Antwort die Runde dennoch speichert. - Hartes Zeitlimit. Brechen Sie eine Runde nach etwa 60 s ab. Das Panel zeigt dann eine „Wiederholen“-Schaltfläche, und die Runde wird als Zeitüberschreitung protokolliert.
- Eine Zeile pro Runde mit Benutzer, Seite, Modell, Eingabe-/Cache-/Ausgabe-/Reasoning-Token, Tools, Beendigungsgrund, Fehler und Dauer. Es speist ein stündliches Limit pro Benutzer und das Kosten-Dashboard.
- Speicher. Kurze Hilfe-Threads (letzte 30 Nachrichten oder etwa 60k Token). Das Schließen des Panels startet eine neue Unterhaltung, und die alte bleibt im Verlauf.
- Tool-Schritte. Zeigen Sie jedes Tool als Schritt mit einem Ergebnis in der Vergangenheitsform („1 Handbuchabschnitt“, „3 Aufgaben“), das eingeklappt wird, sobald die Antwort beginnt. Behaupten Sie nicht, dass eine Abfrage aufgrund der verstrichenen Zeit allein „schwer“ sei.
Referenzzahlen aus dem ausgereiften Build: etwa 11.7k Eingabe-Token und 260 Ausgabe-Token pro Frage, etwa €0.01 pro Frage, 7.7 s Median.
6. Tests und Evaluierung: Schützen Sie den Inhalt, messen Sie das Modell
Deterministische Tests (vitest, keine Modellaufrufe):
- Handbuch. Jeder Abschnitt hat eine eindeutige ID, eine Zusammenfassung von 20+ Zeichen und einen Textkörper, der „Wie“/„Was auf dem Bildschirm ist“ enthält.
- Routen. Jede Route im Handbuch existiert in der App.
- Abdeckung. Jede Seite in der App wird von einem Abschnitt abgedeckt. Dies ist der Test, der das Handbuch am Leben hält.
- Keine Codenamen. Keine internen Namen (
src/,.tsx, Tabellennamen) erscheinen im Handbuch. - Index. Der Prompt-Index listet jeden Abschnitt auf, und die Suche nach dem aktuellen Bildschirm gibt den spezifischsten Abschnitt zuerst zurück.
- Katalog. Katalog und Bilder stimmen eins zu eins überein, es gibt keine verirrten PNGs, und jeder Screenshot gehört zu einem vorhandenen Abschnitt und hat gültige Zonen.
- Marker. Unbekannte IDs werden entfernt, partielle Marker werden während des Streamings ausgeblendet, und das Kopieren entfernt Marker.
- Rollen. Jede Rolle erhält nur die Tools ihrer Module, und die Bildschirmliste enthält nur das, was ihr Menü anzeigt.
- Aktionen. Jede Aktion zielt auf eine reale Seite ab, und ihre Vorausfüllung besteht ihr Schema.
Evaluierung (scripts/eval.mjs): Führen Sie sie gegen den echten Agenten mit Demo-Daten aus, mit 25–35 echten Fragen pro Rolle. Pro Fall behaupten:
- Tools, die es verwenden muss und nicht verwenden darf, und Handbuchabschnitte, die es lesen muss;
- Bezeichnungen, die erscheinen müssen und nicht erscheinen dürfen;
- gültige Screenshots (3 oder weniger, aus dem Katalog) und dass es auf die richtige Zone zeigt;
- Links, die es setzen muss und nicht setzen darf;
- die erwartete Aktion und ihre Daten;
- keine Behauptungen, etwas getan zu haben, und keine Daten außerhalb der Rolle.
Führen Sie die Evaluierung vor und nach jeder Änderung am Prompt, Modell oder den Tools durch.
7. Am Leben erhalten
| Wann | Tun |
|---|---|
| Ein Bildschirm ändert sich | Aktualisieren Sie seinen Abschnitt im selben Commit und führen Sie das Aufnahmeskript erneut aus |
| Ein Bildschirm entsteht | Fügen Sie seine Route zu einem Abschnitt hinzu (der Abdeckungstest schlägt sonst fehl) |
| Prompt, Modell oder Tools ändern sich | Führen Sie die Evaluierung vorher und nachher durch |
| Ein Anbieter ist langsam | Messen Sie die TTFT pro Anbieterroute, bevor Sie den Prompt anfassen |
Lehren aus der Portierung in einen vorhandenen Agenten-Stack
- Erweitern Sie den Router. Wenn die App bereits Runden weiterleitet (konversationell vs. Wissen), fügen Sie diesem Router einen
app_help-Zweig hinzu, anstatt einen zweiten Agenten oder eine zweite Schaltfläche zu erstellen. Wenn der Fragesteller keinen Zugriff auf den anderen Zweig hat, schränken Sie den Router aufconversational | app_helpein und erstellen Sie die Tools des anderen Zweigs niemals serverseitig. - Autorisieren Sie das freigegebene R…
[Der Rest des Inhalts wurde gemäß der Anweisung als gekürzt markiert]