12 KiB
AI Provider Guide
Overview
aiprovider is the model-adapter service for Planet.
It isolates model-vendor details from the main backend so the rest of the system can call a stable business API:
- Caller service ->
planet backend planet backend->aiprovideraiprovider-> concrete model provider
The recommended default is:
- External and cross-service callers use
planet backend - Only infrastructure-grade internal jobs call
aiproviderdirectly
Responsibilities
backend is responsible for:
- authentication and authorization
- business-level request shaping
- stable
/api/v1/ai/...endpoints - internal service-to-service authentication toward
aiprovider - reading the default provider, model, and per-provider keys saved in Settings, then overriding
aiprovider.envdefaults through internal headers
aiprovider is responsible for:
- model protocol adaptation
- provider selection by
.envwhen no backend override headers are present - timeout and lightweight retry
- request tracing via
X-Request-ID
This now follows an OpenClaw-like seam:
AI_PROVIDERidentifies the vendor or logical providerAI_PROVIDER_APIidentifies the wire adapter
That split makes MiniMax, Claude-compatible gateways, and self-hosted OpenAI-compatible services easier to model without overloading one config field.
Supported Providers
aiprovider currently supports these provider identities:
openaianthropicminimaxollama
Supported request adapters:
openai-completionsanthropic-messagesollama-generate
Backward-compatible aliases still accepted:
openai_compatibleanthropic_compatibleclaude_compatible
Provider mapping:
vLLM,LM Studio,One API:AI_PROVIDER=openai,AI_PROVIDER_API=openai-completionsMiniMax:AI_PROVIDER=minimax,AI_PROVIDER_API=anthropic-messages- Claude-compatible gateways:
AI_PROVIDER=anthropic,AI_PROVIDER_API=anthropic-messages Ollama:AI_PROVIDER=ollama,AI_PROVIDER_API=ollama-generate
API Surfaces
Main backend API
Preferred stable entrypoints:
GET /api/v1/ai/provider/statusPOST /api/v1/ai/situational-awareness/analyze
Authentication:
Authorization: Bearer <jwt>
Optional tracing header:
X-Request-ID: <caller-generated-id>
The backend will propagate X-Request-ID to aiprovider and return the same header in the response.
Settings API
The AI settings page uses:
GET /api/v1/settings/integrationsPUT /api/v1/settings/integrationsPOST /api/v1/settings/integrations/ai-provider/connectGET /api/v1/settings/integrations/ai-provider/secretsGET /api/v1/settings/integrations/ai-provider/presetsGET /api/v1/settings/ai-promptsPUT /api/v1/settings/ai-prompts/{task_key}POST /api/v1/settings/ai-prompts/{task_key}/reset
These endpoints require an authenticated user. The secrets endpoint is only used when the settings page reveals a key or token; hiding the field restores the masked preview.
The ai-prompts endpoints back the Prompts tab in AI settings. Shipped defaults come from versioned backend resources, while business code references stable task keys. The API stores only operator overrides. Resetting a prompt removes the override and falls back to the current shipped default.
Prompt Boundary
aiprovider is a pure model adapter and does not inject a global business system prompt. News localization, alert briefing, BGP briefing, location factcheck, datasource mapping, and credential guide generation each resolve their own effective prompt by task key. Alert-analysis system prompts are only sent by alert-related tasks and do not leak into other LLM calls.
AI provider internal API
Internal-only endpoints:
GET /v1/provider/statusPOST /v1/analyze
Authentication:
X-Provider-Token: <shared-secret>
Optional tracing header:
X-Request-ID: <caller-generated-id>
Request Example
Call through backend
curl -X POST http://localhost:8000/api/v1/ai/situational-awareness/analyze \
-H "Authorization: Bearer <access_token>" \
-H "X-Request-ID: bgp-incident-20260407-001" \
-H "Content-Type: application/json" \
-d '{
"title": "BGP异常研判",
"objective": "总结当前风险并给出处置建议",
"observations": [
"collector A 在 5 分钟内出现多次 origin 变更",
"异常集中在同一地区前缀"
],
"constraints": [
"不要编造不存在的数据",
"区分事实和推断"
],
"context": {
"source": "bgp-monitor",
"severity": "high"
}
}'
Call aiprovider directly
curl -X POST http://localhost:8010/v1/analyze \
-H "X-Provider-Token: change_me" \
-H "X-Request-ID: ai-batch-job-001" \
-H "Content-Type: application/json" \
-d '{
"title": "链路波动分析",
"objective": "给出简要态势摘要和下一步建议",
"observations": [
"多个节点出现延迟上升"
],
"constraints": [
"不要假设根因已经确认"
],
"context": {
"region": "APAC"
}
}'
Response Shape
Both backend and aiprovider return the same payload shape:
{
"provider": "minimax",
"api": "anthropic-messages",
"model": "MiniMax-M2.7",
"content": "1) 态势摘要 ...",
"content_blocks": [],
"text_blocks": [],
"thinking_blocks": [],
"raw_response": {}
}
Both services also return:
X-Request-ID: <id>
Configuration
Runtime Configuration Flow
The backend Settings system owns the global LLM default. The runtime flow is:
- Frontend or application code calls a
backend/api/v1/ai/...endpoint. backendreadscategory = external_integrationsfrom the PostgreSQLsystem_settingstable.payload.ai_provider.default_providerselects the active provider.payload.ai_provider.providers[provider]supplies that provider'sapi_key,provider_api,base_url,model,max_tokens, andanthropic_version.backendconverts those values to internal headers such asX-AI-Provider,X-AI-Provider-API,X-AI-Base-URL,X-AI-API-Key, andX-AI-Model.aiprovideruses those headers to override its.envdefaults before calling the real model vendor.
After the AI settings page saves a new default provider/model/key, Playground, alert briefs, datasource mapping generation, and other backend AI calls all use that same default.
Persistence Shape
AI settings are persisted in PostgreSQL, not a JSON file. The core payload shape is:
{
"ai_provider": {
"service_url": "http://localhost:8010",
"service_token": "",
"default_provider": "openai",
"providers": {
"openai": {
"provider_api": "openai-completions",
"base_url": "https://api.openai.com/v1",
"model": "gpt-5.1",
"api_key": "<saved secret>",
"max_tokens": 4096,
"anthropic_version": "2023-06-01"
},
"minimax": {
"provider_api": "anthropic-messages",
"base_url": "https://api.minimaxi.com/anthropic",
"model": "MiniMax-M2.7",
"api_key": "<saved secret>",
"max_tokens": 1200,
"anthropic_version": "2023-06-01"
}
},
"timeout_seconds": 60,
"retry_attempts": 2
}
}
Legacy single-slot settings are mapped to providers[provider] on read and are written back in the new shape on save.
Key Fallback
Each provider has its own key slot. Resolution order is:
providers[provider].api_keyin PostgreSQL- the provider-specific variable in
aiprovider/.env, such asOPENAI_API_KEY,MINIMAX_API_KEY, orANTHROPIC_API_KEY - the generic
AI_API_KEYinaiprovider/.env
.env is only a fallback. After the settings page saves successfully, or after the connection test succeeds, PostgreSQL becomes the global default source.
Settings Page Behavior
- The Provider select controls the global default provider.
- The model select saves the default model for the selected provider.
- The LLM API Key field shows a masked preview while hidden; keys with a
-prefix keep the prefix, for examplesk-********, and keys without a prefix are fully masked. - Clicking the eye icon fetches and displays the full plaintext value; hiding restores the masked preview.
Save AI Configurationsaves the current form as the global default.Test Connectionuses the current form for a real model-chain test, then saves it as the global default only when the test succeeds.- Leaving a key field empty keeps the old key; it does not delete it.
Backend
Recommended backend .env:
AI_PROVIDER_SERVICE_URL=http://localhost:8010
AI_PROVIDER_SERVICE_TOKEN=change_me
AI_PROVIDER_TIMEOUT_SECONDS=60
AI_PROVIDER_RETRY_ATTEMPTS=2
Reference file:
AI Provider
Reference file:
Frontend local reference:
Common settings:
SERVICE_NAME=planet-ai-provider
SERVICE_VERSION=0.1.0
AI_PROVIDER_SERVICE_TOKEN=change_me
AI_TIMEOUT_SECONDS=60
AI_HTTP_RETRY_ATTEMPTS=2
Optional provider-specific keys:
MINIMAX_API_KEY=sk-cp-xxxxx
OPENAI_API_KEY=sk-xxxxx
ANTHROPIC_API_KEY=sk-ant-xxxxx
DEEPSEEK_API_KEY=sk-xxxxx
DASHSCOPE_API_KEY=sk-xxxxx
MOONSHOT_API_KEY=sk-xxxxx
OPENROUTER_API_KEY=sk-or-xxxxx
OpenAI-compatible example
AI_PROVIDER=openai
AI_PROVIDER_API=openai-completions
AI_BASE_URL=http://127.0.0.1:8001/v1
AI_API_KEY=local-key
AI_MODEL=your-local-model
MiniMax CN example
AI_PROVIDER=minimax
AI_PROVIDER_API=anthropic-messages
AI_BASE_URL=https://api.minimaxi.com/anthropic
AI_API_KEY=sk-cp-xxxxx
AI_MODEL=MiniMax-M2.7
AI_MAX_TOKENS=1200
AI_ANTHROPIC_VERSION=2023-06-01
MiniMax note:
- This follows the same Anthropic Messages request shape as the official MiniMax examples.
- For MiniMax,
aiprovidernow disablesthinkingby default unless the caller explicitly passes athinkingobject. - This mirrors OpenClaw's caution around MiniMax Anthropic-compatible behavior.
Anthropic-compatible example
AI_PROVIDER=anthropic
AI_PROVIDER_API=anthropic-messages
AI_BASE_URL=https://your-claude-compatible-endpoint.example.com/anthropic
AI_API_KEY=your_api_key
AI_MODEL=your-model
AI_MAX_TOKENS=1200
AI_ANTHROPIC_VERSION=2023-06-01
Ollama example
AI_PROVIDER=ollama
AI_PROVIDER_API=ollama-generate
AI_BASE_URL=http://127.0.0.1:11434
AI_API_KEY=
AI_MODEL=qwen2.5:7b
Deployment Modes
Single machine
Recommended local flow:
backendonlocalhost:8000aiprovideronlocalhost:8010- local model gateway on
localhost:11434or another local port
Helpers already included:
Multi-machine
Example topology:
- app machine:
backend - AI gateway machine:
aiprovider - model machine: local model service or cloud proxy
In that case, this becomes service-to-service HTTP RPC:
- caller -> backend
- backend ->
http://10.0.0.12:8010 aiprovider-> model endpoint
Recommended cross-machine backend config:
AI_PROVIDER_SERVICE_URL=http://10.0.0.12:8010
AI_PROVIDER_SERVICE_TOKEN=change_me
AI_PROVIDER_TIMEOUT_SECONDS=60
AI_PROVIDER_RETRY_ATTEMPTS=2
Recommended operating rules:
- keep
aiprovideron a private network - protect it with
X-Provider-Tokenat minimum - always send
X-Request-ID - keep callers on the backend API unless they are infrastructure jobs
Retry And Failure Behavior
backend -> aiprovider:
- retries lightweight network / 5xx failures
- returns
502when the provider service is unavailable
aiprovider -> model provider:
- retries lightweight network / 5xx failures
- returns
502when the model provider is unavailable
This is intentionally conservative. It avoids masking persistent errors while still absorbing short hiccups.
Operational Notes
./planet.sh startnow startsaiproviderautomatically./planet.sh restart -arestarts onlyaiprovider./planet.sh log -atailsaiproviderlogs./planet.sh healthreportsaiproviderhealth
Recommended Calling Policy
- Frontend and application services: call
backend - Scheduled infra jobs and diagnostics: optionally call
aiprovider - Do not let multiple business services integrate model vendors independently
That keeps provider switching centralized and avoids model-specific drift across the system.