Skip to main content
BlogAI

kagent Kubernetes Tutorial: AI Agents on a Laptop Cluster

kagent Kubernetes tutorial: run AI agents on a laptop kind cluster, wire RemoteMCPServer tools, keep sessions, and choose between 0.10 and the 1.0 alpha.

Matthews Wong

Software Engineer

October 202612 min read
kagent Kubernetes Tutorial: AI Agents on a Laptop Cluster

Key Takeaway

kagent is a CNCF Sandbox project that runs AI agents as Kubernetes custom resources, reaches tools through shared RemoteMCPServer resources and keeps conversation history in sessions. Two lines ship at once: 0.10.x, used in the CNCF laptop walkthrough, and the 1.0 alpha with Harnesses and Kubernetes 1.37. Choose one before copying any manifest.

The CNCF published a laptop walkthrough for kagent on 2026-10-12, and I tried to line it up with the project's own docs. They did not match. The walkthrough installs Helm chart 0.10.2 and writes kagent.dev/v1alpha2 manifests. The repository's main branch, install page and first-agent guide describe api.kagent.dev/v1alpha3, a new Harness resource and a cluster that must run Kubernetes 1.37 or later.

I did not run a cluster for this post. I read the CNCF project page, the repository README, the architecture guide, the CRD schemas in the Helm chart, the 1.x install and first-agent pages, the tools repository wiki and the walkthrough itself, and I quote a number only where one of them printed it. The aim is a single map of both lines, so you can build the laptop setup that matches the version you actually want.

What kagent is, and what the CNCF accepted

The CNCF project page describes kagent as an open source programming framework for DevOps and platform engineers to run AI agents in Kubernetes. It lists the maturity as Sandbox, the acceptance date as May 22, 2025 and the first commit as January 21, 2025. Sandbox is the CNCF's earliest maturity tier, so read it as an early-stage project, not as a stability promise.

The README names the moving parts. A controller watches kagent custom resources, prepares agents to run, manages sessions and exposes gRPC, A2A and MCP APIs. A web UI and a CLI talk to it. PostgreSQL stores sessions, tasks and conversation history independently of the running agents. Agent runtimes (the Go or Python ADK, Codex, Claude or a custom one) are selected by a Harness, and a component called Substrate runs them and handles suspension, resumption and snapshots. The license is Apache 2.0.

Two kagents are shipping at once

The GitHub releases page shows both lines moving in parallel. v0.10.3 was published on 2026-10-02, and v1.0.0-alpha1 on 2026-09-18 was followed by thirteen more alpha tags, the latest being v1.0.0-alpha14 on 2026-10-16. That is fourteen alpha tags in 28 days. The table puts the two lines next to each other using only what the sources printed.

Aspect0.10.x line (CNCF walkthrough)1.0 alpha line (main branch, 1.x docs)
Latest tag I readv0.10.3, 2026-10-02 (walkthrough pins chart 0.10.2)v1.0.0-alpha14, 2026-10-16 (docs pin CLI v1.0.0-alpha13)
Manifest apiVersionkagent.dev/v1alpha2 in the walkthrough's Agentapi.kagent.dev/v1alpha3 in every CRD on main
Install pathTwo OCI Helm charts: kagent-crds, then kagent, with a values filekagent CLI install: CRDs, Agent Substrate in ate-system, PodCertificate controller, development PostgreSQL, kagent
What an Agent isAn Agent with spec.type Declarative and an inline declarative blockAn Agent that holds a template (ref or inline) plus a harnessRef to a Harness
Local clusterPlain kind create cluster, with Ollama on the hostkind v0.32.0 or later with node image v1.37.0, API keys from a hosted model
Where tools attachRemoteMCPServer, toolNames, and requireApproval naming the gated toolsRemoteMCPServer, mcp binding with a tools allow-list and a requireApproval boolean

The rest of this post keeps the two lines apart. If you want something stable enough to demo, the 0.10 path is the one a CNCF ambassador post walked end to end. If you want to see where the project is going, the 1.0 path is where every commit lands, and its own documentation was one tag behind the newest release on the day I read it.

The 0.10 laptop path: Ollama, kind and a read-only tool server

The walkthrough by Antonio Berben and Felipe Vicens installs chart 0.10.2 into a kind cluster named kagent-builder and points kagent at a local Ollama instance. Their values file sets Ollama as the default provider, trims the tool server to the Kubernetes provider, which they report loads 22 tools, turns on read-only RBAC and disables the sample agents. I rebuilt the values file from the chart's own values.yaml at v0.10.3, where the Ollama block really is providers.ollama.config.host plus options.num_ctx.

# kagent-values.yaml  (0.10.x line, as in the CNCF walkthrough)
providers:
  default: ollama
  ollama:
    provider: Ollama
    model: "qwen3-coder:30b-a3b-q4_K_M"   # ~18 GB on disk; smaller models failed
    config:
      host: host.docker.internal:11434    # Docker Desktop. On Linux this changes.
      options:
        num_ctx: "32768"

kagent-tools:
  tools:
    enabledTools: [k8s]       # only the Kubernetes provider: 22 tools
  rbac:
    readOnly: true            # the default would be cluster-admin

k8s-agent:
  enabled: false              # the chart ships sample agents; switch them off
kind create cluster --name kagent-builder

helm upgrade --install kagent-crds \
  oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds \
  --version 0.10.2 --namespace kagent --create-namespace

helm upgrade --install kagent \
  oci://ghcr.io/kagent-dev/kagent/helm/kagent \
  --version 0.10.2 --namespace kagent --values kagent-values.yaml

kubectl -n kagent rollout status deployment/kagent-controller --timeout=300s
kubectl -n kagent rollout status deployment/kagent-ui --timeout=300s
kubectl -n kagent rollout status deployment/kagent-tools --timeout=300s

# Bind to loopback only. The UI has no real authentication in this setup.
kubectl -n kagent port-forward --address 127.0.0.1 svc/kagent-ui 8080:8080

Two details in that file carry the lesson. First, the chart's default gives the tool server's ServiceAccount cluster-admin, according to the walkthrough, so readOnly is a deliberate downgrade and the one extra rule it adds allows writing only agents.kagent.dev. Second, the model matters: the authors report that qwen2.5:7b-instruct invented its own tool block format, qwen2.5:14b-instruct sometimes answered politely without calling the apply tool, and only qwen3-coder:30b-a3b worked on every run. That model is about 18 GB on disk, which is a real laptop requirement.

The 1.0 alpha path: Harness, AgentTemplate, Agent and a Session

The 1.x install page lists a Kubernetes 1.37 cluster as a prerequisite and gives a kind command with node image v1.37.0, which needs kind v0.32.0 or later. It also asks you to confirm that the certificates.k8s.io API is served. The installer is the kagent CLI, not a hand-run helm install, and it creates the required Secrets for you. The page pins the CLI to v1.0.0-alpha13.

# Node image 1.37.0 and kind v0.32.0 or later, per the 1.x install page.
kind create cluster --name kagent --image kindest/node:v1.37.0
export OPENAI_API_KEY="your-api-key-here"

# The CLI installs CRDs, Agent Substrate (ate-system), the PodCertificate
# controller, a development PostgreSQL and kagent itself.
kagent --config kagent-config.yaml install --namespace kagent
kubectl rollout status deployment/kagent-controller -n kagent --timeout=300s
kubectl get workerpools -n kagent      # one replica should be ready

The first-agent guide then splits what used to be one object into three. A Harness decides how the agent runs: its runtime image, the Substrate worker pool and where snapshots go. An AgentTemplate holds portable behaviour: the model, the prompt, tools. An Agent joins them. The YAML below is the guide's own, with the image digest left as a placeholder.

apiVersion: api.kagent.dev/v1alpha3
kind: Harness
metadata:
  name: my-first-harness
  namespace: kagent
spec:
  kagent: {}
  workload:
    image: ghcr.io/kagent-dev/kagent/golang-adk@<digest>   # pinned by digest
  substrate:
    workerPoolRef:
      name: kagent-default
    snapshotPolicy:
      location: s3://ate-snapshots/kagent/
---
apiVersion: api.kagent.dev/v1alpha3
kind: AgentTemplate
metadata:
  name: my-first-template
  namespace: kagent
spec:
  description: My first kagent agent
  modelConfig:
    name: default-model-config    # created at install from your API key
  systemPrompt: "You are a concise, helpful assistant."
---
apiVersion: api.kagent.dev/v1alpha3
kind: Agent
metadata:
  name: my-first-agent
  namespace: kagent
spec:
  template:
    ref:
      name: my-first-template     # or inline: { ... }, never both
  harnessRef:
    name: my-first-harness
kagent agent get my-first-agent
# READY=False right after apply is normal while the runtime snapshot builds.
kubectl get agent my-first-agent -n kagent -o jsonpath='{.status.conditions}' | jq
# Conditions: Accepted, ResolvedRefs, Compatible, Ready

export SESSION_ID=$(kagent agent session create --agent my-first-agent -o json | jq -r '.session.id')
kagent agent invoke --session $SESSION_ID --task "What is 2+2?"
kagent agent invoke --session $SESSION_ID --task "What did I just ask you?"

The CLI reaches the controller on localhost:8083 and starts a kubectl port-forward by itself when nothing is listening. The guide says the second question is answered correctly because the Session keeps the transcript, and that Ready can be False for about a minute after you apply while the runtime snapshot builds. Conditions to read are Accepted, ResolvedRefs, Compatible and Ready, and status.warnings lists non-blocking compatibility decisions.

Tools: RemoteMCPServer, allow-lists and approval

An agent never holds a tool directly. It binds to a RemoteMCPServer resource, which can be shared across agents. The chart's own template renders one named after the release with the suffix tool-server, pointing at port 8084 on the tools service with a 30 second timeout and a five minute SSE read timeout. In the v1alpha3 CRDs, allowedNamespaces defaults to Same, borrowing the Gateway API cross-namespace pattern, so another namespace's agents cannot use your server unless you say so.

apiVersion: api.kagent.dev/v1alpha3
kind: RemoteMCPServer
metadata:
  name: kagent-tool-server
  namespace: kagent
spec:
  # Chart default shape: http://<tools service>.<namespace>:8084/mcp
  url: "http://kagent-tools.kagent:8084/mcp"
  protocol: STREAMABLE_HTTP     # default; SSE is the other allowed value
  timeout: 30s                  # default
  sseReadTimeout: 5m0s
  description: "Official KAgent tool server"
  allowedNamespaces:
    from: Same                  # default: only Agents in this namespace may use it
---
# Inside an AgentTemplate (or the inline form of an Agent):
spec:
  tools:
    - mcp:
        server:
          kind: RemoteMCPServer   # the CRD rejects any other kind
          name: kagent-tool-server
        tools:                    # allow-list, at most 50 names
          - k8s_get_resources
          - k8s_get_pod_logs
          - k8s_apply_manifest
        requireApproval: true     # pause before EVERY listed tool call

The built-in server ships tools for Kubernetes, Istio, Helm, Argo, Prometheus, Grafana, Cilium and others. I checked the kagent-dev/tools wiki for what is in it. Treat these counts as a snapshot of that README, not as a contract.

ProviderTools in the wiki READMEExamples it names
Kubernetes16kubectl_get, kubectl_apply, kubectl_delete, exec_command, rollout
Helm7helm_install, helm_upgrade, helm_repo_update
Istio13istio_analyze, six waypoint tools
Argo Rollouts7promote_rollout, pause_rollout, set_rollout_image
Cilium12install_cilium, toggle_hubble, list_bgp_peers
Prometheus4query, range query, labels, targets
Grafana4org, dashboard, alert and datasource management

Notice the mismatch: the wiki lists 16 Kubernetes tools, while the walkthrough says enabling the k8s provider loads 22. Tool counts drift between versions, so never hard-code one in a prompt or a test. The same wiki documents a --read-only flag that disables tools performing write operations and a --tools flag that picks which providers to register. In the v1alpha3 CRD, the tools list on a binding is capped at 50 names, and an omitted or empty list exposes every tool on the server.

Sessions: where the conversation actually lives

A Session is not a Kubernetes resource, which surprised me. The architecture guide says PostgreSQL holds runtime identity, A2A history and lifecycle state, and that sessions are exposed over gRPC. So kubectl get will never list one; you use kagent agent session list instead, and you delete Sessions before deleting the Agent that owns them, as the cleanup steps in the first-agent guide do.

What the guide documents you can do with a Session is more interesting than chat history.

  • Checkpoint: stored as a PostgreSQL record plus a Substrate snapshot tag, an immutable restart boundary. A fork creates a new Session from a checkpoint.
  • Suspend: lifecycle workers independently pause or suspend idle Actors, so an idle agent does not hold a running process.
  • A2A: the public gateway maps context IDs to Sessions and exposes each Agent. The walkthrough shows a pending approval coming back as the task state input-required, answered with a data part whose decision_type is approve, on the same taskId and contextId.

What breaks, and what the trade-offs are

The walkthrough is unusually honest about its limits, and the project is honest about its own. Put them together and the failure list for a laptop setup is short but sharp.

Defaults are for a laptop, not a cluster you share. The walkthrough states that the chart gives the tool server's ServiceAccount cluster-admin, that auth mode is unsecure so every request acts as the same user, and that the bundled PostgreSQL uses a built-in password. Keep the port-forward on 127.0.0.1 and do not point this at a cluster that holds real workloads.

  • A model that cannot call tools reliably turns an approval gate into theatre. In the walkthrough, a generated Agent pointed at kagent-tools instead of kagent-tool-server and the controller returned Accepted=False, because the author's script had approved it blindly. Read the condition, not the model's confidence.
  • The prompt is a request, not a guarantee. The walkthrough's author relies on the tool allow-list, human approval and RBAC as the real guardrails, and so should you.
  • Alpha churn is real: fourteen alpha tags in 28 days, docs pinned to alpha13 while alpha14 exists, and an architecture guide that lists dedicated agent bindings, policy-enforced cross-Session delegation, checkpoint sharing and multi-replica gateway coordination as not yet implemented.
  • Hardware cost is hidden in the cheap path. The 0.10 route that avoids API keys needs an 18 GB model, and the 1.0 route needs a Kubernetes 1.37 node image plus an S3-style snapshot location in the guide's Harness.

I would not choose between the lines on features. I would choose on blast radius: 0.10 with read-only RBAC for learning, the 1.0 alpha only in a throwaway cluster until the not-yet-implemented list shrinks.

What to do on Monday

None of this needs a production cluster. Spend an afternoon on a disposable kind cluster and do these in order.

  1. Decide the line. Want to learn agents as resources on a stock cluster: 0.10.x. Want to evaluate where kagent is heading: 1.0 alpha on kind with node image v1.37.0.
  2. Install with sample agents off and the Kubernetes tool provider only, using the values file above or the installer.
  3. Check what the tool server can do with kubectl auth can-i before any agent runs, and aim for no on creating deployments and reading secrets.
  4. Bind an agent to an explicit tools allow-list and turn approval on for the one write tool. Then check the Accepted condition on every Agent you apply.
  5. Open a Session, ask a question, ask a follow-up that depends on it, and only then decide whether the setup is worth taking further.
# Step 3: prove the tool server cannot do what you did not intend.
SA=system:serviceaccount:kagent:kagent-tools
kubectl auth can-i create deployments -n kagent --as=$SA   # want: no
kubectl auth can-i get secrets        -n kagent --as=$SA   # want: no

# Step 4: an Agent that points at the wrong server is Accepted=False.
# Read the condition before you trust a generated manifest.
kubectl get agent -n kagent \
  -o custom-columns=NAME:.metadata.name,ACCEPTED:.status.conditions[?(@.type=="Accepted")].status

Put the approval on the write tool only. Approval on every read call trains you to click yes without reading, which is exactly the habit that approved a wrong manifest in the walkthrough.

When you finish, kind delete cluster removes everything. That is the point of doing this on a laptop first.

kagent makes an agent an ordinary Kubernetes object, which is the good idea. The practical rule I took away is to pin the version before copying any YAML, treat the tool server's RBAC as the real security boundary, and read the Accepted condition instead of trusting a model's reply.

FAQ

Frequently Asked Questions

Short answers to what readers ask most about this topic.

What is kagent?

kagent is an open source framework, accepted as a CNCF Sandbox project on May 22, 2025, for running AI agents in Kubernetes. An agent is a custom resource, and a controller prepares it, manages its sessions and exposes gRPC, A2A and MCP APIs. It ships an MCP server with tools for Kubernetes, Istio, Helm, Argo, Prometheus, Grafana and Cilium.

Can I run kagent on a laptop?

Yes. The CNCF walkthrough from 2026-10-12 installs Helm chart 0.10.2 into a kind cluster and uses a local Ollama model, with qwen3-coder:30b-a3b at about 18 GB the only one that worked on every run. The 1.x docs instead ask for kind v0.32.0 or later with node image v1.37.0.

What is the difference between kagent 0.10 and 1.0?

The 0.10 line uses kagent.dev/v1alpha2 manifests and two Helm charts. The 1.0 alpha line uses api.kagent.dev/v1alpha3, splits an agent into Agent, AgentTemplate and Harness, installs through the kagent CLI and needs Kubernetes 1.37 or later. At the time of writing, v1.0.0-alpha14 was released on 2026-10-16.

How do kagent agents get tools?

Agents bind to a RemoteMCPServer resource, which can be shared across agents and defaults to same-namespace access. In the v1alpha3 CRD a binding can list up to 50 tool names and set requireApproval, so the agent pauses before each call. The built-in tool server also has a --read-only flag.

Is kagent safe to run with default settings?

Not on a shared cluster. The CNCF walkthrough says the chart gives the tool server cluster-admin by default, auth mode is unsecure and the bundled PostgreSQL uses a built-in password. Use read-only RBAC, an explicit tool allow-list, approval on write tools and a port-forward bound to 127.0.0.1.