AI Operations API
AI operations endpoints are superadmin-only and are served under /api/v1.0.
Observability
| Method | Endpoint | Description |
|---|---|---|
| GET | /admin/ai-ops/overview | Unified AI health, usage, failures, guardrail, and remediation overview |
| GET | /admin/ai-workflow-runs | List AI workflow run traces |
| GET | /admin/ai-workflow-runs/{run_id} | Get one AI workflow run trace |
| GET | /admin/ai-logs | List AI logs |
| GET | /admin/ai-logs/usage | Token usage summary |
| GET | /admin/ai-logs/usage/people | Token usage summary by user/person |
| GET | /admin/ai-logs/usage/guardrail-impact | Guardrail impact summary |
| POST | /admin/ai-logs/{log_id}/replay | Replay a logged prompt through the governed prompt replay path |
| POST | /admin/ai-logs/{log_id}/save-prompt | Save a prompt candidate from a log entry |
For full payloads and replay behavior, see AI Logs API.
Provider and Prompt Administration
| Method | Endpoint | Description |
|---|---|---|
| GET | /admin/ai-config/ | Get effective LLM provider configuration |
| POST | /admin/ai-config/ | Create LLM provider configuration |
| PATCH | /admin/ai-config/ | Update LLM provider configuration |
| DELETE | /admin/ai-config/ | Delete LLM provider configuration |
| POST | /admin/ai-config/test-connection | Test the configured LLM provider |
| GET | /admin/ai-model-routing/profiles | List model profiles |
| POST | /admin/ai-model-routing/profiles | Create model profile |
| GET | /admin/ai-model-routing/routes | List model routes |
| PUT | /admin/ai-model-routing/routes | Upsert model route |
| GET | /admin/prompts | List prompt definitions |
| GET | /admin/prompts/{prompt_key} | Get prompt definition details |
| POST | /admin/prompts/{prompt_key}/versions | Create and activate a prompt version |
| POST | /admin/prompts/{prompt_key}/preview | Render a prompt with supplied variables |
| POST | /admin/prompts/{prompt_key}/reset | Reset a prompt route to code defaults |
Embeddings and Budgets
| Method | Endpoint | Description |
|---|---|---|
| GET | /admin/embedding-config/ | Get effective embedding configuration |
| POST | /admin/embedding-config/ | Create embedding configuration |
| PATCH | /admin/embedding-config/ | Update embedding configuration |
| DELETE | /admin/embedding-config/ | Delete embedding configuration |
| POST | /admin/embedding-config/test-embedding | Test the effective embedding provider |
| POST | /admin/embedding-config/reindex-products | Queue product reindexing with current embeddings |
| POST | /admin/embedding-config/reindex-standard-items | Queue published standards reindexing with current embeddings |
| GET | /admin/ai-budgets | List AI budget overrides |
| DELETE | /admin/ai-budgets/{entry_point_id} | Remove an AI budget override |
Embedding Configuration
Embedding configuration controls vector generation for semantic search. It is superadmin-only and can be resolved from saved database configuration or environment defaults.
Supported providers are:
| Provider | Notes |
|---|---|
local | Uses the configured local sentence-transformers backend. Runtime status can be idle, warming, ready, or failed. |
openai | Uses OpenAI-compatible embedding credentials. |
azure_openai | Uses an Azure OpenAI embedding deployment and optional base URL. |
mistral | Uses the Mistral embeddings API. |
voyage | Uses Voyage AI embeddings. |
Create Configuration
POST /admin/embedding-config/
{
"provider": "openai",
"model_name": "text-embedding-3-small",
"dimensions": 1536,
"api_key": "provider-api-key",
"api_base_url": null,
"is_enabled": true,
"index_version": "v1"
}
api_key is stored as a secret and is never returned in plaintext. Custom
api_base_url values must pass public HTTPS URL validation.
Update Configuration
PATCH /admin/embedding-config/
{
"provider": "voyage",
"model_name": "voyage-3",
"dimensions": 1024,
"api_key": "provider-api-key",
"is_enabled": true,
"index_version": "v2"
}
Changing provider, model_name, or dimensions marks the configuration as
pending_reindex. Run the reindex endpoints so existing vectors use the new
shape.
Response Shape
{
"id": "config-uuid",
"instance_id": null,
"provider": "openai",
"model_name": "text-embedding-3-small",
"dimensions": 1536,
"api_base_url": null,
"api_key_set": true,
"is_enabled": true,
"index_version": "v1",
"status": "active",
"runtime_status": "not_applicable",
"runtime_error": null,
"source": "database",
"updated_by": "user-uuid",
"created_at": "2026-06-29T08:00:00Z",
"updated_at": "2026-06-29T08:15:00Z"
}
source is database for saved config and environment for runtime defaults.
Configuration status is active, pending_reindex, or failed.
Test And Reindex
POST /admin/embedding-config/test-embedding
POST /admin/embedding-config/reindex-products
POST /admin/embedding-config/reindex-standard-items
test-embedding returns whether a test vector can be generated and the
resulting dimensions.
{
"success": true,
"error": null,
"dimensions": 1536
}
Reindex endpoints queue background work and return the queued item count.
{
"message": "Queued 240 products for embedding reindex",
"total": 240
}
Product reindexing refreshes product search vectors. Standard-item reindexing refreshes vectors for published standards pages.
Instance Scope
Embedding configuration can be control-plane scoped or instance scoped. For
instance-scoped requests, use the authenticated instance context; X-Instance-Id
is treated as a consistency check against that request context. Instance
overrides allow one tenant instance to use a different embedding provider,
model, dimensions, or credentials from the global default.
Embedding Errors
| Status | Meaning |
|---|---|
404 | Updating or deleting a database-backed configuration that does not exist, or referencing an unknown instance. |
409 | Creating a configuration where one already exists for the scope. |
422 | Unsafe custom base URL or invalid request contract. |
503 | Instance database pool is unavailable for instance-scoped reindexing. |
External AI Tool Providers
External AI tool providers let superadmins register governed MCP stdio servers as read-only tool sources for AI workflows. Provider administration is superadmin-only. Space enablement requires edit access to the target space.
Endpoint Overview
| Method | Endpoint | Description |
|---|---|---|
GET | /admin/ai/tool-providers/ | List configured providers. |
POST | /admin/ai/tool-providers/ | Create a provider. |
PATCH | /admin/ai/tool-providers/{provider_id} | Update provider metadata, command settings, credential, overrides, instructions, or active state. |
DELETE | /admin/ai/tool-providers/{provider_id} | Delete a provider and revoke its active external-research grants. |
POST | /admin/ai/tool-providers/{provider_id}/discover | Start tool discovery for an active provider. |
GET | /admin/ai/tool-providers/{provider_id}/tools | List discovered tools for a provider. |
GET | /spaces/{slug}/ai/tool-providers/ | List provider enablement state for a space. |
PUT | /spaces/{slug}/ai/tool-providers/{provider_id}/enablement | Enable or disable a provider for one space. |
GET | /spaces/{slug}/ai/tool-capabilities/web_search | Read the primary web-search binding and readiness diagnostics. |
PUT | /spaces/{slug}/ai/tool-capabilities/web_search | Select one compatible discovered provider tool. |
DELETE | /spaces/{slug}/ai/tool-capabilities/web_search | Remove the binding and revoke binding-scoped grants. |
Create Provider
POST /admin/ai/tool-providers/
{
"slug": "catalog_mcp",
"name": "Catalog MCP",
"description": "Read-only catalog helper tools.",
"kind": "mcp_stdio",
"command_argv": ["qarion-mcp-catalog", "--stdio"],
"cwd": "mcp/catalog",
"env": {
"QARION_MCP_MODE": "readonly"
},
"credential_id": "credential-uuid",
"secret_env_var": "QARION_MCP_TOKEN",
"tool_overrides": {
"search_products": {
"risk_level": "read",
"read_only": true,
"writes_data": false,
"returns_sensitive": false,
"requires_confirmation": false,
"scope_types": ["space"],
"enabled": true
}
},
"skill_instructions": "Use these tools only for catalog lookup.",
"is_active": true
}
Provider constraints:
| Field | Notes |
|---|---|
slug | Lowercase letters, numbers, hyphens, and underscores; must start with a letter or number. Tool names are namespaced as {slug}.{tool_name}. |
kind | Current supported value is mcp_stdio. |
command_argv | One to 20 argv items. Shell workflows and denied executables are rejected. |
cwd | Optional safe relative working directory. Absolute paths and .. segments are rejected. |
env | Non-secret string environment variables. Sensitive key names are rejected. |
credential_id | Optional credential-store entry used to provide secrets. |
secret_env_var | Environment variable name that receives the credential secret. |
tool_overrides | Optional admin classification and enablement metadata keyed by tool name. |
Provider Response
{
"id": "provider-uuid",
"slug": "catalog_mcp",
"name": "Catalog MCP",
"kind": "mcp_stdio",
"command_argv": ["qarion-mcp-catalog", "--stdio"],
"cwd": "mcp/catalog",
"env": {
"QARION_MCP_MODE": "readonly"
},
"credential_id": "credential-uuid",
"secret_env_var": "QARION_MCP_TOKEN",
"has_credential": true,
"tool_overrides": {},
"skill_instructions": "Use these tools only for catalog lookup.",
"is_active": true,
"last_discovered_at": "2026-06-29T08:00:00Z",
"last_error": null,
"tool_count": 2,
"enabled_tool_count": 2,
"created_at": "2026-06-29T07:45:00Z",
"updated_at": "2026-06-29T08:00:00Z"
}
Discover And List Tools
POST /admin/ai/tool-providers/{provider_id}/discover
GET /admin/ai/tool-providers/{provider_id}/tools
Discovery starts the configured MCP stdio server, lists tools, stores each
tool's input schema and metadata, deletes stale tools that disappeared from the
provider, and updates last_discovered_at or last_error.
Tool responses include tool_name, namespaced_name, description,
input_schema, risk_level, read_only, writes_data, returns_sensitive,
requires_confirmation, scope_types, is_enabled, capability_id,
capability_compatible, capability_validation_error, and discovered_at.
Canonical Web-Search Capability
A discovered tool may be classified with capability_id: "web_search" only
when it is enabled, read-only, non-sensitive, does not require confirmation,
and exactly implements this input contract:
{
"type": "object",
"properties": {
"query": { "type": "string", "minLength": 3, "maxLength": 500 },
"max_results": { "type": "integer", "minimum": 1, "maximum": 8, "default": 8 }
},
"required": ["query"],
"additionalProperties": false
}
The MCP tool result must be JSON with a results array. Each item contains a
bounded title, public HTTPS url, bounded snippet, and optional
published_at. Qarion supplies rank and source domain, rejects private or
non-HTTPS URLs, rejects sensitive or oversized output, and stores only the
normalized evidence. Raw provider responses and unsafe query originals are not
retained.
{
"results": [
{
"title": "Supported versions",
"url": "https://docs.example.com/support",
"snippet": "The current support window is ...",
"published_at": "2026-08-01T00:00:00Z"
}
]
}
Select one primary tool per space with:
PUT /spaces/{slug}/ai/tool-capabilities/web_search
{ "provider_tool_id": "discovered-tool-uuid" }
The response includes healthy and readiness_errors. Missing executables,
inactive or incomplete credentials, failed discovery, incompatible schemas,
missing bindings, inactive providers, and provider health failures fail closed.
Pipeline Authoring exposes only the stable
pipeline_authoring_web_search facade—not provider-specific arguments. The
facade is limited to six successful distinct calls and eight results per call
for one task. It is unavailable to delegated workers and subagents. The first
request creates a consent interaction without contacting the provider;
approval is scoped to the current user, space, definition, root task, binding,
provider, and 24-hour lifetime. Repeated sanitized queries reuse persisted
evidence without spending quota, and replay never performs another live search.
Bundled SearXNG-Compatible Provider
Every Qarion application image includes a stdio MCP adapter for an administrator-controlled SearXNG-compatible JSON endpoint. A representative provider registration is:
{
"slug": "qarion-web-search",
"name": "Qarion Web Search",
"kind": "mcp_stdio",
"command_argv": [
"python",
"-m",
"app.services.platform.external_providers.searxng_web_search"
],
"cwd": null,
"env": {
"QARION_WEB_SEARCH_ENDPOINT": "https://search.example.com/search",
"QARION_WEB_SEARCH_TIMEOUT_SECONDS": "15"
},
"credential_id": null,
"secret_env_var": null,
"tool_overrides": {
"web_search": {
"risk_level": "read",
"read_only": true,
"writes_data": false,
"returns_sensitive": false,
"requires_confirmation": false,
"scope_types": ["public_web"],
"enabled": true,
"capability_id": "web_search"
}
},
"is_active": true
}
For a protected endpoint, set credential_id to an active compatible
credential and secret_env_var to QARION_WEB_SEARCH_API_KEY; the adapter
sends the secret only as a Bearer token. QARION_WEB_SEARCH_USER_AGENT is an
optional non-secret override. The timeout must be between 1 and 30 seconds.
The endpoint may carry fixed query parameters. The adapter replaces q and
format, forces format=json, rejects embedded URL credentials and fragments,
requires a JSON object with a results list, bounds the response to 1 MB, and
returns at most eight normalized items. Run provider discovery after creation,
then use the space enablement and capability-binding endpoints below. The
Docker demo registers this same adapter against its pinned local SearXNG
service; there is no fixture or query-specific fallback.
Space Enablement
GET /spaces/{slug}/ai/tool-providers/
PUT /spaces/{slug}/ai/tool-providers/{provider_id}/enablement
{
"enabled": true,
"max_risk_level": "read",
"allowed_tool_names": ["search_products", "catalog_mcp.get_product"]
}
V1 space enablement only supports max_risk_level: "read". allowed_tool_names
can contain raw tool names or namespaced tool names. Omit it or set it to
null to allow all enabled read-risk tools from the provider.
Available tools for a space must satisfy every condition:
- The provider is active.
- The provider is enabled for the space.
- The discovered tool is enabled.
- The discovered tool has
risk_level: "read". - The tool is included in the space allowlist when an allowlist is present.
Tool Provider Errors
| Status | Meaning |
|---|---|
400 | Invalid provider config, unknown allowlisted tool name, unsupported provider kind, inactive provider discovery, or non-read enablement. |
403 | User is not a superadmin for admin endpoints, or cannot edit space settings for space enablement. |
404 | Provider, credential, or space was not found. |
409 | Provider slug already exists. |
502 | MCP provider discovery failed. |
Evaluation Runs
| Method | Endpoint | Description |
|---|---|---|
| GET | /admin/ai-evals | List deterministic AI evaluation runs |
| GET | /admin/ai-evals/latest | Get latest eval summary |
| POST | /admin/ai-evals/run | Start an evaluation run |
| GET | /admin/ai-evals/{run_id} | Get evaluation run detail |