Developer docs

Bring your own LLM

The Brain separates governance from generation: retrieval, access control, and the egress guard run first, and only already-cleared content ever reaches a model. That means the model is swappable — ours, your cloud provider, or a server in your own rack — without changing what anyone can see.

The three routes

RouteWhat it isSetup
Managed (default)AIVM-hosted Claude models. Zero config — and the fail-open fallback: any broken or incomplete BYO config degrades here, never to a broken chat.None.
Your provider keyYour own API agreement with a cloud provider. One-click presets: OpenAI, Google Gemini, Groq, OpenRouter, Together, Mistral.Settings → Models & providers (workspace admin). Key is sealed at rest and write-only.
Self-hostedYour own inference server speaking the OpenAI-compatible API: Ollama, vLLM, LM Studio, llama.cpp — or anything else serving /v1/chat/completions. API key optional (many local servers ignore it).Same card; see the self-hosted section below for network requirements.

The workspace default applies to every governed answer that doesn’t pick a model explicitly — chat (incl. streaming), the REST query APIs, MCP tools, and agent runs. An explicit per-request model always wins, and an explicit “offline” pick stays offline. Model choice can never widen access: the ACL filter runs before synthesis, so any model only sees documents the caller was already entitled to read.

Configuration API

The Settings card is the intended surface, but everything it does rides two admin endpoints (session-cookie auth — these are dashboard routes, not machine-token routes):

# Read the current workspace config (the key itself is never returned)
curl -b "$SESSION_COOKIE" https://your-workspace.example.com/api/admin/llm-config
# → { "defaultModelId": "byo",
#     "byo": { "endpoint": "https://llm.example.com/v1", "model": "llama3.1", "hasKey": false },
#     "posture": { "allowPrivate": false, "deployment": "saas" } }

# Save a self-hosted default (apiKey semantics: omit = keep sealed key, "" = clear, value = replace)
curl -b "$SESSION_COOKIE" -X POST https://your-workspace.example.com/api/admin/llm-config \
  -H 'content-type: application/json' \
  -d '{ "defaultModelId": "byo",
        "byo": { "endpoint": "https://llm.example.com/v1", "model": "llama3.1" } }'

# Dry-run the saved config (1-token completion + informative /models lookup)
curl -b "$SESSION_COOKIE" -X POST https://your-workspace.example.com/api/admin/llm-config/validate

# A governed answer through whatever the workspace default resolves to (machine token)
curl -X POST https://your-workspace.example.com/api/v1/query \
  -H "authorization: Bearer $AIVM_MACHINE_TOKEN" -H 'content-type: application/json' \
  -d '{ "question": "What changed in pricing last quarter?" }'

What Validate actually checks

ConfigCheckOn failure you see
ManagedA real 1-token completion on the platform key (not just key presence).A fixed, generic status — reachable / key rejected / temporarily unavailable.
BYO / self-hostedA real 1-token POST {endpoint}/chat/completions, plus an informative GET {endpoint}/models — both under one 8-second budget.Status-mapped detail (401/403 key rejected, 404 path/model, timeout), plus whether your model id appears in the endpoint's /models list. A /models failure never fails validation — some gateways don't serve it.

Self-hosted servers: requirements

All four common servers speak the same OpenAI-compatible surface, so they all use the same config — endpoint + model id, key optional:

ServerDefault endpoint shapeWatch out for
Ollamahttp://host:11434/v1Binds 127.0.0.1 by default — set OLLAMA_HOST to expose it beyond the machine. Model ids are name:tag (llama3.1:8b).
vLLMhttp://host:8000/v1Binds 0.0.0.0 by default — firewall it. --served-model-name makes model ids arbitrary aliases; use whatever the server reports in /v1/models.
LM Studiohttp://host:1234/v1Ignores the API key entirely — access control must live at the network layer (VPN / reverse proxy), not in key rotation.
llama.cpp (llama-server)http://host:8080/v1Minimal built-in auth (--api-key optional). Test JSON-mode combos before relying on them.

None of these ship TLS. Put a reverse proxy (Caddy, nginx, Cloudflare Tunnel) or a tailnet in front for HTTPS. Azure OpenAI is deliberately not covered by the generic path (different auth header, deployment-scoped URLs, no /v1/models) — use a managed model or an OpenAI-compatible gateway for now.

Network posture: SaaS vs your own environment

DeploymentReachable endpointsWhy
AIVM-hosted SaaSPublic HTTPS only. Private, loopback, and LAN addresses are blocked by the outbound-network guard.A workspace-supplied private address would make our backend fetch inside our infrastructure — that's a server-side request forgery, for every tenant's protection. Expose your server via reverse proxy, Cloudflare Tunnel, or a tailnet funnel instead.
Brain in your environment (AIVM_DEPLOYMENT=vpc or airgap, or AIVM_ALLOW_PRIVATE_OUTBOUND=1)Private/LAN endpoints and plain http are permitted.You own the network — Ollama on localhost is your own box. These are operator-side environment variables on the deployment itself; they are not settable from the dashboard.

How your provider key is handled

  • Sealed with AES-256-GCM before it is stored, bound to your workspace (the seal’s associated data is the tenant id — another workspace’s Brain cannot open it).
  • Write-only: no read path returns it — the config API reports only hasKey: true. Replacing it is typing a new one; clearing it is saving an empty value.
  • Key rotation is supported operator-side (versioned sealing keys), and saving a key on a deployment without a sealing key configured fails loudly (503) rather than storing anything readable.
  • Never logged, never in telemetry, never in the audit ledger — the ledger records the model id of each answer, not provider credentials.

What still runs on platform models

Your workspace model governs answer synthesis. Background intelligence still runs on AIVM-managed models: document digestion at upload, onboarding genesis, domain classification for access control, and evaluation judging. On a deployment with no platform key at all, each degrades safely rather than fabricating — digestion keeps the raw content, genesis refuses, classification falls back to rules. Routing these through your BYO provider is on the roadmap.

Embeddings are configured per deployment (not per workspace): AIVM_EMBED_PROVIDER supports OpenAI-compatible and Ollama embedding endpoints with AIVM_EMBED_MODEL, AIVM_EMBED_DIM, AIVM_EMBED_BASE_URL, and AIVM_EMBED_API_KEY. Changing the embedding model changes the vector space — it’s a re-index decision for the operator, which is why it isn’t a workspace toggle.

Workspace admins: configure all of this under Settings → Models & providers.