{
  "markdown": "# Kubently\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n[![Python](https://img.shields.io/badge/Python-3.13%2B-blue.svg)](https://www.python.org/)\n[![Kubernetes](https://img.shields.io/badge/Kubernetes-1.28%2B-blue.svg)](https://kubernetes.io/)\n[![A2A Protocol](https://img.shields.io/badge/A2A-Protocol-green.svg)](https://a2a-protocol.org/)\n[![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/)\n[![Helm](https://img.shields.io/badge/Helm-Ready-blue.svg)](https://helm.sh/)\n[![Security Policy](https://img.shields.io/badge/Security-Policy-yellow.svg)](SECURITY.md)\n[![Contributing](https://img.shields.io/badge/Contributing-Welcome-brightgreen.svg)](CONTRIBUTING.md)\n\nKubently - Troubleshooting Kubernetes Agentically\n\n## Overview\n\nKubently (*Kubernetes + Agentically*) is a **free, self-hosted, vendor-neutral multi-cluster Kubernetes troubleshooter**. Ask one question, get AI-diagnosed answers from every cluster in your fleet in parallel — including clusters you can't reach directly: executors dial **outbound** to the central API, so there's no inbound ingress, no shared kubeconfig, and no per-cluster credentials to distribute.\n\nAgents collaborate over the [A2A (Agent-to-Agent) protocol](https://a2a-protocol.org/latest/), and any MCP client (Claude Code, Cursor, Claude Desktop) can use Kubently as a tool out of the box.\n\n## Key Features\n\n- **Multi-Cluster Fleet Troubleshooting**: One question fans out across all registered clusters in parallel\n- **Outbound-Dial Executors**: Reach clusters behind firewalls/NAT — no inbound ingress, no shared kubeconfig\n- **Natural Language Interface**: Conversational Kubernetes troubleshooting and debugging\n- **Comprehensive Analysis**: Automated issue detection, root cause analysis, and solution recommendations\n- **Multi-LLM Support**: Compatible with Google Gemini, OpenAI, Anthropic, and other providers\n- **A2A Protocol**: Industry-standard agent-to-agent communication for complex workflows\n- **MCP Server**: Optional [Model Context Protocol](docs/MCP.md) endpoint so MCP clients (Claude Desktop, Cursor, custom agents) get direct tool access\n- **Security-First**: API key authentication, OAuth/OIDC support, and TLS with cert-manager\n- **Persistent Sessions**: Redis-backed conversation history and context management\n- **Extensive Tool Suite**: kubectl integration, log analysis, resource inspection, and more\n\n## Quick Start\n\n### For Users: Get Started in 5 Minutes\n\nPoint `kubectl` at any cluster (kind, minikube, or real) and run:\n\n```bash\nnpm install -g @kubently/cli\nkubently install\n```\n\nThat's it. The CLI installs Kubently via Helm, wires up secrets and the\nexecutor, port-forwards the API, and drops you into a debug chat:\n\n```\nkubently> why is my nginx pod crashlooping?\n```\n\nYou'll need an LLM API key (Anthropic, OpenAI, or Google) — the installer\nprompts for it, or reads `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` /\n`GOOGLE_API_KEY` from your environment. Use `--provider` to pick the LLM,\n`--chart ./deployment/helm/kubently` to install from a local checkout, and\n`kubently install --help` for everything else.\n\n### Use from Claude Code / Cursor (MCP)\n\nAlready ran `kubently install`? Add Kubently to Claude Code:\n\n```bash\nclaude mcp add kubently -- kubently mcp\n```\n\nOr connect directly over HTTP (no bridge process):\n\n```bash\nclaude mcp add --transport http kubently http://localhost:8080/mcp/ \\\n  --header \"X-API-Key: <your-api-key>\"\n```\n\nThen ask Claude things like *\"use kubently to figure out why payments pods are\ncrashlooping\"*. Any MCP client works — see [docs/MCP.md](docs/MCP.md) for\nCursor and generic configuration.\n\n### Proactive diagnosis (Alertmanager → Slack)\n\nSet `api.env.SLACK_WEBHOOK_URL` to a Slack incoming-webhook URL and point\nAlertmanager at Kubently:\n\n```yaml\nreceivers:\n  - name: kubently\n    webhook_configs:\n      - url: https://<your-kubently-host>/webhooks/alertmanager\n        http_config:\n          http_headers:            # Alertmanager >= 0.28\n            X-API-Key:\n              secrets: [\"<your-api-key>\"]\n```\n\nEach firing alert is diagnosed by the agent and the result is posted to Slack —\nthe bot often explains the root cause before you've opened your laptop.\n\n### Scheduled fleet health digest\n\nAlerts are reactive. A digest sweeps *every* registered cluster on a schedule and\nposts one summary to the same Slack webhook — healthy clusters collapse to a\nsingle line, so what's left is what needs you.\n\n```yaml\nfleetReport:\n  enabled: true\n  schedule: \"0 13 * * 1-5\"   # weekday mornings\n```\n\nPreview it before you schedule it — `dry_run` returns the digest and posts\nnothing:\n\n```bash\ncurl -X POST https://<your-kubently-host>/webhooks/fleet-report \\\n  -H \"X-API-Key: <your-api-key>\" -H 'Content-Type: application/json' \\\n  -d '{\"dry_run\": true}'\n```\n\nThe digest question is yours to change. Pass `query` in that request to try one\nimmediately, then keep the wording you like via `fleetReport.query` in values:\n\n```yaml\nfleetReport:\n  query: |-\n    Check every cluster for pods restarting more than 5 times and for PVCs above\n    85% usage. One line per healthy cluster. No preamble.\n```\n\nTo run the real scheduled path once — image, secrets, in-cluster URL and all:\n\n```bash\nkubectl create job --from=cronjob/kubently-fleet-report fleet-report-test -n kubently\n```\n\n### Deployment verification (did that deploy actually work?)\n\nTell Kubently what you just deployed and it watches the rollout settle, then\nruns a real investigation — pods ready? events clean? errors in the new logs?\nmetrics regressed vs the pre-deploy window (when Prometheus is configured)? —\nand posts a PASS/FAIL verdict with the evidence to Slack. Wire it into the last\nstep of your CI pipeline:\n\n```bash\ncurl -X POST https://<your-kubently-host>/webhooks/verify-deployment \\\n  -H \"X-API-Key: <your-api-key>\" -H 'Content-Type: application/json' \\\n  -d '{\"cluster\": \"prod-east\", \"namespace\": \"shop\",\n       \"workload\": \"deploy/checkout-api\", \"context\": \"v1.42.0\"}'\n```\n\nAdd `\"dry_run\": true` to get the verdict back synchronously without posting.\nNo CI access? Label the workload instead — `kubently.io/verify=enabled` — and\nenable `verifyDeployment.watch` in values: Kubently notices every generation\nchange and verifies the rollout unprompted.\n\n### Scheduled checks (your recurring questions, on cron)\n\nThe digest asks one broad question. Scheduled checks let you ask *your*\nquestions on *their* schedules — each check is a named prompt with a cron\nschedule and optional target clusters, run by the agent and posted to Slack:\n\n```yaml\nscheduledChecks:\n  enabled: true\n  checks:\n    - name: cert-expiry\n      schedule: \"0 8 * * 1\"        # Monday mornings\n      prompt: |-\n        Check TLS secrets for certificates expiring within 21 days.\n        List each as namespace/name with days remaining.\n    - name: pvc-pressure\n      schedule: \"0 */6 * * *\"\n      clusters: [prod-east]\n      prompt: Find PersistentVolumeClaims above 85% usage.\n```\n\nA passing check posts **nothing** — silence means green (set `notifyOnPass:\ntrue` to hear about passes too). Failures always post, evidence included.\nIterate on a check without waiting for cron:\n\n```bash\ncurl -X POST https://<your-kubently-host>/webhooks/scheduled-check \\\n  -H \"X-API-Key: <your-api-key>\" -H 'Content-Type: application/json' \\\n  -d '{\"check\": \"cert-expiry\", \"dry_run\": true}'\n```\n\n**📖 See [QUICK_START.md](docs/QUICK_START.md) for full quick-start guide**\n\n**📚 See [GETTING_STARTED.md](docs/GETTING_STARTED.md) for production deployment**\n\n### For Developers: Local Testing\n\n```bash\n# Deploy to a local kind cluster (builds images from HEAD)\nANTHROPIC_API_KEY=sk-... ./deployment/scripts/kind-e2e.sh\n\n# Run comprehensive test suite\n./test-automation/run_tests.sh test-and-analyze --api-key test-api-key\n```\n\n**📖 See [CLAUDE.md](CLAUDE.md) for development guidelines**\n\n## Configuration\n\n### LLM Providers\n\nPick a provider with `LLM_PROVIDER` and supply that provider's key. There is\nno default provider — the agent refuses to start without `LLM_PROVIDER`. For\nlocal development with `deployment/docker-compose.yaml`, put both in `.env`\n(see `deployment/.env.example`):\n\n```bash\n# Anthropic\nLLM_PROVIDER=anthropic-claude\nANTHROPIC_API_KEY=your-anthropic-api-key\n\n# OpenAI (also matches Azure and OpenAI-compatible endpoints)\nLLM_PROVIDER=openai\nOPENAI_API_KEY=your-openai-api-key\n\n# Google Gemini\nLLM_PROVIDER=google-gemini\nGOOGLE_API_KEY=your-gemini-api-key\n```\n\nIn Kubernetes the keys come from the `kubently-llm-secrets` secret and\n`LLM_PROVIDER` goes under `api.env`.\n\n### Helm Deployment\n\nCustomize deployment using Helm values:\n\nKubently ships as a single chart. Its components are switched on and off with\n`api.enabled`, `redis.enabled` and `executor.enabled` — an executor-only\ninstall on a remote cluster is the same chart with the first two disabled.\n\n```bash\n# From a checkout\nhelm install kubently ./deployment/helm/kubently -n kubently \\\n  -f deployment/helm/test-values.yaml\n\n# Or from the published chart repository\nhelm repo add kubently https://kubently.github.io/kubently\nhelm install kubently kubently/kubently -n kubently -f my-values.yaml\n```\n\n`LLM_PROVIDER` is required and has no chart default — set it under `api.env`\n(`anthropic-claude`, `openai`, or `google-gemini`). See\n[ENVIRONMENT_VARIABLES.md](docs/ENVIRONMENT_VARIABLES.md) for the full\nconfiguration surface, and [GETTING_STARTED.md](docs/GETTING_STARTED.md) for\nthe production walkthrough.\n\n### Operator Runbooks\n\nFeed your organization's tribal knowledge into investigations. Runbooks are\nhand-written markdown files with lightweight frontmatter; when an\ninvestigation (a chat question, an Alertmanager alert, or an A2A call)\nmatches a runbook's criteria, the agent receives it as \"the operator's\nrunbook for this situation\", follows it where applicable, notes deviations,\nand cites it by name in the diagnosis.\n\nA worked example:\n\n```markdown\n---\nname: Payments CrashLoopBackOff\nmatch:\n  alerts: [\"KubePodCrashLooping\", \"PaymentsPod*\"]   # alert-name globs\n  namespaces: [\"payments\", \"payments-*\"]            # namespace selectors\n  workloads: [\"payment-api*\"]                       # matches derived pod names too\n  topics: [\"crashloop\", \"OOMKilled\", \"payment service\"]  # free-text tags\n---\n1. Check recent deploys first: payment-api ships through ArgoCD, and 90% of\n   crashloops here follow a bad config sync.\n2. OOMKilled almost always means the JVM heap flag drifted from the container\n   memory limit — compare `-Xmx` against `resources.limits.memory` before\n   blaming traffic.\n3. If the DB connection pool is exhausted, do NOT restart the pods; escalate\n   to #payments-oncall (restarts thundering-herd the database).\n```\n\nDeploy runbooks as Helm values (they become a ConfigMap mounted into the API\npod; edits go live without a pod restart):\n\n```yaml\n# production-values.yaml\nrunbooks:\n  payments-crashloop.md: |\n    ---\n    name: Payments CrashLoopBackOff\n    match:\n      alerts: [\"KubePodCrashLooping\"]\n      namespaces: [\"payments\"]\n    ---\n    1. Check recent deploys first ...\n```\n\nMatching is scored: an alert-name hit outranks namespace/workload selector\nhits, which outrank topic hits. The best match is injected first, and the\ntotal injected size is capped (`KUBENTLY_RUNBOOKS_MAX_CHARS`, default 8000\ncharacters) — one complete, best-matching runbook beats fragments of many.\nOutside Helm, point `KUBENTLY_RUNBOOKS_DIR` at any directory of `.md` files.\n\n### Incident History\n\nPast diagnoses become searchable institutional memory. Whenever an\ninvestigation concludes with a root cause, Kubently stores a compact record —\ndate, cluster, resources involved, symptom keywords, the root-cause\none-liner, and the resolution when one was stated — in Redis, isolated per\nauthenticated caller (the same namespace boundary as conversation memory, so\nin multi-tenant deployments one tenant's incidents are never visible to\nanother).\n\nThe history is used two ways:\n\n- The agent's **`search_past_incidents`** tool answers \"have we seen this\n  before?\" — keyword search over resources, clusters, symptoms and\n  root-cause text, newest first.\n- **Auto-surface**: when a new investigation strongly matches a past incident\n  (same resources/symptoms/cluster), a one-line\n  `SIMILAR PAST INCIDENT (date): <root cause>` note is injected into\n  context — framed as something to *verify against fresh evidence*, never to\n  assume. When a past incident materially informs the diagnosis, the RCA\n  cites it (\"same root cause as the 2026-07-03 incident\").\n\nThis is retrieval over stored summaries, not a learning system: records are\nplain data with a TTL (default 90 days, `KUBENTLY_INCIDENT_TTL_SECONDS`) and\na per-tenant cap (default 200, `KUBENTLY_INCIDENT_MAX_PER_NAMESPACE`,\noldest evicted). The feature is on by default; set\n`KUBENTLY_INCIDENT_HISTORY=false` (Helm: under `api.env`) to disable both\nrecording and retrieval.\n\n## Architecture\n\n- **API Server**: FastAPI-based REST API for cluster management and authentication\n- **A2A Server**: Implements A2A protocol with LangGraph for workflow orchestration\n- **Test Automation**: Comprehensive testing framework with 20+ Kubernetes scenarios\n- **CLI Tools**: Modern Node.js CLI for interactive debugging\n\n### Agent Toolset\n\nThe diagnostic agent investigates with a small set of read-only tools:\n\n- **`list_clusters`** — enumerate registered clusters\n- **`execute_kubectl`** — read-only kubectl against one cluster (whitelist-enforced on the executor)\n- **`execute_kubectl_multi`** — one read-only kubectl command fanned out across many clusters\n- **`get_recent_changes`** — \"what changed?\" timeline for a workload or namespace: rollouts (ReplicaSet revisions + change-causes), Helm release history *(opt-in: `changeCorrelation.helmHistory.enabled`)*, ArgoCD sync history *(optional: `changeCorrelation.argocd.url`)*, and Normal+Warning events — correlated against first-error timestamps in the RCA\n- **`get_events_for_resource`** — chronological events for a resource and its children (deployment → replicasets → pods)\n- **`search_pod_logs`** — structured log search across every pod/container matching a label selector (substring or regex, time bounds, previous-container support). Logs are filtered on the cluster's executor so only matching lines — capped, with explicit truncation notes — come back\n- **`query_loki`** *(optional)* — LogQL range queries against a cluster's Loki for aggregated/historical log search, including logs from pods that have restarted or been deleted. Enabled by setting `loki.url` in Helm values (unset by default); queries execute on each cluster's executor through the same outbound channel as kubectl commands\n- **`query_prometheus`** *(optional)* — instant and range PromQL queries for latency, saturation, OOM-trend and restarts-over-time evidence. Enabled by setting `prometheus.url` in Helm values (unset by default); queries execute on each cluster's executor through the same outbound channel as kubectl commands\n- **`search_past_incidents`** — keyword search over this deployment's incident history (see below). On by default when Redis is available; disable with `KUBENTLY_INCIDENT_HISTORY=false`\n- **`get_manifest_file`** *(optional)* — read-only fetch of a file from the configured GitOps manifests repo, so proposed fixes are diffed against the real manifest instead of a hallucinated one. Enabled with `gitRemediation` in Helm values (off by default)\n- **`propose_fix_pr`** *(optional)* — proposes a high-confidence manifest fix as a **pull request** against the configured GitOps manifests repo (GitHub or GitLab): branch → commit → PR with the investigation evidence in a body clearly marked machine-proposed. The agent **never merges** — a human reviews and merges, and your GitOps controller applies. Size-capped (files/changed lines), token never enters model context, cluster access stays read-only. See [GitOps PR Remediation](docs/GITOPS_REMEDIATION.md)\n- **`query_cloud_logs`**, **`query_cloud_metrics`**, **`get_recent_cloud_changes`** *(optional)* — read-only cloud telemetry for a cluster: CloudWatch Logs Insights / CloudWatch metrics / CloudTrail on AWS, Cloud Logging / Cloud Monitoring / GKE audit logs on GCP. The executor answers them using the workload identity **you** grant its ServiceAccount (EKS Pod Identity, IRSA, or GKE Workload Identity) — no cloud key is ever stored by Kubently, and revoking the IAM role kills the capability instantly. Enabled per cluster with `executor.cloud.enabled` in Helm values (off by default); each call re-checks that the target cluster's executor actually reports an identity. Operations are additionally limited by a code-level allowlist. See [Cloud Telemetry](docs/CLOUD_TELEMETRY.md)\n- **`mcp_<server>_*`** *(optional)* — tools from external MCP servers (streamable HTTP, e.g. Grafana Cloud's or Datadog's remote MCP) configured via `mcpServers` in Helm values (unset by default). Tool names are prefixed with the server name to avoid collisions; results are treated as untrusted input (framed and size-capped) and credentials stay in Kubernetes secrets. **Connect read-scoped servers/credentials only** — Kubently cannot enforce read-only semantics on a remote server's tools. See `docs/MCP_CLIENT_TOOLS.md`\n\n## Documentation\n\n### Getting Started\n- **[Quick Start Guide](docs/QUICK_START.md)** - Get running in 5 minutes\n- **[Getting Started](docs/GETTING_STARTED.md)** - Complete setup for production use\n- **[Deployment Guide](docs/DEPLOYMENT.md)** - Detailed deployment options and configuration\n\n### Usage & Operations\n- **[CLI Admin Guide](docs/GETTING_STARTED.md#step-5-register-and-deploy-executors)** - Managing clusters and executors\n- **[Test Queries](docs/TEST_QUERIES.md)** - Example API requests and A2A protocol usage\n- **[MCP Connect Guide](docs/MCP.md)** - Connect MCP clients (Claude Desktop, Cursor, custom agents)\n- **[Environment Variables](docs/ENVIRONMENT_VARIABLES.md)** - Configuration reference\n- **[GitOps PR Remediation](docs/GITOPS_REMEDIATION.md)** - Agent-proposed fix PRs (human-merged, default off)\n- **[Cloud Telemetry](docs/CLOUD_TELEMETRY.md)** - Read-only CloudWatch / Cloud Logging access via workload identity (default off)\n- **[External MCP Tools](docs/MCP_CLIENT_TOOLS.md)** - Mounting third-party MCP servers into the agent, including per-request injection\n\n### Architecture & Development\n- **[Architecture](docs/ARCHITECTURE.md)** - System design and components\n- **[A2A Protocol Spec](https://a2a-protocol.org/latest/)** - Official protocol documentation\n- **[Development Guide](CLAUDE.md)** - Guidelines for contributors\n\n### Troubleshooting\n- **[Getting Started - Common Issues](docs/GETTING_STARTED.md#common-issues)** - Troubleshooting guide\n\n## Contributing\n\nSee [CLAUDE.md](CLAUDE.md) for development guidelines and contribution instructions.\n\n## Maintainer\n\n**Kubently Team** - [hello@kubently.io](mailto:hello@kubently.io)\n\n## License\n\nApache 2.0 License - See LICENSE file for details\n",
  "bytes": 19011,
  "sha": "99692117cd911b87251a96acf3abb081b900be1b14bf226c8e1138a298361995",
  "repo_slug": "kubently/kubently",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_kubently_kubently_bf6e2e0f/readme"
}