AgentChat
← Tutti gli articoli
Sicurezza·10 min di lettura

Come fornire a ogni utente SaaS un agente IA sicuro e consapevole del tenant

Usa intestazioni specifiche per ogni chat e il tuo attuale livello di autorizzazione per mantenere isolate le azioni dell’agente per utente, spazio di lavoro o tenant.

Questo caso di studio integra AgentChat in un SaaS multi-tenant per la gestione dei progetti chiamato ProjectDesk. Ogni cliente utilizza le stesse API per progetti e attività, ma l’utente Alice può operare solo in workspace_a e l’utente Bob solo in workspace_b. Riutilizzeremo un unico documento API creando al contempo due sessioni con intestazioni di richiesta diverse e di sola scrittura.

Il confine di sicurezza non è un prompt che chiede al modello di rimanere all’interno di un workspace. ProjectDesk autentica e autorizza ogni richiesta di uno strumento HTTP. AgentChat seleziona le operazioni e inserisce la credenziale di sessione corretta; ProjectDesk decide se ogni operazione è consentita.

Passaggio 1: rendere l’API aziendale consapevole del tenant

GET /v1/projects?status=active
→ { "items": [{ "project_id": "proj_12", "name": "Website launch", "role": "editor" }] }

POST /v1/projects/proj_12/tasks
{ "title": "Review launch checklist", "due_at": "2026-08-28" }
→ { "task_id": "task_91", "project_id": "proj_12", "status": "open" }

ProjectDesk verifica il token bearer, ne ricava l’identità dell’utente, conferma l’appartenenza al workspace indicato da X-Workspace-ID e aggiunge tale workspace a ogni query del database. Il solo ID del progetto non consente mai di ignorare il filtro del tenant. Gli scope di lettura e scrittura vengono verificati separatamente.

Passaggio 2: registrare un documento ProjectDesk riutilizzabile

POST $AGENTCHAT_SITE_URL/api/api-documents
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "ProjectDesk Projects and Tasks",
  "description": "List authorized projects and create tasks inside them.",
  "content": "# ProjectDesk API\nBase URL: https://projects.example.com/v1\n\nGET /projects?status=active returns only projects visible to the authenticated workspace member. Response items contain project_id, name, and role.\n\nPOST /projects/{project_id}/tasks body: title required, due_at optional ISO date. Create only after resolving a project through GET /projects. Response contains task_id, project_id, and status.\n\n401 means the session credential is missing or expired. 403 means the current member lacks permission. On either response, do not retry and tell the user that the chat credential or role must be updated."
}

Questo documento descrive una capacità, non un’identità. ProjectDesk salva una sola volta l’UUID del documento restituito e lo associa alle chat di ogni tenant. Nel documento non sono incorporati ID del tenant, token dell’utente o segreti.

Passaggio 3: creare la sessione AgentChat di Alice

POST $AGENTCHAT_SITE_URL/api/agent/sessions
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "ProjectDesk assistant — Alice",
  "llm_config_id": "llm_config_uuid",
  "api_document_ids": ["projectdesk_document_uuid"],
  "system_prompt": "Help the current member manage projects. Never infer access from names; rely on API results.",
  "max_turns": 10,
  "host_headers": [
    { "host": "projects.example.com", "header_key": "Authorization", "header_value": "Bearer alice_short_lived_token" },
    { "host": "projects.example.com", "header_key": "X-Workspace-ID", "header_value": "workspace_a" }
  ]
}

La risposta della sessione include la configurazione ordinaria, ma non restituisce mai header_value. AgentChat può iniettare il token di Alice in una richiesta HTTP corrispondente, mentre il modello non può vedere né il token né l’header di autorizzazione memorizzato.

Passaggio 4: creare la sessione di Bob dallo stesso documento

POST $AGENTCHAT_SITE_URL/api/agent/sessions
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "ProjectDesk assistant — Bob",
  "llm_config_id": "llm_config_uuid",
  "api_document_ids": ["projectdesk_document_uuid"],
  "system_prompt": "Help the current member manage projects. Never infer access from names; rely on API results.",
  "max_turns": 10,
  "host_headers": [
    { "host": "projects.example.com", "header_key": "Authorization", "header_value": "Bearer bob_short_lived_token" },
    { "host": "projects.example.com", "header_key": "X-Workspace-ID", "header_value": "workspace_b" }
  ]
}

Il contratto dell’API e la configurazione del modello possono essere condivisi, mentre le intestazioni di sessione identificano il chiamante per ogni conversazione. Questo evita di generare documenti duplicati per ogni cliente e mantiene la rotazione delle credenziali indipendente dalla documentazione delle funzionalità.

Passaggio 5: esegui la stessa istruzione in entrambe le sessioni

POST /api/agent/sessions/alice_session_uuid/chat
{ "message": "Create a task called Review launch checklist in the Website launch project, due August 28." }

POST /api/agent/sessions/bob_session_uuid/chat
{ "message": "Create a task called Review launch checklist in the Website launch project, due August 28." }

Per Alice, http_request invia il token di Alice e workspace_a esclusivamente a projects.example.com. ProjectDesk restituisce i progetti visibili ad Alice; l’agente individua il progetto richiesto a partire da quel risultato e pubblica l’attività. L’esecuzione di Bob segue lo stesso piano, ma ProjectDesk filtra in base a workspace_b. Se Bob non può vedere quel progetto, l’agente non riceve alcun progetto corrispondente e non deve inventare né riutilizzare l’ID del progetto di Alice.

Come la corrispondenza degli host impedisce la fuga di credenziali

AgentChat inserisce un'intestazione di sessione solo quando la destinazione HTTP corrisponde al nome host configurato e alla porta opzionale. I reindirizzamenti vengono verificati nuovamente a ogni passaggio. Pertanto, una credenziale per projects.example.com non viene trasmessa a files.example.net, a un host di immagini o a una destinazione di reindirizzamento imprevista.

Limite importante: La corrispondenza dell'host limita la destinazione a cui viene inviato un segreto. L'API ProjectDesk che lo riceve deve comunque convalidare il token, l'appartenenza all'area di lavoro, la titolarità della risorsa e l'ambito dell'operazione.

Come si presenta un errore di autorizzazione

HTTP/1.1 403 Forbidden
Content-Type: application/json

{ "error": "insufficient_scope", "required_scope": "tasks:write" }

Le istruzioni di AgentChat considerano i codici 401 e 403 problemi di configurazione delle credenziali. L'agente deve interrompere l'operazione bloccata e comunicare all'utente quale autorizzazione richiede attenzione. Non deve richiedere il segreto nella chat, rivelare i valori delle intestazioni memorizzati né riprovare ripetutamente dopo un rifiuto.

ProjectDesk dovrebbe mantenere utili le risposte di rifiuto, senza però renderle sensibili. Può indicare l'ambito richiesto senza confermare se esiste un record tra tenant. I log di audit dovrebbero registrare l'attore verificato e la risorsa richiesta, oscurando al contempo i bearer token e gli altri valori degli header.

Passaggio 6: utilizzare separatamente lo stato di AgentChat e lo stato di ProjectDesk

GET /api/agent/sessions/alice_session_uuid/messages?after_id=&after_revision=0
GET /api/agent/sessions/alice_session_uuid/state

GET https://projects.example.com/v1/projects/proj_12/tasks

L'interfaccia di chat di ProjectDesk interroga periodicamente i messaggi di AgentChat e unisce le revisioni dell'assistente durante l'elaborazione. Al termine dell'esecuzione, la bacheca del progetto ricarica le attività dall'API o dal database di ProjectDesk. La risposta dell'assistente spiega l'azione, ma il record dell'attività salvato — non il testo — costituisce lo stato autorevole del prodotto.

Utilizzare sessioni separate per livelli di privilegio separati

Un assistente di sola lettura può allegare documenti di ricerca e reportistica con un token limitato agli ambiti di lettura. Un editor di progetto può allegare documenti per la creazione di attività con un token con ambito di scrittura. Le operazioni ad alto rischio, come modifiche alla fatturazione, eliminazione di account o pubblicazione al pubblico, dovrebbero utilizzare una sessione più ristretta o un endpoint lato prodotto per le approvazioni in sospeso.

Nei flussi di approvazione, l’agente crea un’azione in sospeso e ne restituisce l’ID. ProjectDesk mostra all’utente la modifica esatta, registra l’approvazione esplicita ed esegue l’operazione irreversibile nel proprio backend. La decisione finale di autorizzazione non dipende mai dall’interpretazione da parte del modello di una frase di conferma.

Test di isolamento in produzione

  1. Usa la sessione di Alice per richiedere un ID di progetto noto di workspace_b e verifica che ProjectDesk non restituisca dati tra tenant.
  2. Esegui prompt identici per Alice e Bob e verifica che le loro chiamate HTTP ricevano risultati autorizzati diversi.
  3. Fai scadere, revoca, ometti e corrompi ciascun token di sessione, quindi verifica in ogni caso il corretto comportamento 401.
  4. Assegna a un membro un ambito di sola lettura e verifica che ogni scrittura relativa alle attività restituisca 403 senza modificare il database.
  5. Reindirizza una richiesta a un altro nome host e verifica che AgentChat non inoltri le credenziali configurate.
  6. Esamina le risposte dell’API di sessione, i risultati degli strumenti, i log dell’applicazione e i messaggi di errore per individuare eventuali fughe di segreti.
  7. Arresta e riprendi un’esecuzione, quindi verifica che il lavoro ripreso utilizzi ancora esclusivamente gli header e i collegamenti ai documenti di quella sessione.

Il modello riutilizzabile multi-tenant

Registra la funzionalità aziendale una sola volta. Crea una sessione AgentChat per ogni conversazione dell’utente. Allega gli UUID dei documenti pertinenti, inserisci credenziali a breve durata per l’host API esatto e applica identità e policy all’interno dei tuoi endpoint SaaS. Lascia quindi che AgentChat gestisca il ragionamento e lo stato persistente della conversazione, mentre il tuo database rimane la fonte di verità.