feat: Add support for dynamically managing provider connections

This commit is contained in:
Raghotham Murthy 2025-10-14 22:20:15 -07:00
parent 63422e5b36
commit d11edf6fee
9 changed files with 3176 additions and 8 deletions

View file

@ -40,6 +40,142 @@
}
],
"paths": {
"/v1/admin/providers": {
"post": {
"responses": {
"200": {
"description": "RegisterProviderResponse with the registered provider info.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterProviderResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest400"
},
"429": {
"$ref": "#/components/responses/TooManyRequests429"
},
"500": {
"$ref": "#/components/responses/InternalServerError500"
},
"default": {
"$ref": "#/components/responses/DefaultError"
}
},
"tags": [
"Providers"
],
"summary": "Register a new dynamic provider.",
"description": "Register a new dynamic provider.\nRegister a new provider instance at runtime. The provider will be validated,\ninstantiated, and persisted to the kvstore. Requires appropriate ABAC permissions.",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterProviderRequest"
}
}
},
"required": true
},
"deprecated": false
}
},
"/v1/admin/providers/{provider_id}": {
"post": {
"responses": {
"200": {
"description": "UpdateProviderResponse with updated provider info",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateProviderResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest400"
},
"429": {
"$ref": "#/components/responses/TooManyRequests429"
},
"500": {
"$ref": "#/components/responses/InternalServerError500"
},
"default": {
"$ref": "#/components/responses/DefaultError"
}
},
"tags": [
"Providers"
],
"summary": "Update an existing provider's configuration.",
"description": "Update an existing provider's configuration.\nUpdate the configuration and/or attributes of a dynamic provider. The provider\nwill be re-instantiated with the new configuration (hot-reload). Static providers\nfrom run.yaml cannot be updated.",
"parameters": [
{
"name": "provider_id",
"in": "path",
"description": "ID of the provider to update",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateProviderRequest"
}
}
},
"required": true
},
"deprecated": false
},
"delete": {
"responses": {
"200": {
"description": "OK"
},
"400": {
"$ref": "#/components/responses/BadRequest400"
},
"429": {
"$ref": "#/components/responses/TooManyRequests429"
},
"500": {
"$ref": "#/components/responses/InternalServerError500"
},
"default": {
"$ref": "#/components/responses/DefaultError"
}
},
"tags": [
"Providers"
],
"summary": "Unregister a dynamic provider.",
"description": "Unregister a dynamic provider.\nRemove a dynamic provider, shutting down its instance and removing it from\nthe kvstore. Static providers from run.yaml cannot be unregistered.",
"parameters": [
{
"name": "provider_id",
"in": "path",
"description": "ID of the provider to unregister.",
"required": true,
"schema": {
"type": "string"
}
}
],
"deprecated": false
}
},
"/v1/chat/completions": {
"get": {
"responses": {
@ -1680,6 +1816,51 @@
"deprecated": false
}
},
"/v1/providers/{provider_id}/test": {
"post": {
"responses": {
"200": {
"description": "TestProviderConnectionResponse with health status.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestProviderConnectionResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest400"
},
"429": {
"$ref": "#/components/responses/TooManyRequests429"
},
"500": {
"$ref": "#/components/responses/InternalServerError500"
},
"default": {
"$ref": "#/components/responses/DefaultError"
}
},
"tags": [
"Providers"
],
"summary": "Test a provider connection.",
"description": "Test a provider connection.\nExecute a health check on a provider to verify it is reachable and functioning.\nWorks for both static and dynamic providers.",
"parameters": [
{
"name": "provider_id",
"in": "path",
"description": "ID of the provider to test.",
"required": true,
"schema": {
"type": "string"
}
}
],
"deprecated": false
}
},
"/v1/responses": {
"get": {
"responses": {
@ -4005,6 +4186,351 @@
"title": "Error",
"description": "Error response from the API. Roughly follows RFC 7807."
},
"RegisterProviderRequest": {
"type": "object",
"properties": {
"provider_id": {
"type": "string",
"description": "Unique identifier for this provider instance."
},
"api": {
"type": "string",
"description": "API namespace this provider implements."
},
"provider_type": {
"type": "string",
"description": "Provider type (e.g., 'remote::openai')."
},
"config": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"description": "Provider configuration (API keys, endpoints, etc.)."
},
"attributes": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"description": "Optional attributes for ABAC access control."
}
},
"additionalProperties": false,
"required": [
"provider_id",
"api",
"provider_type",
"config"
],
"title": "RegisterProviderRequest"
},
"ProviderConnectionInfo": {
"type": "object",
"properties": {
"provider_id": {
"type": "string",
"description": "Unique identifier for this provider instance"
},
"api": {
"type": "string",
"description": "API namespace (e.g., \"inference\", \"vector_io\", \"safety\")"
},
"provider_type": {
"type": "string",
"description": "Provider type identifier (e.g., \"remote::openai\", \"inline::faiss\")"
},
"config": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"description": "Provider-specific configuration (API keys, endpoints, etc.)"
},
"status": {
"$ref": "#/components/schemas/ProviderConnectionStatus",
"description": "Current connection status"
},
"health": {
"$ref": "#/components/schemas/ProviderHealth",
"description": "Most recent health check result"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "Timestamp when provider was registered"
},
"updated_at": {
"type": "string",
"format": "date-time",
"description": "Timestamp of last update"
},
"last_health_check": {
"type": "string",
"format": "date-time",
"description": "Timestamp of last health check"
},
"error_message": {
"type": "string",
"description": "Error message if status is failed"
},
"metadata": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"description": "User-defined metadata (deprecated, use attributes)"
},
"owner": {
"type": "object",
"properties": {
"principal": {
"type": "string"
},
"attributes": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"additionalProperties": false,
"required": [
"principal"
],
"description": "User who created this provider connection"
},
"attributes": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"description": "Key-value attributes for ABAC access control"
}
},
"additionalProperties": false,
"required": [
"provider_id",
"api",
"provider_type",
"config",
"status",
"created_at",
"updated_at",
"metadata"
],
"title": "ProviderConnectionInfo",
"description": "Information about a dynamically managed provider connection.\nThis model represents a provider that has been registered at runtime\nvia the /providers API, as opposed to static providers configured in run.yaml.\n\nDynamic providers support full lifecycle management including registration,\nconfiguration updates, health monitoring, and removal."
},
"ProviderConnectionStatus": {
"type": "string",
"enum": [
"pending",
"initializing",
"connected",
"failed",
"disconnected",
"testing"
],
"title": "ProviderConnectionStatus",
"description": "Status of a dynamic provider connection."
},
"ProviderHealth": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"OK",
"Error",
"Not Implemented"
],
"description": "Health status (OK, ERROR, NOT_IMPLEMENTED)"
},
"message": {
"type": "string",
"description": "Optional error or status message"
},
"metrics": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"description": "Provider-specific health metrics"
},
"last_checked": {
"type": "string",
"format": "date-time",
"description": "Timestamp of last health check"
}
},
"additionalProperties": false,
"required": [
"status",
"metrics",
"last_checked"
],
"title": "ProviderHealth",
"description": "Structured wrapper around provider health status.\nThis wraps the existing dict-based HealthResponse for API responses\nwhile maintaining backward compatibility with existing provider implementations."
},
"RegisterProviderResponse": {
"type": "object",
"properties": {
"provider": {
"$ref": "#/components/schemas/ProviderConnectionInfo",
"description": "Information about the registered provider"
}
},
"additionalProperties": false,
"required": [
"provider"
],
"title": "RegisterProviderResponse",
"description": "Response after registering a provider."
},
"UpdateProviderRequest": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"description": "New configuration parameters (merged with existing)"
},
"attributes": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"description": "New attributes for access control"
}
},
"additionalProperties": false,
"title": "UpdateProviderRequest"
},
"UpdateProviderResponse": {
"type": "object",
"properties": {
"provider": {
"$ref": "#/components/schemas/ProviderConnectionInfo",
"description": "Updated provider information"
}
},
"additionalProperties": false,
"required": [
"provider"
],
"title": "UpdateProviderResponse",
"description": "Response after updating a provider."
},
"Order": {
"type": "string",
"enum": [
@ -7242,6 +7768,51 @@
"title": "ListProvidersResponse",
"description": "Response containing a list of all available providers."
},
"TestProviderConnectionResponse": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"description": "Whether the connection test succeeded"
},
"health": {
"type": "object",
"additionalProperties": {
"oneOf": [
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
},
{
"type": "string"
},
{
"type": "array"
},
{
"type": "object"
}
]
},
"description": "Health status from the provider"
},
"error_message": {
"type": "string",
"description": "Error message if test failed"
}
},
"additionalProperties": false,
"required": [
"success"
],
"title": "TestProviderConnectionResponse",
"description": "Response from testing a provider connection."
},
"ListOpenAIResponseObject": {
"type": "object",
"properties": {