Skip to main content

External providers

Backend API​

Routes live in llm_d_lens/ai_providers/router.py. Each endpoint below documents the REST contract and the matching AIProviderService, connectivity probe, or proxy call it uses.

Outbound requests validate HTTPS provider URLs and public DNS answers. When no proxy is active, the backend connects to a validated IP while preserving the original Host header and TLS SNI. When the host environment provides an HTTPS proxy, the backend uses that proxy by default and sends the original hostname, so TLS keeps the correct SNI. Set LENS_TRUSTED_AI_PROVIDER_PROXY only to pin a specific verified proxy URL; a mismatched value or a proxy bypass retains application-side IP pinning. Redirects are not followed. Only configure an egress proxy you trust to resolve public provider hosts.

List saved AI providers​

List the saved external AI provider connections Lens knows about. Returned records mask stored API keys and expose only a safe preview.

GET /api/v1/ai-providers

Request: no request body.

Response: returns an items array of saved AIProvider records with hasApiKey and apiKeyPreview instead of the raw apiKey.

{
"items": [
{
"id": "ai-provider-7f3a2c1d",
"name": "OpenAI-compatible gateway",
"baseUrl": "https://llm.example.com/",
"model": "gpt-4o-mini",
"providerType": "openai",
"timeoutSeconds": 15,
"createdAt": "2026-09-23T08:00:00Z",
"updatedAt": "2026-09-23T08:00:00Z",
"hasApiKey": true,
"apiKeyPreview": "...cdef"
}
]
}

Get a saved AI provider​

Get one saved external AI provider connection by id. The response masks the stored API key and includes only safe metadata.

GET /api/v1/ai-providers/{provider_id}

Request: no request body. Path param: provider_id (str).

Response: returns one masked AIProvider payload.

{
"id": "ai-provider-7f3a2c1d",
"name": "OpenAI-compatible gateway",
"baseUrl": "https://llm.example.com/",
"model": "gpt-4o-mini",
"providerType": "openai",
"timeoutSeconds": 15,
"createdAt": "2026-09-23T08:00:00Z",
"updatedAt": "2026-09-23T08:00:00Z",
"hasApiKey": true,
"apiKeyPreview": "...cdef"
}

Create an AI provider​

Create and persist a new external AI provider configuration. Use this for durable provider definitions Lens may later reuse for agentic planning or other integrations.

POST /api/v1/ai-providers

Request: body fields are name (str), baseUrl (HttpUrl), model (str), apiKey (str, optional), providerType ("openai" | "anthropic"), and timeoutSeconds (float).

{
"name": "OpenAI-compatible gateway",
"baseUrl": "https://llm.example.com/",
"model": "gpt-4o-mini",
"apiKey": "sk-example-secret",
"providerType": "openai",
"timeoutSeconds": 15
}

Response: returns the newly created provider with its secret masked.

{
"id": "ai-provider-7f3a2c1d",
"name": "OpenAI-compatible gateway",
"baseUrl": "https://llm.example.com/",
"model": "gpt-4o-mini",
"providerType": "openai",
"timeoutSeconds": 15,
"createdAt": "2026-09-23T08:00:00Z",
"updatedAt": "2026-09-23T08:00:00Z",
"hasApiKey": true,
"apiKeyPreview": "...cret"
}

Update an AI provider​

Update an existing external AI provider configuration by id. Omit apiKey to keep the stored key unchanged, or pass an empty string to clear it.

PUT /api/v1/ai-providers/{provider_id}

Request: path param provider_id (str). The body is AIProviderUpdateRequest, where every field is optional.

{
"name": "OpenAI-compatible gateway",
"model": "gpt-4.1-mini",
"timeoutSeconds": 30
}

Response: returns the updated provider with the stored secret still masked.

{
"id": "ai-provider-7f3a2c1d",
"name": "OpenAI-compatible gateway",
"baseUrl": "https://llm.example.com/",
"model": "gpt-4.1-mini",
"providerType": "openai",
"timeoutSeconds": 30,
"createdAt": "2026-09-23T08:00:00Z",
"updatedAt": "2026-09-23T08:05:00Z",
"hasApiKey": true,
"apiKeyPreview": "...cret"
}

Delete an AI provider​

Delete a saved external AI provider configuration. Use this when a provider should no longer be available to Lens.

DELETE /api/v1/ai-providers/{provider_id}

Request: no request body. Path param: provider_id (str).

Response: no response body. The endpoint returns 204 No Content when deletion succeeds.

Test a draft AI provider​

Test connectivity for a not-yet-saved external AI provider configuration. Use this before creating or updating a durable provider entry.

The URL must use a public HTTPS destination without embedded credentials, query parameters, or a fragment. Base paths with version segments (for example /openai/v1.0) are supported. The same destination rules apply to saved-provider chat and agentic requests.

POST /api/v1/ai-providers/test

Request: body fields are baseUrl (HttpUrl), model (str), apiKey (str, optional), providerType ("openai" | "anthropic"), and timeoutSeconds (float).

{
"baseUrl": "https://api.openai.com/",
"model": "gpt-4o-mini",
"apiKey": "sk-abc",
"providerType": "openai",
"timeoutSeconds": 15
}

Response: returns an AIProviderTestResult with success, model lookup status, and latency.

{
"success": true,
"message": "Connected successfully.",
"modelFound": true,
"availableModels": ["gpt-4o-mini", "gpt-4.1-mini"],
"latencyMs": 182.4
}

Test a saved AI provider​

Test connectivity for an already-saved external AI provider by id, reusing its stored API key. Use this to validate an existing provider definition.

POST /api/v1/ai-providers/{provider_id}/test

Request: no request body. Path param: provider_id (str).

Response: returns an AIProviderTestResult using the provider's persisted baseUrl, model, apiKey, timeoutSeconds, and providerType.

{
"success": true,
"message": "Connected successfully.",
"modelFound": true,
"availableModels": ["gpt-4o-mini", "gpt-4.1-mini"],
"latencyMs": 176.9
}

Proxy a chat completion through a saved provider​

Send a chat completion request through a saved AI provider. The route only supports saved openai-type providers and forwards an OpenAI-compatible JSON body with the server-held API key attached.

POST /api/v1/ai-providers/{provider_id}/chat/completions

Request: path param provider_id (str). The body is forwarded as an OpenAI-style chat/completions payload. If model is omitted, the router fills in the saved provider model before proxying.

{
"messages": [
{
"role": "user",
"content": "Give me a one-line health summary for cluster-123."
}
]
}

Response: returns the upstream provider JSON response.

{
"choices": [
{
"message": {
"role": "assistant",
"content": "Cluster cluster-123 is reachable and reports healthy control-plane status."
}
}
]
}

See the full request/response schemas in the FastAPI OpenAPI schema (regenerate with npm run docs:api).