internal/ai engine. It reads your apps, deploys, logs, metrics and diagnostics through the same tool surface the MCP server exposes, and it can propose actions. Every action that would change anything pauses for an explicit confirmation click first. AI in Levelrail only reads and suggests on top of the API, and this chat uses the same engine and confirmation gate described in AI assistant integration, as a dashboard panel and a CLI command.
This is separate from levelrail-mcp. To point an external MCP client (Claude Desktop, Claude Code, your own) at this control plane, read AI assistant integration instead.
Source: internal/ai, internal/api/ai_chat.go, internal/api/ai_settings.go, web/src/components/AiChatPanel.tsx, cmd/levelrail-cli/ai.go.
Enabling it
Two things are required.1
Turn on the experimental flag
The chat is gated behind With the flag off (the default), every route under
ai-chat (see Experimental features). Set this on the control plane:/api/v1/ai/sessions and /api/v1/settings/ai-assistant answers 404, the dashboard hides the AI assistant nav entry and the /ai-assistant page, and the CLI hides ai chat and ai sessions from --help and completion.2
Configure a provider key
Nothing runs until you bring your own key. Only
anthropic is supported today. The key is stored with the same envelope encryption as other secrets and is never returned or logged.- CLI
- Dashboard
levelrail-cli settings ai-assistant get reports only whether a key is configured.levelrail-cli ai chat stops returning the experimental-disabled error.
What it can do
- Read, always: logs, metrics, deploy history, node status, certificates, and crashloop diagnosis, through the read-only tool classification described under Modes and toolsets. These run automatically, with no confirmation, the moment the model asks for them.
- Propose, never execute directly: a mutating tool call (deploy, rollback, restart, an env change, and so on) is recorded as a pending confirmation and streamed to the UI as a
tool_call_proposedevent. It does not run until a human clicks Approve (dashboard) or runslevelrail-cli ai sessions resolve <session> <confirmation-id> --approve(CLI). Rejecting it is just as explicit a path (--reject), and the model sees “User declined to run this action” as the result either way, so it can explain and move on rather than retry blindly. - Never in the reconciliation path: the assistant only calls the platform’s own REST API (
internal/apiclient), the same path any external MCP client or the CLI uses. It has no privileged entry point into the reconciler, the Docker client, or the database.
Using it
Dashboard
AI assistant in the global nav (hidden unless the flag is on) opens a chat panel: a message composer, a transcript with the assistant’s replies rendered as markdown (code blocks, lists, links; raw HTML and images are stripped, since a reply can echo untrusted tool output), and a confirmation card with Approve/Reject buttons for any pending mutating tool call. History lists past sessions so you can resume or delete one; New chat starts a fresh one.CLI
--json on any ai subcommand switches to one JSON object per stream event (or the plain resource for sessions list/get/delete), the same --json/--output/--query convention every other levelrail-cli command follows.
REST API
POST /api/v1/ai/sessions, GET /api/v1/ai/sessions, GET/DELETE /api/v1/ai/sessions/{id}, POST /api/v1/ai/sessions/{id}/messages (Server-Sent Events: text_delta, tool_call_proposed, tool_result, done), and POST /api/v1/ai/sessions/{id}/confirmations/{confirmation_id} (same SSE framing, for resolving a pending call). All of it requires AbilityRoot: a confirmed message can execute any mutating tool the platform exposes once approved, the same blast radius a root-scoped token would need to reach those actions directly, so do not hand this surface to a lower-privileged token.
Scope and limits
- Single admin user, no per-user session isolation beyond the root-only gate: anyone who can authenticate as root can see and act on any session.
- One provider: Anthropic only, with no model routing or fallback.
- Not yet covered by real-infrastructure testing:
test/e2e/ai_chat_test.goproves the full session lifecycle (create, send a message with an auto-executed read tool call, get, list, delete, and the flag-off 404) over real HTTP against a real router and a realai.Engine, but with a scripted fakeai.Provider, never a live call to Anthropic’s API. See Feature status for the current evidence tier.
See also
- ai-assistant.md:
levelrail-mcp, the standalone MCP server for an external AI client, and the confirmation/untrusted-text mechanism this chat shares with it. - experimental-features.md: the
APP_EXPERIMENTALswitch and what “off” means everywhere. - identity-and-access.md: API tokens and abilities (
aiCLI commands and/api/v1/ai/...routes needroot). - cli-reference.md: full flag reference for
ai chatandai sessions.