Trwały magazyn stanów dla agentów hostowanych w Microsoft Foundry (wersja zapoznawcza)

Trwały magazyn stanów dla agentów hostowanych Microsoft Foundry zapewnia magazyn wartości klucza opartej na serwerze dla danych JSON, które muszą być utrwalane w przypadku awarii, ponownego uruchomienia lub eksmitowania kontenera agenta po okresie bezczynności. Służy do przechowywania punktów kontrolnych struktury, historii konwersacji zarządzanej przez aplikację, artefaktów pośrednich i preferencji użytkownika.

Agent jawnie zapisuje i aktualizuje elementy repozytorium stanów. W przeciwieństwie do sesji i rozmów, platforma nie wypełnia repozytorium automatycznie. Magazyn danych obsługuje izolację dla poszczególnych użytkowników, tagi, optymistyczną współbieżność i konfigurowany czas wygaśnięcia.

W tym artykule wyjaśniono, jak partycjonować dane, zarządzać tożsamością wywołującego, tworzyć magazyny i elementy oraz uzyskiwać do nich dostęp, a także pracować w granicach limitów usługi. W wersji zapoznawczej magazyn stanu jest dostępny tylko dla agentów hostowanych.

Ważna

Elementy oznaczone podglądem w tym artykule są obecnie w wersji zapoznawczej. Ta wersja zapoznawcza jest udostępniana bez umowy dotyczącej poziomu usług, a Microsoft nie zaleca korzystania z niej w przypadku obciążeń produkcyjnych. Niektóre funkcje mogą nie być obsługiwane lub mogą mieć ograniczone możliwości. Aby uzyskać więcej informacji, zobacz Warunki dodatkowe korzystania z testowych wersji Microsoft Azure.

Co przechowywać w magazynie stanu

Zasoby obliczeniowe hostowanego agenta są tymczasowe. Gdy kontener zostanie uruchomiony ponownie lub platforma eksmituje go po okresie bezczynności, agent utraci wszystko, co zapisuje na dysku lokalnym poza sesją. Magazyn stanu przechowuje stan, który musi istnieć dłużej niż kontener.

Typowe treści obejmują:

  • Punkty kontrolne platformy, dzięki czemu platforma agentowa umożliwiająca użycie własnego agenta, taka jak LangGraph lub Microsoft Agent Framework, może wznowić własny graf lub stan przepływu pracy.
  • Historia konwersacji, którą Twój agent sam zarządza, czyli przypadek protokołu Invocations, w którym platforma nie przechowuje tej historii za Ciebie.
  • Wygenerowane artefakty i wyniki pośrednie potrzebne na późniejszym etapie.
  • Profile poszczególnych użytkowników, preferencje i inne długotrwale przechowywane dane aplikacji.

Magazyn stanów nie jest jedyną opcją. Baza danych, magazyn obiektów blob lub inny magazyn należący do aplikacji działa w taki sam sposób. Magazyn stanu eliminuje konieczność samodzielnego konfigurowania i zabezpieczania tego magazynu oraz automatycznie stosuje model tożsamości agenta.

Utrzymuj wartości na tyle małe, aby można je było pobierać na żądanie. Element ma maksymalny rozmiar 1 MB, więc duże pliki binarne powinny być przechowywane w magazynie obiektów blob, a magazyn przechowuje do nich odwołanie.

Tip

Długotrwałi agenci mogą przechowywać znaczniki postępu i zbiorcze punkty kontrolne w osobnych elementach w tym samym magazynie stanów. Informacje o wzorcu odzyskiwania znajdziesz w temacie Zarządzanie stanem dla długotrwale działających agentów.

Sklepy

Klient FoundryStateStore wiąże się z jedną wybraną nazwą sklepu. Ta nazwa służy zarówno jako tożsamość magazynu, jak i jego najbardziej zewnętrzna partycja. Magazyn zawiera kluczowe elementy JSON, które można odczytywać, zapisywać, usuwać i wyświetlać.

  • Nazwa sklepu to tożsamość: nie można zmienić nazwy sklepu po utworzeniu, więc wybierz stabilny schemat nazewnictwa z góry.
  • Pobierz lub utwórz to operacja na poziomie sklepu: pojedyncze wywołanie „pobierz lub utwórz” pobiera sklep lub tworzy go, jeśli jeszcze nie istnieje. Opcje tworzenia mają zastosowanie tylko podczas pierwszego tworzenia, więc usługa ignoruje je, gdy sklep już istnieje. Zapis elementu nie powoduje utworzenia brakującego magazynu danych.
  • Okres istnienia elementu: okno bezczynności na poziomie magazynu usuwa elementy. Wartość domyślna to 30 dni i można skonfigurować magazyn tak, aby elementy nigdy nie wygasały. Zapisy powodują odnowienie okna, a odczyty nie powodują jego odnowienia. Tę opcję można ustawić podczas tworzenia.

Partycjonowanie danych

Magazyn zapewnia dwa niezależne sposoby partycjonowania danych, a większość agentów potrzebuje tylko jednego z nich.

  • Według nazwy sklepu: Każda nazwa sklepu stanowi osobną partycję. Nazwy mogą zawierać /, więc można go używać jako separatora hierarchii, jak w checkpoints/thread-abc lub workflow-state/run-42. Wybierz tę partycję, gdy kod odczytujący element zawsze ma identyfikator partycji dostępny do ponownego skompilowania nazwy.
  • Na użytkownika końcowego: magazyn utworzony z partycjami izolacji użytkowników partycjonuje swoje elementy według użytkownika końcowego, dzięki czemu pojedyncza nazwa magazynu może być bezpiecznie współdzielona przez użytkowników agenta wielodzierżawnego. Wybierz tę partycję, gdy ta sama nazwa magazynu będzie obsługiwać więcej niż jednego użytkownika. Tę opcję ustawia się podczas tworzenia, a magazyn danych ustala użytkownika na podstawie żądania, a nie na podstawie danych przekazywanych przez kod. Aby uzyskać szczegółowe informacje, zobacz Identyfikator wywołującego.

Wybierz najwęższą partycję, którą można odtworzyć na podstawie ścieżki wyszukiwania. Nazwa magazynu, która koduje identyfikator, jest przydatna tylko wtedy, gdy każdy, kto odczytuje ten element, nadal ma ten identyfikator. Gdy wyszukiwanie zawiera sam klucz elementu, ponieważ moduł ładujący punkt kontrolny platformy zwykle wykonuje, zachowaj płaską nazwę sklepu i niech zamiast tego izolacja użytkownika wykonuje partycjonowanie.

Te dwa wymiary łączą się, ale należy je traktować jako odrębne: nazwa magazynu powinna zawierać wyłącznie zakres niezwiązany z użytkownikiem, taki jak identyfikator wątku, wykonania lub przepływu pracy.

Ważna

Nie koduj identyfikatora użytkownika końcowego w nazwie sklepu. Nazwy magazynów danych pojawiają się w obszarach operacyjnych, takich jak dzienniki i komunikaty o błędach, a nazwa tworzona przez własny kod nie jest zweryfikowanym identyfikatorem. Użyj izolacji użytkownika do partycjonowania per użytkownik, dzięki czemu platforma egzekwuje granicę na podstawie wywołującego, którego sama ustaliła, a nie na podstawie wartości dostarczonej przez Twojego agenta.

Tożsamość wywołującego

Magazyn stanu używa modelu tożsamości hostowanego agenta. W protokole kontenera 2.0.0 każde żądanie, które platforma kieruje do Twojego agenta, zawiera nagłówek x-agent-foundry-call-id, który identyfikuje podmiot wywołujący, a sklep ustala na jego podstawie działającego użytkownika końcowego. Pakiety SDK Foundry przekazują ten nagłówek za Ciebie podczas wywołań store, więc większość agentów nigdy nie obsługuje go bezpośrednio.

Dwie konsekwencje mają znaczenie podczas projektowania z nim:

  • Izolacja użytkownika wynika z ID wywołania: W magazynie z izolacją użytkownika partycja jest określana na podstawie wywołującego zidentyfikowanego przez platformę, a nie na podstawie czegokolwiek przekazywanego przez agenta. Hostowany agent nie dostarcza własnego identyfikatora użytkownika końcowego. Jeśli środowisko uruchomieniowe wysyła własne żądania HTTP zamiast używać klienta zestawu SDK, prześlij nagłówek bez zmian i traktuj wartość jako nieprzezroczystą.
  • Lokalne uruchomienia nie obsługują izolacji użytkownika: Platforma nie udostępnia identyfikatora wywołania poza platformą. Ani Python, ani zestaw SDK .NET nie mogą wymuszać izolacji użytkownika podczas lokalnego uruchamiania kontenera. Przetestuj granice izolacji użytkownika za pomocą wdrożonego hostowanego agenta.

Przenieś identyfikator wywołania do zadania odroczonego

Operacje na elementach działają w imieniu wywołującego, a operacje magazynu nie.

Operacja Scope Działający użytkownik
create_item, set_item, , get_item, delete_itemlist_keys Elementy w powiązanym sklepie Rozwiązano problem z identyfikatorem wywołania, gdy magazyn korzysta z izolacji użytkownika
Pobierz lub utwórz dla sklepu Sam sklep Nie rozwiązano problemu; operacja jest ograniczona do zakresu magazynu

Domyślnie operacja na elemencie używa identyfikatora wywołania żądania, w ramach którego jest wykonywana, co jest właściwym rozwiązaniem w przypadku zadań kończących się podczas obsługi tego żądania.

Zadanie, które trwa dłużej niż żądanie, nie ma kontekstowego identyfikatora wywołania, który mogłoby dziedziczyć, na przykład w przypadku przetwarzania w tle lub kroku, który zostanie wznowiony w późniejszym cyklu życia procesu. Każda operacja na elemencie przyjmuje jawny identyfikator wywołania dla tego przypadku. Przechwyć je, póki nadal masz dostęp do żądania, przenoś je wraz z wykonywaną pracą i przekazuj je z powrotem przy każdej operacji na elemencie, aby operacje te nadal działały w imieniu pierwotnego wywołującego.

Identyfikator wywołania identyfikuje podmiot wywołujący bieżące żądanie i rozdziela tylko elementy w magazynie izolowanym dla użytkownika. Nie partycjonuje żadnych innych magazynów kontenerów. W przypadku plików, wierszy bazy danych lub wpisów w pamięci podręcznej, którymi zarządza własny kod, należy używać identyfikatora sesji i identyfikatora użytkownika jako klucza, zgodnie z opisem w sekcji Multipleksowanie użytkowników we współdzielonej sesji.

Przedmioty

Element jest kluczem i wartością JSON z opcjonalnymi tagami ciągów.

  • Wartości to kod JSON aplikacji: magazyn nie interpretuje wartości elementu. Serializuj modele platformy lub domeny jawnie.
  • Tagi służą do filtrowania: Tagi to proste etykiety tekstowe, łączone operatorem AND podczas listowania kluczy. Promuj tylko pola, według których chcesz filtrować.
  • Wyświetlanie listy zwraca tylko klucze: strona kluczy jest tania nawet wtedy, gdy wartości są duże, więc wyświetlanie listy i pobieranie są oddzielnymi krokami.
  • Optymistyczna współbieżność: każdy element nosi element ETag. Użyj warunku wstępnego If-Match dla operacji typu odczyt-modyfikacja-zapis na modyfikowalnych elementach, takich jak liczniki, gdy utrata aktualizacji mogłaby uszkodzić stan. Warunek wstępny, który zakończył się niepowodzeniem, zgłasza bieżący element ETag.
  • Punkty kontrolne tylko do dołączania nie wymagają warunków wstępnych: gdy każdy zapis zapisuje nowy klucz, nie ma rywalizacji o zapis, więc ścieżka punktu kontrolnego nigdy nie wymaga If-Match.

Tworzenie magazynu i elementów

Poniższy przykład pobiera lub tworzy magazyn izolowany dla użytkownika, zapisuje element, odczytuje go z powrotem i wyświetla klucze dla danego tagu. Get-or-create to jedyne wywołanie dotyczące magazynu, którego potrzebuje agent: pobiera magazyn lub, jeśli ten nie istnieje, tworzy go z użyciem przekazanych opcji.

from azure.ai.agentserver.core.storage import FoundryStateStore

# Fetch the store, or create it on first use
store = await FoundryStateStore.get_or_create(
    "checkpoints/thread-abc",
    user_isolation=True,
)

# Write an item; the value is your own application JSON
await store.set_item(
    "step-1",
    {"done": False, "attempt": 1},
    tags={"kind": "checkpoint"},
)

# Read it back
item = await store.get_item("step-1")
if item is not None:
    print(item.key, item.value["done"], item.etag)

# List keys by tag, then fetch only the values you need
page = await store.list_keys(tags={"kind": "checkpoint"}, limit=50, order="asc")
for key in page.keys:
    print(key.key, key.etag)

Jeśli nie przekażesz punktu końcowego, klient ustali punkt końcowy projektu ze środowiska, które platforma konfiguruje dla agenta hostowanego.

Limity usług

Usługa wymusza te limity. W przypadku naruszenia limitu usługa zwraca 400 Bad Request i nazywa nieprawidłowe pole w komunikacie o błędzie.

Pole Limit
Nazwa sklepu Od 1 do 128 znaków, unikalne w obrębie projektu i agenta.
Klucz elementu 1–128 znaków, unikatowe w sklepie.
Wartość elementu Do 1 MB serializowanego kodu JSON.
Tagi sklepu lub produktu Maksymalnie 16 wpisów. Klucz ma od 1 do 64 znaków, a wartość ma maksymalnie 256 znaków.
Description Maksymalnie 1024 znaki.
Klucze na stronę listy 1–100, z wartością domyślną 20.