Aller au contenu principal

D-02 Passerelle d'outils

Brique D: Outils, skills, plugins, MCP, connecteurs. Version anglaise: D-02-tool-gateway

1. Rôle et responsabilités​

Point unique d'invocation des outils par les agents : scopes, politique, DLP, approbation, lease de credential, coût, audit.

  • Valider l'entrée contre input_schema
  • Évaluer OPA tool.invoke et ses obligations
  • DLP sur entrée et sortie
  • Obtenir un lease (D-11) puis appeler l'endpoint ou le sandbox

2. Position dans l'architecture et interactions​

  • Appelants: Loop Controller (C-03), SDK.
  • Chemin d'exécution: Synchrone ; peut basculer en attente d'approbation (durable).
  • Toute interaction passe par l'API Control Plane v1 (/v1) derrière la passerelle API (D-14).

3. Composant open source et partie développée​

  • Open source: aucun (à développer)
  • Développé: Entièrement développé.
  • Intégration externe via un adaptateur eai/integrations/<system>.py avec repli in-process lorsque l'URL n'est pas configurée.

4. Modèle de données​

Tables (schéma eai, RLS tenant_id):

  • eai.tool_invocations

Colonnes communes : id uuid, tenant_id uuid NOT NULL, created_at, updated_at ; politique RLS current_setting('app.tenant_id', true)::uuid.

5. Contrat​

  • Contrat appliqué: tool-manifest
  • Schéma JSON: contracts/v1/tool-manifest.schema.json
  • Champs clés: spec.requires_approval, spec.rate_limit, spec.sandbox_profile, spec.credential_ref
  • Validation : POST /v1/contracts/{name}/validate ; application d'un manifeste : POST /v1/manifests/apply.

6. Endpoints API​

  • POST /v1/tools/{name}/invoke
  • GET /v1/tools/invocations

Requête POST /v1/tools/{name}/invoke:

{
"input": {
"q": "INC-42"
},
"run_id": "run_01J9",
"step_index": 4
}

Réponse:

{
"invocation_id": "tinv_77",
"status": "succeeded",
"output": {
"issues": [
{
"key": "INC-42"
}
]
},
"decision_id": "dec_51",
"cost": {
"amount": "0.001",
"currency": "EUR"
}
}

7. Exemples SDK​

Python:

from enterprise_ai import EnterpriseAI

client = EnterpriseAI(base_url="<control-plane-url>", api_key="eai_xxx_secret")
out = client.tools.invoke("jira.search", {"q": "INC-42"}, run_id="run_01J9")

TypeScript:

import { EnterpriseAI } from "@enterprise-ai/sdk";

const client = new EnterpriseAI({ baseUrl: "<control-plane-url>", apiKey: process.env.EAI_API_KEY });
const out = await client.tools.invoke("jira.search", { arguments: { q: "INC-42" }, run_id: "run_01J9" });

Java:

EnterpriseAIClient client = EnterpriseAIClient.builder()
.baseUrl("<control-plane-url>")
.apiKey(System.getenv("EAI_API_KEY"))
.build();
JsonNode out = client.tools().invoke("jira.search", Map.of("arguments", Map.of("q", "INC-42")));

Go:

c, _ := eai.NewClient(eai.WithBaseURL("<control-plane-url>"), eai.WithAPIKey(os.Getenv("EAI_API_KEY")))
out, _ := c.Tools.Invoke(ctx, "jira.search", map[string]any{"arguments": map[string]any{"q": "INC-42"}})

8. Configuration​

  • Variables d'environnement: EAI_DATABASE_URL
  • Clés Helm: controlPlane.config, controlPlane.secrets

9. Contrôles de sécurité​

  • Scope tools:invoke + scopes_required
  • Secrets jamais exposés à l'agent : lease injecté côté passerelle
  • Approbation si requires_approval ou obligation OPA
  • Toutes les requêtes portent le tenant issu du credential ; RLS PostgreSQL
  • Chaque mutation et décision de politique écrit un événement d'audit chaîné

10. Observabilité​

  • Métriques Prometheus: eai_tool_invocations_total{tool,status}, eai_tool_latency_seconds
  • Traces: spans OpenTelemetry avec conventions sémantiques GenAI (gen_ai.operation.name, gen_ai.agent.id, gen_ai.tool.name), attributs eai.tenant_id, eai.run_id, propagation traceparent.
  • Actions d'audit: tool.invoke, dlp.redact

11. Unités FinOps​

  • Appels d'outils (unité tool_call) et coût déclaré spec.cost.
  • Émis comme Usage Event (POST /v1/finops/usage) avec tenant, projet, agent et run.

12. Modes de défaillance et résilience​

  • Outil non idempotent : aucune nouvelle tentative automatique
  • Délai d'expiration et disjoncteur (circuit breaker) par outil
  • Limite de débit -> 429
  • Erreurs normalisées (enveloppe error, message_i18n en/fr)

13. Adoption autonome (client d'un client)​

  • enterprise_ai.tools + Control Plane ; OPA et OpenBao optionnels (replis).
  • SDK: enterprise_ai.tools / mcp / skills / plugins / connectors / channels
  • Déploiement minimal : chart Helm avec controlPlane.enabled=true et PostgreSQL ; les composants externes désactivés utilisent leur repli in-process.

14. Tests d'acceptation​

  1. Invocation sans scope -> 403 policy_denied
  2. Sortie contenant un IBAN masquée
  3. requires_approval -> état waiting_approval
  4. Accès inter-tenant refusé
  5. Erreur renvoyée en fr avec Accept-Language: fr