Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Un singolo agente ospitato serve molti utenti da un endpoint. Questo articolo illustra come Microsoft Foundry mantiene private le sessioni, le conversazioni e i dati archiviati di ogni utente e come estendere tale isolamento agli utenti della propria applicazione. Alla fine, è possibile richiamare un agente e confermare che un chiamante non può visualizzare sessioni, conversazioni o dati archiviati di un altro chiamante.
Prerequisites
- Un agente ospitato distribuito. Per distribuirne una, vedere Distribuire un agente ospitato.
- Le estensioni Foundry di Azure Developer CLI, per i passaggi della CLI. Consultare Installare le estensioni Foundry di Azure Developer CLI.
- Sessione autenticata. Esegui
azd auth login, oppure accedi con la credenziale Microsoft Entra usata dal tuo SDK o client REST. - Il ruolo Foundry User nel progetto.
Important
I ruoli di Controllo degli accessi in base al ruolo di Foundry sono stati recentemente rinominati. Foundry User, Foundry Owner, Foundry Account Owner e Foundry Project Manager erano precedentemente denominati Azure AI User, Azure AI Owner, Azure AI Account Owner e Azure AI Project Manager. È possibile che i nomi precedenti vengano visualizzati in alcune posizioni durante l'esecuzione della ridenominazione. Gli ID ruolo e le autorizzazioni di base sono invariati dalla ridenominazione.
Comprendere l'isolamento per utente
La piattaforma identifica ogni chiamante dal token Microsoft Entra e mantiene i dati privati per tale identità, anche se ogni chiamante raggiunge lo stesso agente tramite un endpoint condiviso. Per ogni utente, quanto segue rimane isolato:
- Conversazioni. La cronologia della conversazione di ogni utente, ovvero i messaggi, le chiamate agli strumenti e le risposte che threadano tramite il protocollo Risposte, è privata per tale utente. Un utente non può leggere o elencare le conversazioni di un altro utente.
- Sessioni. Ogni chiamante ottiene la propria sessione per impostazione predefinita, quindi le sessioni che un utente può elencare e gestire non includono sessioni di un altro utente.
- Dati archiviati. I dati archiviati dall'agente per un utente hanno come ambito tale utente, quindi non vengono restituiti a un utente diverso.
Si pensi a un agente che gestisce molte aree di lavoro private. Ogni sessione dispone anche di un file system privato $HOME all'interno della propria sandbox, isolato per impostazione predefinita poiché ogni utente dispone della propria sessione. Se invece si inserisce più utenti in una sessione, tale sandbox viene condivisa. Vedere Multiplex multiple users in una sessione dell'agente ospitato. Per altre informazioni sul modello di sessione, vedere Agenti ospitati nel servizio agente Foundry.
Gli scenari tipici includono:
- Chat per utente. Ogni cliente connesso ottiene la propria cronologia delle conversazioni, le sessioni e i dati archiviati.
- Applicazioni multi-tenant. Gli utenti di ogni tenant sono isolati dagli utenti di ogni altro tenant.
Questo isolamento è disponibile per impostazione predefinita. Le sezioni seguenti illustrano il percorso predefinito, quindi come estenderlo agli utenti autenticati manualmente.
Richiamare un agente con isolamento automatico
Richiamare l'agente come identità di accesso. La piattaforma crea una sessione associata a tale identità e restituisce agent_session_id.
azd ai agent invoke "Summarize the latest support tickets"
La sessione appartiene all'identità proveniente da azd auth login. Un utente connesso diverso che esegue lo stesso comando ottiene una sessione privata separata.
Configurare le variabili condivise usate dagli esempi REST:
BASE_URL="https://my-account.services.ai.azure.com/api/projects/my-project"
API_VERSION="v1"
RESOURCE="https://ai.azure.com"
AGENT_NAME="my-agent"
az rest --method POST \
--url "${BASE_URL}/agents/${AGENT_NAME}/endpoint/protocols/openai/responses?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--body '{
"input": "Summarize the latest support tickets",
"stream": false
}'
Il token Microsoft Entra nella richiesta identifica il chiamante. Il payload di risposta include agent_session_id, creato dalla piattaforma e associato a tale identità.
openai_client = project.get_openai_client(agent_name="my-agent")
response = openai_client.responses.create(
input="Summarize the latest support tickets",
)
session_id = response.model_extra.get("agent_session_id")
print(f"Session: {session_id}")
Il client OpenAI esegue l'autenticazione con la credenziale Microsoft Entra del chiamante, quindi la sessione ha come ambito tale identità.
Installare i pacchetti con dotnet add package Azure.AI.Projects --prerelease, dotnet add package Azure.AI.Extensions.OpenAIe dotnet add package Azure.Identity.
using System.ClientModel;
using System.Text.Json;
using Azure.AI.Extensions.OpenAI;
using Azure.AI.Projects;
using Azure.Identity;
using OpenAI.Responses;
#pragma warning disable AAIP001, OPENAI001
AIProjectClient projectClient = new(new Uri(projectEndpoint), new DefaultAzureCredential());
ProjectResponsesClient responsesClient = projectClient.ProjectOpenAIClient
.GetProjectResponsesClientForAgentEndpoint("my-agent");
ClientResult<ResponseResult> result = responsesClient.CreateResponse(
"Summarize the latest support tickets");
// The session identifier is returned on the raw response payload.
using JsonDocument payload = JsonDocument.Parse(result.GetRawResponse().Content.ToString());
string sessionId = payload.RootElement.GetProperty("agent_session_id").GetString()!;
Console.WriteLine($"Session: {sessionId}");
Il client esegue l'autenticazione con la credenziale Microsoft Entra del chiamante, quindi la sessione ha come ambito tale identità.
const openAIClient = project.getOpenAIClient({
azureConfig: { allowPreview: true, agentName: "my-agent" },
});
const response = await openAIClient.responses.create({
input: "Summarize the latest support tickets",
});
const sessionId = (response as any).agent_session_id;
console.log(`Session: ${sessionId}`);
Il client OpenAI esegue l'autenticazione con la credenziale Microsoft Entra del chiamante, quindi la sessione ha come ambito tale identità.
Isolare le sessioni per i propri utenti
Se l'applicazione autentica i propri utenti finali, ad esempio tramite Google, GitHub o un provider di identità personalizzato, un servizio attendibile può indicare a Foundry a quale utente finale appartiene una richiesta, quindi la piattaforma isola le sessioni per utente finale anziché per ogni servizio chiamante.
Il servizio invia l'identificatore stabile dell'utente finale nell'intestazione x-ms-user-identity . La piattaforma tratta il valore come una stringa opaca e limita la sessione a tale valore. Il valore deve essere composto da 1 a 256 caratteri e deve contenere solo lettere, cifre e caratteri . _ : - @. Gli altri valori vengono rifiutati.
Per passare x-ms-user-identity, l'identità chiamante deve contenere l'autorizzazione Microsoft.CognitiveServices/accounts/AIServices/agents/endpoints/UserIdentityImpersonation/action per l'agente. Questa autorizzazione non è inclusa in alcun ruolo predefinito. In precedenza era coperto dall'azione dati Microsoft.CognitiveServices/*, ma tale azione non lo concede più. Concederlo esplicitamente creando un ruolo personalizzato che includa l'azione dati e assegnando tale ruolo all'identità del servizio di livello intermedio. Chi chiama senza di esso riceve un 403. Per i comandi di definizione e assegnazione del ruolo personalizzati, vedere Delegare l'identità dell'utente finale.
Se un servizio dispone di questa autorizzazione ma non invia l'header in una richiesta, la piattaforma limita quella sessione all'identità del servizio stesso anziché a quella di un utente finale. Il servizio può combinare chiamate delegate e non delegate, ma solo le richieste che includono x-ms-user-identity sono isolate per ogni utente finale.
Avvertimento
All'interno della delega, la piattaforma non delimita un utente finale delegato da un altro. Applica un limite rigido solo tra i chiamanti delegati e non delegati, consentendo a qualsiasi utente delegato di accedere a una sessione creata dall'app. Assegnare a ogni utente il proprio ID sessione; se si instradano due utenti alla stessa sessione, possono visualizzare i dati degli altri. Per condividere deliberatamente una sessione, vedi Gestire più utenti in un'unica sessione di un agente ospitato.
az rest --method POST \
--url "${BASE_URL}/agents/${AGENT_NAME}/endpoint/protocols/openai/responses?api-version=${API_VERSION}" \
--resource "${RESOURCE}" \
--headers "x-ms-user-identity=<stable-end-user-id>" \
--body '{
"input": "Summarize my open tickets",
"stream": false
}'
Sostituire <stable-end-user-id> con l'identificatore assegnato dal servizio all'utente finale connesso, ad esempio un ID utente con ambito tenant.
openai_client = project.get_openai_client(agent_name="my-agent")
response = openai_client.responses.create(
input="Summarize my open tickets",
extra_headers={"x-ms-user-identity": "<stable-end-user-id>"},
)
Sostituire <stable-end-user-id> con l'identificatore assegnato dal servizio all'utente finale connesso. La sessione ha come ambito l'utente finale anziché il servizio chiamante.
Il client .NET imposta l'intestazione per ogni richiesta tramite un criterio della pipeline:
using System.ClientModel.Primitives;
// Sends the end-user identifier that the platform uses to scope the session.
public sealed class UserIdentityPolicy(string userId) : PipelinePolicy
{
public override void Process(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int index)
{
message.Request.Headers.Set("x-ms-user-identity", userId);
ProcessNext(message, pipeline, index);
}
public override ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int index)
{
message.Request.Headers.Set("x-ms-user-identity", userId);
return ProcessNextAsync(message, pipeline, index);
}
}
Creare un client per utente finale e quindi richiamare l'agente:
var options = new AIProjectClientOptions();
options.AddPolicy(new UserIdentityPolicy("<stable-end-user-id>"), PipelinePosition.PerCall);
AIProjectClient projectClient = new(new Uri(projectEndpoint), new DefaultAzureCredential(), options);
ProjectResponsesClient responsesClient = projectClient.ProjectOpenAIClient
.GetProjectResponsesClientForAgentEndpoint("my-agent");
ClientResult<ResponseResult> result = responsesClient.CreateResponse("Summarize my open tickets");
using JsonDocument payload = JsonDocument.Parse(result.GetRawResponse().Content.ToString());
Console.WriteLine($"Session: {payload.RootElement.GetProperty("agent_session_id").GetString()}");
Sostituire <stable-end-user-id> con l'identificatore assegnato dal servizio all'utente finale connesso. Ogni identificatore dell'utente finale ottiene la propria sessione, quindi due utenti che richiamano lo stesso agente ricevono ID sessione diversi.
const openAIClient = project.getOpenAIClient({
azureConfig: { allowPreview: true, agentName: "my-agent" },
});
const response = await openAIClient.responses.create(
{ input: "Summarize my open tickets" },
{ headers: { "x-ms-user-identity": "<stable-end-user-id>" } },
);
console.log(response.output_text);
Sostituire <stable-end-user-id> con l'identificatore assegnato dal servizio all'utente finale connesso. La sessione ha come ambito l'utente finale anziché il servizio chiamante.
Passare a --user-identity per inviare l'intestazione x-ms-user-identity con Azure Developer CLI. Il chiamante connesso deve disporre dell'autorizzazione di delega descritta in precedenza.
azd ai agent invoke --protocol responses \
--user-identity "user-123" \
--new-session --new-conversation \
"Summarize my open tickets"
Sostituire user-123 con l'identificatore stabile assegnato dal servizio all'utente finale autenticato. Includere --user-identity a ogni chiamata.
L'esempio avvia una nuova sessione e una nuova conversazione perché azd salva questi ID per agente, non per identità utente. Omettere --new-session e --new-conversation continuare lo stesso stato salvato dall'utente. Per riprendere lo stato esistente di un altro utente, specificare esplicitamente i relativi --session-id e --conversation-id.
Per altri esempi, incluse le restrizioni di chiamata e intestazione locali, vedere Passare un'identità dell'utente finale.
Proteggere l'identità dell'utente finale
Quando si usa l'isolamento delegato, il servizio è il limite di attendibilità. Scegliere gli identificatori stabili per utente, univoci e difficili da indovinare. Riutilizzare lo stesso valore per lo stesso utente in modo che le sessioni riprendano correttamente.
Important
Derivare il valore da un'identità x-ms-user-identity autenticata sul lato server: mai da un valore fornito direttamente dal browser o dal client. In caso contrario, un chiamante può impostare l'intestazione sull'identificatore di un altro utente e leggere i dati dell'utente. Qualsiasi servizio con l'autorizzazione di delega può agire per conto di qualsiasi utente finale, quindi concederlo solo ai servizi attendibili.
Verificare l'isolamento
Verificare che due identità ottengano due sessioni separate:
- Richiamare l'agente usando un'identità e prendere nota del
agent_session_idrestituito. - Richiama l'agente con una seconda identità, ovvero un altro utente connesso o un valore
x-ms-user-identitydiverso, e prendi nota del suoagent_session_id. Conazd, passa--new-sessionper evitare di riutilizzare la sessione salvata. - Verificare che i due ID siano diversi. Per i chiamanti non delegati senza autorizzazioni di sessione tra utenti, verificare che ogni chiamante possa accedere solo alle proprie sessioni. Per gli utenti delegati, verificare che il mapping da utente a sessione dell'applicazione impedisca l'accesso tra utenti; la piattaforma non impone tale limite.
Per testare file di sessione separati, distribuire l'esempio dell'agente per prendere appunti, che archivia le note per sessione in $HOME. Usare sessioni separate e verificare l'accesso ai file tramite l'API File di sessione, tenendo conto delle autorizzazioni del chiamante e del mapping dell'utente delegato dell'applicazione.
Visualizzare le sessioni tra gli utenti
Per impostazione predefinita, ogni chiamante vede solo le proprie sessioni. Un amministratore o un'automazione che ha il ruolo Foundry User nel progetto può elencare e gestire tutte le sessioni sull'agente, indipendentemente dall'identità che le ha create. Per gestire le sessioni, vedere Gestire le sessioni dell'agente ospitato.
Chiavi di isolamento nel protocollo contenitore 1.0.0 (non supportato)
Gli agenti configurati con il protocollo contenitore versione 1.0.0 usano il modello di chiave di isolamento precedente, in cui il chiamante fornisce una chiave di isolamento per le sessioni di ambito anziché la piattaforma che deriva l'identità dal token Microsoft Entra. Il protocollo 1.0.0 non è più supportato e la piattaforma blocca le richieste agli agenti che lo usano ancora.
Eseguire l'aggiornamento al protocollo 2.0.0 per ottenere l'isolamento automatico per utente descritto in precedenza in questo articolo. Il protocollo 2.0.0 richiede AgentServer SDK che la supporta: azure-ai-agentserver-core 2.0.0b7 o versione successiva per Python o Azure.AI.AgentServer.Core 1.0.0-beta.26 o versione successiva per .NET. Le versioni precedenti usano il protocollo 1.0.0; aggiornarli come parte dell'aggiornamento.
- Sostituire i flag di isolamento dell'interfaccia della riga di comando rimossi seguendo Migrare le chiavi di isolamento all'identità utente.
- Per eseguire l'aggiornamento, vedere Eseguire la migrazione degli agenti ospitati.
Risolvere i problemi di isolamento
| Sintomo | Causa possibile | Cosa provare |
|---|---|---|
403 o session_not_accessible quando si accede a una sessione |
La sessione appartiene a un'identità diversa. | Usare la stessa identità che ha creato la sessione o mantenere il ruolo Utente Foundry per visualizzare le sessioni di altre identità. |
403 su una richiesta che imposta x-ms-user-identity |
Il chiamante non dispone dell'autorizzazione UserIdentityImpersonation , che non è più concessa dai ruoli predefiniti. |
Creare un ruolo personalizzato che includa l'azione dati Microsoft.CognitiveServices/accounts/AIServices/agents/endpoints/UserIdentityImpersonation/action e assegnarlo al servizio chiamante. |
| Le esecuzioni locali non isolano le sessioni | Le esecuzioni in locale non impongono l'isolamento. | Testare l'isolamento rispetto a un agente distribuito. La modalità locale (--local, azd ai agent run) è destinata a un singolo utente. |
Contenuti correlati
- Gestire le sessioni dell'agente ospitato per elencare, controllare ed eliminare sessioni, inclusi gli utenti.
- Multiplexing di più utenti in un'unica sessione di agente ospitato quando diversi utenti condividono intenzionalmente un'unica sessione.
- Concetti relativi all'identità dell'agente in Microsoft Foundry per comprendere il funzionamento delle identità degli agenti e degli utenti.
- Richiama un agente ospitato con Azure Developer CLI per ogni variante e opzione di invocazione.
- Esempio di agente di acquisizione note per un agente eseguibile che archivia i dati di proprietà dell'utente per sessione (Python e C#).