Skip to main content
The ChatCLI Operator goes beyond instance management. It implements a complete AIOps platform that autonomously detects anomalies, correlates signals, requests AI analysis, and executes remediation β€” all without external dependencies beyond the LLM provider. The platform supports Deployments, StatefulSets, DaemonSets, Jobs, and CronJobs, integrates with Helm, ArgoCD, and Flux for GitOps-aware remediation, analyzes application logs with stack trace extraction (Java, Go, Python, Node.js), correlates Prometheus metrics with incidents, and allows linking source code repositories for code-aware diagnostics.

API Group and CRDs

The operator uses the API group platform.chatcli.io/v1alpha1 with 17 Custom Resource Definitions:
For detailed documentation on each v2 CRD (NotificationPolicy, EscalationPolicy, SLO, SLA, ApprovalPolicy, ApprovalRequest, ClusterRegistration, AuditEvent, ChaosExperiment), see the AIOps Platform sub-pages.

Operator Installation

A single command installs everything: 17 CRDs + RBAC + Deployment + Service + Dashboard.
The operator chart (chatcli-operator) is separate from the server chart (chatcli). The operator manages the controllers and AIOps dashboard. The server is deployed via Instance CR or the chatcli chart with watcher enabled.

AIOps Platform Architecture

Autonomous Pipeline

Issue State Machine

Create Secret with API Keys

Before creating an Instance, you need a Secret with the LLM provider API keys. The Instance references this Secret via apiKeys.name β€” without it, the server cannot call the AI.
The Secret must exist in the same namespace as the Instance CR. The Secret name must match the apiKeys.name field in the Instance spec. Without this Secret, the server starts but cannot execute AI analysis or agentic remediation.

CRD: Instance

The Instance manages ChatCLI server instances in the cluster.

Complete Specification

Spec Fields

Root

AIOpsSpec

Configures the automatic remediation pipeline. All fields are optional with sensible defaults. AI auto-generated runbooks inherit maxRemediationAttempts from this configuration.
In agentic mode, the postmortem includes the full AI reasoning for each step β€” which action was chosen, why, and the observed result. This ensures complete audit trail of autonomous AI decisions.

FallbackSpec

Configures automatic failover between LLM providers. When the primary provider fails (rate limit, timeout, server error), the system automatically tries the next provider in the chain.

FallbackProviderEntry

The primary provider (spec.provider) is always tried first. Providers in fallback.providers are tried in order when the primary fails. The Secret in apiKeys must contain API keys for all providers in the chain.

WatcherSpec

WatchTargetSpec

Use name + kind to monitor any Kubernetes workload type. When kind is omitted, it defaults to Deployment. The legacy deployment field still works as alias for name. Examples:
The AIOps pipeline will automatically use resource-specific remediation actions (e.g., ScaleStatefulSet, RestartDaemonSet, SuspendCronJob) based on the detected resource kind.

Resources Created by Instance

gRPC Load Balancing

gRPC uses persistent HTTP/2 connections that pin to a single pod via kube-proxy, leaving extra replicas idle.
  • 1 replica (default): Standard ClusterIP Service
  • Multiple replicas: Headless Service (ClusterIP: None) is created automatically, enabling client-side round-robin via gRPC dns:/// resolver
  • Keepalive: WatcherBridge pings every 30s (5s timeout) to detect inactive pods quickly. The server accepts pings with a minimum interval of 20s (EnforcementPolicy.MinTime)
  • Transition: When scaling from 1 to 2+ replicas (or back), the operator deletes and recreates the Service automatically (ClusterIP is immutable in Kubernetes)

Automatic RBAC

  • Same namespace (all targets in the same namespace as the Instance): Creates per-Instance Role + RoleBinding
  • Cross-namespace (targets in a different namespace than the Instance, or in multiple namespaces): Creates only a per-Instance ClusterRoleBinding pointing at the shared chatcli-watcher ClusterRole (pre-provisioned by the Helm chart / kustomize overlay)
  • On CR deletion, the finalizer removes the ClusterRoleBinding; the shared ClusterRole stays (owned by the release)
As of v1.172.0, the operator no longer creates ClusterRole resources at runtime (H5 hardening). Shared ClusterRoles β€” chatcli-watcher for the watcher and chatcli-role-{viewer,operator,admin,superadmin} for platform roles β€” are installed by the operator Helm chart. The operator’s ServiceAccount carries the bind verb restricted to those exact names via resourceNames, preventing privilege escalation even if the operator is compromised.
Upgrading from v1.105.0: clusters with pre-existing multi-namespace Instances had a ClusterRoleBinding pointing to a per-Instance ClusterRole (legacy shape). Because roleRef is immutable in Kubernetes, a direct helm upgrade used to freeze the reconcile with cannot change roleRef. As of v1.172.0, the operator detects the divergent roleRef at the top of reconcileClusterRBAC, deletes the stale binding, and recreates it pointing at chatcli-watcher β€” transparent migration, no manual intervention.

Server Image and Auto-Resolution

The server image tag (spec.image.tag) follows a three-step priority:
  1. Explicit pin in spec.image.tag β€” honored verbatim (GitOps-friendly).
  2. Omitted β€” the operator resolves it from the CHATCLI_OPERATOR_APP_VERSION env var, which the Helm chart injects automatically from .Chart.AppVersion. Effect: helm upgrade chatcli-operator rolls the server of every Instance that opted into auto-resolution, with no per-Instance patch.
  3. Fallback β€” latest when neither is present (e.g., make deploy without Helm).
For environments that want immutable versioning, keep spec.image.tag pinned and manage upgrades manually. For environments that want β€œhelm upgrade = full upgrade,” omit the tag.

Auto-Rollout on Configuration Changes

The operator monitors changes in ConfigMaps and Secrets referenced by the Instance and triggers rolling updates automatically via hash annotations on the PodTemplate:
Adding/removing targets in watcher.targets and applying the Instance causes automatic rollout. Creating or updating the API keys Secret and renewing TLS certificates also trigger rollout automatically.

Secret and ConfigMap Observation

The operator watches (Watches) Secrets in the Instance namespace. When a Secret referenced in apiKeys.name or server.tls.secretName is created or updated, the reconciler is triggered automatically β€” even if the Secret did not exist when the Instance was created.
  • ConfigMap and Secret envFrom: Marked as optional: true, allowing the Instance to be created before the Secret/ConfigMap
  • Flexible deploy order: Namespace -> Instance -> Secret/ConfigMap (any order after the namespace)

AIOps Platform CRDs

Anomaly

Represents a raw signal detected by the WatcherBridge.

Anomaly Spec Fields

Signals Detected (21 types)

Watcher signals: Additional signals (via Prometheus, webhooks, or internal detection):

Node Monitoring

The watcher automatically monitors the health of nodes where target pods are running. On each collection cycle, it:
  1. Identifies nodes via label selector from the target’s pods
  2. Collects all 5 official Kubernetes conditions: Ready, DiskPressure, MemoryPressure, PIDPressure, NetworkUnavailable
  3. Collects node CPU/memory metrics (via metrics server)
  4. Counts active pods vs node pod capacity
  5. Checks if the node is cordoned (unschedulable)
Node information is included in the AI analysis context, enabling root cause correlation with infrastructure problems (e.g., β€œOOMKill caused by MemoryPressure on node X”).

Issue

Correlated incident that groups anomalies and manages the remediation lifecycle.

Issue States

AIInsight

AI-generated root cause analysis with suggested actions for automatic remediation.

AIInsight Status Fields

SuggestedAction

RemediationPlan

Concrete remediation plan automatically generated from a Runbook or AI actions.

Automatic Rollback and State Protection

The operator implements an automatic rollback system that ensures unsuccessful remediations do not leave the cluster in a worse state than before. Before executing any action, the complete resource state is captured in a structured restorable snapshot.
1

Pre-Remediation Snapshot

Before the first action, the RollbackEngine captures a structured ResourceSnapshot with: replicas, container images, CPU/memory requests and limits, HPA state (min/max replicas), and node state (schedulable/unschedulable). Works for Deployments, StatefulSets, DaemonSets, Nodes, and HPAs.
2

Per-Action Checkpoint

In plans with multiple actions, an ActionCheckpoint is captured before each individual action. This makes it possible to know exactly which action modified what and at which point the plan failed.
3

Automatic Rollback on Action Failure

If any action fails during execution, the operator automatically restores the resource to the PreflightSnapshot state. Replicas, images, resource requests/limits, and HPA state are reverted. The plan transitions to RolledBack state (not Failed).
4

Rollback on Verification Timeout

If all actions execute successfully but the resource does not become healthy within 90 seconds (verification timeout), the operator also performs automatic rollback to the pre-remediation state.
5

Post-Failure Health Check

After the rollback, the operator verifies whether the resource returned to a healthy state (PostFailureHealthy). This information is recorded in the plan status for auditing and retry decisions.
What is captured per resource type: Example of a RemediationPlan with rollback executed:
Automatic rollback restores the state prior to remediation, it does not fix the original issue. After the rollback, the IssueReconciler evaluates whether there are remaining attempts and triggers re-analysis with failure context β€” the AI receives what failed and suggests a different strategy.
Complete flow on failure: Status fields added to RemediationPlan:

Action Types (54 types)

Workload: GitOps: Autoscaling: Infrastructure: Storage: Security: Networking: Advanced:

ExecDiagnostic Allowlist

ExecDiagnostic does an exact-string match against a read-only command allowlist. Any variation (different flags, alternate host, etc.) is rejected with command "..." not in approved diagnostic commands whitelist. Default approved commands (~90): Extend via the CHATCLI_ALLOWED_DIAGNOSTIC_COMMANDS env var (comma-separated, read once at startup):
Each entry is matched exactly. nslookup <other-host> will not work β€” it is rejected. If you need a specific host, add the full string to the env var.
The AI is given this allowlist in the remediation prompt (server/handler_analysis.go) and is instructed to pick the right command per symptom: memory.events for OOM, cpu.stat for CPU throttling, getent/dig for DNS, pprof for stuck Go apps, nc -zv for external dependency reachability.
StatefulSet: DaemonSet: Job: CronJob:

RemediationPlan Examples with New Actions

Runbook (Manual or Auto-generated)

Operational procedures. Manual Runbooks have priority over everything. When there is no manual Runbook, the AI automatically generates a reusable Runbook CR from the suggested actions.

RemediationPlan (Agentic Mode)

When there is no manual Runbook or AI-suggested actions, the operator creates an agentic plan. The AI acts as an agent with Kubernetes skills in an observe-decide-act loop:
Safety Guards: Maximum of 10 steps (configurable via agenticMaxSteps), timeout of 10 minutes. If an action fails, the observation reports β€œFAILED: error” and the loop continues β€” the AI receives the feedback and adapts.
On agentic resolution: The operator automatically generates:
  1. PostMortem CR with timeline, root cause, impact, lessons learned
  2. Reusable Runbook CR with successful steps (label source=agentic)

PostMortem (Auto-generated)

Incident report automatically generated after any remediation resolution (standard or agentic). Contains the complete incident history: detection, analysis, executed actions, resolution, plus metrics, git correlation, cascade chain, recurring incident trending, and developer feedback field.

PostMortem Status Fields

Runbook Matching (Tiered)

Remediation Priority

SourceRepository (Code-Aware Diagnostics)

Links a Kubernetes workload to its source code repository. When configured, the AI receives code context during incident analysis: recent commits correlated with the timestamp, code snippets referenced in stack traces, and configuration files (Dockerfile, values.yaml).
Input validation (hardening): spec.url only accepts the https://, ssh:// or git@host:path forms, and spec.branch is restricted to [A-Za-z0-9._/-] with no leading - β€” closing the git argument-injection vector (e.g. --upload-pack). Reads of code referenced by stack traces are confined to the repository clone via os.Root (no traversal, no symlink escape). Out-of-pattern URLs or branches fail the sync with an explicit status error.
What the operator does with SourceRepository:
  1. Shallow clone of the repository (depth 50) and periodic sync
  2. Indexes detected languages, entrypoints (main.go, app.py, etc.), config files
  3. Temporal correlation: finds commits within 30 min before the incident
  4. Suspect commit: identifies the most likely commit to have caused the problem
  5. Code extraction: when stack traces reference files, extracts the relevant snippets
  6. Feed to AI: all context is included in the analysis prompt
The repository is cloned locally on the operator pod. For private repos, create a Secret with the key corresponding to the chosen authType and reference it in secretRef. The operator supports HTTPS repos (token/basic) and SSH (ssh-key).

Correlation Engine

The correlation engine groups anomalies into issues using:

Risk Scoring

Each signal type has a weight: The risk score is the sum of correlated anomaly weights (maximum 100).

Severity Classification

Grouping

  • Anomalies on the same resource (deployment + namespace) within the same time window are grouped into the same Issue
  • Incident ID is deterministic: hash of resource + signal type (prevents duplicates)

WatcherBridge

The WatcherBridge is the component that connects the ChatCLI server to the operator:
  • Polling: Queries GetAlerts from the server every 30 seconds
  • Discovery: Locates the server via Instance CRs (first Instance with a ready gRPC endpoint)
  • Dedup: SHA256 hash of type+deployment+namespace (no temporal component β€” a continuous problem generates only one Anomaly). 2-hour TTL
  • Dedup invalidation: When an Issue reaches a terminal state (Resolved/Escalated), dedup entries for the resource are removed, allowing immediate recurrence detection
  • Pruning: Removes expired hashes automatically (> 2h)
  • Creation: Converts alerts to Anomaly CRs with valid K8s names

Usage Examples

Status and Monitoring

Development

Security

The Operator implements multiple security layers by default, following the fail-closed principle (deny by default):

REST API Authentication

The REST API operates in fail-closed mode by default β€” there is no dev mode without authentication. Every request must include a valid X-API-Key header with a mapped role (viewer/operator/admin). API keys are loaded with the following priority order and hot-reloaded every 30 seconds:
  1. Secret chatcli-operator-secrets (priority) β€” api-keys field containing a YAML list of {key, role, description} entries
  2. ConfigMap chatcli-operator-config (fallback) β€” same api-keys field
  3. Reject the request (or accept in dev-mode if CHATCLI_OPERATOR_DEV_MODE=true)
Two distinct Secrets in this project β€” do not confuse it with the LLM provider keys consumed by the chatcli server (chatcli-api-keys, referenced via Instance.spec.apiKeys.name). See the comparison table in Security β€” Operator Authentication.The chatcli-operator-secrets Secret must live in the same namespace as the operator pod (the controller resolves it via the POD_NAMESPACE env var / ServiceAccount namespace file, falling back to chatcli-system). If you ran helm install --namespace <X>, create the Secret in <X>.
Changes to API keys β€” in either the Secret or the ConfigMap β€” are picked up automatically every 30s. No operator restart is needed.

Resource Type Allowlist

The Operator classifies Kubernetes resource types into two categories:
Pods, Deployments, StatefulSets, DaemonSets, Services, ConfigMaps, Ingresses, Jobs, CronJobs, ReplicaSets, Endpoints, PersistentVolumeClaims, HorizontalPodAutoscalers, NetworkPolicies, ServiceAccounts, Namespaces, Events.

Log Scrubbing

Before sending application logs to the LLM for analysis, the Operator removes 18 sensitive patterns, including:
  • JWT/Bearer tokens, API keys, passwords
  • Email addresses, internal IPs, URLs with credentials
  • Credit card numbers, SSNs, PEM certificates

TLS and RBAC

  • TLS 1.3 required on all ChatCLI server connections
  • ClusterRoles with least privilege (read-only by default)
  • NetworkPolicy configurable to restrict network traffic to the Operator namespace
  • H5 hardening β€” no runtime RBAC escalation: the operator never creates or mutates ClusterRole/ClusterRoleBinding at runtime. Shared ClusterRoles (chatcli-watcher, chatcli-role-*) are pre-provisioned by the Helm chart, and the operator’s SA holds the bind verb restricted to those exact names via resourceNames. A compromised operator cannot reference a more-privileged ClusterRole from a new ClusterRoleBinding.

Audit

  • AuditEvent CRD for immutable audit trail (append-only)
  • Structured logs with Request ID for correlation
  • Integration with CHATCLI_AUDIT_LOG_PATH via extraEnv
In strict mode, agent security blocks any cluster write operations not on the allowlist. This is recommended for production environments.

Next Steps

AIOps Platform

Deep-dive into the AIOps architecture

K8s Watcher

Collection and budget details

Server Mode

GetAlerts and AnalyzeIssue RPCs

K8s Monitoring

Recipe: K8s Monitoring with AI