# DevOps AI Toolkit > AI-powered Kubernetes operations for DevOps teams. Deploy, query, remediate, and operate Kubernetes resources through natural language using MCP, CLI, a Kubernetes controller, and a web UI. ## Getting Started # DevOps AI Toolkit Stack **Deploy the complete DevOps AI Toolkit stack with a single Helm command.** ## Overview The dot-ai-stack umbrella chart installs all DevOps AI Toolkit components with a single command: - **DevOps AI Toolkit** - MCP server for AI-powered Kubernetes operations - **DevOps AI Toolkit Controller** - Kubernetes controller for intelligent resource management and autonomous operations - **DevOps AI Toolkit Web UI** - Web interface for visual cluster management > **Note:** This guide covers Kubernetes deployment using the umbrella Helm chart. For other installation options (Docker, NPX, individual charts, etc.), see [devopstoolkit.ai](/). ## Prerequisites - **Helm 3.x** installed - **kubectl** configured with cluster access - **AI API keys** for AI-powered features (see [AI Model Configuration](/docs/ai-engine/setup/deployment#ai-model-configuration) for supported providers) ## Step 1: Create a Local Cluster (Optional) > Skip this step if you already have a Kubernetes cluster. You will also need a [Gateway API](https://gateway-api.sigs.k8s.io/implementations/) implementation or an ingress controller installed in the cluster. Create a Kind cluster with ingress port mappings: ```bash kind create cluster --name dot-ai-stack --config - < **Note:** This quickstart uses ingress-nginx for simplicity. The community-maintained ingress-nginx project reached [End of Life in March 2026](https://github.com/kubernetes/ingress-nginx). For production clusters, consider using [Gateway API](/docs/ai-engine/setup/gateway-api) instead — see also the [deployment guide](/docs/ai-engine/setup/deployment) for configuration options. ```bash kubectl apply \ --filename https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml ``` Wait for the ingress controller to be ready: ```bash kubectl wait --namespace ingress-nginx \ --for=condition=ready pod \ --selector=app.kubernetes.io/component=controller \ --timeout=90s ``` ## Step 2: Set Environment Variables Set your API keys for AI-powered features: ```bash export ANTHROPIC_API_KEY="your-anthropic-api-key" ``` > **Note:** Multiple AI providers are supported. See [AI Model Configuration](/docs/ai-engine/setup/deployment#ai-model-configuration) for all options including Google Gemini, AWS Bedrock, Azure OpenAI, and others. Generate random authentication tokens for the MCP server and Web UI: ```bash export DOT_AI_AUTH_TOKEN=$(openssl rand -base64 32) export DOT_AI_UI_AUTH_TOKEN=$(openssl rand -base64 32) ``` ## Step 3: Install the Stack Install the complete dot-ai stack with a single Helm command: ```bash helm upgrade --install dot-ai-stack \ oci://ghcr.io/vfarcic/dot-ai-stack/charts/dot-ai-stack \ --namespace dot-ai --create-namespace \ --set dot-ai.secrets.anthropic.apiKey=$ANTHROPIC_API_KEY \ --set dot-ai.secrets.auth.token=$DOT_AI_AUTH_TOKEN \ --set dot-ai.localEmbeddings.enabled=true \ --set dot-ai.ingress.enabled=true \ --set dot-ai.ingress.className=nginx \ --set dot-ai.ingress.host=dot-ai.127.0.0.1.nip.io \ --set dot-ai.webUI.baseUrl=http://dot-ai-ui.127.0.0.1.nip.io \ --set dot-ai-ui.uiAuth.token=$DOT_AI_UI_AUTH_TOKEN \ --set dot-ai-ui.ingress.enabled=true \ --set dot-ai-ui.ingress.host=dot-ai-ui.127.0.0.1.nip.io \ --wait ``` > **Note:** Replace the ingress hosts with your actual domain names for production deployments. This installs: - **dot-ai** - MCP server with ingress at `dot-ai.127.0.0.1.nip.io` - **dot-ai-controller** - Kubernetes controller for autonomous operations - **dot-ai-ui** - Web interface at `dot-ai-ui.127.0.0.1.nip.io` - **Qdrant** - Vector database for pattern and policy storage - **Local Embeddings** - In-cluster embedding service ([HuggingFace TEI](https://huggingface.co/docs/text-embeddings-inference)) so semantic search works without external embedding API keys - **ResourceSyncConfig** - Enables resource discovery - **CapabilityScanConfig** - Enables cluster capability scanning ## Step 4: Verify Installation Check that all pods are running: ```bash kubectl get pods --namespace dot-ai ``` You should see all pods in `Running` status: ``` NAME READY STATUS RESTARTS AGE dot-ai-577db5b4fc-j8kgf 1/1 Running 0 50s dot-ai-controller-manager-c898b5697-dqk2m 1/1 Running 0 50s dot-ai-stack-qdrant-0 1/1 Running 0 50s dot-ai-ui-69d586db8b-ccqrm 1/1 Running 0 50s ``` Test the MCP server health: ```bash curl -H "Authorization: Bearer $DOT_AI_AUTH_TOKEN" \ http://dot-ai.127.0.0.1.nip.io/healthz ``` Expected output: ```json {"status":"ok"} ``` ## Step 5: Choose Your Client The DevOps AI Toolkit can be accessed through two client options - **MCP** or **CLI**. Both provide AI agent integration with full feature parity. ### Option A: MCP Client **Best for:** Curated high-level operations designed to minimize context window usage. Create the MCP client configuration file: ```bash cat > .mcp.json << EOF { "mcpServers": { "dot-ai": { "type": "http", "url": "http://dot-ai.127.0.0.1.nip.io", "headers": { "Authorization": "Bearer $DOT_AI_AUTH_TOKEN" } } } } EOF ``` > **Note:** This example creates `.mcp.json` in the current directory for Claude Code. Other MCP-enabled agents may expect the configuration in a different location (e.g., `~/.config/` or within the agent's settings). Consult your agent's documentation for the correct path. **Learn more:** [MCP Setup Documentation](/docs/ai-engine/setup/deployment) ### Option B: CLI Client **Best for:** Comprehensive API access with lower token overhead for AI agents, plus scripting and automation support. Install the CLI: **macOS (Homebrew):** ```bash brew install vfarcic/tap/dot-ai ``` **Windows (Scoop):** ```powershell scoop bucket add dot-ai https://github.com/vfarcic/scoop-dot-ai scoop install dot-ai ``` **Other platforms:** Download from [releases](https://github.com/vfarcic/dot-ai-cli/releases) or see [installation guide](/docs/cli/setup/installation/). Configure the CLI: ```bash export DOT_AI_URL="http://dot-ai.127.0.0.1.nip.io" ``` Generate skills for your AI agent: ```bash # For Claude Code dot-ai skills generate --agent claude-code # For Cursor dot-ai skills generate --agent cursor # For Windsurf dot-ai skills generate --agent windsurf ``` **Learn more:** [CLI Quick Start](/docs/cli/quick-start/) | [Installation](/docs/cli/setup/installation/) | [Agent Integration](/docs/cli/guides/skills-generation/) ### Choosing Between MCP and CLI - **Use MCP** for simpler, high-level operations with minimal tool descriptions - **Use CLI** for comprehensive API access with lower token costs and better economy for agents executing multiple commands ## Step 6: Start Using Launch your AI agent: ```bash claude ``` > **Note:** If your agent doesn't automatically detect the client, explicitly invoke it with "Use dot-ai MCP" or "Use dot-ai CLI" depending on which client you configured. Try these example prompts: | What You Want | Example Prompt | |---------------|----------------| | Check system status | "Show dot-ai status" | | Query cluster | "What pods are running in the dot-ai namespace?" | | List capabilities | "List all capabilities" | | Deploy an app | "I want to deploy a web application" | | Fix issues | "Something is wrong with my database" | ## Configuration Override any component value by prefixing with the chart name: ```bash --set dot-ai.resources.limits.memory=4Gi --set dot-ai-controller.resources.limits.memory=1Gi --set dot-ai-ui.ingress.host=ui.example.com ``` For available options, see each component's documentation: - [DevOps AI Toolkit values](/docs/ai-engine/setup/deployment) - [Controller values](/docs/controller/) - [Web UI values](/docs/ui/) ## Next Steps - [MCP Tools Overview](/docs/ai-engine/tools/overview) - Complete feature reference - [Pattern Management](/docs/ai-engine/organizational-data/patterns) - Create organizational patterns - [Policy Management](/docs/ai-engine/organizational-data/policies) - Define governance policies ## Cleanup To remove the stack: ```bash helm uninstall dot-ai-stack --namespace dot-ai kubectl delete namespace dot-ai ``` To delete the Kind cluster: ```bash kind delete cluster --name dot-ai-stack ``` # Operate Feature Architecture This document provides a detailed architecture overview of the Operate feature in the DevOps AI Toolkit. ## Overview The Operate feature provides AI-powered Day 2 operations for Kubernetes applications. It handles updates, scaling, enhancements, rollbacks, and deletions through natural language intents while applying organizational patterns and policies, validating changes via dry-run, and executing approved operations safely. ## High-Level Architecture ```mermaid flowchart TB subgraph Users["User / AI Agent"] Agent["Claude Code, Cursor,
VS Code, etc."] end subgraph MCP["MCP Server (dot-ai)"] Operate["operate Tool"] AI["AI Provider"] Session["Session
Manager"] Kubectl["Kubectl Tools"] VectorClient["Vector DB
Client"] end subgraph External["External Services"] LLM["Claude, OpenAI,
Gemini, etc."] Qdrant["Qdrant
(Patterns, Policies,
Capabilities)"] end subgraph K8s["Kubernetes Cluster"] API["Kubernetes API"] Controller["Controller
(dot-ai-controller)"] Resources["Cluster Resources
Deployments, StatefulSets,
CRDs, etc."] end subgraph WebUI["Web UI (dot-ai-ui)"] Viz["Visualization Dashboard
- Current State
- Proposed Changes
- Risk Assessment"] end Agent <-->|MCP Protocol| Operate Operate --> AI Operate --> Session Operate --> Kubectl Operate --> VectorClient AI --> LLM AI <-->|Tool Loop| Kubectl VectorClient --> Qdrant Kubectl --> API Operate -->|Execute Commands| API Controller -->|Scan & Embed| Qdrant Controller -->|Watch| Resources Agent -.->|User opens
Visualization URL| WebUI ``` ## Operation Workflow The operate tool implements a three-phase workflow with persistent session management: ```mermaid flowchart TD subgraph Phase1["Phase 1: Intent Analysis"] Intent["User Intent
(natural language)"] CreateSession["Create Session
(opr-{ts}-{uuid})"] EmbedContext["Embed Context:
- Search Patterns
- Search Policies
- Search Capabilities"] ContextCheck{"Capabilities
Found?"} NoCapError["Error: Run
capability scan first"] Investigation["AI Investigation Loop
(max 30 iterations)"] KubectlTools["kubectl Tools:
get, describe, logs,
patch_dryrun, apply_dryrun,
delete_dryrun, get_crd_schema"] Intent --> CreateSession --> EmbedContext EmbedContext --> ContextCheck ContextCheck -->|No| NoCapError ContextCheck -->|Yes| Investigation Investigation <-->|Tool Calls| KubectlTools end subgraph Phase2["Phase 2: Analysis & Validation"] ParseResponse["Parse AI Response"] DryRunCheck{"Dry-Run
Validated?"} RetryAnalysis["AI Iterates with
Corrected Commands"] Analysis["Generate Analysis:
- Current State
- Proposed Changes
- Commands
- Risk Assessment"] SaveSession["Save Session
(status: analysis_complete)"] ReturnAnalysis["Return with
Visualization URL"] Investigation --> ParseResponse --> DryRunCheck DryRunCheck -->|No| RetryAnalysis --> Investigation DryRunCheck -->|Yes| Analysis Analysis --> SaveSession --> ReturnAnalysis end subgraph Phase3["Phase 3: User Approval & Execution"] UserChoice["User Approval
(executeChoice=1)"] LoadSession["Load Session"] ExecuteCommands["Execute Commands
(continue-on-error)"] PostValidation{"Has
validationIntent?"} CallRemediate["Call remediate
Internally"] SaveResults["Save Results
(status: executed_*)"] ReturnResults["Return Execution
Results"] ReturnAnalysis -.->|"User reviews
and approves"| UserChoice UserChoice --> LoadSession --> ExecuteCommands ExecuteCommands --> PostValidation PostValidation -->|Yes| CallRemediate --> SaveResults PostValidation -->|No| SaveResults SaveResults --> ReturnResults end ``` ## Component Details ### MCP Server (dot-ai) The MCP server provides the core operations engine: | Component | File | Description | |-----------|------|-------------| | `operate` tool | `src/tools/operate.ts` | Entry point, routing, context embedding, formatting | | Analysis workflow | `src/tools/operate-analysis.ts` | Intent analysis, AI tool loop, response parsing | | Execution workflow | `src/tools/operate-execution.ts` | Command execution, post-validation, results | | System Prompt | `prompts/operate-system.md` | AI instructions for operation behavior | | User Prompt | `prompts/operate-user.md` | Handlebars template with context injection | | `GenericSessionManager` | `src/core/generic-session-manager.ts` | File-based session persistence | | `AIProvider` | `src/core/ai-provider.interface.ts` | AI abstraction with tool loop support | | `kubectl-tools` | `src/core/kubectl-tools.ts` | Kubectl investigation and validation tools | | Vector Services | `src/services/*-vector-service.ts` | Pattern, policy, capability search | | `visualization` | `src/core/visualization.ts` | URL generation for web UI | ### Kubectl Investigation & Validation Tools Tools available during AI analysis: | Tool | Description | |------|-------------| | `kubectl_api_resources` | Discover available resources in cluster | | `kubectl_get` | List resources with table format | | `kubectl_describe` | Detailed resource information with events | | `kubectl_logs` | Container logs for debugging | | `kubectl_patch_dryrun` | Validate patch operations before execution | | `kubectl_apply_dryrun` | Validate apply operations before execution | | `kubectl_delete_dryrun` | Validate delete operations before execution | | `kubectl_get_crd_schema` | Get CRD schema for custom resources | ### Controller (dot-ai-controller) The Kubernetes controller provides capability scanning: | Component | File | Description | |-----------|------|-------------| | Capability Scanner | `internal/controller/capability_scanner.go` | Discovers cluster resources and capabilities | | Embedding Service | `internal/controller/embedding_service.go` | Generates embeddings for semantic search | | Qdrant Client | `internal/controller/qdrant_client.go` | Stores capabilities in vector database | ### Web UI (dot-ai-ui) Provides visualization for operation analysis and execution: | Component | File | Description | |-----------|------|-------------| | Visualization Page | `src/pages/Visualization.tsx` | Main page for `/v/{sessionId}` | | MermaidRenderer | `src/components/renderers/MermaidRenderer.tsx` | Interactive flowcharts | | CardRenderer | `src/components/renderers/CardRenderer.tsx` | Current state and proposed changes | | CodeRenderer | `src/components/renderers/CodeRenderer.tsx` | Commands with syntax highlighting | | InsightsPanel | `src/components/InsightsPanel.tsx` | AI observations and risk assessment | ## Integration Points ```mermaid flowchart LR subgraph MCP["MCP Server"] Operate["operate tool"] AIProvider["AI Provider"] KubectlTools["Kubectl Tools"] SessionMgr["Session Manager"] VectorSvc["Vector Services"] end subgraph AI["AI Providers"] Anthropic["Claude API"] OpenAI["OpenAI API"] Google["Gemini API"] Others["xAI, Bedrock,
OpenRouter, etc."] end subgraph VectorDB["Vector Database"] Patterns["Patterns
Collection"] Policies["Policies
Collection"] Capabilities["Capabilities
Collection"] end subgraph K8s["Kubernetes"] API["API Server"] Controller["Capability
Scanner"] end subgraph Storage["Session Storage"] Files["File System
~/.dot-ai/sessions/opr-sessions/"] end subgraph UI["Web UI"] Viz["Visualization
Dashboard"] end AIProvider <-->|Tool Loop| KubectlTools AIProvider --> Anthropic AIProvider --> OpenAI AIProvider --> Google AIProvider --> Others VectorSvc --> Patterns VectorSvc --> Policies VectorSvc --> Capabilities KubectlTools -->|Investigation| API Operate -->|Execute Commands| API Controller -->|Scan & Embed| Capabilities SessionMgr --> Files Operate -.->|Session URL| Viz ``` ### MCP Server ↔ AI Provider - **Tool Loop**: AI iteratively calls kubectl tools (max 30 iterations) - **Investigation**: Gathers current cluster state to understand resources - **Dry-Run Validation**: Validates all commands before proposing - **Analysis**: Generates JSON response with changes, commands, and risk assessment ### MCP Server ↔ Vector Database - **Patterns**: Organizational patterns for operational best practices - **Policies**: Policy intents for validation and compliance - **Capabilities**: Cluster resource capabilities for intelligent recommendations - Capabilities are **mandatory**; patterns/policies are optional ### MCP Server ↔ Kubernetes API - **Read Operations**: `kubectl get`, `describe`, `logs` - **Validation**: `kubectl patch/apply/delete --dry-run=server` - **Execution**: Sequential command execution via `child_process.exec()` ### MCP Server ↔ Remediate Tool - **Post-Execution Validation**: Internally calls remediate with `validationIntent` - **Verification**: Confirms operations completed successfully - **Error Detection**: Identifies issues introduced by operations ### MCP Server ↔ Web UI - **Session Storage**: Operation data stored with session IDs - **Visualization API**: `/api/v1/visualize/{sessionId}` endpoint - **URL Generation**: `WEB_UI_BASE_URL/v/{sessionId}` ## Session Management Sessions persist workflow state across tool calls: ``` Session ID Format: opr-{timestamp}-{uuid8} Example: opr-1704067200000-a1b2c3d4 Session Data: ├── toolName: 'operate' ├── intent: "Update my-api to v2.0 with zero downtime" ├── context: │ ├── patterns: OrganizationalPattern[] │ ├── policies: PolicyIntent[] │ └── capabilities: ResourceCapability[] ├── proposedChanges: │ ├── create: ResourceChange[] │ ├── update: ResourceChange[] │ └── delete: ResourceChange[] ├── commands: ["kubectl set image...", "kubectl patch..."] ├── dryRunValidation: │ ├── status: 'success' | 'failed' │ └── details: string ├── patternsApplied: ["Zero-Downtime Rolling Update"] ├── capabilitiesUsed: ["metrics-server", "KEDA"] ├── policiesChecked: ["Production Update Policy"] ├── risks: { level: 'low', description: "..." } ├── validationIntent: "Verify deployment rollout complete" ├── status: 'analyzing' | 'analysis_complete' | 'executing' | 'executed_*' └── executionResults: [{command, success, output, error}] ``` ### Session States | State | Description | |-------|-------------| | `analyzing` | AI is gathering data and generating commands | | `analysis_complete` | Analysis done, awaiting user approval | | `executing` | Commands are being executed | | `executed_successfully` | All commands succeeded | | `executed_with_errors` | Some commands failed | | `failed` | Analysis or execution failed | ## Organizational Context Integration The operate tool integrates organizational knowledge via vector database search: ```mermaid flowchart TB subgraph Input["User Intent"] Intent["Update my-api to v2.0
with zero downtime"] end subgraph Search["Vector DB Search"] PatternSearch["Search Patterns
(limit: 5)"] PolicySearch["Search Policies
(limit: 5)"] CapSearch["Search Capabilities
(limit: 50)"] end subgraph Results["Search Results"] Patterns["Patterns Found:
- Zero-Downtime Rolling Update
- Blue-Green Deployment"] Policies["Policies Found:
- Production Update Policy
- Change Management"] Caps["Capabilities Found:
- metrics-server
- KEDA Operator
- Argo Rollouts"] end subgraph Prompt["AI Prompt"] Context["Embedded Context:
patterns + policies + capabilities"] end Intent --> PatternSearch & PolicySearch & CapSearch PatternSearch --> Patterns PolicySearch --> Policies CapSearch --> Caps Patterns & Policies & Caps --> Context ``` ### Context Priority 1. **Capabilities** (Mandatory): What the cluster can do 2. **Patterns** (Optional): Organizational best practices 3. **Policies** (Optional): Compliance and validation rules ## Output Formats The operate tool returns structured output at different stages: ### Analysis Response | Field | Description | |-------|-------------| | `status` | `awaiting_user_approval` | | `sessionId` | Session ID for continuation | | `visualizationUrl` | URL to view analysis in web UI | | `currentState` | Current cluster resource state | | `proposedChanges` | Create, update, delete operations | | `commands` | Pre-validated kubectl commands | | `dryRunValidation` | Dry-run validation results | | `patternsApplied` | Applied organizational patterns | | `capabilitiesUsed` | Used cluster capabilities | | `policiesChecked` | Checked policies | | `risks` | Risk assessment (level + description) | | `validationIntent` | Post-execution validation instructions | ### Execution Response | Field | Description | |-------|-------------| | `status` | `success` or `failed` | | `sessionId` | Session ID for reference | | `results` | Per-command execution results | | `validation` | Post-execution validation summary | | `message` | Human-readable summary | ## Error Handling The operation workflow includes robust error handling: 1. **No Capabilities Found**: Clear guidance to run capability scan first 2. **Session Not Found**: Guidance to start new operation 3. **Dry-Run Failures**: AI iterates to fix commands before proposing 4. **Command Execution Failures**: Continue-on-error, capture all results 5. **Validation Failures**: Report issues via remediate tool integration 6. **AI Service Errors**: Logged with request IDs for debugging 7. **Investigation Timeouts**: Max 30 iterations prevents infinite loops ## Configuration ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `AI_PROVIDER` | AI provider selection | `anthropic` | | `ANTHROPIC_API_KEY` | Anthropic API key | Required if using | | `OPENAI_API_KEY` | OpenAI API key | Required if using | | `QDRANT_URL` | Qdrant vector database URL | `http://localhost:6333` | | `QDRANT_API_KEY` | Qdrant API key | Optional | | `QDRANT_CAPABILITIES_COLLECTION` | Capabilities collection name | `capabilities` | | `KUBECONFIG` | Kubernetes config path | Auto-detected | | `DOT_AI_SESSION_DIR` | Session storage directory | `~/.dot-ai/sessions` | | `WEB_UI_BASE_URL` | Web UI base URL | Optional | | `DEBUG_DOT_AI` | Enable debug logging | `false` | ### Supported AI Providers | Provider | Models | Notes | |----------|--------|-------| | Anthropic | Claude Sonnet 4.5, Opus, Haiku | Default, 1M token context | | OpenAI | GPT-5.1-codex | | | Google | Gemini 3 Pro, Flash | | | xAI | Grok-4 | | | Amazon Bedrock | Various | Uses AWS credential chain | | OpenRouter | Multi-model | Proxy to multiple providers | | Custom | Ollama, vLLM, LocalAI | Via `baseURL` config | ## Workflow Example ``` User Intent: "Update my-api deployment in prod to v2.0 with zero downtime" 1. CONTEXT EMBEDDING └─ embedContext(intent) ├─ Search patterns → "Zero-Downtime Rolling Update" ├─ Search policies → "Production Update Requirements" └─ Search capabilities → "metrics-server", "KEDA Operator" 2. AI INVESTIGATION LOOP └─ AI Tool Loop (30 iterations max) ├─ kubectl_get deployment/my-api -n prod ├─ kubectl_describe deployment/my-api -n prod ├─ kubectl_patch_dryrun (test maxUnavailable: 0) └─ kubectl_set_image (test v2.0 image --dry-run=server) 3. ANALYSIS GENERATION └─ Session created: opr-1704067200000-a1b2c3d4 ├─ Status: analysis_complete ├─ Current: 3 replicas, my-api:v1.5, maxUnavailable: 1 ├─ Proposed: image v2.0, maxUnavailable: 0 ├─ Commands: set image + patch strategy ├─ Risk: LOW └─ Visualization URL: https://dot-ai-ui/v/opr-1704067200000-a1b2c3d4 4. USER APPROVAL └─ User reviews analysis in terminal or web UI └─ Calls: operate({ sessionId: 'opr-...', executeChoice: 1 }) 5. COMMAND EXECUTION └─ executeOperations() ├─ Load session (status: analysis_complete) ├─ Update status to executing ├─ Execute commands sequentially │ ├─ kubectl set image deployment/my-api my-api=my-api:v2.0 -n prod │ └─ kubectl patch deployment/my-api -n prod -p '{"spec":...}' ├─ Call remediate internally for validation └─ Update status to executed_successfully 6. RETURN RESULTS └─ Results: 2 commands succeeded ├─ Validation: "Rollout complete, all pods running v2.0" └─ Status: success ``` ## See Also - [MCP Operate Guide](//mcp/operate/) - [Remediate Architecture](./remediate.md) - [Recommendation Architecture](./recommendation.md) - [Controller Documentation](//controller/) - [Web UI Documentation](//ui/) # Query Feature Architecture This document provides a detailed architecture overview of the Query feature in the DevOps AI Toolkit. ## Overview The Query feature provides a natural language interface for Kubernetes cluster intelligence. Users can ask questions about cluster resources, capabilities, and status in plain English, with the AI autonomously deciding which tools to call to gather the necessary information. ## High-Level Architecture ```mermaid flowchart TB subgraph Users["User / AI Agent"] Agent["Claude Code, Cursor,
VS Code, etc."] end subgraph MCP["MCP Server (dot-ai)"] Query["query Tool"] AI["AI Provider"] Session["Session
Manager"] CapTools["Capability
Tools"] ResTools["Resource
Tools"] KubectlTools["Kubectl
Tools"] end subgraph External["External Services"] LLM["Claude, OpenAI,
Gemini, etc."] Qdrant["Qdrant
Vector DB"] Embeddings["Embedding
Service"] end subgraph K8s["Kubernetes Cluster"] API["Kubernetes API"] Controller["Controller
(dot-ai-controller)"] Resources["Cluster Resources
Pods, Deployments,
Services, etc."] CRDs["Custom Resource
Definitions"] end subgraph WebUI["Web UI (dot-ai-ui)"] Viz["Visualization Dashboard
- Mermaid Diagrams
- Tables & Cards
- Code Blocks"] end Agent <-->|MCP Protocol| Query Query --> AI Query --> Session AI --> LLM AI <-->|Tool Loop| CapTools AI <-->|Tool Loop| ResTools AI <-->|Tool Loop| KubectlTools CapTools --> Qdrant ResTools --> Qdrant KubectlTools --> API Qdrant --> Embeddings Controller -->|Sync Resources| Qdrant Controller -->|Watch| Resources Controller -->|Watch| CRDs Agent -.->|User opens
Visualization URL| WebUI ``` ## Query Workflow The query tool operates as an agentic loop where the AI autonomously decides which tools to call: ```mermaid flowchart TD subgraph Phase1["Phase 1: Input Processing"] Intent["User Intent
(natural language)"] Validate["Validate Input
(1-1000 chars)"] RequestId["Generate RequestId
for tracking"] Intent --> Validate --> RequestId end subgraph Phase2["Phase 2: AI Initialization"] LoadPrompt["Load System Prompt
(query-system.md)"] InitProvider["Initialize AI Provider
(from environment)"] BuildTools["Build Tool Definitions
- search_capabilities
- query_capabilities
- search_resources
- query_resources
- kubectl_*"] RequestId --> LoadPrompt --> InitProvider --> BuildTools end subgraph Phase3["Phase 3: Agentic Tool Loop"] ToolLoop["AI Tool Loop
(Vercel AI SDK)"] Decision{"AI
Decision"} SemanticSearch["Semantic Search
(Qdrant vectors)"] FilterQuery["Filter Query
(Qdrant filters)"] KubectlExec["Kubectl Execution
(live cluster)"] CollectResults["Collect Tool Results"] BuildTools --> ToolLoop --> Decision Decision -->|search_* tools| SemanticSearch --> CollectResults Decision -->|query_* tools| FilterQuery --> CollectResults Decision -->|kubectl_* tools| KubectlExec --> CollectResults CollectResults -->|Continue| ToolLoop end subgraph Phase4["Phase 4: Response Generation"] MaxIterations{"Max Iterations
Reached?"} FinalResponse["AI Final Response
(JSON format)"] ParseJSON["Parse Summary
from JSON"] Decision -->|Done| FinalResponse CollectResults --> MaxIterations MaxIterations -->|Yes| FinalResponse MaxIterations -->|No| ToolLoop FinalResponse --> ParseJSON end subgraph Phase5["Phase 5: Session & Output"] CreateSession["Create Session
(qry-{ts}-{uuid})"] StoreData["Store Session Data
- intent
- summary
- toolsUsed
- toolCallsExecuted"] GenURL{"WEB_UI_BASE_URL
Configured?"} VizURL["Generate Visualization URL
{baseUrl}/v/{sessionId}"] BuildOutput["Build QueryOutput
- success: true
- summary
- toolsUsed
- sessionId
- visualizationUrl"] ParseJSON --> CreateSession --> StoreData --> GenURL GenURL -->|Yes| VizURL --> BuildOutput GenURL -->|No| BuildOutput end ``` ## Component Details ### MCP Server (dot-ai) The MCP server hosts the query tool and orchestrates AI-driven investigation: | Component | File | Description | |-----------|------|-------------| | `query` tool | `src/tools/query.ts` | Entry point, orchestrates tool loop and session | | System Prompt | `prompts/query-system.md` | AI instructions for query behavior | | `GenericSessionManager` | `src/core/generic-session-manager.ts` | File-based session persistence | | `AIProvider` | `src/core/ai-provider.interface.ts` | AI abstraction with tool loop support | | `AIProviderFactory` | `src/core/ai-provider-factory.ts` | Multi-provider factory | | `capability-tools` | `src/core/capability-tools.ts` | Semantic search for capabilities | | `resource-tools` | `src/core/resource-tools.ts` | Semantic search for resources | | `kubectl-tools` | `src/core/kubectl-tools.ts` | Kubectl read-only tools | | `CapabilityVectorService` | `src/core/capability-vector-service.ts` | Capability embeddings storage | | `ResourceVectorService` | `src/core/resource-vector-service.ts` | Resource embeddings storage | | `EmbeddingService` | `src/core/embedding-service.ts` | Multi-provider embedding generation | | `visualization` | `src/core/visualization.ts` | URL generation for web UI | ### Query Tools Available to AI The AI can autonomously call these tools during investigation: | Tool | Type | Description | |------|------|-------------| | `search_capabilities` | Semantic | Vector similarity search for resource capabilities | | `query_capabilities` | Filter | Structured filter queries for capabilities | | `search_resources` | Semantic | Vector similarity search for cluster resources | | `query_resources` | Filter | Structured filter queries for resources | | `kubectl_api_resources` | Kubectl | List all available API resources | | `kubectl_get` | Kubectl | Get resources with current state | | `kubectl_describe` | Kubectl | Detailed resource information | | `kubectl_logs` | Kubectl | Container logs from pods | | `kubectl_events` | Kubectl | Kubernetes events for troubleshooting | | `kubectl_get_crd_schema` | Kubectl | OpenAPI v3 schema for CRDs | ### Controller (dot-ai-controller) The Kubernetes controller syncs cluster data to Qdrant for semantic search: | Component | File | Description | |-----------|------|-------------| | `ResourceSyncReconciler` | `internal/controller/resourcesync_controller.go` | Watches all resources, syncs to MCP | | `CapabilityScanReconciler` | `internal/controller/capabilityscan_controller.go` | Triggers capability scans on CRD changes | | `ResourceSyncConfig` CRD | `api/v1alpha1/resourcesyncconfig_types.go` | Configuration for resource sync | | `CapabilityScanConfig` CRD | `api/v1alpha1/capabilityscanconfig_types.go` | Configuration for capability scanning | | MCP Resource Client | `internal/controller/resourcesync_mcp.go` | HTTP client for `/api/v1/resources/sync` | | MCP Capability Client | `internal/controller/capabilityscan_mcp.go` | HTTP client for `/api/v1/tools/manageOrgData` | | Debounce Buffer | `internal/controller/resourcesync_debounce.go` | Batches changes before sync | ### Web UI (dot-ai-ui) Provides visualization for query results: | Component | File | Description | |-----------|------|-------------| | Visualization Page | `src/pages/Visualization.tsx` | Main page for `/v/{sessionId}` | | MermaidRenderer | `src/components/renderers/MermaidRenderer.tsx` | Interactive diagrams with zoom/pan | | CardRenderer | `src/components/renderers/CardRenderer.tsx` | Resource cards in grid layout | | TableRenderer | `src/components/renderers/TableRenderer.tsx` | Tabular data display | | CodeRenderer | `src/components/renderers/CodeRenderer.tsx` | Syntax-highlighted code/YAML | | InsightsPanel | `src/components/InsightsPanel.tsx` | AI observations display | | TabContainer | `src/components/TabContainer.tsx` | Multi-visualization tabs | | API Client | `src/api/client.ts` | Data fetching from MCP server | ## Integration Points ```mermaid flowchart LR subgraph MCP["MCP Server"] Query["query tool"] AIProvider["AI Provider"] CapTools["Capability Tools"] ResTools["Resource Tools"] KubectlTools["Kubectl Tools"] SessionMgr["Session Manager"] end subgraph Vector["Vector Database"] Qdrant["Qdrant"] CapColl["capabilities
collection"] ResColl["resources
collection"] end subgraph AI["AI Providers"] Anthropic["Claude API"] OpenAI["OpenAI API"] Google["Gemini API"] Others["xAI, Bedrock,
OpenRouter, etc."] end subgraph Embed["Embedding Providers"] OpenAIEmbed["OpenAI
text-embedding-3-small"] GoogleEmbed["Google
gemini-embedding-001"] BedrockEmbed["Bedrock
titan-embed-text-v2"] end subgraph K8s["Kubernetes"] API["API Server"] Controller["dot-ai-controller"] end subgraph Storage["Session Storage"] Files["File System
~/.dot-ai/sessions/qry-*"] end subgraph UI["Web UI"] Viz["Visualization
Dashboard"] end AIProvider <-->|Tool Loop| CapTools AIProvider <-->|Tool Loop| ResTools AIProvider <-->|Tool Loop| KubectlTools AIProvider --> Anthropic AIProvider --> OpenAI AIProvider --> Google AIProvider --> Others CapTools --> Qdrant ResTools --> Qdrant Qdrant --> CapColl Qdrant --> ResColl Qdrant --> OpenAIEmbed Qdrant --> GoogleEmbed Qdrant --> BedrockEmbed KubectlTools --> API Controller -->|POST /api/v1/resources/sync| MCP Controller -->|POST /api/v1/tools/manageOrgData| MCP Controller -->|Watch| K8s SessionMgr --> Files Query -.->|Session URL| Viz ``` ### MCP Server ↔ AI Provider - **Tool Loop**: AI iteratively calls tools (max 20 iterations by default) - **Autonomous Decision**: AI decides which tools to call based on user intent - **JSON Output**: AI returns structured JSON with summary ### MCP Server ↔ Qdrant - **Semantic Search**: Vector similarity using embeddings - **Filter Queries**: Structured queries by namespace, kind, labels, etc. - **Capability Data**: Resource kinds with capabilities, providers, abstractions - **Resource Data**: Cluster resources with labels, annotations, timestamps ### Controller ↔ MCP Server - **Resource Sync**: Controller watches all resources and syncs to MCP - **Capability Scanning**: Controller triggers scans when CRDs change - **Debounced Batching**: Changes batched every 10s to reduce API calls - **Periodic Resync**: Full resync every 60 minutes for consistency ### MCP Server ↔ Web UI - **Session Storage**: Query results stored with session IDs - **Visualization API**: `/api/v1/visualize/{sessionId}` endpoint - **URL Generation**: `WEB_UI_BASE_URL/v/{sessionId}` - **Cached Visualizations**: AI-generated visualizations cached in session ## Session Management Sessions persist query data for visualization: ``` Session ID Format: qry-{timestamp}-{uuid8} Example: qry-1767465086590-a1b2c3d4 Session Data: ├── toolName: 'query' ├── intent: "What databases are running in the cluster?" ├── summary: "Found 3 PostgreSQL clusters and 2 Redis instances..." ├── toolsUsed: ['search_capabilities', 'kubectl_get', ...] ├── iterations: 5 ├── toolCallsExecuted: │ ├── {tool: 'search_capabilities', input: {...}, output: {...}} │ ├── {tool: 'kubectl_get', input: {...}, output: {...}} │ └── ... ├── cachedVisualization: │ ├── title: "Database Resources" │ ├── visualizations: [...] │ ├── insights: [...] │ └── generatedAt: ISO timestamp └── timestamp: ISO date ``` ## Data Flow: Resource Sync ```mermaid flowchart LR subgraph K8s["Kubernetes Cluster"] Resources["Resources
(Pods, Deployments, etc.)"] CRDs["Custom Resources"] end subgraph Controller["dot-ai-controller"] Informers["Dynamic
Informers"] CRDWatcher["CRD
Watcher"] DebounceRes["Resource
Debounce Buffer"] DebounceCap["Capability
Debounce Buffer"] end subgraph MCP["MCP Server"] SyncAPI["POST /api/v1/
resources/sync"] ManageAPI["POST /api/v1/
tools/manageOrgData"] VectorSvc["Vector
Services"] end subgraph Qdrant["Qdrant"] ResColl["resources
collection"] CapColl["capabilities
collection"] end Resources -->|Watch| Informers CRDs -->|Watch| CRDWatcher Informers -->|Queue| DebounceRes CRDWatcher -->|Queue| DebounceCap DebounceRes -->|Batch every 10s| SyncAPI DebounceCap -->|Batch every 10s| ManageAPI SyncAPI --> VectorSvc ManageAPI --> VectorSvc VectorSvc -->|Upsert/Delete| ResColl VectorSvc -->|Scan/Delete| CapColl ``` ## Output Formats The query tool returns structured output: | Field | Description | |-------|-------------| | `success` | Boolean indicating query success | | `summary` | Human-readable summary of findings | | `toolsUsed` | List of tools called during investigation | | `iterations` | Number of AI tool loop iterations | | `sessionId` | Session ID for visualization | | `visualizationUrl` | URL to view results (if configured) | | `guidance` | Instructions for agent on presenting results | | `error` | Error object with code and message (if failed) | ## Error Handling The query workflow includes robust error handling: 1. **Input Validation**: Intent must be non-empty string (1-1000 chars) 2. **AI Provider Errors**: Logged with request IDs for debugging 3. **Vector DB Unavailable**: Falls back to keyword search or kubectl-only 4. **JSON Parsing Failures**: Original AI response logged for analysis 5. **Tool Execution Errors**: Captured in toolCallsExecuted, investigation continues 6. **Max Iterations**: Default 20 iterations prevents infinite loops ## Configuration ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `AI_PROVIDER` | AI provider selection | `anthropic` | | `ANTHROPIC_API_KEY` | Anthropic API key | Required if using | | `OPENAI_API_KEY` | OpenAI API key | Required if using | | `QDRANT_URL` | Qdrant vector DB endpoint | `http://localhost:6333` | | `QDRANT_API_KEY` | Qdrant authentication | Optional | | `QDRANT_CAPABILITIES_COLLECTION` | Capabilities collection name | `capabilities` | | `QDRANT_RESOURCES_COLLECTION` | Resources collection name | `resources` | | `CUSTOM_EMBEDDINGS_API_KEY` | Embedding service API key | Falls back to provider key | | `KUBECONFIG` | Kubernetes config path | Auto-detected | | `WEB_UI_BASE_URL` | Web UI base URL | Optional | | `DEBUG_DOT_AI` | Enable debug logging | `false` | ### Supported AI Providers | Provider | Models | Notes | |----------|--------|-------| | Anthropic | Claude Sonnet 4.5, Opus, Haiku | Default, 1M token context | | OpenAI | GPT-5.1-codex | | | Google | Gemini 3 Pro, Flash | | | xAI | Grok-4 | | | Amazon Bedrock | Various | Uses AWS credential chain | | OpenRouter | Multi-model | Proxy to multiple providers | | Custom | Ollama, vLLM, LocalAI | Via `baseURL` config | ### Supported Embedding Providers | Provider | Model | Dimensions | |----------|-------|------------| | OpenAI | text-embedding-3-small | 1536 | | Google | gemini-embedding-001 | 768 | | Amazon Bedrock | titan-embed-text-v2:0 | 1024 | ## See Also - [MCP Query Guide](//mcp/query/) - [Controller Documentation](//controller/) - [Web UI Documentation](//ui/) - [Vector Database Setup](//setup/qdrant/) # Recommendation Feature Architecture This document provides a detailed architecture overview of the Recommendation feature in the DevOps AI Toolkit. ## Overview The Recommendation feature provides AI-powered Kubernetes deployment recommendations. It analyzes user intent, discovers cluster capabilities, and generates deployment solutions with full manifest generation and deployment capabilities. ## High-Level Architecture ```mermaid flowchart TB subgraph Users["User / AI Agent"] Agent["Claude Code, Cursor,
VS Code, etc."] end subgraph MCP["MCP Server (dot-ai)"] Recommend["recommend Tool"] AI["AI Provider"] Vector["Vector DB
Client"] Discovery["Discovery
Engine"] end subgraph External["External Services"] LLM["Claude, OpenAI,
Ollama, etc."] Qdrant["Qdrant
(Semantic Search)"] end subgraph K8s["Kubernetes Cluster"] API["Kubernetes API"] Controller["Controller
(dot-ai-controller)"] Resources["Deployed Resources
Deployments, Services,
Ingress, HPA, PDB, etc."] end subgraph WebUI["Web UI (dot-ai-ui)"] Viz["Visualization Dashboard
- Solution Comparisons
- Resource Diagrams
- Generated Manifests"] end Agent <-->|MCP Protocol| Recommend Recommend --> AI Recommend --> Vector Recommend --> Discovery AI --> LLM Vector -->|Embeddings| LLM Vector --> Qdrant Discovery --> API Recommend --> API Controller --> Resources Controller -->|Sync with Embeddings| Qdrant Agent -.->|User opens
Visualization URL| WebUI ``` ## Recommendation Workflow Stages The recommendation tool operates as a unified multi-stage workflow: ```mermaid flowchart TD subgraph Stage1["Stage 1: recommend"] UserIntent["User Intent"] IntentCheck{"Intent < 100 chars?"} Refine["Return Refinement Guidance"] CapSearch["Capability Search
(Vector DB)"] AIRank["AI Ranking
(Claude)"] CapMatch{"Capability
Match?"} ResourceSol["Generate Resource-Based
Solutions"] HelmSearch["Search ArtifactHub
for Helm Charts"] Solutions["Solutions with solutionIds
+ visualization URL"] UserIntent --> IntentCheck IntentCheck -->|Yes| Refine IntentCheck -->|No| CapSearch CapSearch --> AIRank AIRank --> CapMatch CapMatch -->|Yes| ResourceSol CapMatch -->|No| HelmSearch ResourceSol --> Solutions HelmSearch --> Solutions end subgraph Stage2["Stage 2: chooseSolution"] SelectSol["solutionId"] LoadSession["Load Session"] GenQuestions["Generate Questions
(if Helm)"] ReturnQuestions["Required Questions"] SelectSol --> LoadSession --> GenQuestions --> ReturnQuestions end subgraph Stage3["Stage 3-6: answerQuestion"] Required["answerQuestion:required
(name, namespace, image, port)"] Basic["answerQuestion:basic
(replicas, resources, ingress)"] Advanced["answerQuestion:advanced
(probes, PDB, security)"] Open["answerQuestion:open
(free-form, AI enhancement)"] Ready["ready_for_manifest_generation"] Required --> Basic --> Advanced --> Open --> Ready end subgraph Stage4["Stage 7: generateManifests"] GenType{"Solution
Type?"} subgraph Capability["Capability-Based"] C1["1. Retrieve Schemas"] C2["2. AI Generation"] C3["3. YAML Validation"] C4["4. kubectl Dry-Run"] C5["5. Retry Loop (max 10)"] C6["6. Package Output"] C1 --> C2 --> C3 --> C4 --> C5 --> C6 end subgraph Helm["Helm-Based"] H1["1. Fetch Chart"] H2["2. AI Values Gen"] H3["3. Helm Dry-Run"] H4["4. Retry Loop"] H1 --> H2 --> H3 --> H4 end GenType -->|Capability| C1 GenType -->|Helm| H1 C6 --> Manifests H4 --> Manifests Manifests["Manifests + visualization URL"] end subgraph Stage5["Stage 8: deployManifests"] DeployType{"Solution
Type?"} CapDeploy["kubectl apply -k
--wait"] HelmDeploy["helm upgrade
--install --wait"] Status["Deployment Status
+ Next Steps"] DeployType -->|Capability| CapDeploy DeployType -->|Helm| HelmDeploy CapDeploy --> Status HelmDeploy --> Status end Solutions --> SelectSol ReturnQuestions --> Required Ready --> GenType Manifests --> DeployType ``` ## Component Details ### MCP Server (dot-ai) The MCP server is the core recommendation engine: | Component | File | Description | |-----------|------|-------------| | `recommend` tool | `src/tools/recommend.ts` | Entry point, routes to stages, generates solutions | | `chooseSolution` | `src/tools/choose-solution.ts` | Loads selected solution, returns questions | | `answerQuestion` | `src/tools/answer-question.ts` | Processes answers, manages stage progression | | `generateManifests` | `src/tools/generate-manifests.ts` | AI manifest generation with validation loop | | `deployManifests` | `src/tools/deploy-manifests.ts` | Deploys via kubectl or helm | | `ResourceRecommender` | `src/core/schema.ts` | AI-powered solution ranking and filtering | | `CapabilityVectorService` | `src/core/capability-vector-service.ts` | Semantic search for capabilities | | `PatternVectorService` | `src/core/pattern-vector-service.ts` | Organizational pattern matching | | `PolicyVectorService` | `src/core/policy-vector-service.ts` | Policy enforcement | | `GenericSessionManager` | `src/core/generic-session-manager.ts` | Session state management | | `ArtifactHubService` | `src/core/artifacthub.ts` | Helm chart discovery | ### Controller (dot-ai-controller) The Kubernetes controller manages deployed solutions: | CRD | Description | |-----|-------------| | `Solution` | Groups related resources, manages ownerReferences, aggregates health | | `ResourceSyncConfig` | Syncs resource metadata to MCP for semantic search | | `CapabilityScanConfig` | Scans cluster for resource capabilities | | `RemediationPolicy` | Event-driven remediation (separate feature) | ### Web UI (dot-ai-ui) Provides visualization for recommendation results: - **Visualization Page** (`/v/{sessionId}`) - Renders solution comparisons - **Mermaid Diagrams** - Architecture and flow diagrams - **Resource Cards** - Solution component details - **Code Blocks** - Generated manifests with syntax highlighting - **Tables** - Configuration summaries ## Integration Points ```mermaid flowchart LR subgraph MCP["MCP Server"] Recommend["recommend tool"] Schema["ResourceRecommender"] CapVec["CapabilityVectorService"] PatVec["PatternVectorService"] PolVec["PolicyVectorService"] Discovery["Discovery Engine"] ArtHub["ArtifactHubService"] end subgraph VectorDB["Qdrant"] Capabilities["Capabilities
Collection"] Patterns["Patterns
Collection"] Policies["Policies
Collection"] end subgraph AI["AI Provider"] Claude["Claude API"] OpenAI["OpenAI API"] end subgraph K8s["Kubernetes"] API["API Server"] Controller["dot-ai-controller"] end subgraph External["External"] ArtifactHub["ArtifactHub API"] end subgraph UI["Web UI"] Viz["Visualization
Dashboard"] end CapVec <-->|Semantic Search| Capabilities PatVec <-->|Pattern Match| Patterns PolVec <-->|Policy Lookup| Policies Schema -->|Solution Ranking| Claude Schema -->|Solution Ranking| OpenAI Discovery -->|kubectl explain| API Recommend -->|kubectl apply| API ArtHub -->|Chart Search| ArtifactHub Recommend -.->|Session URL| Viz Controller -->|Watch Resources| API ``` ### MCP Server ↔ Vector DB (Qdrant) - **Capability Storage**: Resource capabilities with semantic embeddings - **Pattern Storage**: Organizational patterns for solution enhancement - **Policy Storage**: Policy intents for configuration enforcement - **Semantic Search**: Natural language queries matched to stored data ### MCP Server ↔ Kubernetes API - **Resource Discovery**: `kubectl api-resources`, `kubectl explain` - **Schema Retrieval**: OpenAPI schemas for manifest generation - **Manifest Validation**: `kubectl apply --dry-run=server` - **Deployment**: `kubectl apply`, `helm upgrade --install` ### MCP Server ↔ AI Provider - **Solution Assembly**: Ranking and filtering discovered capabilities - **Question Generation**: Creating configuration questions from schemas - **Manifest Generation**: Generating YAML from solution + answers - **Helm Values**: Generating values.yaml for chart installations ### MCP Server ↔ Web UI - **Session Storage**: Solution data stored with session IDs - **Visualization API**: `/api/visualize/{sessionId}` endpoint - **URL Generation**: `WEB_UI_BASE_URL/v/{sessionId}` ### Controller ↔ MCP Server - **Resource Sync**: Controller syncs resource metadata to MCP - **Capability Scan**: Controller triggers capability discovery - **Solution CR**: MCP generates Solution CR for controller management ## Session Management Sessions persist workflow state across tool calls: ``` Session ID Format: sol-{timestamp}-{uuid8} Example: sol-1765409923079-fa3f055c Session Data: ├── toolName: 'recommend' ├── stage: 'recommend' | 'generateManifests' | ... ├── intent: "Deploy PostgreSQL database" ├── type: 'single' | 'combination' | 'helm' ├── score: 96 ├── description: "Multi-cloud PostgreSQL via DevOps Toolkit" ├── resources: [{kind, apiVersion, group, description}] ├── chart: {repository, chartName, version} (if Helm) ├── questions: {required, basic, advanced, open} ├── answers: {questionId: value} ├── appliedPatterns: ["DevOps Toolkit DB Pattern"] ├── generatedManifests: {type, files, helmCommand} └── timestamp: ISO date ``` ## Output Formats The recommendation tool supports three output formats for capability-based solutions: | Format | Description | Files Generated | |--------|-------------|-----------------| | `raw` | Plain YAML manifests | `manifests.yaml` | | `helm` | Helm chart structure | `Chart.yaml`, `values.yaml`, `templates/*.yaml` | | `kustomize` | Kustomize overlay | `kustomization.yaml`, `base/`, `overlays/` | ## Error Handling The recommendation workflow includes robust error handling: 1. **Intent Refinement**: Vague intents get guidance, not failure 2. **Validation Loops**: Up to 10 retries for manifest generation 3. **Capability Gaps**: Clear error when enhancement isn't possible 4. **Session Expiry**: Graceful handling of expired sessions 5. **AI Service Errors**: Fallback to original solution on enhancement failure ## See Also - [MCP Recommendation Guide](//mcp/recommend/) - [Capability Management Guide](//mcp/capability-management/) - [Pattern Management Guide](//mcp/pattern-management/) - [Controller Documentation](//controller/) - [Web UI Documentation](//ui/) # Remediate Feature Architecture This document provides a detailed architecture overview of the Remediate feature in the DevOps AI Toolkit. ## Overview The Remediate feature provides AI-powered Kubernetes issue analysis and remediation. It investigates problems using kubectl tools, identifies root causes with confidence scoring, and executes verified fixes with optional post-execution validation. ## High-Level Architecture ```mermaid flowchart TB subgraph Users["User / AI Agent"] Agent["Claude Code, Cursor,
VS Code, etc."] end subgraph MCP["MCP Server (dot-ai)"] Remediate["remediate Tool"] AI["AI Provider"] Session["Session
Manager"] Kubectl["Kubectl Tools"] end subgraph External["External Services"] LLM["Claude, OpenAI,
Gemini, etc."] end subgraph K8s["Kubernetes Cluster"] API["Kubernetes API"] Controller["Controller
(dot-ai-controller)"] Events["Kubernetes Events"] Resources["Cluster Resources
Pods, Deployments,
Services, etc."] end subgraph WebUI["Web UI (dot-ai-ui)"] Viz["Visualization Dashboard
- Investigation Flow
- Root Cause Analysis
- Remediation Commands"] end subgraph Notifications["Notifications"] Slack["Slack"] GChat["Google Chat"] end Agent <-->|MCP Protocol| Remediate Remediate --> AI Remediate --> Session Remediate --> Kubectl AI --> LLM AI <-->|Tool Loop| Kubectl Kubectl --> API Remediate -->|Execute Commands| API Controller -->|Watch| Events Controller -->|RemediationPolicy| Remediate Controller -.->|Webhook| Slack Controller -.->|Webhook| GChat Events --> Resources Agent -.->|User opens
Visualization URL| WebUI ``` ## Remediation Workflow The remediate tool operates as a multi-phase workflow with persistent session management: ```mermaid flowchart TD subgraph Phase1["Phase 1: Investigation"] Issue["Issue Description"] CreateSession["Create Session
(rem-{ts}-{uuid})"] Investigation["AI Investigation Loop
(max 30 iterations)"] KubectlTools["kubectl Tools:
get, describe, logs,
events, api-resources, patch"] Issue --> CreateSession --> Investigation Investigation <-->|Tool Calls| KubectlTools end subgraph Phase2["Phase 2: Analysis"] ParseResponse["Parse AI Response"] StatusCheck{"Issue
Status?"} AlreadyResolved["Return: Issue already
resolved/non-existent"] Analysis["Root Cause Analysis
+ Confidence Score
+ Contributing Factors"] Investigation --> ParseResponse --> StatusCheck StatusCheck -->|resolved| AlreadyResolved StatusCheck -->|non_existent| AlreadyResolved StatusCheck -->|active| Analysis end subgraph Phase3["Phase 3: Execution Decision"] ModeCheck{"Execution
Mode?"} subgraph Manual["Manual Mode (default)"] ReturnChoices["Return 2 Choices:
1. Execute via MCP
2. Execute via Agent"] WaitApproval["await_user_approval"] end subgraph Auto["Automatic Mode"] ThresholdCheck{"Confidence >= threshold
AND Risk <= maxRisk?"} AutoExecute["Execute Automatically"] Fallback["Return with
fallbackReason"] end Analysis --> ModeCheck ModeCheck -->|manual| ReturnChoices --> WaitApproval ModeCheck -->|automatic| ThresholdCheck ThresholdCheck -->|Yes| AutoExecute ThresholdCheck -->|No| Fallback end subgraph Phase4["Phase 4: Command Execution"] UserChoice["User Choice
(executeChoice=1 or 2)"] Choice1{"Choice?"} ExecuteMCP["Execute via MCP
(child_process.exec)"] ExecuteAgent["Return Commands
for Agent Execution"] LogResults["Log Results
(success/failure/output)"] WaitApproval --> UserChoice --> Choice1 Choice1 -->|1| ExecuteMCP --> LogResults Choice1 -->|2| ExecuteAgent AutoExecute --> ExecuteMCP end subgraph Phase5["Phase 5: Validation"] ValidationCheck{"All Commands
Succeeded?"} HasValidation{"Has validationIntent?"} RecursiveCall["Recursive Investigation
with validationIntent"] WaitReconcile["Wait 30s
(automatic mode)"] FinalStatus["Final Status:
resolved / still_active"] LogResults --> ValidationCheck ValidationCheck -->|Yes| HasValidation ValidationCheck -->|No| FinalStatus HasValidation -->|Yes| WaitReconcile --> RecursiveCall --> FinalStatus HasValidation -->|No| FinalStatus end ``` ## Component Details ### MCP Server (dot-ai) The MCP server is the core remediation engine: | Component | File | Description | |-----------|------|-------------| | `remediate` tool | `src/tools/remediate.ts` | Entry point, orchestrates investigation and execution | | System Prompt | `prompts/remediate-system.md` | AI instructions for investigation behavior | | `GenericSessionManager` | `src/core/generic-session-manager.ts` | File-based session persistence | | `AIProvider` | `src/core/ai-provider.interface.ts` | AI abstraction with tool loop support | | `AIProviderFactory` | `src/core/ai-provider-factory.ts` | Multi-provider factory (Anthropic, OpenAI, etc.) | | `kubectl-tools` | `src/core/kubectl-tools.ts` | Kubectl investigation tools | | `visualization` | `src/core/visualization.ts` | URL generation for web UI | ### Kubectl Investigation Tools Tools available during AI investigation: | Tool | Description | |------|-------------| | `kubectl_api_resources` | Discover available resources in cluster | | `kubectl_get` | List resources with table format (compact) | | `kubectl_describe` | Detailed resource information with events | | `kubectl_logs` | Container logs (supports `--previous` for crashes) | | `kubectl_events` | Cluster events for understanding state changes | | `kubectl_patch_dryrun` | Validate patches before actual execution | ### Controller (dot-ai-controller) The Kubernetes controller provides event-driven remediation: | Component | File | Description | |-----------|------|-------------| | `RemediationPolicy` CRD | `config/crd/bases/` | Custom resource for remediation rules | | Policy Controller | `internal/controller/remediationpolicy_controller.go` | Event matching and MCP dispatch | | Rate Limiter | `internal/controller/remediationpolicy_ratelimit.go` | Per-object cooldowns and rate limits | | MCP Client | `internal/controller/remediationpolicy_mcp.go` | HTTP client for remediate tool | | Cooldown State | ConfigMaps | Persistent cooldown state across restarts | ### Web UI (dot-ai-ui) Provides visualization for remediation results: | Component | File | Description | |-----------|------|-------------| | Visualization Page | `src/pages/Visualization.tsx` | Main page for `/v/{sessionId}` | | MermaidRenderer | `src/components/renderers/MermaidRenderer.tsx` | Interactive flowcharts (collapsible) | | CardRenderer | `src/components/renderers/CardRenderer.tsx` | Issue/solution cards | | CodeRenderer | `src/components/renderers/CodeRenderer.tsx` | Commands and logs with syntax highlighting | | InsightsPanel | `src/components/InsightsPanel.tsx` | AI observations display | | API Client | `src/api/client.ts` | Data fetching from MCP server | ## Integration Points ```mermaid flowchart LR subgraph MCP["MCP Server"] Remediate["remediate tool"] AIProvider["AI Provider"] KubectlTools["Kubectl Tools"] SessionMgr["Session Manager"] end subgraph AI["AI Providers"] Anthropic["Claude API"] OpenAI["OpenAI API"] Google["Gemini API"] Others["xAI, Bedrock,
OpenRouter, etc."] end subgraph K8s["Kubernetes"] API["API Server"] Controller["RemediationPolicy
Controller"] Events["Kubernetes Events"] end subgraph Storage["Session Storage"] Files["File System
tmp/sessions/*.json"] ConfigMaps["ConfigMaps
(cooldown state)"] end subgraph UI["Web UI"] Viz["Visualization
Dashboard"] end subgraph Notif["Notifications"] Slack["Slack"] GChat["Google Chat"] end AIProvider <-->|Tool Loop| KubectlTools AIProvider --> Anthropic AIProvider --> OpenAI AIProvider --> Google AIProvider --> Others KubectlTools -->|Investigation| API Remediate -->|Execute Commands| API Controller -->|Watch| Events Controller -->|HTTP POST| Remediate Controller -.->|Webhook| Slack Controller -.->|Webhook| GChat SessionMgr --> Files Controller --> ConfigMaps Remediate -.->|Session URL| Viz ``` ### MCP Server ↔ AI Provider - **Tool Loop**: AI iteratively calls kubectl tools (max 30 iterations) - **Investigation**: Gathers cluster data to understand the issue - **Analysis**: Parses JSON response with root cause, confidence, and remediation steps - **Validation**: Optional recursive investigation after command execution ### MCP Server ↔ Kubernetes API - **Read Operations**: `kubectl get`, `describe`, `logs`, `events` - **Validation**: `kubectl patch --dry-run=server` - **Execution**: `child_process.exec()` for remediation commands ### Controller ↔ MCP Server - **Event-Driven**: Controller watches Kubernetes events - **Policy Matching**: Events matched against RemediationPolicy selectors - **HTTP Dispatch**: POST to MCP `/api/v1/tools/remediate` - **Rate Limiting**: Per-object cooldowns prevent remediation storms ### MCP Server ↔ Web UI - **Session Storage**: Remediation data stored with session IDs - **Visualization API**: `/api/v1/visualize/{sessionId}` endpoint - **URL Generation**: `WEB_UI_BASE_URL/v/{sessionId}` ### Controller ↔ Notifications - **Slack Webhooks**: Controller sends remediation events to Slack channels - **Google Chat Webhooks**: Controller sends remediation events to Google Chat spaces - **Secret References**: Webhook URLs stored securely in Kubernetes Secrets - **Event Types**: Notifications sent on remediation start, success, and failure ## Session Management Sessions persist workflow state across tool calls: ``` Session ID Format: rem-{timestamp}-{uuid8} Example: rem-1767465086590-11029192 Session Data: ├── toolName: 'remediate' ├── issue: "Pod my-app is crashing with OOMKilled" ├── mode: 'manual' | 'automatic' ├── interaction_id: (for evaluation dataset) ├── status: 'investigating' | 'analysis_complete' | 'executed_*' | ... ├── finalAnalysis: │ ├── rootCause: "Container memory limit too low" │ ├── confidence: 0.92 │ ├── factors: ["High memory usage", "No HPA"] │ ├── remediation: │ │ ├── summary: "Increase memory limit" │ │ ├── actions: [{description, command, risk, rationale}] │ │ └── risk: 'low' | 'medium' | 'high' │ └── validationIntent: "Verify pod is running" ├── executionResults: [{command, success, output, error}] └── timestamp: ISO date ``` ### Session States | State | Description | |-------|-------------| | `investigating` | AI is gathering data via kubectl tools | | `analysis_complete` | Analysis done, awaiting user approval | | `failed` | Investigation failed (error) | | `executed_successfully` | All commands succeeded | | `executed_with_errors` | Some commands failed | | `cancelled` | User cancelled the remediation | ## RemediationPolicy CRD The controller uses a CRD for event-driven remediation: ```yaml apiVersion: dot-ai.devopstoolkit.live/v1alpha1 kind: RemediationPolicy metadata: name: oom-killer-policy spec: eventSelectors: - type: Warning reason: OOMKilled involvedObjectKind: Pod namespace: production message: ".*memory.*" # Regex support mode: automatic # Override per selector confidenceThreshold: 0.9 maxRiskLevel: low mcpEndpoint: https://mcp.example.com/api/v1/tools mcpAuthSecretRef: name: mcp-auth key: token mcpTool: remediate mode: manual # Default mode confidenceThreshold: 0.8 maxRiskLevel: low rateLimiting: eventsPerMinute: 10 cooldownMinutes: 5 notifications: slack: webhookSecretRef: name: slack-webhook key: url channel: "#alerts" googleChat: webhookSecretRef: name: gchat-webhook key: url status: totalEventsProcessed: 150 successfulRemediations: 142 failedRemediations: 8 rateLimitedEvents: 25 lastProcessedEvent: "2025-01-07T10:30:00Z" ``` ## Output Formats The remediate tool returns structured output: | Field | Description | |-------|-------------| | `status` | `success`, `failed`, or `awaiting_user_approval` | | `sessionId` | Session ID for continuation or visualization | | `investigation.iterations` | Number of AI tool loop iterations | | `investigation.dataGathered` | List of kubectl tools called | | `analysis.rootCause` | Identified root cause | | `analysis.confidence` | Confidence score (0-1) | | `analysis.factors` | Contributing factors | | `remediation.summary` | Human-readable summary | | `remediation.actions` | Commands with risk levels | | `remediation.risk` | Overall risk level | | `validationIntent` | Post-execution validation instructions | | `executionChoices` | Available execution options | | `results` | Execution results (if executed) | ## Error Handling The remediation workflow includes robust error handling: 1. **Session Not Found**: Clear guidance to start new investigation 2. **AI Service Errors**: Logged with request IDs for debugging 3. **JSON Parsing Failures**: Original AI response logged for analysis 4. **Command Execution Failures**: Individual command results tracked 5. **Validation Failures**: Recursive investigation continues despite errors 6. **Investigation Timeouts**: Max 30 iterations prevents infinite loops ## Configuration ### Environment Variables | Variable | Description | Default | |----------|-------------|---------| | `AI_PROVIDER` | AI provider selection | `anthropic` | | `ANTHROPIC_API_KEY` | Anthropic API key | Required if using | | `OPENAI_API_KEY` | OpenAI API key | Required if using | | `KUBECONFIG` | Kubernetes config path | Auto-detected | | `DOT_AI_SESSION_DIR` | Session storage directory | `./tmp/sessions` | | `WEB_UI_BASE_URL` | Web UI base URL | Optional | | `DEBUG_DOT_AI` | Enable debug logging | `false` | ### Supported AI Providers | Provider | Models | Notes | |----------|--------|-------| | Anthropic | Claude Sonnet 4.5, Opus, Haiku | Default, 1M token context | | OpenAI | GPT-5.1-codex | | | Google | Gemini 3 Pro, Flash | | | xAI | Grok-4 | | | Amazon Bedrock | Various | Uses AWS credential chain | | OpenRouter | Multi-model | Proxy to multiple providers | | Custom | Ollama, vLLM, LocalAI | Via `baseURL` config | ## See Also - [MCP Remediate Guide](//mcp/remediate/) - [Controller Documentation](//controller/) - [Web UI Documentation](//ui/) - [RemediationPolicy Reference](//controller/remediationpolicy/) ## AI Engine # DevOps AI Toolkit **AI-powered platform engineering and DevOps automation through intelligent Kubernetes operations and conversational workflows.** # REST API Gateway **Complete guide for accessing DevOps AI Toolkit functionality via standard HTTP REST endpoints.** ## Overview The REST API Gateway provides HTTP access to all DevOps AI Toolkit capabilities without requiring MCP protocol implementation. Perfect for: - **DevOps Engineers**: Integrate tools into automation scripts and CI/CD pipelines - **Platform Teams**: Add AI-powered Kubernetes assistance to existing HTTP-based infrastructure - **QA/Testing Teams**: Create comprehensive integration tests with simple HTTP calls - **Kubernetes Controller Developers**: Access AI tools via familiar REST patterns ### What it provides: - **Universal Tool Access**: All 9 tools available via `POST /api/v1/tools/{toolName}` endpoints - **Auto-Generated Documentation**: OpenAPI 3.0 specification with interactive documentation - **Zero Maintenance**: Automatically stays current when new tools are added - **Standard HTTP**: JSON request/response with proper status codes - **Tool Discovery**: Searchable catalog of available tools and capabilities ## Setup The REST API is automatically available when you deploy the DevOps AI Toolkit. **No special configuration is needed** - the same server provides MCP protocol, CLI, and REST API access simultaneously. **🎯 Follow the [Deployment Guide](../setup/deployment.md) to deploy the server.** The Kubernetes deployment automatically provides: - ✅ **REST API endpoints** on the configured ingress URL - ✅ **MCP protocol access** for AI development tools - ✅ **All dependencies** including Qdrant vector database - ✅ **Both protocols simultaneously** with no conflicts ## Quick Start ### 1. Discover Available Tools ```bash curl -s http://localhost:3456/api/v1/tools | jq '.data.tools[] | {name, description, category}' ``` **Response**: List of 9 available tools with descriptions: ```json [ { "name": "version", "description": "Get comprehensive system status including version information, Vector DB connection status, embedding service capabilities, Anthropic API connectivity, Kubernetes cluster connectivity, Kyverno policy engine status, and pattern management health check", "category": "System" }, { "name": "recommend", "description": "Deploy, create, setup, install, or run applications, infrastructure, and services on Kubernetes with AI recommendations", "category": "AI Tools" }, { "name": "remediate", "description": "AI-powered Kubernetes issue analysis that provides root cause identification and actionable remediation steps", "category": "Troubleshooting" } ] ``` ### 2. Get System Status ```bash curl -s -X POST http://localhost:3456/api/v1/tools/version \ -H "Content-Type: application/json" \ -d '{}' ``` **Response**: Comprehensive system status (truncated): ```json { "success": true, "data": { "result": { "status": "success", "system": { "version": { "version": "0.90.0", "nodeVersion": "v23.11.0", "platform": "darwin" }, "vectorDB": { "connected": true, "collections": { "patterns": {"exists": true, "documentsCount": 3}, "policies": {"exists": true, "documentsCount": 3}, "capabilities": {"exists": true, "documentsCount": 157} } }, "kubernetes": { "connected": true, "context": "kind-kind" } } } } } ``` ### 3. Access Interactive API Documentation ```bash # Get OpenAPI specification curl -s http://localhost:3456/api/v1/openapi | jq '.info' ``` **Response**: OpenAPI 3.0 specification with all tool schemas: ```json { "title": "DevOps AI Toolkit REST API", "description": "REST API gateway for DevOps AI Toolkit tools", "version": "1.0.0", "contact": { "name": "Viktor Farcic", "url": "https://devopstoolkit.live/" } } ``` ## API Reference ### Base URL and Versioning **Base URL**: `http://localhost:3456/api/v1` All endpoints use `/api/v1/` prefix for versioning. Future API changes will use new version paths (`/api/v2/`) maintaining backward compatibility. ### Core Endpoints #### Tool Discovery ```http GET /api/v1/tools ``` **Query Parameters**: - `category` - Filter by tool category (e.g., "AI Tools", "System", "Troubleshooting") - `tag` - Filter by a single tag (e.g., "kubernetes", "deployment", "analysis") - `search` - Search tool names and descriptions **Examples**: ```bash # Get all AI-powered tools curl "http://localhost:3456/api/v1/tools?category=AI%20Tools" # Find deployment-related tools curl "http://localhost:3456/api/v1/tools?tag=deployment" # Search for troubleshooting tools curl "http://localhost:3456/api/v1/tools?search=troubleshoot" ``` #### Tool Execution ```http POST /api/v1/tools/{toolName} Content-Type: application/json ``` **Request Body**: Tool-specific parameters (see OpenAPI spec for schemas) **Response**: Standardized JSON response with tool results #### OpenAPI Documentation ```http GET /api/v1/openapi ``` Returns complete OpenAPI 3.0 specification with: - All tool endpoints and schemas - Parameter descriptions and validation rules - Response formats and error codes - Interactive documentation support #### Health and Scan Readiness Two endpoints outside `/api/v1/` report process health and capability-scan readiness: ```http GET /healthz GET /readyz ``` - **`/healthz` (liveness)** — always returns `200 {"status":"ok"}` while the process is running. It is unauthenticated and backs both the chart's liveness and readiness probes. - **`/readyz` (scan readiness)** — verifies that Qdrant and embeddings can serve a new capability scan. It follows the server's normal bearer-authentication policy and is an on-demand diagnostic endpoint; the chart does not use it as a Kubernetes probe. It returns `200` when ready and `503` when a required dependency is unavailable. A scan is ready when the vector DB is reachable and embeddings actually serve. `embeddingsRequired` is therefore always `true`. Collection existence and `storedCount` are informational because a scan can initialize an absent collection. Results are cached for 30 seconds, and a dependency that does not answer within 10 seconds produces `503`. The `/readyz` body is a raw JSON object (not the standard envelope): ```json { "ready": true, "vectorDBHealthy": true, "collectionAccessible": true, "embeddingsRequired": true, "embeddingHealthy": true, "storedCount": 19, "checkedAt": "2026-08-20T02:25:21.644Z" } ``` ### Response Format All REST API responses follow this standard format: ```json { "success": boolean, "data": { "result": any, // Tool execution result "tool": string, // Tool name "executionTime": number // Execution time in milliseconds }, "error": { // Only present if success: false "code": string, "message": string, "details": any }, "meta": { "timestamp": string, // ISO 8601 timestamp "requestId": string, // Unique request identifier "version": string // API version } } ``` ### HTTP Status Codes - **200 OK**: Successful tool execution - **400 Bad Request**: Invalid request parameters or missing required fields - **404 Not Found**: Tool does not exist - **405 Method Not Allowed**: Invalid HTTP method (tools only accept POST) - **500 Internal Server Error**: Tool execution failure or server error ## Tool Discovery and Filtering Instead of listing all tools statically, use the API to discover available tools dynamically: ### Discover All Tools ```bash curl http://your-ingress-url/api/v1/tools | jq '.data.tools[] | {name, description, category}' ``` ### Filter by Category ```bash # Get all AI-powered tools curl "http://your-ingress-url/api/v1/tools?category=AI%20Tools" # Available categories: AI Tools, Deployment, Management, System, Troubleshooting, Documentation ``` ### Filter by Tags ```bash # Find deployment-related tools curl "http://your-ingress-url/api/v1/tools?tags=deployment" # Find troubleshooting tools curl "http://your-ingress-url/api/v1/tools?tags=troubleshooting" ``` ### Search Tools ```bash # Search for specific functionality curl "http://your-ingress-url/api/v1/tools?search=kubernetes" curl "http://your-ingress-url/api/v1/tools?search=database" ``` ### Get Complete Tool Documentation For detailed parameter schemas and usage instructions: ```bash # Get OpenAPI specification with all tool schemas curl http://your-ingress-url/api/v1/openapi | jq '.paths' ``` ## Prompts Endpoints Three REST endpoints expose the shared prompt library. Each one accepts an optional `repo` parameter that, when supplied, fetches prompts from that repository instead of the one configured via `DOT_AI_USER_PROMPTS_REPO`. When `repo` is omitted, behavior is identical to the env-var-configured setup. The override can additionally carry three **optional, additive** qualifiers — a subdirectory (`path`), a `branch`, and a per-request git credential (the `X-Dot-AI-Git-Token` header). They only apply to a request that already supplies `repo`, and each one defaults to today's behavior when omitted: `path` defaults to the repo root, `branch` defaults to `main`, and the credential defaults to the server's `DOT_AI_GIT_TOKEN`. > **Unchanged by default.** A request that supplies no `path`, no `branch`, and no `X-Dot-AI-Git-Token` header keeps the same clone target (repo root on `main`) and the same response shape, and still authenticates with `DOT_AI_GIT_TOKEN` — for the env-var-configured repo always, and for an `https://` `?repo=` override whose host is on the [repository host allowlist](#the-server-credential-and-the-host-allowlist) (default `github.com` and `www.github.com`). An `http://` override is cloned unauthenticated whatever host it names. All three qualifiers remain opt-in per request. A fourth endpoint — `POST /api/v1/prompts/sources` — works the other way around: instead of the server fetching a repo, the **caller uploads** a skill source it fetched itself, which the server then caches and renders through the same render path. It exists for sources the server cannot reach (SSO/device-gated VPNs, hardened clusters, and on-disk `--repo-dir` dev loops). It is purely additive — deployments and callers that never upload see zero change. See [Ingested (CLI-uploaded) skill sources](#ingested-cli-uploaded-skill-sources) below. See the [Shared Prompt Library](../tools/prompts.md) for the user-facing tool guide. ### Endpoint Summary | Endpoint | `repo` / `path` / `branch` / `source` placement | Credential | |----------|--------------------------------------|------------| | `POST /api/v1/prompts/refresh` | JSON body: `{ "repo": "", "path": "", "branch": "" }` | `X-Dot-AI-Git-Token` header | | `GET /api/v1/prompts` | Query string: `?repo=&path=&branch=` | `X-Dot-AI-Git-Token` header | | `POST /api/v1/prompts/:promptName` | Query string: `?repo=&path=&branch=` (clone) **or** `?source=` (render an ingested source) | `X-Dot-AI-Git-Token` header | | `POST /api/v1/prompts/sources` | JSON body manifest: `{ "source", "contentHash", "files" }` — no `repo`/`path`/`branch` | Never clones (n/a) | `path` and `branch` follow the same placement as `repo` on each endpoint (query string for `GET` and `POST /:promptName`, JSON body for `refresh`). The credential **always** travels as the `X-Dot-AI-Git-Token` request header — never in the query string or body. See [Per-request `path`, `branch`, and credential](#per-request-path-branch-and-credential) below. The `?source=` render signal and the `POST /api/v1/prompts/sources` upload endpoint are documented under [Ingested (CLI-uploaded) skill sources](#ingested-cli-uploaded-skill-sources). > **Every endpoint is bearer-gated.** All of these requests pass through the same bearer-auth check as every non-OpenAPI route (`Authorization: Bearer `). The local-development examples below target `localhost` and omit the header for brevity; a deployed server requires it. ### The `source` field Every response from these endpoints includes a `source` field identifying which repository the prompts came from. `source` values: | Request | `source` value | |---------|----------------| | `repo` parameter supplied | The supplied URL (credentials scrubbed) | | `repo` omitted, `DOT_AI_USER_PROMPTS_REPO` set | The env-var URL (credentials scrubbed) | | `repo` omitted, no env-var repo | `"built-in"` | **Credential scrubbing**: URLs with embedded credentials are scrubbed before being echoed back. `https://user:tok@host/repo` becomes `https://***:***@host/repo`. The transform is deterministic, so the same credentialed URL always produces the same `source` value across requests. > **`source` is keyed on the repo URL only.** Adding `path`, `branch`, or the `X-Dot-AI-Git-Token` header does **not** change the `source` value for a given repo — it still echoes the (scrubbed) override URL and stays stable per repo. This lets a caller use `source` as a stable skill-tagging key regardless of which subdirectory, branch, or credential it pulled with. ### Per-request `path`, `branch`, and credential These three qualifiers extend a `repo` override so a secondary source can live under a `skills/`-style subdirectory, on a non-default branch, and in a different authentication realm than the server's env-var repo. All three are optional and additive. | Qualifier | Placement | Default when omitted | |-----------|-----------|----------------------| | `path` | `?path=` (query) or `"path"` (JSON body) | Repo root | | `branch` | `?branch=` (query) or `"branch"` (JSON body) | `main` | | Credential | `X-Dot-AI-Git-Token` request header (never query/body) | Server's `DOT_AI_GIT_TOKEN` env credential, for an `https://` URL on an allowlisted host (see below) | **Credential precedence.** When the `X-Dot-AI-Git-Token` header is present, the server clones the override repo with that token **for that request only**; it takes precedence over `DOT_AI_GIT_TOKEN`. When the header is absent, the override clone falls back to the server's `DOT_AI_GIT_TOKEN`. The forwarded token is scoped to the host in `repo` (it is not forwarded across a cross-host redirect) and never appears in logs, error messages, the `source` field, or the cache key. > **The credential header is inert without `repo`.** A request that sends `X-Dot-AI-Git-Token` but no `?repo=` is unaffected by the header — it is read only to authenticate an override clone. The env-var-configured path never changes behavior based on the header. #### The server credential and the host allowlist `repo` is caller-supplied, so the server's own credential is not attached to any host a request names. Two conditions gate that fallback: the URL must be `https://`, and its host must appear in the `gitops.allowedRepoHosts` Helm value (default `["github.com", "www.github.com"]`). Both, not either: | Case | Credential used for the clone | |------|-------------------------------| | `X-Dot-AI-Git-Token` present | The forwarded token — for **any** host, on either scheme. Never gated by the allowlist (but the input-validation rejections below still apply). | | Header absent, `https://` `repo` on an allowlisted host | The server's `DOT_AI_GIT_TOKEN`, as before | | Header absent, `https://` `repo` on a host **not** allowlisted | **None** — the clone proceeds unauthenticated | | Header absent, `http://` `repo` — **any** host, allowlisted or not | **None** — the clone proceeds unauthenticated. `https:` is the only scheme the server's credential travels over, so an allowlist entry does not restore it here. | | No `repo` (env-var `DOT_AI_USER_PROMPTS_REPO`) | The server's `DOT_AI_GIT_TOKEN`. Never gated — the URL is the operator's, not a caller's. | Two kinds of `repo` never reach this decision at all — [input validation](#validation-rules-for-repo-path-and-branch) rejects them with `HTTP 400` before the loader is touched: a scheme other than `http` or `https`, and a host that is a non-public IP literal (loopback, private, link-local, and so on). Neither is a credential decision, and the `X-Dot-AI-Git-Token` header does not change either outcome. The override is **degraded, not rejected**: an unlisted host still returns `200` for a public repository. A **private** repository on an unlisted host fails with `502 PROMPTS_SOURCE_ERROR`, and the error message names the host and both remedies — send `X-Dot-AI-Git-Token`, or add the host to the Helm value. (An `http://` URL fails with the scheme explanation instead, which offers only the `https://` remedy: the header would put the caller's own token on a cleartext request.) A cache **refresh** that is gated does not fail at all; the cached copy keeps being served. See [GitOps Repository Host Allowlist](../setup/deployment.md#gitops-repository-host-allowlist) for the matching rules and [Shared Prompt Library](../tools/prompts.md#the-server-credential-and-the-host-allowlist) for the operator-facing walkthrough. The `path` and `branch` values map onto the same layout an env-var repo uses via `DOT_AI_USER_PROMPTS_PATH` / `DOT_AI_USER_PROMPTS_BRANCH` — they are simply supplied per request instead of via deployment configuration. ### `POST /api/v1/prompts/refresh` Force-refreshes the prompts cache. Use this when you've pushed new prompts to the repository and don't want to wait for `DOT_AI_USER_PROMPTS_CACHE_TTL` to expire. **Request body** (all fields optional): | Field | Type | Description | |-------|------|-------------| | `repo` | string | Override repository URL (HTTPS). When supplied, bypasses `DOT_AI_USER_PROMPTS_REPO` for this request. | | `path` | string | Subdirectory within the override repo to load prompts from. Omit for the repo root. Only applies when `repo` is supplied. | | `branch` | string | Branch of the override repo to clone. Omit for `main`. Only applies when `repo` is supplied. | The override credential travels as the `X-Dot-AI-Git-Token` header (see [above](#per-request-path-branch-and-credential)), never as a body field. **Built-in case** (no env-var repo, no override): ```bash curl -s -X POST http://localhost:3456/api/v1/prompts/refresh \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "success": true, "data": { "refreshed": true, "promptsLoaded": 11, "source": "built-in" }, "meta": { "timestamp": "2026-05-26T19:51:50.367Z", "requestId": "rest_1779825110366_3", "version": "v1" } } ``` **Per-request override case**: ```bash curl -s -X POST http://localhost:3456/api/v1/prompts/refresh \ -H "Content-Type: application/json" \ -d '{"repo":"https://github.com/vfarcic/dot-ai-user-prompts"}' ``` ```json { "success": true, "data": { "refreshed": true, "promptsLoaded": 11, "source": "https://github.com/vfarcic/dot-ai-user-prompts" }, "meta": { "timestamp": "2026-05-26T19:52:06.738Z", "requestId": "rest_1779825126117_6", "version": "v1" } } ``` **Credential-scrubbing case**: a credentialed URL is echoed back scrubbed. ```bash curl -s -X POST http://localhost:3456/api/v1/prompts/refresh \ -H "Content-Type: application/json" \ -d '{"repo":"https://user:secrettoken@example.com/repo"}' ``` ```json { "success": true, "data": { "refreshed": true, "promptsLoaded": 11, "source": "https://***:***@example.com/repo" } } ``` > **Illustrative example** (placeholder token, non-runnable as written). The response shape is shown for reference, not captured from a live run. Replace `` with a real token — it is scrubbed from logs and never appears in the response. **Subdirectory + branch + per-request credential**: load prompts from a `skills/` subdirectory on a non-default branch of a private repo, authenticating with a request-supplied token: ```bash curl -s -X POST http://localhost:3456/api/v1/prompts/refresh \ -H "Content-Type: application/json" \ -H "X-Dot-AI-Git-Token: " \ -d '{"repo":"https://forgejo.example.com/team/skills","path":"skills","branch":"team-skills"}' ``` The response has the same shape as the per-request override case above. `source` still echoes the override repo URL (`"https://forgejo.example.com/team/skills"`, credentials scrubbed) — unchanged by `path`, `branch`, or the header — while `promptsLoaded` reflects the prompts found under `skills/` on the `team-skills` branch. The token is used only to clone that host and never appears in the response. ### `GET /api/v1/prompts` Lists all available prompts (built-in plus user-defined). Returns the prompt names, descriptions, and any declared arguments. **Query parameters** (all optional): | Parameter | Description | |-----------|-------------| | `repo` | Override repository URL (HTTPS). When supplied, bypasses `DOT_AI_USER_PROMPTS_REPO` for this request. | | `path` | Subdirectory within the override repo to load prompts from. Omit for the repo root. Only applies when `repo` is supplied. | | `branch` | Branch of the override repo to clone. Omit for `main`. Only applies when `repo` is supplied. | The override credential travels as the `X-Dot-AI-Git-Token` header (see [above](#per-request-path-branch-and-credential)), never as a query parameter. **Built-in case**: ```bash curl -s http://localhost:3456/api/v1/prompts ``` Response (abbreviated — the full response carries every prompt's metadata): ```json { "success": true, "data": { "prompts": [ { "name": "generate-cicd", "description": "Generate intelligent CI/CD workflows..." }, { "name": "generate-dockerfile", "description": "Generate production-ready..." }, { "name": "prd-create", "description": "Create documentation-first PRDs..." } ], "source": "built-in" } } ``` **Per-request override case**: ```bash curl -s "http://localhost:3456/api/v1/prompts?repo=https://github.com/vfarcic/dot-ai-user-prompts" ``` The `source` field echoes the override URL (credentials scrubbed): ```json { "success": true, "data": { "prompts": [ /* … */ ], "source": "https://github.com/vfarcic/dot-ai-user-prompts" } } ``` > **Illustrative example** (placeholder token, non-runnable as written). The response shape is shown for reference, not captured from a live run. Replace `` with a real token — it is scrubbed from logs and never appears in the response. **Subdirectory + branch + per-request credential**: list the prompts a private cross-realm source publishes under `skills/` on a non-default branch: ```bash curl -s "http://localhost:3456/api/v1/prompts?repo=https://forgejo.example.com/team/skills&path=skills&branch=team-skills" \ -H "X-Dot-AI-Git-Token: " ``` The response shape is identical to the per-request override case above — the `prompts` array carries whatever lives under `skills/` on the `team-skills` branch, and `source` still echoes `"https://forgejo.example.com/team/skills"` (unaffected by `path`, `branch`, or the header). ### `POST /api/v1/prompts/:promptName` Returns the rendered content (`messages`, optional `files`) of a single prompt by name. **Query parameters** (all optional): | Parameter | Description | |-----------|-------------| | `repo` | Override repository URL (HTTPS). When supplied, bypasses `DOT_AI_USER_PROMPTS_REPO` for this request. | | `path` | Subdirectory within the override repo to load prompts from. Omit for the repo root. Only applies when `repo` is supplied. | | `branch` | Branch of the override repo to clone. Omit for `main`. Only applies when `repo` is supplied. | | `source` | Render an already-**ingested** (CLI-uploaded) source by its identifier instead of cloning. Takes precedence over `repo`; the server never clones a `?source=` identifier. See [Ingested (CLI-uploaded) skill sources](#ingested-cli-uploaded-skill-sources). | The override credential travels as the `X-Dot-AI-Git-Token` header (see [above](#per-request-path-branch-and-credential)), never as a query parameter or body field. **Request body** (all fields optional): | Field | Type | Description | |-------|------|-------------| | `arguments` | object | Argument values for prompts that declare `arguments` in their frontmatter (substituted via `{{argumentName}}` placeholders). | **Per-request override example**: ```bash curl -s -X POST "http://localhost:3456/api/v1/prompts/prd-create?repo=https://github.com/vfarcic/dot-ai-user-prompts" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "success": true, "data": { "messages": [ /* prompt content */ ], "source": "https://github.com/vfarcic/dot-ai-user-prompts" } } ``` > **Illustrative example** (placeholder token, non-runnable as written). The response shape is shown for reference, not captured from a live run. Replace `` with a real token — it is scrubbed from logs and never appears in the response. **Subdirectory + branch + per-request credential**: render a prompt that lives under `skills/` on a non-default branch of a private cross-realm repo: ```bash curl -s -X POST "http://localhost:3456/api/v1/prompts/deploy-app?repo=https://forgejo.example.com/team/skills&path=skills&branch=team-skills" \ -H "Content-Type: application/json" \ -H "X-Dot-AI-Git-Token: " \ -d '{}' ``` The response carries the rendered `messages` for the prompt resolved under `skills/` on the `team-skills` branch; `source` still echoes `"https://forgejo.example.com/team/skills"`, unchanged by `path`, `branch`, or the header. ## Ingested (CLI-uploaded) skill sources Every endpoint above has the server **fetch** the source: the caller names a repo and the server clones it. After the per-request credential override, that model reaches any source a server-side clone can authenticate to. Two classes of source remain unreachable — and in both, the laptop where the CLI runs **can** fetch while the server **cannot**: 1. **Sources the server cannot authenticate or route to**, even with a static token — VPNs gated by SSO / OIDC / device attestation, and managed/hardened clusters with no egress path the operator can open. 2. **On-disk directories** — work-in-progress skills on a developer's filesystem with no remote at all. For these, the CLI fetches the source locally and **uploads** it; the server caches it and renders it through the **same** render path — one renderer, server-side, so a CLI-fetched skill renders byte-identically to one cloned from `?repo=`. Upload via `POST /api/v1/prompts/sources`; render via `POST /api/v1/prompts/:promptName?source=`. > **Bearer-gated, like every endpoint here.** Both the upload and the `?source=` render pass through the same `Authorization: Bearer ` check as the rest of the API. ### Source-identifier key space An uploaded source is keyed by a **stable identifier** that the render request later names verbatim via `?source=`: | CLI flag | Identifier | Server behavior | |----------|------------|-----------------| | `--repo-fetch ` | the git URL verbatim (credentials scrubbed in echoes) | render from the **ingested** source; the server **never clones** this URL — the whole point is that it cannot reach it | | `--repo-dir --source-label