-
Notifications
You must be signed in to change notification settings - Fork 55
add agentharness docs #372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,73 @@ | ||||||
| --- | ||||||
| title: "Agent Harness" | ||||||
| pageOrder: 4 | ||||||
| description: "Understand AgentHarness resources, OpenShell-backed execution environments, and backend-specific channel configuration." | ||||||
| --- | ||||||
|
|
||||||
| export const metadata = { | ||||||
| title: "Agent Harness", | ||||||
| description: "Understand AgentHarness resources, OpenShell-backed execution environments, and backend-specific channel configuration.", | ||||||
| author: "kagent.dev" | ||||||
| }; | ||||||
|
|
||||||
| # Agent Harness | ||||||
|
|
||||||
| An `AgentHarness` is a Kubernetes resource that asks kagent to provision a long-running remote execution environment through an 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. | ||||||
|
|
||||||
| `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. | ||||||
|
|
||||||
| 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. | ||||||
|
|
||||||
| ## Backend model | ||||||
|
|
||||||
| The `spec.backend` field selects the backend implementation. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am wondering if these backends are separate resources that you have to already have deployed to the cluster? |
||||||
|
|
||||||
| | 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`. | ||||||
|
|
||||||
| ## Lifecycle and status | ||||||
|
|
||||||
| 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. | ||||||
|
|
||||||
| The resource reports two primary conditions: | ||||||
|
|
||||||
| - `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. | ||||||
|
|
||||||
| Once the sandbox exists, `.status.backendRef` records the backend and sandbox ID, and `.status.connection.endpoint` contains the connection hint returned by kagent. | ||||||
|
|
||||||
| ## Models and images | ||||||
|
|
||||||
| `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. | ||||||
|
|
||||||
| 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. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the default base image something that kagent sets somewhere? or for nemoclaw would it be something like the most recent tag? |
||||||
|
|
||||||
| ## Network access | ||||||
|
|
||||||
| `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. | ||||||
|
|
||||||
| ## Channels | ||||||
|
|
||||||
| `spec.channels` declares messaging integrations inside the harness environment. Each channel has a stable `name`, a `type`, and exactly one matching channel spec. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| Slack has backend-specific settings because OpenClaw/NemoClaw and Hermes use Slack differently: | ||||||
|
|
||||||
| - OpenClaw and NemoClaw 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`. | ||||||
|
|
||||||
| ## 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). | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| --- | ||
| title: "Agent Harness" | ||
| pageOrder: 8 | ||
| description: "Provision OpenClaw, NemoClaw, and Hermes sandboxes 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.", | ||
| 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. | ||
|
|
||
| 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. | ||
|
|
||
| ## Before you begin | ||
|
|
||
| 1. Install kagent v{VERSIONS.kagent} 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`. | ||
|
|
||
| When `OPENSHELL_GATEWAY_URL` is empty, the AgentHarness backends are not registered by the controller. | ||
|
|
||
| ## 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`. | ||
|
|
||
| ## Create an OpenClaw harness | ||
|
|
||
| The following resource creates an OpenClaw harness and lets it reach the OpenAI and Slack APIs. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have to allowlist the LLM APIs that match the ModelConfig LLM provider that you set up? so this allows OpenAI because the default ModelConfig is for OpenAI. |
||
|
|
||
| ```yaml | ||
| apiVersion: kagent.dev/v1alpha2 | ||
| kind: AgentHarness | ||
| metadata: | ||
| name: openclaw-shell | ||
| namespace: kagent | ||
| 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 | ||
| ``` | ||
|
|
||
| Apply the resource and wait for it to become ready. | ||
|
|
||
| ```bash | ||
| kubectl apply -f openclaw-shell.yaml | ||
| kubectl -n kagent get agentharness openclaw-shell | ||
| ``` | ||
|
|
||
| Example output: | ||
|
|
||
| ```txt | ||
| NAME BACKEND READY ID AGE | ||
| openclaw-shell openclaw True kagent-openclaw-shell 30s | ||
| ``` | ||
|
|
||
| ## Create a Hermes harness | ||
|
|
||
| Hermes uses the same `AgentHarness` API with `spec.backend: hermes`. | ||
|
|
||
| ```yaml | ||
| apiVersion: kagent.dev/v1alpha2 | ||
| kind: AgentHarness | ||
| metadata: | ||
| name: hermes-shell | ||
| namespace: kagent | ||
| 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 | ||
| ``` | ||
|
|
||
| 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. | ||
|
|
||
| ## Configure Slack | ||
|
|
||
| Slack channels require a bot token and an app-level token. Store them in a Kubernetes `Secret` and reference them from the harness. | ||
|
|
||
| ```yaml | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: slack-tokens | ||
| namespace: kagent | ||
| type: Opaque | ||
| stringData: | ||
| bot-token: xoxb-your-bot-token | ||
| app-token: xapp-your-app-token | ||
| ``` | ||
|
|
||
| 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`. | ||
|
|
||
| ### OpenClaw Slack | ||
|
|
||
| OpenClaw and NemoClaw Slack settings control channel access and interactive replies. | ||
|
|
||
| ```yaml | ||
| apiVersion: kagent.dev/v1alpha2 | ||
| kind: AgentHarness | ||
| metadata: | ||
| name: openclaw-slack | ||
| namespace: kagent | ||
| spec: | ||
| backend: openclaw | ||
| modelConfigRef: default-model-config | ||
| channels: | ||
| - name: platform | ||
| type: slack | ||
| slack: | ||
| botToken: | ||
| valueFrom: | ||
| type: Secret | ||
| name: slack-tokens | ||
| key: bot-token | ||
| appToken: | ||
| valueFrom: | ||
| type: Secret | ||
| name: slack-tokens | ||
| key: app-token | ||
| openclaw: | ||
| channelAccess: allowlist | ||
| allowlistChannels: | ||
| - C0123456789 | ||
| interactiveReplies: true | ||
| ``` | ||
|
|
||
| Set `channelAccess` to `open`, `allowlist`, or `disabled`. When `channelAccess` is `allowlist`, `allowlistChannels` must include at least one Slack channel ID. | ||
|
|
||
| ### Hermes Slack | ||
|
|
||
| Hermes Slack settings control allowed users and the home channel used for scheduled messages. | ||
|
|
||
| ```yaml | ||
| apiVersion: kagent.dev/v1alpha2 | ||
| kind: AgentHarness | ||
| metadata: | ||
| name: hermes-slack | ||
| namespace: kagent | ||
| spec: | ||
| backend: hermes | ||
| modelConfigRef: default-model-config | ||
| channels: | ||
| - name: platform | ||
| type: slack | ||
| slack: | ||
| botToken: | ||
| valueFrom: | ||
| type: Secret | ||
| name: slack-tokens | ||
| key: bot-token | ||
| appToken: | ||
| valueFrom: | ||
| type: Secret | ||
| name: slack-tokens | ||
| key: app-token | ||
| hermes: | ||
| allowedUserIDs: | ||
| - U01234567 | ||
| - U89ABCDEF | ||
| homeChannel: C0123456789 | ||
| homeChannelName: platform-alerts | ||
| ``` | ||
|
|
||
| Use `allowedUserIDsFrom` instead of `allowedUserIDs` when you want to load the Slack member allowlist from a Secret or ConfigMap key. The two fields are mutually exclusive. | ||
|
|
||
| ## Check status | ||
|
|
||
| Use `kubectl` to confirm the harness was accepted and is ready. | ||
|
|
||
| ```bash | ||
| 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. | ||
|
|
||
| ## 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. | ||
| - `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. | ||
|
|
||
| For the complete generated schema, see the [API reference](/docs/kagent/resources/api-ref#agentharness). | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.