diff --git a/package-lock.json b/package-lock.json
index 3169b2d0..a4a9bcfe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -39,7 +39,8 @@
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1",
"tailwind-merge": "^3.3.1",
- "tailwindcss-animate": "^1.0.7"
+ "tailwindcss-animate": "^1.0.7",
+ "unist-util-visit": "^5.0.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
diff --git a/public/sitemap.xml b/public/sitemap.xml
index feb7196f..dcd24913 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -2,847 +2,840 @@
https://kagent.dev/agents
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/blog
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/community
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts/agent-harness
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts/agent-memory
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts/agent-substrate
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts/agents
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts/architecture
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/concepts/tools
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/a2a-agents
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/a2a-byo
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/agent-harness
- 2026-06-22
- weekly
- 0.8
-
-
-
- https://kagent.dev/docs/kagent/examples/agent-sandbox
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/agent-substrate
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/agentgateway
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/agents-mcp
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/crewai-byo
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/discord-a2a
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/documentation
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/human-in-the-loop
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/langchain-byo
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/skills
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/slack-a2a
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/examples/telegram-bot
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/getting-started/first-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/getting-started/first-mcp-tool
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/getting-started/local-development
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/getting-started
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/getting-started/quickstart
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/getting-started/system-prompts
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/introduction/features
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/introduction/installation
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/introduction
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/introduction/what-is-kagent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/observability/audit-prompts
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/observability/launch-ui
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/observability
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/observability/tracing
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/operations/debug
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/operations/operational-considerations
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/operations
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/operations/uninstall
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/operations/upgrade
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/api-ref
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-add-mcp
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-bug-report
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-build
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-completion
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-dashboard
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-deploy
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-get
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-help
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-init
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-install
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-invoke
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-mcp
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-run
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-uninstall
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli/kagent-version
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/cli
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/faq
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/helm
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/release-notes
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/resources/tools-ecosystem
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/amazon-bedrock
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/anthropic
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/azure-openai
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/byo-openai
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/gemini
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/google-vertexai
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/ollama
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/openai
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/sap-ai-core
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kagent/supported-providers/xai
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/deploy/install-controller
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/deploy
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/deploy/server
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/develop/fastmcp-python
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/develop/mcp-go
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/develop
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/introduction
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/quickstart
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/api-ref
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-add-tool
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-build
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-completion
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-deploy
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-help
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-init
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-install
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-run
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference/kmcp-secrets
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/reference
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs/kmcp/secrets
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/docs
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/enterprise
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/page.tsx
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/argo-rollouts-conversion-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/cilium-crd-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/helm-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/istio-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/k8s-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/kgateway-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/observability-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/agents/promql-agent
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/istio
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/kubernetes
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/prometheus
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/documentation
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/helm
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/argo
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/grafana
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/other
- 2026-06-22
+ 2026-06-26
weekly
0.8
https://kagent.dev/tools/cilium
- 2026-06-22
+ 2026-06-26
weekly
0.8
diff --git a/src/app/docs/_constants.ts b/src/app/docs/_constants.ts
index 80b0dce0..08eb7024 100644
--- a/src/app/docs/_constants.ts
+++ b/src/app/docs/_constants.ts
@@ -9,7 +9,6 @@ export const VERSIONS = {
kmcp: "0.3.0",
// External dependencies
- agentSandbox: "0.3.10",
agentSubstrate: "0.0.6",
loki: "6.24.0",
tempo: "1.16.0",
@@ -19,5 +18,4 @@ export const VERSIONS = {
kubernetesAppsApi: "apps/v1",
kubernetesApi: "v1",
kagentApi: "kagent.dev/v1alpha2",
- agentSandboxApi: "agents.x-k8s.io/v1alpha1",
};
diff --git a/src/app/docs/kagent/concepts/agent-harness/page.mdx b/src/app/docs/kagent/concepts/agent-harness/page.mdx
index 4e92ec5e..f30dc277 100644
--- a/src/app/docs/kagent/concepts/agent-harness/page.mdx
+++ b/src/app/docs/kagent/concepts/agent-harness/page.mdx
@@ -1,28 +1,28 @@
---
title: "Agent Harness"
pageOrder: 4
-description: "Understand AgentHarness resources, OpenShell-backed execution environments, and backend-specific channel configuration."
+description: "Understand AgentHarness resources, Substrate-backed execution environments, and how kagent talks to them over the Agent Client Protocol (ACP)."
---
export const metadata = {
title: "Agent Harness",
- description: "Understand AgentHarness resources, OpenShell-backed execution environments, and backend-specific channel configuration.",
+ description: "Understand AgentHarness resources, Substrate-backed execution environments, and how kagent talks to them over the Agent Client Protocol (ACP).",
author: "kagent.dev"
};
# Agent Harness
-An `AgentHarness` is a Kubernetes custom resource that asks kagent to provision a long-running remote execution environment through an [OpenShell](https://github.com/NVIDIA/OpenShell) gateway. It is useful when you want a managed sandbox that can be attached to, bootstrapped, and connected to messaging channels, but you do not want kagent to package and run a full agent runtime inside the workload.
+An `AgentHarness` is a Kubernetes custom resource that asks kagent to provision a long-running remote execution environment on [Agent Substrate](/docs/kagent/concepts/agent-substrate). It is useful when you want a managed sandbox that runs a coding agent (such as OpenClaw or Hermes) that you can chat with and connect to messaging channels, but you do not want kagent to package and run a full agent runtime inside the workload.
`AgentHarness` resources appear alongside agents in kagent APIs and status views, but they are not the same thing as `Agent` or `SandboxAgent`.
## How it differs from agents
- `Agent` runs a kagent-managed agent runtime, such as a declarative agent or a bring-your-own container.
-- `SandboxAgent` runs an agent runtime inside a restricted sandboxed workload.
-- `AgentHarness` provisions the execution environment itself. The selected backend decides what is installed and how the environment is bootstrapped.
+- `SandboxAgent` runs a (Go) declarative agent runtime inside a sandboxed Agent Substrate actor.
+- `AgentHarness` provisions the execution environment itself and runs a third-party coding agent inside it. The selected backend decides what is installed and how the environment is bootstrapped.
-Think of `AgentHarness` as lifecycle management for a remote shell or VM-like sandbox. It gives kagent a Kubernetes-native handle for creating, tracking, deleting, and surfacing that environment.
+Think of `AgentHarness` as lifecycle management for a remote coding-agent sandbox. It gives kagent a Kubernetes-native handle for creating, tracking, deleting, and surfacing that environment, plus a standard chat surface to interact with it.
## Backend model
@@ -31,43 +31,74 @@ The `spec.backend` field selects the backend implementation.
| Backend | Purpose |
| --- | --- |
| `openclaw` | Provisions an OpenClaw-compatible sandbox and writes OpenClaw configuration when a `ModelConfig` is referenced. |
-| `nemoclaw` | Uses the OpenClaw/NemoClaw backend path while preserving a distinct backend value for NemoClaw-oriented environments. |
| `hermes` | Provisions a Hermes sandbox and writes Hermes configuration plus environment files for supported messaging channels. |
-All backends use the same top-level `AgentHarness` shape: `backend`, `description`, `image`, `env`, `network`, `modelConfigRef`, and `channels`.
+All backends use the same top-level `AgentHarness` shape: `backend`, `substrate`, `description`, `image`, `env`, `modelConfigRef`, and `channels`.
-## Lifecycle and status
+## Runtime: Agent Substrate
-When the controller reconciles an `AgentHarness`, it translates the Kubernetes spec into an OpenShell sandbox request. If the sandbox already exists, reconciliation is idempotent and kagent reuses it.
+Every `AgentHarness` runs on [Agent Substrate](/docs/kagent/concepts/agent-substrate). The `spec.substrate` field is required and configures the Substrate provisioning stack:
-The resource reports two primary conditions:
+- `workerPoolRef` — references an existing `WorkerPool` in the harness namespace. When unset, the controller uses its configured default WorkerPool.
+- `snapshotsConfig` — configures where actor memory snapshots are stored. Defaults to `gs://ate-snapshots//` when unset.
+- `workloadImage` — overrides the default backend sandbox image used in the generated `ActorTemplate`.
-- `Accepted` tells you whether kagent accepted the spec and could hand it to the selected backend.
-- `Ready` tells you whether the backend sandbox is available.
+When the controller reconciles an `AgentHarness`, it generates a per-harness `ActorTemplate` and waits for its golden snapshot to become Ready. A single shared actor is then created on demand from that template on the first chat connection. Every chat is multiplexed as an ACP session inside that one long-lived actor.
-Once the sandbox exists, `.status.backendRef` records the backend and sandbox ID, and `.status.connection.endpoint` contains the connection hint returned by kagent.
+## Lifecycle and status
-## Models and images
+The resource reports these primary conditions:
-`spec.modelConfigRef` points at a kagent `ModelConfig`. OpenClaw-compatible backends translate that model configuration into OpenClaw bootstrap config. Hermes uses the referenced model while building its Hermes configuration.
+- `Accepted` tells you whether kagent accepted the spec and could hand it to the selected backend.
+- `Ready` tells you whether the harness `ActorTemplate` golden snapshot is ready. Once ready, the harness can serve chat sessions.
+
+`.status.backendRef` records the backend and instance ID, and `.status.connection.endpoint` contains the connection hint returned by kagent.
+
+## Chatting with a harness over ACP
+
+kagent talks to harness backends using the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/), a JSON-RPC protocol for driving coding agents. Both OpenClaw and Hermes implement ACP.
+
+Because Substrate exposes only network ingress into actors (no SSH or exec), kagent runs an in-sandbox `acp-shim` that bridges the agent's stdio ACP server to a WebSocket endpoint. The kagent controller connects to that endpoint and exposes the harness as a regular agent in the kagent UI and API:
+
+```mermaid
+flowchart TB
+ client["kagent UI / A2A client"]
+ controller["kagent controller
A2A↔ACP bridge (ACP client)"]
+ subgraph actor["Substrate actor"]
+ shim["acp-shim (WS ↔ stdio)"]
+ backend["openclaw acp / hermes acp"]
+ shim --> backend
+ end
+ client -->|"A2A (JSON-RPC over HTTP/SSE)"| controller
+ controller -->|"ACP over WebSocket (Substrate ingress)"| shim
+ client:::external
+ controller:::internal
+ shim:::internal
+ backend:::internal
+ classDef internal stroke:#a78bfa,fill:transparent
+ classDef external stroke:#fb923c,fill:transparent
+ style actor stroke:#2962FF,fill:transparent
+```
+
+This means you can open a harness in the kagent UI and chat with it like any other agent — see streamed tool activity and answer tool-approval prompts — without any backend-specific UI. Tool approvals from the harness map onto kagent's human-in-the-loop flow.
-If `spec.image` is omitted, kagent uses the default base image for the selected backend. Set `spec.image` only when you have a backend-compatible custom image.
+## Models and images
-## Network access
+`spec.modelConfigRef` points at a kagent `ModelConfig`. OpenClaw-compatible backends translate that model configuration into OpenClaw bootstrap config. Hermes uses the referenced model while building its Hermes configuration.
-`spec.network.allowedDomains` limits outbound access from the harness when the backend supports network policy. Keep this list focused on the APIs the harness needs, such as model provider endpoints or messaging-provider APIs.
+If `spec.image` is omitted, kagent uses the default sandbox base image for the selected backend. Set `spec.image` only when you have a backend-compatible custom image.
## Channels
`spec.channels` declares the external messaging platform (such as Slack) that you want to integrate with the harness. Each channel has a stable `name`, a `type`, and exactly one matching channel spec.
-Slack has backend-specific settings because OpenClaw/NemoClaw and Hermes use Slack differently:
+Slack has backend-specific settings because OpenClaw and Hermes use Slack differently:
-- OpenClaw and NemoClaw settings live under `slack.openclaw` and configure channel access, allowlisted Slack channels, and interactive replies.
+- OpenClaw settings live under `slack.openclaw` and configure channel access, allowlisted Slack channels, and interactive replies.
- Hermes settings live under `slack.hermes` and configure allowed Slack users plus the home channel used for scheduled messages.
-The API uses CEL validation to ensure Slack settings match the selected backend. A Hermes harness must use `slack.hermes`; an OpenClaw or NemoClaw harness must use `slack.openclaw`.
+The API uses CEL validation to ensure Slack settings match the selected backend. A Hermes harness must use `slack.hermes`; an OpenClaw harness must use `slack.openclaw`.
## Next steps
-For OpenShell installation and kagent Helm values, see [Enable AgentHarness support](/docs/kagent/introduction/installation#enable-agentharness-support). For complete YAML examples, including Slack token references and backend-specific Slack settings, see the [Agent Harness example](/docs/kagent/examples/agent-harness). For the generated schema, see the [API reference](/docs/kagent/resources/api-ref#agentharness).
+For enabling Agent Substrate so the controller can provision harnesses, see [Enable AgentHarness support](/docs/kagent/introduction/installation#enable-agentharness-support). For complete YAML examples, including Slack token references and backend-specific Slack settings, see the [Agent Harness example](/docs/kagent/examples/agent-harness). For the generated schema, see the [API reference](/docs/kagent/resources/api-ref#agentharness).
diff --git a/src/app/docs/kagent/concepts/agent-substrate/page.mdx b/src/app/docs/kagent/concepts/agent-substrate/page.mdx
index e9531efa..7acbbfd1 100644
--- a/src/app/docs/kagent/concepts/agent-substrate/page.mdx
+++ b/src/app/docs/kagent/concepts/agent-substrate/page.mdx
@@ -17,7 +17,7 @@ Agent Substrate is a Kubernetes-native runtime for running AI agents and other s
kagent can run workloads on Agent Substrate in two ways:
- **Declarative agents** — A declarative `Agent` describes its model, instructions, and tools (see [Agents](/docs/kagent/concepts/agents)). Its sandboxed variant, the [`SandboxAgent`](/docs/kagent/resources/api-ref) CRD, lets you run a (Go) declarative agent on Agent Substrate.
-- **AgentHarness** — The [`AgentHarness`](/docs/kagent/concepts/agent-harness) CRD provisions a long-running execution environment. Select Agent Substrate as its runtime by setting `runtime` to `substrate`; kagent then generates a per-harness `ActorTemplate` and creates an `Actor` from it, referencing a `WorkerPool` for capacity.
+- **AgentHarness** — The [`AgentHarness`](/docs/kagent/concepts/agent-harness) CRD provisions a long-running execution environment for a coding agent (OpenClaw or Hermes). It always runs on Agent Substrate: kagent generates a per-harness `ActorTemplate` and creates an `Actor` from it on demand, referencing a `WorkerPool` for capacity.
## Why Agent Substrate
@@ -67,12 +67,13 @@ Run a (Go) declarative agent on Agent Substrate by creating a `SandboxAgent` res
### AgentHarness
-Set the harness runtime to `substrate` and provide the substrate configuration. The key fields are:
+An `AgentHarness` always runs on Agent Substrate; `spec.substrate` is required. The key fields are:
- `workerPoolRef` — references an existing WorkerPool in the harness namespace. When unset, the controller uses its configured default WorkerPool.
- `snapshotsConfig` — configures where actor memory snapshots are stored. Defaults to `gs://ate-snapshots//` when unset.
-- `workloadImage` — overrides the default NemoClaw/OpenClaw sandbox image used in the generated ActorTemplate.
-- `gatewayTokenSecretRef` — references a Secret (with a `token` key) holding the OpenClaw gateway Bearer token. Prefer this over an inline `gatewayToken` for production secrets.
+- `workloadImage` — overrides the default OpenClaw or Hermes sandbox image used in the generated ActorTemplate.
+
+kagent talks to the harness over the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) so you can chat with it from the kagent UI. See the [Agent Harness concept page](/docs/kagent/concepts/agent-harness) for details.
See the [API reference](/docs/kagent/resources/api-ref) for the full `AgentHarnessSubstrateSpec` schema.
diff --git a/src/app/docs/kagent/concepts/agents/page.mdx b/src/app/docs/kagent/concepts/agents/page.mdx
index c72cf2dc..4cd4f5c4 100644
--- a/src/app/docs/kagent/concepts/agents/page.mdx
+++ b/src/app/docs/kagent/concepts/agents/page.mdx
@@ -300,9 +300,9 @@ Compaction removes older conversation events to free up space in the context win
## Sandboxed Agents
-You can run agents in an isolated sandbox by creating a `SandboxAgent` resource instead of a regular `Agent`. The `SandboxAgent` spec is identical to the `Agent` spec, but the kagent controller creates an upstream [agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox) workload instead of a Deployment. Sandboxed agents enforce process isolation, deny all outbound network access by default, and restrict filesystem writes to the working directory and `/tmp`. To allow outbound access to specific domains, set the `spec.sandbox.network.allowedDomains` field.
+You can run a declarative agent in an isolated sandbox by creating a `SandboxAgent` resource instead of a regular `Agent`. A `SandboxAgent` runs on [Agent Substrate](/docs/kagent/concepts/agent-substrate): the kagent controller runs it as a gVisor-sandboxed actor instead of a Deployment, snapshotting it to object storage when idle and rehydrating it on demand. The spec mirrors the `Agent` spec, with a few constraints: sandboxed agents always use the Go ADK runtime, and `spec.skills` and `BYO` agents are not supported. Configure substrate placement with the optional `spec.substrate` field (for example, `workerPoolRef`).
-For setup steps, see the [Agent Sandbox example](/docs/kagent/examples/agent-sandbox).
+For setup steps, see the [Agent Substrate example](/docs/kagent/examples/agent-substrate).
## Agents as Tools
diff --git a/src/app/docs/kagent/concepts/page.mdx b/src/app/docs/kagent/concepts/page.mdx
index 341a0749..aec49eca 100644
--- a/src/app/docs/kagent/concepts/page.mdx
+++ b/src/app/docs/kagent/concepts/page.mdx
@@ -24,7 +24,7 @@ import QuickLink from '@/components/quick-link';
-
+
diff --git a/src/app/docs/kagent/examples/agent-harness/page.mdx b/src/app/docs/kagent/examples/agent-harness/page.mdx
index 75975559..b021131e 100644
--- a/src/app/docs/kagent/examples/agent-harness/page.mdx
+++ b/src/app/docs/kagent/examples/agent-harness/page.mdx
@@ -1,44 +1,42 @@
---
title: "Agent Harness"
pageOrder: 8
-description: "Provision OpenClaw, NemoClaw, and Hermes sandboxes with the AgentHarness API."
+description: "Provision OpenClaw and Hermes sandboxes on Agent Substrate with the AgentHarness API."
---
import { VERSIONS } from "../../../_constants";
export const metadata = {
title: "Agent Harness",
- description: "Provision OpenClaw, NemoClaw, and Hermes sandboxes with the AgentHarness API.",
+ description: "Provision OpenClaw and Hermes sandboxes on Agent Substrate with the AgentHarness API.",
author: "kagent.dev"
};
# Agent Harness
-`AgentHarness` creates a long-running remote execution environment through an OpenShell gateway. Unlike an `Agent` or `SandboxAgent`, it does not package a kagent runtime into the workload. The backend provisions a sandbox that operators, tools, or chat integrations can attach to.
+`AgentHarness` creates a long-running remote execution environment on [Agent Substrate](/docs/kagent/concepts/agent-substrate). Unlike an `Agent` or `SandboxAgent`, it does not package a kagent runtime into the workload. The backend provisions a sandbox that runs a coding agent (OpenClaw or Hermes), which you can chat with from the kagent UI and wire into messaging channels.
-Use `AgentHarness` when you want kagent to manage the lifecycle of an OpenClaw, NemoClaw, or Hermes sandbox and surface it in the kagent API/UI alongside regular agents.
+Use `AgentHarness` when you want kagent to manage the lifecycle of an OpenClaw or Hermes sandbox and surface it in the kagent API/UI alongside regular agents.
## Before you begin
-1. Install kagent v0.9.2 or later by following the [quick start](/docs/kagent/getting-started/quickstart) guide.
-2. Install and expose an OpenShell gateway that the kagent controller can reach over gRPC. For Helm-based setup instructions, see [Enable AgentHarness support](/docs/kagent/introduction/installation#enable-agentharness-support).
-3. Configure the kagent controller with the gateway address. For example, set the controller environment variable `OPENSHELL_GATEWAY_URL` to a gRPC target such as `dns:///openshell.openshell.svc:443`.
+1. Install kagent v0.9.9 or later by following the [quick start](/docs/kagent/getting-started/quickstart) guide.
+2. Install Agent Substrate and enable the substrate integration in kagent. For Helm-based setup instructions, see [Enable AgentHarness support](/docs/kagent/introduction/installation#enable-agentharness-support) and the [Agent Substrate example](/docs/kagent/examples/agent-substrate).
-When `OPENSHELL_GATEWAY_URL` is empty, the AgentHarness backends are not registered by the controller.
+When the substrate integration is not enabled, the controller cannot provision AgentHarness resources.
## Choose a backend
`spec.backend` selects the sandbox backend.
- `openclaw` provisions an OpenClaw-compatible sandbox. When `modelConfigRef` is set, kagent translates the referenced `ModelConfig` and writes OpenClaw configuration into the sandbox.
-- `nemoclaw` uses the same kagent backend path as `openclaw`, but lets you label the resource for NemoClaw-oriented usage.
- `hermes` provisions a Hermes sandbox. kagent writes Hermes configuration and environment files into the sandbox and wires supported messaging channels into Hermes environment variables.
-All three backends share the same top-level `AgentHarness` shape: `backend`, optional `description`, optional `image`, optional `env`, optional `network`, optional `modelConfigRef`, and optional `channels`.
+Both backends share the same top-level `AgentHarness` shape: `backend`, required `substrate`, optional `description`, optional `image`, optional `env`, optional `modelConfigRef`, and optional `channels`.
## Create an OpenClaw harness
-The following resource creates an OpenClaw harness and lets it reach the OpenAI and Slack APIs.
+The following resource creates an OpenClaw harness on Agent Substrate.
```yaml
apiVersion: kagent.dev/v1alpha2
@@ -50,16 +48,13 @@ spec:
backend: openclaw
description: "OpenClaw shell for platform experiments"
modelConfigRef: default-model-config
- network:
- allowedDomains:
- - api.openai.com
- - slack.com
- - api.slack.com
- - hooks.slack.com
- - wss-primary.slack.com
- - wss-backup.slack.com
+ substrate:
+ workerPoolRef:
+ name: kagent-default
```
+`spec.substrate` is required. Set `workerPoolRef` to an existing `WorkerPool`, or omit it to use the controller's configured default WorkerPool. You can also set `substrate.snapshotsConfig.location` (a `gs://` prefix) and `substrate.workloadImage` to override the default backend image.
+
Apply the resource and wait for it to become ready.
```bash
@@ -88,13 +83,9 @@ spec:
backend: hermes
description: "Hermes shell for scheduled and chat-driven workflows"
modelConfigRef: default-model-config
- network:
- allowedDomains:
- - api.openai.com
- - slack.com
- - api.slack.com
- - wss-primary.slack.com
- - wss-backup.slack.com
+ substrate:
+ workerPoolRef:
+ name: kagent-default
```
If `spec.image` is omitted, kagent uses the backend's default sandbox base image. Set `spec.image` only when you need a custom image that is compatible with the selected backend.
@@ -118,11 +109,11 @@ stringData:
Backend-specific Slack settings are nested under the backend name. The API validates this with CEL:
- `backend: hermes` requires `slack.hermes` and rejects `slack.openclaw`.
-- `backend: openclaw` and `backend: nemoclaw` require `slack.openclaw` and reject `slack.hermes`.
+- `backend: openclaw` requires `slack.openclaw` and rejects `slack.hermes`.
### OpenClaw Slack
-OpenClaw and NemoClaw Slack settings control channel access and interactive replies.
+OpenClaw Slack settings control channel access and interactive replies.
```yaml
apiVersion: kagent.dev/v1alpha2
@@ -133,6 +124,9 @@ metadata:
spec:
backend: openclaw
modelConfigRef: default-model-config
+ substrate:
+ workerPoolRef:
+ name: kagent-default
channels:
- name: platform
type: slack
@@ -169,6 +163,9 @@ metadata:
spec:
backend: hermes
modelConfigRef: default-model-config
+ substrate:
+ workerPoolRef:
+ name: kagent-default
channels:
- name: platform
type: slack
@@ -202,14 +199,29 @@ kubectl -n kagent get agentharnesses
kubectl -n kagent describe agentharness hermes-slack
```
-The `Accepted` condition reports whether kagent accepted the spec. The `Ready` condition reports whether the backend sandbox is ready. Once ready, `.status.backendRef` identifies the sandbox in the OpenShell control plane and `.status.connection.endpoint` shows the connection hint returned by kagent.
+The `Accepted` condition reports whether kagent accepted the spec. The `Ready` condition reports whether the harness `ActorTemplate` golden snapshot is ready. Once ready, `.status.backendRef` identifies the harness instance and `.status.connection.endpoint` shows the connection hint returned by kagent.
+
+## Chat with the harness
+
+Once the harness is `Ready`, it appears in the kagent UI alongside your other agents. kagent talks to the backend over the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/): an in-sandbox `acp-shim` bridges the agent's stdio ACP server to a WebSocket endpoint, and the controller exposes it through the standard agent chat surface.
+
+1. Port-forward the kagent UI.
+
+ ```bash
+ kubectl port-forward -n kagent svc/kagent-ui 8001:8080
+ ```
+
+2. Open [http://localhost:8001](http://localhost:8001), select your harness (for example `kagent/openclaw-shell`) from the Agents list, and send a message.
+
+The first chat connection creates a shared Substrate actor from the harness template; every chat is multiplexed as an ACP session inside that actor. You see streamed tool activity, and any tool-approval prompts the backend raises are surfaced through kagent's [human-in-the-loop](/docs/kagent/examples/human-in-the-loop) flow.
## Troubleshooting
If the harness is not accepted or ready, check these common causes.
-- The kagent controller was not configured with `OPENSHELL_GATEWAY_URL`, so AgentHarness backends were not registered.
-- The OpenShell gateway address is not reachable from the controller pod.
+- The kagent controller was not installed with the Agent Substrate integration enabled, so AgentHarness resources cannot be provisioned.
+- The referenced `WorkerPool` does not exist, or no default WorkerPool is configured.
+- The `ActorTemplate` golden snapshot has not finished building yet — wait for the `Ready` condition.
- `modelConfigRef` points to a missing or unsupported `ModelConfig`.
- A Slack channel has the wrong backend settings, such as `slack.hermes` on an OpenClaw harness or `slack.openclaw` on a Hermes harness.
- A Slack credential uses neither `value` nor `valueFrom`, or sets both.
diff --git a/src/app/docs/kagent/examples/agent-sandbox/page.mdx b/src/app/docs/kagent/examples/agent-sandbox/page.mdx
deleted file mode 100644
index 1333b191..00000000
--- a/src/app/docs/kagent/examples/agent-sandbox/page.mdx
+++ /dev/null
@@ -1,296 +0,0 @@
----
-title: "Agent Sandbox"
-pageOrder: 1
-description: "Run agents in isolated sandboxes with deny-by-default networking and filesystem restrictions."
----
-
-import { VERSIONS } from "../../../_constants";
-
-export const metadata = {
- title: "Agent Sandbox",
- description: "Run agents in isolated sandboxes with deny-by-default networking and filesystem restrictions.",
- author: "kagent.dev"
-};
-
-# Agent Sandbox
-
-Sandboxed agents run in isolated pods managed by the upstream [agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox) project. Each sandbox enforces process isolation, denies all outbound network access by default, and restricts filesystem writes to the working directory and `/tmp`.
-
-## About
-
-When the kagent controller reconciles a `SandboxAgent`, it does the following.
-
-1. Generates an `srt-settings.json` file with the sandbox runtime configuration and mounts it into the pod.
-2. Creates an upstream `agents.x-k8s.io/v1alpha1` Sandbox resource instead of a Deployment.
-3. Delegates pod lifecycle to the agent-sandbox controller, which manages process-level isolation.
-
-The default runtime settings are:
-
-| Category | Default |
-| --- | --- |
-| Network | All outbound denied unless listed in `allowedDomains` |
-| Filesystem writes | Allowed in `.` (working directory) and `/tmp` |
-| Filesystem reads | Unrestricted |
-
-## Before you begin
-
-1. Install kagent v0.9.0 or later by following the [quick start](/docs/kagent/getting-started/quickstart) guide.
-
-2. Install the agent-sandbox controller and CRDs. The example uses version {VERSIONS.agentSandbox}.
-
- ```bash
- kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/manifest.yaml
- kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/extensions.yaml
- ```
-
-3. If you installed agent-sandbox after kagent was already running, restart the kagent controller so it registers the new Sandbox API.
-
- ```bash
- kubectl -n kagent rollout restart deploy/kagent-controller
- ```
-
-## Create a sandboxed agent
-
-A `SandboxAgent` has the same spec as a regular `Agent`. The only difference is `kind: SandboxAgent`. Instead of creating a Deployment, the kagent controller creates an upstream `agents.x-k8s.io` Sandbox CR.
-
-1. Apply the following SandboxAgent resource.
-
- ```yaml
- kubectl apply -f - < SKILL.md <<'EOF'
- ---
- name: fetch-url-skill
- description: Fetch a URL using curl and return the HTTP status code. Use this when the user asks to fetch, get, or download a URL.
- ---
-
- # Fetch URL skill
-
- Use this skill when the user asks you to fetch, GET, or test a URL.
-
- ## Instructions
-
- - Run the `bash` tool with the command `curl -sS -o /dev/null -w "HTTP %{http_code}\n" --max-time 10 ` where `` is the URL the user wants to fetch.
- - Report the exact HTTP status line back to the user, including any error message that curl prints.
- EOF
- ```
-
-2. Build the skill image and push it to a local registry. For full prerequisites and registry setup, see [Add skills to agents](/docs/kagent/examples/skills).
-
- ```bash
- cat > Dockerfile <<'EOF'
- FROM scratch
- COPY . /
- EOF
- docker build -t localhost:5000/fetch-url-skill:latest .
- docker push localhost:5000/fetch-url-skill:latest
- ```
-
-### Step 2: Add the skill to the SandboxAgent
-
-Re-apply `sandbox-agent` with the skill reference and an updated system message that points the agent at the skill.
-
-```yaml
-kubectl apply -f - <//` endpoint. Sandboxed agents support exactly one chat session, so the second request must reuse the `contextId` returned by the first.
-
-> Alternatively, you can [open the agent in the kagent UI](/docs/kagent/getting-started/first-agent#testing-the-agent) and then send requests through the UI's chat interface to try to access allowed or denied domains.
-
-1. Port-forward the kagent controller.
-
- ```bash
- kubectl -n kagent port-forward svc/kagent-controller 8083:8083
- ```
-
-2. Send a request that hits an allowed domain. Capture the `contextId` from the response.
-
- ```bash
- UUID=$(uuidgen)
- curl -sS -X POST 'http://localhost:8083/api/a2a-sandboxes/kagent/sandbox-agent/' \
- -H 'Content-Type: application/json' \
- -d "{\"jsonrpc\":\"2.0\",\"id\":\"$UUID\",\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"user\",\"parts\":[{\"kind\":\"text\",\"text\":\"Fetch https://api.github.com/zen and tell me exactly what curl returned\"}],\"messageId\":\"$UUID\",\"kind\":\"message\"}}}"
- ```
-
- The agent runs `curl https://api.github.com/zen` through `srt`, which lets the request through. Example response (truncated):
-
- ```json
- {
- "result": {
- "status": { "state": "completed" },
- "contextId": "707433f6-6d11-4a4d-9756-b4e0b1d9203a",
- "artifacts": [{
- "parts": [{
- "kind": "text",
- "text": "The exact response from curl when fetching https://api.github.com/zen is: ..."
- }]
- }]
- }
- }
- ```
-
-3. Send a second request with a denied domain, reusing the `contextId` from the first response.
-
- ```bash
- CTX="707433f6-6d11-4a4d-9756-b4e0b1d9203a" # from previous response
- UUID=$(uuidgen)
- curl -sS -X POST 'http://localhost:8083/api/a2a-sandboxes/kagent/sandbox-agent/' \
- -H 'Content-Type: application/json' \
- -d "{\"jsonrpc\":\"2.0\",\"id\":\"$UUID\",\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"user\",\"parts\":[{\"kind\":\"text\",\"text\":\"Fetch https://example.com and tell me exactly what curl returned, including any error messages\"}],\"messageId\":\"$UUID\",\"contextId\":\"$CTX\",\"kind\":\"message\"}}}"
- ```
-
- The sandbox blocks the request because `example.com` is not in the allowlist. The agent reports the curl error verbatim:
-
- ```txt
- The exact response from curl when fetching https://example.com is:
-
- curl: (56) CONNECT tunnel failed, response 403
- ```
-
- The `403` comes from `srt`'s outbound HTTPS proxy, which rejects connections to hosts outside `allowedDomains`. Add `example.com` to `spec.sandbox.network.allowedDomains` and reapply if you want to permit it.
-
-## Cleanup
-
-When you are done, remove the resources that you created.
-
-1. Delete the SandboxAgent. The kagent controller deletes the upstream Sandbox resource and pod with it.
-
- ```bash
- kubectl delete sandboxagent sandbox-agent -n kagent
- ```
-
-2. Remove the skill image from your local registry and delete the skill directory.
-
- ```bash
- docker rmi localhost:5000/fetch-url-skill:latest
- cd ..
- rm -rf fetch-url-skill
- ```
-
-3. Optionally, uninstall the agent-sandbox controller and CRDs if you no longer need sandboxed agents in this cluster.
-
- ```bash
- kubectl delete -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/extensions.yaml
- kubectl delete -f https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v{VERSIONS.agentSandbox}/manifest.yaml
- ```
-
-## Next steps
-
-Continue configuring your sandboxed agent, such as with [skills](/docs/kagent/examples/skills), [tools](/docs/kagent/concepts/tools), or [human-in-the-loop](/docs/kagent/examples/human-in-the-loop) safeguards.
diff --git a/src/app/docs/kagent/examples/agent-substrate/page.mdx b/src/app/docs/kagent/examples/agent-substrate/page.mdx
index f5d67ca8..85ce8ece 100644
--- a/src/app/docs/kagent/examples/agent-substrate/page.mdx
+++ b/src/app/docs/kagent/examples/agent-substrate/page.mdx
@@ -127,7 +127,7 @@ If you see `CreateContainerConfigError` on the default agent pods, the secret di
`substrateWorkerPool.replicas=1` is the chart default. One worker is enough for a declarative-only walkthrough: session actors release their slot the moment they snapshot back to object storage, so a single worker can serve many sequential sessions. Increase the replica count when:
-- You add a long-lived `AgentHarness`. The `ahr-<...>` actor pins a slot for the lifetime of the CR, so you need at least `1 + (number of harnesses)`.
+- You add a long-lived `AgentHarness`. Its shared actor is created on the first chat connect and then pins a slot, so you need at least `1 + (number of active harnesses)`.
- You want simultaneous, overlapping declarative sessions.
You can change the size three ways, depending on how permanent you want the change.
@@ -154,7 +154,7 @@ Open [http://localhost:8001](http://localhost:8001). Skip the first-run wizard i
## Step 5: Create a declarative agent on substrate
-A `SandboxAgent` with `platform: substrate` and a `substrate.workerPoolRef` runs as a substrate actor instead of a plain Deployment. Pick one of the two paths below.
+A `SandboxAgent` runs as a substrate actor instead of a plain Deployment. Set `substrate.workerPoolRef` to target a specific WorkerPool, or omit it to use the controller's default. Pick one of the two paths below.
### Option A: Via the UI
@@ -170,7 +170,7 @@ A `SandboxAgent` with `platform: substrate` and a `substrate.workerPoolRef` runs
When asked who you are, say "I am hello-substrate, a Go ADK declarative
agent running inside a gVisor actor."
```
-3. In the **Sandbox** / **Platform** section (the label depends on UI version), set **Platform** to **`substrate`** and select the worker pool `kagent-default`.
+3. In the **Sandbox** section, select the worker pool `kagent-default`.
4. Save.
### Option B: Via kubectl
@@ -192,7 +192,6 @@ spec:
You are a friendly assistant living inside an Agent Substrate sandbox.
When asked who you are, say "I am hello-substrate, a Go ADK declarative
agent running inside a gVisor actor."
- platform: substrate
substrate:
workerPoolRef:
name: kagent-default
@@ -226,5 +225,4 @@ kind delete cluster --name kagent-substrate
## Next steps
- [Agent Substrate concept page](/docs/kagent/concepts/agent-substrate) — runtime architecture and how snapshots, actors, and worker pools fit together.
-- [AgentHarness](/docs/kagent/examples/agent-harness) — provision long-running OpenClaw, NemoClaw, or Hermes sandboxes. Set `runtime: substrate` to run a harness on Agent Substrate too.
-- [Agent Sandbox](/docs/kagent/examples/agent-sandbox) — the upstream `kubernetes-sigs/agent-sandbox` backend for `SandboxAgent`, a separate path from substrate.
+- [AgentHarness](/docs/kagent/examples/agent-harness) — provision long-running OpenClaw and Hermes coding-agent sandboxes on Agent Substrate and chat with them over ACP.
diff --git a/src/app/docs/kagent/examples/page.mdx b/src/app/docs/kagent/examples/page.mdx
index 19bd89db..ddc46915 100644
--- a/src/app/docs/kagent/examples/page.mdx
+++ b/src/app/docs/kagent/examples/page.mdx
@@ -30,9 +30,8 @@ import QuickLink from '@/components/quick-link';
-
-
+
diff --git a/src/app/docs/kagent/introduction/installation/page.mdx b/src/app/docs/kagent/introduction/installation/page.mdx
index f923b5bf..c31bce32 100644
--- a/src/app/docs/kagent/introduction/installation/page.mdx
+++ b/src/app/docs/kagent/introduction/installation/page.mdx
@@ -201,46 +201,33 @@ Review the following advanced configuration options that you might want to set u
### Enable AgentHarness support
-`AgentHarness` resources require an OpenShell gateway that the kagent controller can reach. To enable the AgentHarness backends, install OpenShell and set `OPENSHELL_GATEWAY_URL` on the kagent controller deployment.
+`AgentHarness` resources run on [Agent Substrate](/docs/kagent/concepts/agent-substrate). To enable them, install Agent Substrate and turn on the substrate integration in kagent. When the integration is disabled, the controller cannot provision AgentHarness resources.
-1. Install OpenShell in your cluster.
+1. Install Agent Substrate (CRDs, then the control plane and data plane).
```bash
- kubectl create namespace openshell
- kubectl -n openshell create secret generic openshell-ssh-handshake \
- --from-literal=secret="$(openssl rand -hex 32)"
-
- kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/latest/download/manifest.yaml
-
-
- helm upgrade --install openshell oci://ghcr.io/nvidia/openshell/helm-chart \
- --version 0.0.49 \
- --namespace openshell \
- --create-namespace \
- --values - <<'EOF'
- server:
- disableTls: true
- auth:
- allowUnauthenticatedUsers: true
- service:
- metricsPort: 0
- EOF
-
- This example disables TLS and authentication. For production environments, configure TLS and authentication according to your OpenShell requirements.
+ helm upgrade --install substrate-crds \
+ oci://ghcr.io/kagent-dev/substrate/helm/substrate-crds \
+ --namespace ate-system --create-namespace --wait
+
+ helm upgrade --install substrate \
+ oci://ghcr.io/kagent-dev/substrate/helm/substrate \
+ --namespace ate-system --wait --timeout 10m
+ ```
-2. Configure the kagent controller with the OpenShell gateway URL.
+2. Install (or upgrade) kagent with the substrate integration and a WorkerPool enabled.
**Helm values file:**
```yaml
controller:
- openshell:
- enabled: "true"
- env:
- - name: OPENSHELL_GATEWAY_URL
- value: dns:///openshell.openshell.svc:8080
- - name: OPENSHELL_INSECURE
- value: "true"
+ substrate:
+ enabled: true
+ ateApiEndpoint: dns:///api.ate-system.svc:443
+ ateApiInsecure: true
+ substrateWorkerPool:
+ create: true
+ replicas: 1
```
**Helm `--set` flags:**
@@ -248,17 +235,16 @@ Review the following advanced configuration options that you might want to set u
```bash
helm upgrade --install kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \
--namespace kagent \
- --set controller.openshell.enabled=true \
- --set 'controller.env[0].name=OPENSHELL_GATEWAY_URL' \
- --set-string 'controller.env[0].value=dns:///openshell.openshell.svc:8080' \
- --set 'controller.env[1].name=OPENSHELL_INSECURE' \
- --set-string 'controller.env[1].value=true'
-
+ --set controller.substrate.enabled=true \
+ --set controller.substrate.ateApiEndpoint=dns:///api.ate-system.svc:443 \
+ --set controller.substrate.ateApiInsecure=true \
+ --set substrateWorkerPool.create=true \
+ --set substrateWorkerPool.replicas=1
```
- If you already configure `controller.env`, merge the `OPENSHELL_GATEWAY_URL` entry into your existing values. When `OPENSHELL_GATEWAY_URL` is empty, the controller does not register AgentHarness backends.
+ Pin the kagent chart to v0.9.9 or later — earlier versions do not include the `controller.substrate.*` and `substrateWorkerPool.*` values.
-For more information about creating harness resources, see [Agent Harness](/docs/kagent/examples/agent-harness).
+For an end-to-end walkthrough on a kind cluster, see the [Agent Substrate example](/docs/kagent/examples/agent-substrate). For more information about creating harness resources, see [Agent Harness](/docs/kagent/examples/agent-harness).
### Database configuration
diff --git a/src/config/navigation.json b/src/config/navigation.json
index ea7d4bbc..77ba7ad6 100644
--- a/src/config/navigation.json
+++ b/src/config/navigation.json
@@ -92,7 +92,7 @@
{
"title": "Agent Harness",
"href": "/docs/kagent/concepts/agent-harness",
- "description": "Understand AgentHarness resources, OpenShell-backed execution environments, and backend-specific channel configuration."
+ "description": "Understand AgentHarness resources, Substrate-backed execution environments, and how kagent talks to them over the Agent Client Protocol (ACP)."
},
{
"title": "Agent Substrate",
@@ -178,11 +178,6 @@
"href": "/docs/kagent/examples/a2a-byo",
"description": "Bring your own ADK agent to kagent"
},
- {
- "title": "Agent Sandbox",
- "href": "/docs/kagent/examples/agent-sandbox",
- "description": "Run agents in isolated sandboxes with deny-by-default networking and filesystem restrictions."
- },
{
"title": "agentgateway",
"href": "/docs/kagent/examples/agentgateway",
@@ -236,7 +231,7 @@
{
"title": "Agent Harness",
"href": "/docs/kagent/examples/agent-harness",
- "description": "Provision OpenClaw, NemoClaw, and Hermes sandboxes with the AgentHarness API."
+ "description": "Provision OpenClaw and Hermes sandboxes on Agent Substrate with the AgentHarness API."
},
{
"title": "Agent Substrate",
diff --git a/src/mdx-components.tsx b/src/mdx-components.tsx
index e6a7555c..2d897d51 100644
--- a/src/mdx-components.tsx
+++ b/src/mdx-components.tsx
@@ -4,6 +4,7 @@ import { PlatformTabs, GenericTabs, LLMProviderTabs } from "./components/mdx/pla
import { Tabs } from "./components/mdx/tabs";
import SmartLink from "./components/mdx/smart-link";
import { CodeBlock } from "./components/mdx/code-block";
+import { Mermaid } from "./components/mdx/mermaid";
import { LabCTA } from "./components/mdx/lab-cta";
import { Aside } from "./components/mdx/aside";
import Image from "next/image";
@@ -134,6 +135,10 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
code: ({ children, className = "", ...props }) => {
// Extract language from className if present
const language = className?.replace("language-", "") || "";
+ // Render fenced ```mermaid code blocks as diagrams
+ if (language === "mermaid") {
+ return ;
+ }
return (
{children}