Archivio di stato durevole per gli agenti ospitati di Microsoft Foundry (anteprima)

L'archivio di stato durevole per gli agenti ospitati di Microsoft Foundry fornisce un'archiviazione chiave-valore sul server per i dati JSON che devono persistere quando un contenitore di un agente si arresta in modo anomalo, viene riavviato o viene rimosso dopo un periodo di inattività. Utilizzalo per archiviare i checkpoint del framework, la cronologia delle conversazioni gestite dall'applicazione, gli artefatti intermedi e le preferenze utente.

Il tuo agente scrive e aggiorna esplicitamente gli elementi dello state store. A differenza delle sessioni e delle conversazioni, la piattaforma non popola automaticamente l'archivio. L'archivio supporta l'isolamento per utente, i tag, la concorrenza ottimistica e la scadenza configurabile.

Questo articolo illustra come partizionare i dati, gestire l'identità del chiamante, creare e accedere a archivi ed elementi e lavorare entro i limiti del servizio. Durante l'anteprima, l'archivio dello stato è disponibile solo per gli agenti ospitati.

Importante

Gli elementi contrassegnati come anteprima in questo articolo sono attualmente in anteprima. Questa anteprima viene fornita senza un contratto di servizio e Microsoft non lo consiglia per i carichi di lavoro di produzione. Alcune funzionalità potrebbero non essere supportate o potrebbero avere funzionalità limitate. Per ulteriori informazioni, vedere Condizioni supplementari per l'uso delle versioni di anteprima di Microsoft Azure.

Cosa conservare nell'archivio di stato

La potenza di calcolo di un agente ospitato è effimera. Quando il contenitore viene riavviato o la piattaforma lo rimuove dopo un periodo di inattività, l'agente perde tutto ciò che scrive nel disco locale all'esterno di una sessione. L'archivio di stato contiene lo stato che deve persistere oltre il contenitore.

I contenuti tipici includono:

  • I checkpoint del framework, così che un framework di agenti bring-your-own come LangGraph o Microsoft Agent Framework possa ripristinare lo stato del proprio grafo o flusso di lavoro.
  • Cronologia delle conversazioni gestita direttamente dal tuo agente, ovvero nel caso del protocollo Invocations in cui la piattaforma non archivia la cronologia.
  • Elementi generati e lavoro intermedio necessari per un turno successivo.
  • Profili, preferenze e altri dati applicativi persistenti per utente.

L'archivio di stato non è l'unica opzione. Un database, un archivio BLOB o un altro archivio di proprietà dell'applicazione funziona allo stesso modo. L'archivio di stato elimina la necessità di eseguire personalmente il provisioning e mettere in sicurezza tale archiviazione, applicando automaticamente il modello di identità dell'agente.

Mantenere i valori sufficientemente piccoli da recuperare su richiesta. Un elemento ha una dimensione massima di 1 MB, quindi i file binari di grandi dimensioni vanno archiviati nell'archiviazione BLOB, mentre l'archivio ne conserva un riferimento.

Tip

Gli agenti di lunga durata possono conservare marcatori di avanzamento e checkpoint multipli in elementi separati nello stesso archivio di stato. Per uno schema di ripristino, vedi Gestire lo stato per gli agenti di lunga durata.

Negozi

Un client FoundryStateStore si collega a un nome di archivio che scegli. Tale nome funge sia come identità dell'archivio sia come relativa partizione più esterna. Un archivio contiene elementi JSON con chiave che è possibile leggere, scrivere, eliminare ed elencare.

  • Nome archivio è l'identità: non è possibile modificare il nome di un archivio dopo la creazione, quindi scegliere uno schema di denominazione stabile in anticipo.
  • Get-or-create è l'operazione a livello di store: Una singola chiamata get-or-create recupera lo store oppure lo crea se non esiste. Le opzioni di creazione si applicano solo alla prima creazione, quindi il servizio li ignora quando l'archivio esiste già. La scrittura di un elemento non crea un archivio inesistente.
  • Durata dell'elemento: una finestra di inattività a livello di archivio rimuove gli elementi. Il valore predefinito è 30 giorni ed è possibile configurare un archivio in modo che gli elementi non scadano mai. Le operazioni di scrittura rinnovano la finestra, mentre quelle di lettura no. Questa opzione viene impostata al momento della creazione.

Dati di partizione

L'archivio offre due modi indipendenti per partizionare i dati e la maggior parte degli agenti ne necessita solo una.

  • Per nome del negozio: ogni nome di negozio costituisce una partizione a sé stante. I nomi possono contenere /, in modo che sia possibile usarlo come separatore di gerarchia, come in checkpoints/thread-abc o workflow-state/run-42. Scegliere questa partizione quando il codice che legge un elemento ha sempre l'identificatore di partizione disponibile per ricompilare il nome.
  • Per utente finale: un archivio creato con isolamento utente partiziona gli elementi per ogni utente finale, quindi un singolo nome di archivio è sicuro da condividere tra gli utenti di un agente multi-tenant. Scegliere questa partizione quando lo stesso nome di archivio serve più di un utente. Imposti questa opzione in fase di creazione e lo store determina l'utente dalla richiesta anziché da qualsiasi valore passato dal codice. Per informazioni dettagliate, vedere Identità chiamante.

Preferisci la partizione più stretta che il tuo percorso di ricerca sia in grado di ricostruire. Un nome di archivio che codifica un identificatore è utile solo se ogni chiamante che legge l'elemento contiene ancora tale identificatore. Quando un’operazione di ricerca include solo la chiave dell’elemento, come fa di solito un caricatore di checkpoint del framework, mantenere normale il nome dell’archivio e lasciare invece che sia l’isolamento dell’utente a occuparsi del partizionamento.

I due assi si combinano, ma vanno tenuti distinti per tipologia: il nome dello store deve includere solo un ambito non legato all’utente, come un identificatore di thread, esecuzione o flusso di lavoro.

Importante

Non codificare un identificatore dell'utente finale in un nome di archivio. I nomi degli store vengono visualizzati nelle interfacce operative, ad esempio nei log e nei messaggi di errore, e un nome generato dal proprio codice non è un'identità verificata. Usa l'isolamento utente per il partizionamento per singolo utente, in modo che la piattaforma applichi il confine che il chiamante ha stabilito anziché quello derivato da un valore fornito dal tuo agente.

Identità chiamante

L'archivio di stato usa il modello di identità dell'agente ospitato. Nel protocollo container 2.0.0, ogni richiesta che la piattaforma instrada al tuo agente include un'intestazione x-agent-foundry-call-id che identifica il chiamante e lo store ricava da essa l'utente finale effettivo. Gli SDK di Foundry inoltrano l'intestazione nelle chiamate di archiviazione, quindi la maggior parte degli agenti non deve gestirla direttamente.

Due conseguenze sono importanti quando si progetta con esso:

  • L'isolamento dell'utente deriva dall'ID della chiamata: in un archivio con isolamento per utente, la partizione deriva dal chiamante identificato dalla piattaforma, non da alcun dato passato dal tuo agente. Un agente ospitato non fornisce un identificatore dell'utente finale di propria proprietà. Se il runtime emette richieste HTTP proprie invece di usare un client SDK, inoltrate l'intestazione senza modificarla e trattatene il valore come opaco.
  • Le esecuzioni locali non supportano l'isolamento dell'utente: la piattaforma non fornisce l'ID chiamata fuori piattaforma. Né il Python né .NET SDK possono applicare l'isolamento dell'utente quando si esegue il contenitore in locale. Testare i limiti di isolamento dell'utente con un agente ospitato distribuito.

Riportare l'ID della chiamata nell'attività differita

Le operazioni sugli elementi vengono eseguite per conto del chiamante, mentre le operazioni di archiviazione no.

Operation Scope Utente che agisce
create_item, set_item, get_item, delete_item, list_keys Gli elementi nell'archivio associato Risolto tramite l'ID della chiamata quando l'archivio usa l'isolamento dell'utente
Ottenere o creare per l'archivio Il negozio stesso Non risolto; l'operazione è con ambito archivio

Per impostazione predefinita, un'operazione su un elemento usa l'ID della chiamata della richiesta all'interno della quale viene eseguita, ed è ciò che serve per il lavoro che si conclude durante tale richiesta.

Il lavoro che continua oltre la richiesta non dispone di un ID chiamata ambientale da ereditare, ad esempio l'elaborazione in background o una fase che riprende in una successiva esecuzione del processo. Ogni operazione sull'elemento accetta un ID di chiamata esplicito per questo caso. Acquisirlo finché è disponibile la richiesta, trasportarlo insieme al lavoro e ripassarlo a ogni operazione sull’elemento, in modo che tali operazioni continuino a operare per conto del chiamante originale.

L'ID della chiamata identifica il chiamante della richiesta corrente e serve solo a suddividere gli elementi all'interno di un archivio isolato per utente. Non partiziona nient'altro di ciò che il contenitore archivia. Per i file, le righe del database o le cache gestiti dal proprio codice, usare come chiave l'ID della sessione e l'ID dell'utente, come descritto in Gestire più utenti in una sessione condivisa.

Elementi

Un elemento è una chiave e un valore JSON, con tag stringa facoltativi.

  • I valori sono il JSON della tua applicazione: l'archivio dati non interpreta il valore di un elemento. Serializzare in modo esplicito il framework o i modelli di dominio.
  • I tag sono destinati ai filtri: i tag sono etichette di stringa semplici, corrispondenti a AND quando si elencano le chiavi. Alzare di livello solo i campi su cui è necessario filtrare.
  • L'elenco restituisce solo le chiavi: una pagina di chiavi è economica anche quando i valori sono di grandi dimensioni, quindi l'elenco e il recupero sono passaggi separati.
  • Concorrenza ottimistica: ogni elemento contiene un ETag. Usare la precondizione If-Match per le operazioni di lettura-modifica-scrittura su elementi mutabili, ad esempio i contatori, in cui un aggiornamento perso corromperebbe lo stato. Una precondizione non riuscita segnala l'ETag corrente.
  • I checkpoint solo in aggiunta non richiedono precondizioni: quando ogni salvataggio scrive una nuova chiave, non c’è contesa in scrittura, quindi il percorso del checkpoint non richiede mai If-Match.

Creare un negozio e degli articoli

L'esempio seguente recupera o crea un archivio isolato per l'utente, scrive un elemento, lo rilegge ed elenca le chiavi in base al tag. Ottenere o creare è l'unica chiamata a livello di archivio di cui un agente ha bisogno: recupera l'archivio o lo crea con le opzioni specificate se l'archivio non esiste.

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)

Quando non si specifica un endpoint, il client determina l'endpoint di progetto dalle variabili d'ambiente che la piattaforma imposta per un agente ospitato.

Limiti di servizio

Il servizio applica questi limiti. Se si viola un limite, il servizio restituisce 400 Bad Request e denomina il campo non valido nel messaggio di errore.

Campo Limit
Nome negozio 1-128 caratteri, univoci all'interno del progetto e dell'agente.
Chiave dell'elemento da 1 a 128 caratteri, univoco all'interno dello store.
Valore dell'elemento Fino a 1 MB di JSON serializzato.
Archiviare o aggiungere tag Fino a 16 voci. Una chiave è di 1-64 caratteri e un valore è composto da un massimo di 256 caratteri.
Description Fino a 1.024 caratteri.
Chiavi per pagina dell'elenco 1-100, con un valore predefinito pari a 20.