Notiz 7 · Microsoft Foundry (3/12)

Microsoft Foundry: Wie speicherst du Agent-Sessions außerhalb der Chat-Shell?

Wo der Gesprächszustand liegen sollte, wenn eine Browser-Shell einen Plattform-Agent umhüllt, und warum Neuladen und Beenden eine Architekturfrage sind.

24. Juli 2026 9 Min. Lesezeit

Das Wichtigste in Kürze

  • Behandle Auth-Session, UI-Zustand und Agent-Gespräch als drei getrennte Uhren.
  • Führe die Gesprächsliste in deiner eigenen API. Lass Playground- und Portal-Müll draußen.
  • Speichere eine dauerhafte Gesprächs-ID, bevor du den Stream öffnest.
  • Lege das Verhalten bei Neuladen, Beenden, Recycle und Token-Erneuerung in einem ADR fest.
  • Zeig unvollständige Läufe auf Basis der Wahrheit auf dem Server, nicht danach, ob die EventSource noch lebt.
  • Trenne im Support die Lebensdauer der Anmeldung sauber von der Lebensdauer des Gesprächs.

Nutzer erwarten die Regeln von ChatGPT: Tab schließen, zurückkommen, der Thread ist noch da. Agent-Dienste von Plattformen haben oft ihren eigenen Gesprächsspeicher. Deine Shell ist ein drittes Ding.

Wenn diese drei sich widersprechen, bekommst du Threads ohne Titel aus dem Portal, Agents, die nach dem Neuladen "gestoppt" aussehen, und unvollständige Chats, die nach einer neuen Anmeldung verschwinden.

Benanntes Modell: drei Uhren

  • Auth-Session: MSAL-Cache, Cookies, Lebensdauer der Tokens. Belegt, wer aufruft. Entscheidet nicht, welcher Thread geöffnet wird.
  • UI-Zustand der App: ausgewählter Agent, Panels, Entwürfe, Scrollposition. Meist wegwerfbar. Ihn zu verlieren sollte sich anfühlen wie eine Schublade zu schließen.
  • Agent-Gespräch: Nachrichten, Läufe, Tool-Aufrufe, Zitate. Liegt in der Plattform oder in deinem Backend, zugeordnet zum Nutzer.
  • Vertrag: Nur Uhr (3) hat über Tabs hinweg dauerhafte Bedeutung. Noch angemeldet heißt nicht noch im selben Chat.

Drei Uhren: Auth-Session, UI-Zustand der App und Agent-Gespräch, wobei nur das Gespräch als dauerhaft markiert ist

Abbildung 1. Auth, UI-Zustand und Agent-Gespräch sind drei Uhren. Nur die Uhr des Gesprächs sollte Beenden und Neuladen als Produktverlauf überstehen.

Kontext und Rahmenbedingung

Fehler, die wie Modellversagen aussehen, entpuppen sich oft als Grenzen von Sessions. Der Lauf war in Ordnung. Die Oberfläche hat die ID verloren. Oder die Oberfläche hat einen Portal-Thread gezeigt, den der Nutzer nie in der App gestartet hat. Neuladen und Beenden sind der Produktvertrag, keine Randfälle.

  1. Auth-Session. MSAL-Cache, Cookies, Lebensdauer der Tokens. Übersteht das Neuladen, wenn du es so entwirfst. Belegt, wer aufruft. Entscheidet nicht, welcher Thread geöffnet wird.
  2. UI-Zustand der App. Ausgewählter Agent, offene Panels, lokale Entwürfe, Scrollposition. Meist wegwerfbar. Ihn zu verlieren sollte sich anfühlen wie eine Schublade zu schließen, nicht wie verlorene Arbeit.
  3. Agent-Gespräch. Nachrichten, Läufe, Tool-Aufrufe, Zitate. Sollte in der Plattform oder in deinem Backend liegen, zugeordnet zum Nutzer, nicht zu einem flüchtigen Browser-Tab.

Der wiederkehrende Fehler ist die Annahme, dass (3) automatisch funktioniert, weil (1) funktioniert. Dass die Anmeldung das Neuladen übersteht, heißt nicht, dass der Gesprächsgraph es überstanden hat oder dass deine Shell weiß, welches Gespräch sie neu laden soll. "Noch angemeldet" und "noch im selben Chat" sind zwei verschiedene Sätze.

Abbildung 2 ist die Darstellung auf Learn für die Authentifizierung von der SPA zur API: Die Shell holt sich Tokens und ruft APIs auf. Die Dauerhaftigkeit von Gesprächen ist ein eigenes Design.

SPA, die eine Web-API aufruft

Abbildung 2. Die Shell holt sich Tokens und ruft APIs auf. Die Dauerhaftigkeit von Gesprächen ist ein eigenes Design. Quelle: Microsoft Learn: authentication flows and app scenarios.

Was "läuft in der Plattform noch weiter" wirklich bedeutet

Speicher der Plattform können Läufe behalten, nachdem der Browser gestorben ist. Das ist nützlich. Es ist aber kein Produktversprechen, das du ohne Tests in eine Support-FAQ kopieren kannst.

Diese Dauerhaftigkeit heißt nicht, dass deine Shell:

  • jedes Gespräch im Projekt auflisten sollte, einschließlich Playground- und API-Experimenten
  • einen Lauf ohne dauerhafte Gesprächs-ID in deinem eigenen Speicher fortsetzen sollte
  • so tun sollte, als wäre ein SSE-Stream, der mitten im Token abgerissen ist, ohne Protokoll für die Wiederverbindung noch interaktiv
  • Threads ohne Titel, die im Portal angelegt wurden, als vollwertigen Produktverlauf behandeln sollte

Behandle die Dauerhaftigkeit der Plattform als Fähigkeit, die du mit Tests für Beenden und Neuladen auf einem produktionsnahen Build überprüfst. Recycles, Token-Erneuerung und zwei offene Tabs zeigen den echten Pfad.

Design

1. Führe die Gesprächsliste in deiner eigenen API

Zeig nur Threads an, die über die Shell angelegt wurden. Nutzer sollten keine Playground-Chats ohne Titel oder Nachbar-Experimente aus demselben Plattformprojekt erben. Wenn Betreiber Einblick ins Portal brauchen, gib ihnen das Portal. Beim Rendern zu filtern reicht nicht. Der Listen-Endpunkt sollte schon ehrlich sein.

2. Erst speichern, dann streamen

Leg zuerst den Gesprächsdatensatz an. Dann streame. Wenn das Backend recycelt wird und die Oberfläche die SSE-Verbindung verliert, hast du trotzdem eine ID, um den Verlauf neu zu laden oder einen klaren Zustand "Lauf beendet" zu zeigen. IDs, die bis zum ersten Token nur lokal existieren, sind die Quelle der Fehler mit leerem Bildschirm nach dem Neuladen. Abbildung 3 zeigt diese Reihenfolge der Verantwortung.

Gesprächsdatensatz anlegen, dann SSE-Stream öffnen, dann über die ID neu laden; das Anti-Pattern zeigt eine nur lokale ID bis zum ersten Token, die zu einem leeren Bildschirm führt

Abbildung 3. Leg zuerst den Datensatz an. Dann streame. IDs, die bis zum ersten Token nur lokal existieren, sind die Quelle der Fehler mit leerem Bildschirm nach dem Neuladen.

3. Lege das Verhalten beim Neuladen in einem ADR fest

Sinnvolle Optionen:

  • den Verlauf für diese Gesprächs-ID neu laden
  • einen laufenden Lauf erkennen und Weitermachen oder Warten anbieten
  • fail closed mit einer klaren Meldung

Wähle eine pro Produktoberfläche. Dokumentiere sie. Teste sie auf einem echten Build mit Beenden, Neuladen und Token-Erneuerung. Lass das Verhalten bei F5 nicht zu Stammeswissen werden.

4. Trenne die Lebensdauer der Anmeldung von der Lebensdauer des Gesprächs

Ein Nutzer kann angemeldet bleiben und trotzdem einen Lauf verlieren. Ein Nutzer kann Tokens erneuern und trotzdem den Thread von gestern öffnen. Wer diese Uhren vermischt, erzeugt Support-Tickets, die mystisch klingen: "Der Agent hat aufgehört", wenn der Stream abgerissen ist, oder "Mein Chat ist weg", wenn die Oberfläche die ID nie zum Principal gespeichert hat.

5. Stell unvollständige Läufe als vollwertigen UI-Zustand dar

Lange Tool-Aufrufe überleben einen Tab. Zeig "läuft", "unterbrochen" oder "ohne Antwort beendet" auf Basis der Wahrheit auf dem Server, nicht danach, ob die EventSource noch offen ist. Abbildung 4 ist der UI-Vertrag.

Drei UI-Zustände für unvollständige Läufe: läuft, unterbrochen, ohne Antwort beendet, gesteuert von der Wahrheit auf dem Server

Abbildung 4. Läuft, unterbrochen und ohne Antwort beendet sind Produktzustände. Leite sie vom Server ab, nicht davon, ob die EventSource noch offen ist.

Abbildung 5 ist die Darstellung auf Learn für privates Networking. Die Netzwerkkonfiguration der Shell ist unabhängig vom Gesprächsspeicher. Private Endpoints erfinden keine Session-Semantik.

Schema eines Private Endpoint für App Service

Abbildung 5. Die Netzwerkkonfiguration der Shell ist unabhängig vom Gesprächsspeicher. Quelle: Microsoft Learn: App Service private endpoints.

Häufige Fehler

Plattformweite Liste in der Shell. Die Oberfläche zeigt plattformweite Chats gemischt mit Chats aus der App. Das verwirrt und kann Chats offenlegen, die der Nutzer nie gestartet hat. Playground-Müll landet neben echter Arbeit.

Neuladen ohne Gesprächs-ID. Das Neuladen beendet den Lauf, und die Oberfläche hat keine Gesprächs-ID. Der Nutzer sieht einen leeren Bildschirm und geht von Datenverlust aus. Oft hat die Plattform den Lauf noch, nur hat deine Shell den Zeiger weggeworfen.

IDs nie an den Principal gebunden. Nach einer neuen Anmeldung lassen sich unvollständige Chats nicht öffnen. Die IDs wurden nie zum Principal des Nutzers gespeichert oder lagen nur im sessionStorage, zugeordnet zu einem Tab.

Nur Streams im Arbeitsspeicher. Ein Neustart des Backends verwirft Streams im Arbeitsspeicher, ohne dauerhaftes Transkript. Funktioniert auf einer Maschine bis zum ersten Recycle oder Scale-out.

Optimistische UI ohne Bestätigung vom Server. Wirkt schnell, bis sich zwei Tabs widersprechen oder eine Wiederverbindung eine halbe Runde erneut abspielt.

Wiederverbindung heißt hoffen. Wiederverbindung bedeutet "Seite neu laden und hoffen". Für Agents, die minutenlang Tools aufrufen, ist Hoffnung kein Protokoll.

So übernehmen oder anpassen

So übernehmen

  • Die Quelle der Wahrheit für Nachrichten (Speicher der Plattform, deine Datenbank oder beides).
  • Welche Chats in der Liste der Shell erscheinen und welche ausgeschlossen sind (Playground, andere Apps, gelöschte).
  • Das Verhalten bei Neuladen, Beenden, Recycle des Backends und Token-Erneuerung.
  • Wie unvollständige und unterbrochene Läufe in der Oberfläche dargestellt werden.
  • Aufbewahrung und Löschung, gebunden an die Identität des Nutzers.
  • Erwartungen an die Wiederverbindung bei langen Tool-Aufrufen oder ein explizites "nicht unterstützt" mit passender UX.

Vor dem Einsatz anpassen

Gesprächsmetadaten im eigenen Backend zu führen bringt zusätzliche Arbeit für Speicherung und Löschung mit sich (DSGVO, Offboarding von Konten, "lösch meinen Verlauf"). Sich nur auf den Speicher der Plattform zu verlassen, kann einfacher sein, bis Listenfilter und Produkt-UX Felder brauchen, die die Plattform nicht sauber liefert.

Lang laufende Tool-Aufrufe brauchen ein Konzept für die Wiederverbindung. Das ist schwieriger als bei einem reinen Chat-Spielzeug. Plane es ein, wenn deine Agents Tools aufrufen, die Minuten dauern.

Privates Networking und IP-Allowlists schützen die Ebene. Sie reparieren keine Session-Semantik. Du brauchst trotzdem das ADR.

Wichtigste Quellen: Microsoft Learn: authentication flows and app scenarios, App Service private endpoints und die Gesprächs-APIs deiner Plattform für die Agent-Laufzeit, gegen die du auslieferst.

Auth-Session, UI-Zustand und Gesprächszustand sind drei Uhren. Zeichne alle drei, sonst lügt deine Shell die Nutzer weiter höflich an.