Skip to main content

B03 - Provider Registry

GroupTechnologyStatusServiceRoadmap phaseContracts
B - LLM management and Model GatewayDeveloped (PostgreSQL + OpenBao)to developllm2-

Back to index - Français

Role and responsibilities​

Configured providers, endpoints, regions, write-only credentials, status and kill switch.

Position in the architecture and interactions​

Read by the Router (B05) and the LiteLLM config generator; written by tenant admins through the portal or POST /v1/providers. GET /v1/providers/catalog lists presets with status configured / not configured / not connected.

Open source component vs developed part​

Fully developed (PostgreSQL table + OpenBao for credentials).

Provider idProviderPath through LiteLLMAdmin configuration fields
openaiOpenAInativeapi_key, organization, base_url
anthropicAnthropicnativeapi_key, base_url
google_ai_studioGoogle AI Studio / Gemininative (gemini/)api_key
vertex_aiVertex AInative (vertex_ai/)project, location, service account JSON (or workload identity)
azure_openaiAzure OpenAInative (azure/)endpoint, deployment name, api_version, api_key or Entra ID
azure_ai_foundryAzure AI Foundryadapter selected by endpoint type (OpenAI style or model inference style)endpoint, api_key or Entra ID, api_version
aws_bedrockAWS Bedrocknative (bedrock/)aws_region_name, aws_access_key_id + aws_secret_access_key, or IAM role (aws_role_arn / IRSA), or Bedrock API bearer token (aws_bearer_token)
mistralMistralnativeapi_key
cohereCoherenative (chat, embed, rerank)api_key
deepseekDeepSeeknativeapi_key
groqGroqnativeapi_key
together_aiTogether AInativeapi_key
fireworks_aiFireworks AInativeapi_key
openrouterOpenRouternativeapi_key
ollamaOllamanativebase_url
vllmvLLM (local, brick B02)OpenAI compatible (hosted_vllm/)base_url, optional api_key
qwenQwen (DashScope)OpenAI compatibleapi_key, base_url
zaiZ.AI (GLM)OpenAI compatibleapi_key, base_url
minimaxMiniMaxOpenAI compatibleapi_key, base_url
lm_studioLM StudioOpenAI compatible (lm_studio/)base_url
openai_codexOpenAI CodexOpenAI compatible, OAuth accountOAuth token (brokered)
github_copilotGitHub Copilotnative (github_copilot/)OAuth device token (brokered)
huggingfaceHugging Facenative (huggingface/)api_key, endpoint (Inference Endpoints)
customCustom OpenAI compatibleopenai/ with custom base_urlbase_url, api_key, headers
custom_anthropicCustom Anthropic compatibleanthropic/ with custom base_urlbase_url, api_key

AWS Bedrock admin fields: aws_region_name, then one of aws_access_key_id + aws_secret_access_key, aws_role_arn (IRSA / assume role, recommended), aws_web_identity_token + aws_role_arn or aws_bearer_token (Bedrock API key).

Vertex AI admin fields: project, location, service_account_json (or workload identity federation).

Data model​

eai.llm_providers(id, tenant_id, name, provider_type, api_base, config, secret_fields, credential_ref, regions, retention, enabled, connected, last_test, created_by, created_at, updated_at); credential_ref points to OpenBao (provider secrets are held in eai.llm_provider_secrets), the value is never stored in clear.

Tables (schema eai, every tenant table carries tenant_id uuid NOT NULL with an RLS policy on current_setting('app.tenant_id', true)::uuid): eai.llm_providers, eai.audit_events.

API endpoints​

  • GET /v1/providers
  • POST /v1/providers
  • GET /v1/providers/catalog
  • GET /v1/providers/{id}
  • PATCH /v1/providers/{id}
  • DELETE /v1/providers/{id}
  • POST /v1/providers/{id}/test
  • POST /v1/providers/{id}/disable
  • POST /v1/providers/{id}/enable
POST /v1/providers HTTP/1.1
Host: <control-plane-host>
X-API-Key: eai_xxx_secret
Accept-Language: en
Content-Type: application/json

{"provider_type": "aws_bedrock", "name": "bedrock-eu-west-3", "regions": ["eu-west-3"], "credentials": {"aws_region_name": "eu-west-3", "aws_role_arn": "arn:aws:iam::123456789012:role/eai-bedrock"}}
{"id": "4d2c2cff-7f37-4110-ae93-f8fc8dd771a7", "name": "bedrock-eu-west-3", "provider_type": "aws_bedrock", "scope": "tenant", "api_base": "https://bedrock-runtime.{aws_region_name}.amazonaws.com", "base_url": "https://bedrock-runtime.{aws_region_name}.amazonaws.com", "type": "aws_bedrock", "config": {}, "credentials_set": ["aws_region_name", "aws_role_arn"], "credential_ref": "openbao://llm/providers/4d2c2cff-7f37-4110-ae93-f8fc8dd771a7", "regions": ["eu-west-3"], "retention": {}, "enabled": true, "connected": null, "last_test": null, "status": "configured", "created_at": "2026-10-30T02:38:20.544170+01:00", "updated_at": "2026-10-30T02:38:20.551425+01:00"}

Errors use the common envelope {"error": {"code", "message", "message_i18n", "details", "request_id"}}; lists are paginated with limit and cursor.

SDK usage​

Python (enterprise_ai):

from enterprise_ai import EnterpriseAI

client = EnterpriseAI(base_url="<control-plane-url>", api_key="eai_xxx_secret")
items = client.providers.list()

TypeScript (@enterprise-ai/sdk):

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

const eai = new EnterpriseAI({ baseUrl: "<control-plane-url>", apiKey: process.env.EAI_API_KEY });
const items = await eai.providers.list();

Java (enterprise-ai-java):

EnterpriseAIClient client = EnterpriseAIClient.builder()
.baseUrl("<control-plane-url>")
.apiKey(System.getenv("EAI_API_KEY"))
.build();
var items = client.providers().list();

Go (enterprise-ai-go):

client, _ := eai.NewClient(eai.WithBaseURL("<control-plane-url>"), eai.WithAPIKey(os.Getenv("EAI_API_KEY")))
items, err := client.Providers.List(ctx)

Configuration​

  • Environment: EAI_DATABASE_URL, EAI_OTEL_EXPORTER_OTLP_ENDPOINT.
  • Helm values: controlPlane.enabled, controlPlane.replicas, controlPlane.resources, controlPlane.config, litellm.enabled, litellm.config.

Security controls​

  • Authentication by OIDC JWT, tenant API key with scopes, or SPIFFE mTLS; tenant resolved from the credential, never from the body.
  • Authorization through OpenFGA and OPA decisions; every mutation and decision writes a hash-chained eai.audit_events row.
  • Secrets never returned by the API; TLS everywhere; Cilium network policies restrict who can reach the service.
ControlEnforcement
Provider / model / region allowlistsPer tenant and project in eai.policies; the Router only selects allowed triples (provider, model, region)
Data classificationRequest eai.data_classification must be <= model data_classification_max; very sensitive (restricted, secret) data stays on local models (vLLM)
DLPDLP Gateway (E02) inspects and masks or tokenizes prompts before any remote call
Secret isolationCredentials write-only, stored in OpenBao, injected into LiteLLM at sync, never returned by the API or logged
TLSTLS 1.2+ to every provider, mTLS SPIFFE inside the cluster
Provider retentionRegistry records the provider retention / zero data retention terms; models without acceptable terms are restricted
Fallback policyFallback chains are filtered with the same allowlists: never a forbidden region, model or classification
Cost guardrailsEstimate and quota reservation before execution (POST /v1/gateway/estimate, POST /v1/quotas/reserve), streaming cut-off during execution when the budget is reached
Logging without exposurePrompts and completions logged only according to policy, redacted, never with credentials
Kill switchPOST /v1/providers/{id}/disable and POST /v1/models/{model_id}/disable take effect at the next call

Remote models are allowed for some uses (public or internal data, approved purposes) while very sensitive data stays on local models.

Observability​

  • Metrics: eai_provider_registry_requests_total, eai_provider_registry_errors_total, eai_provider_registry_latency_seconds (Prometheus).
  • Traces: OpenTelemetry spans eai.providers.* with W3C traceparent propagation, AI spans forwarded to Opik.
  • Audit actions: provider.create, provider.update, provider.delete, provider.test, policy.evaluate.

FinOps aspects​

Operating cost is allocated per tenant and project through labels on Usage Events and Kubernetes resource requests; no direct per-call cost.

Failure modes and resilience​

  • Stateless replicas behind the API Gateway, PostgreSQL HA for state; readiness probe GET /readyz removes unhealthy pods.
  • External system unavailable: fail closed for security decisions, explicit error code, no silent bypass.

Standalone adoption (client of a client)​

A client of a client can adopt this brick alone with the Python SDK sub-client client.providers (TS eai.providers, Java client.providers(), Go client.Providers). Minimal deployment: Control Plane API + PostgreSQL + Keycloak (or API keys), the Control Plane loads every domain of services/control-plane/src/eai/domains; the optional chart components are switched off in deploy/helm/enterprise-ai/values.yaml (vllm.enabled, qdrant.enabled, nats.enabled, workers.enabled).

Acceptance tests​

  1. A tenant cannot read or modify another tenant's resources (RLS test).
  2. Every mutation produces an audit event verifiable by GET /v1/audit/verify.
  3. Errors are returned in English and French according to Accept-Language.