Documentation

Agent Harness

Exécutez Claude Code et Codex sur votre machine sous la politique de votre organisation : trafic de modèles gouverné, outils gouvernés, une seule piste d'audit mesurée et scellée.

Rien de l'agent ne part dans le cloud. Claude Code et Codex continuent de tourner sur la machine du développeur, avec leurs processus, leurs fichiers, leurs outils intégrés et leur boucle d'agent. Ce que Sluis gouverne, c'est le trafic qui sort : les requêtes de modèle et les appels d'outils.

La région n'est pas imposée pour les agents de codeUn agent de code parle à votre propre abonnement fournisseur (Anthropic, OpenAI ou Cursor), et c'est le fournisseur qui décide où la requête est traitée. Sluis ne peut pas fixer cette région, donc sur le plan agent la résidence est enregistrée, pas imposée : un tour d'agent n'est jamais refusé au motif de la juridiction, et sa ligne d'audit indique la région comme non vérifiée au lieu d'en revendiquer une. Tout le reste s'applique toujours : clés agent à usage isolé, activation progressive par organisation, analyse DLP et pseudonymisation (y compris sur le fil protobuf de Cursor), gouvernance des plugins et des outils, plafonds de budget et de débit, et audit scellé.

Le client local s'authentifie auprès de Sluis avec une clé agent et parle à l'entrée correspondant à son protocole : /agent/claude expose l'API Anthropic pour Claude Code, /agent/codex/v1 expose l'API OpenAI Responses pour Codex, /agent/cursor parle le protocole Connect de Cursor en protobuf, et /agent/mcp est un point d'accès MCP Streamable HTTP sans état qui porte les outils gouvernés.

Claude Code et Codex sont des exemples, pas une liste fermée. Pi, T3 Code et tout client acceptant une URL et une clé Anthropic Messages, OpenAI Responses ou MCP utilisent le même Agent Harness.

Toute la mise en place suit un seul ordre, et chaque étape a besoin de la précédente :

  • 1. Connectez un abonnement. Claude ou Codex, connecté une fois par compte fournisseur.
  • 2. Créez une clé agent. Le secret n'est affiché qu'une fois, à la création.
  • 3. Liez la clé à ce compte. Une clé ne dépense que les comptes auxquels elle est liée.
  • 4. Configurez le client local. La clé se conserve dans SLUIS_AGENT_KEY, et l'URL de base pointe sur /agent/claude pour Claude Code, /agent/codex/v1 pour Codex ou /agent/cursor pour Cursor, qui porte la même clé dans Authorization: Bearer.
  • 5. Enregistrez le point d'accès des outils. Les outils n'arrivent que par /agent/mcp, enregistré séparément : une URL de base n'en ajoute aucun.

Connecter un abonnement

Une organisation connecte un ou plusieurs comptes d'abonnement Claude et Codex dans la vue Agent Harness. Claude se connecte avec un jeton issu de claude setup-token, Codex par l'autorisation d'appareil d'OpenAI. Sluis vérifie l'identifiant auprès du fournisseur avant de stocker quoi que ce soit.

Claude : jeton de configuration

Il vous faut Claude Code installé sur votre machine et connecté à un abonnement Claude autorisé à faire des requêtes de modèle.

  • 1. Lancez claude setup-token dans un terminal. La commande imprime un jeton de longue durée, valable environ un an, commençant par sk-ant-oat.
  • 2. Collez-le dans le champ Claude de la Console. Le champ est masqué et l'autocomplétion est désactivée.
  • 3. À la validation, Sluis vérifie le jeton auprès d'Anthropic avant de stocker quoi que ce soit.
  • 4. Un jeton vérifié est scellé chiffré dans le coffre de la passerelle. Il n'est plus jamais affiché, jamais renvoyé à un client et jamais envoyé ailleurs qu'à Anthropic.

Un jeton qu'Anthropic ne confirme pas est refusé par un 422 : aucun compte n'est créé, rien n'est stocké et rien n'est facturé. Reconnecter le même abonnement plus tard réutilise le compte existant au lieu d'en ajouter un second facturable.

Codex : autorisation d'appareil

Il vous faut un forfait ChatGPT qui inclut Codex.

  • 1. Démarrez la connexion d'appareil dans la Console. Sluis interroge OpenAI et vous affiche une URL de vérification et un code utilisateur.
  • 2. Ouvrez cette URL avec le bouton, connectez-vous à OpenAI, saisissez le code et approuvez. OpenAI peut exiger une authentification multifacteur.
  • 3. La Console interroge le serveur pendant votre approbation. L'échange se déroule dans cet onglet du navigateur : quitter la page, ou passer à un autre onglet de la vue, annule la connexion et ne stocke rien, exactement comme l'action Annuler.
  • 4. Après approbation, Sluis conserve les jetons d'accès et de rafraîchissement chiffrés dans le coffre de la passerelle et les renouvelle pour vous ; la rotation du jeton de rafraîchissement est sérialisée entre les répliques.

Un code utilisateur expire. Un flux expiré signale expired et doit être relancé — comme un compte dont OpenAI rejette plus tard l'identifiant stocké, qui cesse de servir jusqu'à une reconnexion humaine.

Sluis chiffre ces identifiants, les conserve dans le coffre de la passerelle et les renouvelle sur place. Un jeton fournisseur n'atteint jamais le client local, les journaux, les enregistrements d'audit ni les traces : Claude Code et Codex ne détiennent que leur clé agent Sluis.

La connexion est en libre-service : un membre peut ajouter son propre abonnement. Les propriétaires et administrateurs voient tous les comptes de l'organisation ; un membre ne voit et ne déconnecte que le sien.

Créer une clé agent

Les clés agent se créent dans cette même vue, séparément de vos clés API, car les deux usages sont isolés. Une clé agent ne s'authentifie que sur /agent/*, une clé API ordinaire uniquement sur /v1/*. L'une ou l'autre sur la mauvaise surface donne un 401, et le refus ne révèle jamais l'usage de la clé.

Le secret n'est affiché qu'une fois, à la création, et seule son empreinte est conservée. Chaque clé passe par les comptes fournisseur que vous choisissez pour elle : connecter l'abonnement d'un second membre ne redirige jamais une clé déjà en service.

Une clé enregistre aussi le plafond de l'organisation sur les outils intégrés du client local, écrit dans la grammaire d'outils de Claude Code et validé à la création. C'est le client du développeur qui applique cette liste sur la machine ; Sluis ne la lit jamais pendant une requête, donc aucun porteur ne peut élargir sa propre clé, et une liste vide n'enregistre simplement aucun plafond.

Les outils que Sluis contrôle lui-même, à chaque requête, sont les outils MCP qu'il expose : voir les plugins ci-dessous.

Pointer les clients vers Sluis

Claude Code a besoin d'une URL de base et d'un identifiant. Réglez ANTHROPIC_BASE_URL sur l'entrée Claude de cette passerelle et ANTHROPIC_API_KEY sur la clé agent conservée dans SLUIS_AGENT_KEY. La Console génère le bloc ci-dessous avec l'URL publique de votre passerelle déjà renseignée.

Une URL de base n'ajoute aucun outil : le protocole Anthropic n'a pas de découverte de plugins, les outils n'arrivent donc que par un point d'accès MCP que vous enregistrez vous-même, avec claude mcp add ou une entrée .mcp.json. Les deux référencent ${SLUIS_AGENT_KEY} plutôt que la clé, pour qu'aucun secret n'atterrisse dans un fichier versionné.

Codex lit son bloc de fournisseur dans ~/.codex/config.toml. Pointez base_url sur l'entrée Responses /agent/codex/v1, indiquez wire_api = "responses" et env_key = "SLUIS_AGENT_KEY", puis ajoutez le même point d'accès MCP sous [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 pointe vers la même passerelle. Réglez son URL de base sur l'entrée Cursor de cette passerelle, /agent/cursor, avec la clé agent dans l'en-tête Authorization. La route documentée est POST /agent/cursor/agent.v1.AgentService/Run, portée par Connect avec le type de contenu application/connect+proto. Un client incapable de définir une URL de base peut viser l'origine nue, car le protocole de Cursor fixe un chemin absolu.

Sluis parcourt ces trames Connect sans schéma et applique le mode de protection des données de l'organisation au texte du prompt qu'elles contiennent : tokenize remplace les valeurs détectées par des marqueurs réversibles et restitue les originaux dans la réponse diffusée, mask les masque purement et simplement, block refuse le tour avant que quoi que ce soit n'atteigne Cursor, et une trame que Sluis ne sait pas décoder est refusée plutôt que transmise. Seul allow_log la transmet, et la piste d'audit note qu'elle n'était pas inspectable.

Deux limites appartiennent à ce transport. Le détecteur de noms et la garde contre l'injection de prompt lisent un corps de requête JSON, ce que Connect protobuf n'est pas : ils ne s'exécutent donc pas, la ligne d'audit les note comme non exécutés, et une organisation qui a rendu la détection de noms obligatoire obtient un refus au lieu d'un envoi non inspecté. Le protocole Connect ne rapporte par ailleurs aucune consommation de jetons, donc un tour Cursor est scellé dans la piste d'audit sans décompte de jetons.

Chaque surface accepte son identifiant sous une seule forme : x-api-key sur l'entrée Claude, ce qu'envoient les clients Anthropic, et Authorization: Bearer sur les entrées Codex, Cursor et MCP. La même clé dans l'autre en-tête est refusée.

Plugins MCP

Les outils gouvernés arrivent par un unique point d'accès sans état, POST /agent/mcp. Il ne garde aucune session : chaque requête redérive toute la chaîne d'autorisation, donc révoquer une clé, un plugin ou une clé de signature prend effet à l'appel suivant.

Il existe deux classes. Les plugins maintenus par Sluis sont du code Sluis compilé, proposé à toute l'organisation, et n'exécutent aucun code client. Les plugins d'organisation sont les vôtres : un manifeste TOML, signé en Ed25519.

Un manifeste n'est accepté que si sa signature se vérifie sous une clé de signature enrôlée par votre organisation, et il est immuable par (organisation, id, version) : une définition d'outil modifiée devient une nouvelle version, jamais une retouche silencieuse. Chaque plugin est épinglé à un serveur MCP HTTPS gouverné, dont le point d'accès doit correspondre exactement à l'URL inscrite dans le manifeste signé.

Le travail de l'opérateur tient en trois étapes. Le propriétaire enrôle la clé de signature de l'organisation. Un propriétaire ou un administrateur enregistre le manifeste signé face à un serveur MCP gouverné. Le plugin est ensuite lié aux clés agent autorisées à l'utiliser, et un plugin lié à rien n'est exposé à personne.

Les URL de serveur, les manifestes, les signatures et les identifiants amont n'atteignent jamais un client. Un développeur voit des noms d'outils et des schémas, rien d'autre.

Contexte et compétences injectés par la passerelle

Vos standards d'ingénierie ne sont une politique que si un développeur ne peut pas les oublier. Un CLAUDE.md commité dans le dépôt est une suggestion : il peut être modifié, supprimé ou simplement pas lu, et rien n'enregistre lequel des trois s'est produit. Le même texte poussé par la passerelle dans chaque requête d'agent gouvernée, c'est la décision de l'organisation — écrire le test qui échoue avant le correctif, n'ajouter aucune dépendance sans ADR approuvé, ce dépôt contient des données personnelles donc pseudonymisez avant de coller. C'est la moitié du harnais qui gouverne la manière dont un agent travaille, et non le modèle ni les outils qu'il peut atteindre.

Deux types de plugin le portent, et aucun des deux n'accorde de capacité propre :

  • Contexte. Du texte tel quel, injecté avant le prompt du développeur, jusqu'à 16 Kio par version.
  • Compétence. Un nom, ses instructions et les noms d'outils qu'elle attend. Ces noms sont intersectés avec le plafond d'outils enregistré sur la clé : une compétence déclare ce dont elle a besoin et ne peut jamais élargir une clé — un outil absent du plafond est simplement retiré de ce qui est dit au modèle.

Une version est liée à l'une des trois portées, et chaque requête résout les trois :

  • Organisation. Toutes les clés agent de l'organisation, y compris celles créées après la liaison. C'est la portée d'une règle que personne ne devrait avoir à penser à rattacher.
  • Utilisateur. Toutes les clés agent d'un membre — un brief d'intégration, ou une posture plus stricte pour une seule personne.
  • Clé. Une clé agent précise, ce que faisait déjà une liaison.

La résolution est déterministe, car l'ordre d'injection change le prompt. Sluis prend l'union des trois portées, revérifie chaque plugin exactement comme pour les outils, écarte les versions en double, puis ordonne l'organisation d'abord, l'utilisateur ensuite, la clé en dernier : la règle générale est lue en premier et l'exception étroite en dernier. Le contexte est injecté tel quel, une compétence comme section nommée. Sur l'entrée Claude, les blocs sont ajoutés en tête de system, dans l'une ou l'autre forme que cette API autorise ; sur l'entrée Codex, en tête de instructions, ou comme instruction developer initiale quand la requête n'en porte aucune.

Tout ce qui est injecté dans une requête tient dans 32 Kio. Au-delà, la requête est refusée avec un 422 qui nomme les plugins ayant dépassé le plafond. Rien n'est tronqué en silence : une demi-instruction est pire qu'aucune, et une organisation qui croit une règle en vigueur doit être avertie quand elle ne l'est pas.

Le texte injecté n'est pas réécrit par la protection des données, et l'ordre est à sens unique : le prompt du développeur est d'abord analysé et pseudonymisé, puis votre politique est ajoutée en tête. Ces blocs sont votre propre contenu gouverné, rédigé dans votre propre Console : il n'y a personne dont il faille les protéger — et les tokeniser détruirait ce qu'ils disent. “Escalader vers security@example.com avant de coller” devenu “escalader vers «EMAIL_1» avant de coller” n'est plus une instruction applicable.

Ces deux types sont rédigés dans la Console et ne portent aucune signature. Une signature sert à empêcher un manifeste de pointer un identifiant gouverné vers un endpoint que personne n'a approuvé ; un bloc de texte ne pointe vers rien. Tout le reste de ce qui rend un enregistrement fiable tient toujours : une version est immuable, ses octets exacts sont hachés, et la ligne enregistre qui l'a écrite et quand. Un manifeste portant une entrée MCP conserve la signature obligatoire et la vérification du signataire enrôlé à chaque requête. L'onglet Plugins indique lequel des deux est une version — « rédigé dans la Console » est donc un fait énoncé et non un champ absent — et il prévisualise les blocs résolus dans l'ordre où la passerelle les injecte, pour une clé ou un membre choisi.

Chaque bloc injecté laisse un marqueur sur la ligne d'audit scellée, context:<plugin_id>@<version>#<digest8>, où l'empreinte est constituée des huit premiers caractères du hachage de cette version. Comme une version est immuable, le marqueur suffit à reconstituer le texte exact remis au modèle : la piste d'audit seule dit si un agent était soumis à une règle donnée au moment où il a agi.

Cursor est la limite assumée. Son transport /agent/cursor est un schéma binaire propriétaire : Sluis sait trouver et réécrire le texte à l'intérieur de ces trames — c'est ainsi que fonctionne la protection des données là-bas — mais il ne peut pas savoir quel champ est le prompt système, et écrire dans un champ deviné corromprait la requête au lieu de la gouverner. Rien n'est donc injecté sur cette entrée, et un tour Cursor ne porte votre contexte que si le client du développeur l'envoie lui-même. L'aperçu de la Console dit la même chose.

La gouvernance qui s'applique toujours

Le trafic d'agent est du trafic Sluis ordinaire, à une exception près. La pseudonymisation et le DLP s'exécutent avant l'envoi, y compris dans les trames protobuf de Cursor, les limites de débit et de budget de la clé s'appliquent à chaque requête, les outils MCP sont contrôlés appel par appel, et chaque appel de modèle et d'outil est audité et mesuré. L'exception, c'est la résidence : sur le plan agent, la politique est enregistrée et non imposée, pour la raison exposée dans l'encadré en haut de cette page.

Les règles sont celles décrites sous Protection des données et Budgets & cache, et elles relèvent de la politique de l'organisation : une clé agent ne peut pas les assouplir.

Facturation

Chaque compte fournisseur actif géré par Sluis coûte 16,50 € de prix catalogue par mois civil, facturé au plus une fois par compte et par mois. Il est facturé à votre racine de facturation de plus haut niveau et apparaît sur sa propre ligne de facture, distincte de l'usage mesuré. La TVA et la majoration liée au moyen de paiement s'appliquent exactement comme sur le reste de la facture.

Déconnecter un compte arrête les mois suivants. Reconnecter le même abonnement amont réutilise le compte existant au lieu d'en ajouter un second facturable : une déconnexion puis reconnexion dans le même mois ne facture qu'une fois.

L'usage de la passerelle reste facturé à la consommation, exactement comme pour les clés API.

Disponibilité

La vue Agent Harness apparaît dans la Console dès que l'indicateur de déploiement agent_harness est activé pour votre organisation. Demandez-nous de l'activer si vous ne la voyez pas.

Dépannage

SymptômeCause et correction
401 sur un appel /agent/*La clé est sur la mauvaise surface ou dans le mauvais en-tête. Une clé API ne donne rien sur les routes agent et une clé agent ne donne rien sur le plan de modèles ; chaque entrée n'accepte qu'une seule forme d'en-tête.
502 no credential configured for providerLa clé agent nomme un fournisseur pour lequel elle n'a aucun compte lié. Une clé ne dépense que les abonnements auxquels elle est liée et ne se rabat jamais sur les autres identifiants de l'organisation : liez un compte pour ce fournisseur, ou nommez un modèle que le compte lié dessert.
Renouvellement d'abonnement refuséLe fournisseur a refusé définitivement le renouvellement : le compte cesse de servir jusqu'à une reconnexion humaine. Reconnectez-le dans la Console ; le même abonnement réutilise son compte existant et sa redevance mensuelle existante.
400 mcp_servers is not supportedUne déclaration MCP distante dans un corps Responses est refusée avant l'envoi, car un serveur atteint depuis le modèle contournerait l'écluse d'outils. Enregistrez le serveur auprès de Sluis et atteignez-le par l'entrée MCP.
Aucun extrait de configuration dans la ConsoleLe déploiement n'a pas d'URL publique de passerelle validée : la configuration prête à l'emploi ne peut pas être affichée. Configurez SLUIS_GATEWAY_PUBLIC_URL, puis lisez les points d'accès dans l'onglet Connections.