Documentazione

Agent Harness

Esegui Claude Code e Codex sulla tua macchina secondo la policy della tua organizzazione: traffico di modello governato, strumenti governati, un'unica traccia di audit misurata e sigillata.

Niente dell'agente si sposta nel cloud. Claude Code e Codex continuano a girare sulla macchina dello sviluppatore, con i loro processi, i loro file, i loro strumenti integrati e il loro ciclo di agente. Ciò che Sluis governa è il traffico in uscita: le richieste al modello e le chiamate agli strumenti.

La regione non è imposta per gli agenti di codiceUn agente di codice parla con il tuo abbonamento al provider (Anthropic, OpenAI o Cursor), ed è il provider a decidere dove viene servita la richiesta. Sluis non può fissare la regione di servizio, quindi sul piano agenti la residenza è registrata, non imposta: un turno di agente non viene mai rifiutato per giurisdizione, e la sua riga di audit registra la regione come non verificata invece di rivendicarne una. Tutto il resto resta valido: chiavi agente a scopo isolato, rilascio graduale per organizzazione, analisi DLP e pseudonimizzazione (anche sul filo protobuf di Cursor), governance di plugin e strumenti, tetti di budget e di frequenza, e audit sigillato.

Il client locale si autentica su Sluis con una chiave agente e parla con l'ingresso del suo protocollo: /agent/claude espone l'API Anthropic per Claude Code, /agent/codex/v1 espone l'API Responses di OpenAI per Codex, /agent/cursor parla il protocollo Connect di Cursor su protobuf e /agent/mcp è un endpoint MCP Streamable HTTP senza stato che porta gli strumenti governati.

Claude Code e Codex sono esempi, non una lista chiusa. Pi, T3 Code e ogni client che accetta URL e chiave Anthropic Messages, OpenAI Responses o MCP usano lo stesso Agent Harness.

Tutta la configurazione segue un unico ordine, e ogni passo ha bisogno del precedente:

  • 1. Collega un abbonamento. Claude o Codex, collegato una volta per account provider.
  • 2. Crea una chiave agente. Il segreto viene mostrato una volta sola, alla creazione.
  • 3. Collega la chiave a quell'account. Una chiave spende solo gli account a cui è collegata.
  • 4. Configura il client locale. La chiave sta in SLUIS_AGENT_KEY e il base URL punta a /agent/claude per Claude Code, /agent/codex/v1 per Codex oppure /agent/cursor per Cursor, che porta la stessa chiave in Authorization: Bearer.
  • 5. Registra l'endpoint degli strumenti. Gli strumenti arrivano solo da /agent/mcp, registrato a parte: un base URL non ne aggiunge nessuno.

Collega un abbonamento

Un'organizzazione collega uno o più account di abbonamento Claude e Codex nella vista Agent Harness. Claude si collega con un token generato da claude setup-token, Codex tramite l'autorizzazione dispositivo di OpenAI. Sluis verifica la credenziale presso il provider prima di salvare qualsiasi cosa.

Claude: token di setup

Ti serve Claude Code installato sulla tua macchina e collegato a un abbonamento Claude che possa fare richieste al modello.

  • 1. Esegui claude setup-token in un terminale. Stampa un token di lunga durata, valido circa un anno, che inizia con sk-ant-oat.
  • 2. Incollalo nel campo Claude della Console. Il campo è mascherato e l'autocompletamento è disattivato.
  • 3. All'invio Sluis verifica il token presso Anthropic prima di salvare qualsiasi cosa.
  • 4. Un token verificato viene sigillato cifrato nel vault del gateway: non viene più mostrato, non torna mai a un client e non va da nessuna parte tranne Anthropic.

Un token che Anthropic non conferma viene rifiutato con un 422: nessun account viene creato, niente viene salvato e niente viene addebitato. Ricollegare lo stesso abbonamento più tardi riusa l'account esistente invece di aggiungerne un secondo fatturabile.

Codex: autorizzazione dispositivo

Ti serve un piano ChatGPT che includa Codex.

  • 1. Avvia il login dispositivo nella Console. Sluis interroga OpenAI e ti mostra un URL di verifica e un codice utente.
  • 2. Apri quell'URL con il pulsante, accedi a OpenAI, inserisci il codice e approva. OpenAI può chiedere l'MFA.
  • 3. La Console interroga il server mentre approvi. Lo scambio avviene in questa scheda del browser: uscire dalla pagina, o passare a un'altra scheda della vista, annulla il login e non salva nulla, esattamente come l'azione Annulla.
  • 4. All'approvazione Sluis salva i token di accesso e di refresh cifrati nel vault del gateway e li rinnova per te; la rotazione del refresh token è serializzata tra le repliche.

Un codice utente scade. Un flusso scaduto segnala expired e va riavviato, come un account la cui credenziale salvata viene poi rifiutata da OpenAI: resta fermo finché qualcuno non lo ricollega.

Sluis cifra queste credenziali, le conserva nel vault del gateway e le rinnova lì. Un token del provider non raggiunge mai il client locale, i log, i record di audit o le tracce: Claude Code e Codex hanno soltanto la loro chiave agente Sluis.

Il collegamento è self-service: un membro può aggiungere il proprio abbonamento. Owner e amministratori vedono ogni account dell'organizzazione; un membro vede e scollega solo il proprio.

Crea una chiave agente

Le chiavi agente si creano nella stessa vista, separatamente dalle chiavi API, perché i due scopi sono isolati. Una chiave agente si autentica solo su /agent/*, una normale chiave API solo su /v1/*. Una delle due sulla superficie sbagliata dà un 401, e il rifiuto non rivela mai lo scopo della chiave.

Il segreto viene mostrato una volta sola, alla creazione, e ne viene conservato solo l'hash. Ogni chiave passa dagli account provider che le assegni, quindi collegare l'abbonamento di un secondo membro non reindirizza mai una chiave già in uso.

Una chiave registra anche il tetto dell'organizzazione sugli strumenti integrati del client locale, scritto nella grammatica degli strumenti di Claude Code e validato alla creazione. È il client dello sviluppatore ad applicare quella lista sulla macchina; Sluis non la legge mai durante una richiesta, quindi nessun titolare può allargare la propria chiave, e una lista vuota semplicemente non registra alcun tetto.

Gli strumenti che Sluis controlla in prima persona, a ogni richiesta, sono gli strumenti MCP che espone: vedi i plugin qui sotto.

Punta i client su Sluis

Claude Code ha bisogno di un base URL e di una credenziale. Imposta ANTHROPIC_BASE_URL sull'ingresso Claude di questo gateway e ANTHROPIC_API_KEY sulla chiave agente che tieni in SLUIS_AGENT_KEY. La Console genera il blocco qui sotto con l'URL pubblica del tuo gateway già inserita.

Un base URL non aggiunge strumenti: il protocollo Anthropic non ha scoperta dei plugin, quindi gli strumenti arrivano solo da un endpoint MCP che registri tu, con claude mcp add o una voce .mcp.json. Entrambi citano ${SLUIS_AGENT_KEY} invece della chiave, così nessun segreto finisce in un file versionato.

Codex legge il suo blocco provider da ~/.codex/config.toml. Punta base_url sull'ingresso Responses /agent/codex/v1, imposta wire_api = "responses" e env_key = "SLUIS_AGENT_KEY" e aggiungi lo stesso endpoint MCP sotto [mcp_servers.sluis].

# the agent key is shown once, at creation: keep it in the environment
export SLUIS_AGENT_KEY='sluis-9f2c…'
export ANTHROPIC_BASE_URL='https://api.sluis.ai/agent/claude'
export ANTHROPIC_API_KEY="$SLUIS_AGENT_KEY"

Cursor punta allo stesso gateway. Imposta il suo URL di base sull'ingresso Cursor di questo gateway, /agent/cursor, con la chiave agente nell'header Authorization. La rotta documentata è POST /agent/cursor/agent.v1.AgentService/Run, portata da Connect con content type application/connect+proto. Un client che non può impostare un URL di base può puntare all'origine nuda, perché il protocollo di Cursor fissa un percorso assoluto.

Sluis attraversa quei frame Connect senza schema e applica al testo del prompt che contengono la modalità di protezione dei dati dell'organizzazione: tokenize sostituisce i valori rilevati con segnaposto reversibili e ripristina gli originali nella risposta in streaming, mask li redige del tutto, block rifiuta il turno prima che qualcosa raggiunga Cursor, e un frame che Sluis non riesce a decodificare viene rifiutato invece di essere inoltrato. Solo allow_log lo inoltra, e la traccia di audit registra che non era ispezionabile.

Due limiti sono propri di questo trasporto. Il rilevamento dei nomi e la guardia contro la prompt injection leggono un corpo di richiesta JSON, e Connect protobuf non lo è: per questo non girano, la riga di audit li registra come non eseguiti, e un'organizzazione che ha reso obbligatorio il rilevamento dei nomi ottiene un rifiuto invece di un inoltro non ispezionato. Il protocollo Connect inoltre non riporta il consumo di token, quindi un turno Cursor viene sigillato nella traccia di audit senza conteggi di token.

Ogni superficie accetta la credenziale in una sola forma: x-api-key sull'ingresso Claude, che è ciò che inviano i client Anthropic, e Authorization: Bearer sugli ingressi Codex, Cursor e MCP. La stessa chiave nell'altro header viene rifiutata.

Plugin MCP

Gli strumenti governati arrivano da un unico endpoint senza stato, POST /agent/mcp. Non conserva sessioni: ogni richiesta rideriva l'intera catena di autorizzazione, quindi revocare una chiave, un plugin o una chiave di firma ha effetto alla chiamata successiva.

Esistono due classi. I plugin mantenuti da Sluis sono codice Sluis compilato, offerto a tutta l'organizzazione, e non eseguono codice del cliente. I plugin di organizzazione sono i tuoi: un manifest TOML, firmato con Ed25519.

Un manifest viene accettato solo se la firma si verifica con una chiave di firma registrata dalla tua organizzazione, ed è immutabile per (organisation, id, version): una definizione di strumento modificata è una nuova versione, mai una correzione silenziosa. Ogni plugin è vincolato a un server MCP HTTPS governato, il cui endpoint deve corrispondere esattamente all'URL contenuta nel manifest firmato.

Il flusso per l'operatore è di tre passi. L'owner registra la chiave di firma dell'organizzazione. Un owner o un amministratore registra il manifest firmato contro un server MCP governato. Poi il plugin viene collegato alle chiavi agente autorizzate a usarlo, e un plugin senza collegamenti non è esposto a nessuno.

URL dei server, manifest, firme e credenziali upstream non raggiungono mai un client. Uno sviluppatore vede nomi di strumenti e schemi, nulla di più.

Contesto e skill iniettati dal gateway

I tuoi standard di ingegneria sono una policy solo se uno sviluppatore non può dimenticarli. Un CLAUDE.md committato nel repository è un suggerimento: si può modificare, cancellare o semplicemente non leggere, e nulla registra quale delle tre cose è successa. Lo stesso testo che il gateway spinge in ogni richiesta di agente governata è la decisione dell'organizzazione — scrivi prima il test che fallisce, non aggiungere dipendenze senza un ADR approvato, questo repository contiene dati personali quindi pseudonimizza prima di incollare. È la metà dell'harness che governa come lavora un agente, non quale modello e quali strumenti può raggiungere.

Due tipi di plugin lo trasportano, e nessuno dei due concede una capacità propria:

  • Contesto. Testo letterale, iniettato prima del prompt dello sviluppatore, fino a 16 KiB per versione.
  • Skill. Un nome, le sue istruzioni e i nomi degli strumenti che si aspetta. Quei nomi vengono intersecati con il tetto di strumenti registrato sulla chiave: una skill dichiara ciò che le serve e non può mai allargare una chiave, quindi uno strumento che il tetto non porta viene semplicemente omesso da ciò che il modello sente.

Una versione è legata a uno di tre ambiti, e ogni richiesta risolve tutti e tre:

  • Organizzazione. Ogni chiave agente dell'organizzazione, comprese quelle create dopo il collegamento. È l'ambito per una regola che nessuno dovrebbe dover ricordarsi di attaccare.
  • Utente. Ogni chiave agente di un membro — un briefing di onboarding, o una postura più severa per una singola persona.
  • Chiave. Una chiave agente esatta, ossia ciò che un collegamento faceva già.

La risoluzione è deterministica, perché l'ordine di iniezione cambia il prompt. Sluis prende l'unione dei tre ambiti, riverifica ogni plugin esattamente come per gli strumenti, scarta le versioni duplicate e ordina prima l'organizzazione, poi l'utente, infine la chiave: la regola generale si legge per prima e l'eccezione più stretta per ultima. Il contesto è iniettato letteralmente, una skill come sezione con nome. Sull'ingresso Claude i blocchi sono anteposti a system, in entrambe le forme che quell'API consente; sull'ingresso Codex a instructions, oppure come istruzione developer iniziale quando la richiesta non ne porta nessuna.

Tutto ciò che viene iniettato in una richiesta sta in 32 KiB. Oltre quel limite la richiesta è rifiutata con un 422 che nomina i plugin che hanno sfondato il tetto. Nulla è troncato in silenzio: metà istruzione è peggio di nessuna, e un'organizzazione che crede una regola in vigore deve sapere quando non lo è.

Il testo iniettato non viene riscritto dalla protezione dei dati, e l'ordine è a senso unico: prima il prompt dello sviluppatore viene analizzato e pseudonimizzato, poi la tua policy viene anteposta. Questi blocchi sono il tuo contenuto governato, scritto nella tua Console: non c'è nessuno da cui proteggerli, e tokenizzarli distruggerebbe ciò che dicono. “Escala a security@example.com prima di incollare” diventato “escala a «EMAIL_1» prima di incollare” non è più un'istruzione eseguibile.

Questi due tipi si scrivono nella Console e non portano firma. Una firma serve a impedire che un manifest punti una credenziale governata verso un endpoint che nessuno ha approvato; un blocco di testo non punta a nulla. Tutto il resto di ciò che rende affidabile una registrazione resta valido: una versione è immutabile, i suoi byte esatti sono hashati, e la riga registra chi l'ha scritta e quando. Un manifest con una voce MCP conserva la firma obbligatoria e la verifica del firmatario iscritto a ogni richiesta. La scheda Plugins mostra quale dei due è una versione, così «scritto nella Console» è un fatto dichiarato e non un campo assente, e mostra un'anteprima dei blocchi risolti nell'ordine in cui il gateway li inietta per una chiave o un membro scelti.

Ogni blocco iniettato lascia un marcatore sulla riga di audit sigillata, context:<plugin_id>@<version>#<digest8>, dove il digest sono i primi otto caratteri dell'hash di quella versione. Poiché una versione è immutabile, il marcatore basta a ricostruire il testo esatto consegnato al modello: la sola pista di audit dice se un agente era soggetto a una data regola nel momento in cui ha agito.

Cursor è il limite dichiarato. Il suo trasporto /agent/cursor è uno schema binario proprietario: Sluis sa trovare e riscrivere il testo dentro quei frame — è così che lì funziona la protezione dei dati — ma non può sapere quale campo sia il prompt di sistema, e scrivere in un campo indovinato corromperebbe la richiesta invece di governarla. Su quell'ingresso quindi non viene iniettato nulla, e un turno Cursor porta il tuo contesto solo se il client dello sviluppatore lo invia. L'anteprima della Console dice la stessa cosa.

La governance che continua a valere

Il traffico degli agenti è normale traffico Sluis, con una sola eccezione. Pseudonimizzazione e DLP girano prima dell'invio, anche dentro i frame protobuf di Cursor, i limiti di rate e budget della chiave valgono per ogni richiesta, gli strumenti MCP sono autorizzati chiamata per chiamata, e ogni chiamata a modello e a strumento è sottoposta ad audit e misurata. L'eccezione è la residenza: sul piano agenti la policy è registrata, non imposta, per il motivo indicato nel riquadro in cima a questa pagina.

Valgono le stesse regole descritte in Protezione dei dati e Budget e caching, e sono policy dell'organizzazione: una chiave agente non può allentarle.

Fatturazione

Ogni account provider attivo gestito da Sluis costa 16,50 € di prezzo di listino per mese di calendario, addebitato al massimo una volta per account al mese. Viene fatturato alla tua radice di fatturazione di livello più alto e compare come riga di fattura a sé, separata dall'uso misurato. IVA e maggiorazione per il metodo di pagamento si applicano esattamente come al resto della fattura.

Scollegare un account ferma i mesi successivi. Ricollegare lo stesso abbonamento upstream riusa l'account esistente invece di aggiungerne un secondo fatturabile, quindi scollegare e ricollegare nello stesso mese costa una volta.

L'uso del gateway resta fatturato a consumo, esattamente come per le chiavi API.

Disponibilità

La vista Agent Harness compare nella Console quando il flag di rollout agent_harness è attivo per la tua organizzazione. Chiedici di attivarlo se non la vedi.

Risoluzione dei problemi

SintomoCausa e rimedio
401 su una chiamata /agent/*La chiave è sulla superficie sbagliata o nell'header sbagliato. Una chiave API non serve a nulla sulle rotte agente e una chiave agente non serve a nulla sul piano dei modelli; ogni ingresso accetta una sola forma di header.
502 no credential configured for providerLa chiave agente nomina un provider per cui non ha un account collegato. Una chiave spende solo gli abbonamenti a cui è collegata e non ripiega mai sulle altre credenziali dell'organizzazione: collega un account per quel provider, oppure nomina un modello servito dall'account collegato.
Rinnovo dell'abbonamento rifiutatoIl provider ha rifiutato definitivamente il rinnovo, quindi l'account resta fermo finché qualcuno non lo ricollega. Ricollegalo nella Console; lo stesso abbonamento riusa l'account esistente e la sua quota mensile esistente.
400 mcp_servers is not supportedUna dichiarazione MCP remota in un corpo Responses viene rifiutata prima dell'invio, perché un server raggiunto dal modello aggirerebbe la chiusa degli strumenti. Registra il server su Sluis e raggiungilo dall'ingresso MCP.
Nessuno snippet di configurazione nella ConsoleIl deployment non ha un'URL pubblica di gateway validata, quindi la configurazione pronta all'uso non può essere mostrata. Configura SLUIS_GATEWAY_PUBLIC_URL, poi leggi gli endpoint nella scheda Connections.