Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/images/authors/sebastianmaniak.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/app/blog/authors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ export const authors: Author[] = [
photo: "/images/authors/jetchiang.jpg",
bio: "Jet is an aspiring machine learning engineer + researcher studying at the University of Toronto. He is the Linux Foundation Mentee at Kagent for 2025.",
},
{
id: "sebastianmaniak",
name: "Sebastian Maniak",
title: "Field CTO",
photo: "/images/authors/sebastianmaniak.jpg",
bio: "Sebastian Maniak is a Field CTO at Solo.io, helping organizations adopt cloud-native technologies and AI-powered infrastructure.",
},
{
id: "michaellevan",
name: "Michael Levan",
Expand Down
7 changes: 7 additions & 0 deletions src/app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ const posts = [
description: 'Discover kmcp, the lightweight toolkit that takes MCP servers from prototype to production. Learn how to scaffold, build, and deploy enterprise-grade MCP services to Kubernetes in minutes—no Dockerfiles or complex manifests required. Includes demo video and complete getting started guide.',
authorId: "christianposta",
},
{
slug: 'human-in-the-loop-kagent',
publishDate: '2026-03-11',
title: 'Human-in-the-Loop with kagent: Keeping Humans in Control of AI Agents',
description: 'How to build Kubernetes-native AI agents that pause and ask for approval before taking destructive actions, using kagent\'s human-in-the-loop capabilities.',
authorId: 'sebastianmaniak',
},
{
slug: 'inside-kagent-oss-ent-ai-meshes',
publishDate: '2025-11-18',
Expand Down
245 changes: 245 additions & 0 deletions src/app/docs/kagent/examples/human-in-the-loop/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
---
title: "Human-in-the-Loop"
pageOrder: 7
description: "Build a Kubernetes-native AI agent that pauses and asks for your approval before taking destructive actions."
---

export const metadata = {
title: "Human-in-the-Loop with kagent",
description: "Build a Kubernetes-native AI agent that pauses and asks for your approval before taking destructive actions.",
author: "kagent.dev"
};

# Human-in-the-Loop with kagent

AI agents that can take action are powerful — but you don't always want them acting without your say-so. This tutorial walks you through building a Kubernetes-native AI agent that **pauses and asks for your approval** before doing anything destructive.

## What You'll Build

By the end of this tutorial, you'll have an agent running on a local Kind cluster that:

- **Reads cluster resources** freely (no approval needed)
- **Pauses for your approval** before creating, modifying, or deleting resources
- **Asks you questions** when it needs more information

---

## Prerequisites

Make sure you have these installed before starting:

| Tool | Install Link |
|------|-------------|
| Docker | [get-docker](https://docs.docker.com/get-docker/) |
| Kind | [quick-start](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) |
| kubectl | [install-tools](https://kubernetes.io/docs/tasks/tools/) |
| Helm | [install](https://helm.sh/docs/intro/install/) |

You'll also need an **OpenAI API key**.

---

## Step 1 — Create a Kind Cluster

Spin up a local Kubernetes cluster:

```bash
kind create cluster --name kagent-hitl
```

Verify it's running:

```bash
kubectl cluster-info --context kind-kagent-hitl
```

You should see the control plane address printed. If so, you're good to go.

---

## Step 2 — Install kagent

There are two Helm charts to install: the CRDs first, then kagent itself.

**Install the CRDs:**

```bash
helm install kagent-crds oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds \
--namespace kagent \
--create-namespace
```

**Set your API key:**

```bash
export OPENAI_API_KEY="your-api-key-here"
```

**Install kagent:**

```bash
helm install kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \
--namespace kagent \
--set providers.default=openAI \
--set providers.openAI.apiKey=$OPENAI_API_KEY
```

**Wait for everything to come up:**

```bash
kubectl wait --for=condition=ready pod --all -n kagent --timeout=120s
```

Once all pods report `condition met`, move on.

---

## Step 3 — Deploy the Agent

This is the core of the tutorial. You'll create an agent that uses kagent's **built-in Kubernetes tools** (served via the kagent tool server), with **approval gates** on the destructive ones.

Save this as `hitl-agent.yaml`:

```yaml
apiVersion: kagent.dev/v1alpha2
kind: Agent
metadata:
name: hitl-agent
namespace: kagent
spec:
description: A Kubernetes agent with human-in-the-loop approval for destructive operations.
type: Declarative
declarative:
modelConfig: default-model-config
systemMessage: |
You are a Kubernetes management agent. You help users inspect and manage
resources in the cluster. Before making any changes, explain what you
plan to do. If the user's request is ambiguous, use the ask_user tool
to clarify before proceeding.
tools:
- type: McpServer
mcpServer:
name: kagent-tool-server
kind: RemoteMCPServer
apiGroup: kagent.dev
toolNames:
- k8s_get_resources
- k8s_describe_resource
- k8s_get_pod_logs
- k8s_get_events
- k8s_get_resource_yaml
- k8s_apply_manifest
- k8s_delete_resource
- k8s_patch_resource
requireApproval:
- k8s_apply_manifest
- k8s_delete_resource
- k8s_patch_resource
```

Create the agent:

```bash
kubectl apply -f hitl-agent.yaml
```

**Here's what each tool does:**

| Tool | What Happens |
|------|-------------|
| `k8s_get_resources` | Runs immediately — lists pods, services, deployments, etc. |
| `k8s_describe_resource` | Runs immediately — shows resource details |
| `k8s_get_pod_logs` | Runs immediately — reads pod logs |
| `k8s_get_events` | Runs immediately — shows cluster events |
| `k8s_get_resource_yaml` | Runs immediately — exports resource YAML |
| `k8s_apply_manifest` | **Pauses for approval** — creates or updates resources |
| `k8s_delete_resource` | **Pauses for approval** — deletes resources |
| `k8s_patch_resource` | **Pauses for approval** — modifies resources |
| `ask_user` | Built-in on every agent — asks you questions anytime |

The key is `requireApproval` — any tool listed there will pause execution until you explicitly approve it. Read-only tools run freely; write operations need your sign-off.

---

## Step 4 — Open the UI

Port-forward the kagent dashboard:

```bash
kubectl port-forward -n kagent svc/kagent-ui 8080:8080
```

Open [http://localhost:8080](http://localhost:8080) in your browser. You should see the kagent UI with your **hitl-agent** listed.

---

## Step 5 — Try It Out

Now for the fun part. Run through these tests to see human-in-the-loop in action.

### Test 1: Read Without Approval

1. Select the **hitl-agent** in the UI
2. Type: `List all pods in the kagent namespace`
3. The agent calls `k8s_get_resources` — it runs **immediately** with no approval prompt
4. You see the pod listing right away

This shows that read-only tools are not gated.

### Test 2: Approve a Create

1. Type: `Create a ConfigMap called test-config in the default namespace with the key message set to "hello from kagent"`
2. The agent calls `k8s_apply_manifest` — execution **pauses**
3. You'll see **Approve / Reject** buttons appear, along with the YAML it wants to apply
4. Click **Approve**
5. The agent creates the ConfigMap and confirms

### Test 3: Reject a Delete

1. Type: `Delete the ConfigMap test-config in the default namespace`
2. The agent calls `k8s_delete_resource` — execution **pauses**
3. Click **Reject** and enter a reason: `I want to keep this ConfigMap for now`
4. The agent sees your reason and responds accordingly — it doesn't delete anything

### Test 4: Agent Asks You a Question

1. Type: `Set up a namespace for my application`
2. The request is vague, so the agent calls `ask_user` to clarify (e.g., "What should the namespace be called?")
3. Answer the question and the agent continues with your input

---

## How It Works

The flow is straightforward:

```
You send a message
-> Agent decides which tool to call
-> Is the tool in requireApproval?
-> YES: Execution pauses, you see Approve/Reject in the UI
-> Approve: tool runs normally
-> Reject: agent receives your reason and adapts
-> NO: Tool runs immediately
```

The `ask_user` tool works the same way — the agent pauses, you answer, and it continues. Both use the same underlying confirmation mechanism, which keeps things simple.

---

## Cleanup

Delete the cluster when you're done:

```bash
kind delete cluster --name kagent-hitl
```

---

## Key Takeaways

- **`requireApproval`** is all you need — list the tools that need human sign-off
- **Read-only tools run freely**, write operations pause for approval
- **`ask_user`** is built-in on every agent — no extra config required
- **Rejection reasons** are sent back to the LLM so it can adjust its approach
1 change: 1 addition & 0 deletions src/app/docs/kagent/examples/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ import QuickLink from '@/components/quick-link';
<QuickLink title="Skills" description="Add skills to your agents to guide their behavior and tool usage for more autonomous operation." href="/docs/kagent/examples/skills" />
<QuickLink title="Slack and A2A" description="Manage Kubernetes resources in your cluster by chatting with kagent in Slack." href="/docs/kagent/examples/slack-a2a" />
<QuickLink title="Discord and A2A" description="Manage Kubernetes resources in your cluster by chatting with kagent in Discord." href="/docs/kagent/examples/discord-a2a" />
<QuickLink title="Human-in-the-Loop" description="Build an agent that pauses for your approval before creating, modifying, or deleting Kubernetes resources." href="/docs/kagent/examples/human-in-the-loop" />
</div>
</div>
Loading