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
27 changes: 22 additions & 5 deletions docs-site/content/kagent/1.x/about/substrate-runtime/identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ aliases:
- /kagent/1.x/substrate-runtime/identity/
---

A {{< reuse "kagent-docs/snippets/name-product.md" >}} installation identifies three different kinds of callers, and each one is handled by a different system.
A {{< reuse "kagent-docs/snippets/name-product.md" >}} installation identifies each kind of caller with a different system.

- An operator applying a {{< gloss "Harness" >}}Harness{{< /gloss >}} is authenticated by [Kubernetes](#the-kubernetes-plane).
- A caller that reaches [kagent's own gRPC API](#the-kagent-control-plane) is assigned a principal by kagent, both for a {{< gloss "Session" >}}Session{{< /gloss >}} and for the resources that the API writes.
- A caller that reaches [kagent's gRPC API](#the-kagent-control-plane) is assigned a principal by kagent, both for a {{< gloss "Session" >}}Session{{< /gloss >}} and for the resources that the API writes.
- An agent's runtime calls the same API with a [token that Agent Substrate issues](#agent-runtime-calls).
- The components inside [Agent Substrate](#the-agent-substrate-plane) authenticate each other.

## The Kubernetes plane

Kubernetes role-based access control (RBAC) governs who can create, read, edit, or delete Kubernetes resources with `kubectl`, including Harness, AgentTemplate, and {{< gloss "Agent" >}}Agent{{< /gloss >}} resources. A cluster's existing roles and bindings decide who authors an agent's runtime, its behavior, and the pairing of the two on that path.
Kubernetes role-based access control (RBAC) governs who can create, read, edit, or delete Kubernetes resources with `kubectl`, including Harness, AgentTemplate, and {{< gloss "Agent" >}}Agent{{< /gloss >}} resources. A cluster's existing roles and bindings decide who authors an agent's Harness and AgentTemplate, and the pairing of the two on that path.

Because neither a Harness nor an AgentTemplate names the other, the Agent resource carries the pairing, and RBAC on Agents governs it. Whoever can write Agents in a namespace controls which template runs on which Harness, even without edit access to the Harnesses and AgentTemplates that those Agents name. For more information about the pairing, see the [Agent core concept]({{< link path="about/core-concepts#agent" >}}).

Expand Down Expand Up @@ -44,14 +45,14 @@ Any other value fails controller startup rather than falling back to a default.
> [!WARNING]
> **`insecure` lets a caller select its own principal.** It verifies neither the header nor the query parameter, and the same authenticator guards the controller's `/mcp` endpoint. Treat the principal on a call as a label that the caller chose, and restrict network access to both endpoints rather than relying on it.

Authorization is separate from both modes. kagent installs an authorizer that permits every check regardless of the authentication mode, so neither mode constrains what an authenticated caller may do.
Authorization is separate from both modes. For user calls, kagent installs an authorizer that permits every check regardless of the authentication mode, so neither mode constrains what an authenticated user can do. For agent runtime calls, kagent applies a fixed policy that limits each Actor to its own resources. For more information, see [Agent runtime calls](#agent-runtime-calls).

### Resources that the API writes

kagent's gRPC API reaches the same resources by a second path. The AgentTemplate service creates, updates, and deletes AgentTemplates, and the Harness service creates and deletes Harnesses, both through the kagent controller. The `kagent apply -f` command calls the AgentTemplate service, and any client that reaches the gRPC endpoint can call either service. The controller writes these resources with its own service account rather than the caller's, so Kubernetes RBAC never evaluates the caller. The authenticator above resolves the caller instead.

> [!WARNING]
> By default, kagent neither authenticates nor authorizes this path. The `insecure` authenticator admits every request, and the authorizer it installs permits every check. Any caller that reaches the gRPC endpoint can author an agent's runtime and behavior, regardless of their Kubernetes permissions. Do not expose port `8083` outside the cluster. For the identity that this mode gives an anonymous caller, and for the mode that changes it, see [Controller authentication modes](#controller-authentication-modes).
> By default, kagent neither authenticates nor authorizes this path. The `insecure` authenticator admits every request, and the authorizer it installs permits every check. Any caller that reaches the gRPC endpoint can author an agent's Harness and AgentTemplate, regardless of their Kubernetes permissions. Do not expose port `8083` outside the cluster. For the identity that this mode gives an anonymous caller, and for the mode that changes it, see [Controller authentication modes](#controller-authentication-modes).

### Creator ownership

Expand All @@ -74,6 +75,22 @@ The returned `SessionShare.expiresAt` field records when the token stops grantin

A share widens what the holder can reach to what the owner can see, and the underlying record is read as the owner rather than as the visitor. Revoking the share withdraws that access.

### Agent runtime calls

An agent's runtime calls the controller to store task state and memories, and to read its own Agent and Session. These calls arrive on the same port as user calls, `8083`. However, the controller authenticates agent runtime calls separately from the user authentication mode. The task state and memory calls that only an agent makes always need a valid token, even in `insecure` mode. The controller treats a call that sends no `Authorization` header as a user call, and applies the user authentication mode to it.

The runtime, the Agent Substrate egress gateway, and the controller each take one step to authenticate a call.

1. The runtime sends a placeholder bearer token in the `Authorization` header.
2. The Agent Substrate egress gateway replaces the placeholder with a JSON Web Token (JWT) that identifies the {{< gloss "Actor" >}}Actor{{< /gloss >}}. The token is valid for five minutes, and its audience is `kagent-runtime`. The gateway adds the token only to calls to the controller. Actor snapshots do not store the token.
3. The controller verifies the token's signature, issuer, audience, and lifetime, and allows 30 seconds of clock skew. The controller then binds the token to the Actor's current Session. The controller rejects a token that fails verification, and does not fall back to user authentication.

An authenticated Actor can read its own Agent and use its own task state and memories. The Actor can also read, update, and send messages to its own Session. The Actor cannot create or delete a Session, use a share, reach any other Session, or act with its owner's permissions. That restriction includes other Sessions of the same agent and the same owner.

The controller trusts the issuer in the `config.substrate.actorJwtIssuer` Helm value, which must match the `ateApi.actorJWTIssuer` value of the Agent Substrate chart. Both values default to `https://idp.ate-system.svc`, so change them only together. The controller fetches the issuer's signing keys at startup, and a controller that cannot reach the issuer does not start.

Upgrade the controller and the runtime images together. An Actor snapshot from an earlier runtime image still sends an identity header that the controller no longer accepts, so you must recreate that snapshot after an upgrade.

## The Agent Substrate plane

{{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} authenticates its own components rather than authenticating end users. Its API server accepts Kubernetes ServiceAccount tokens issued for its audience, and the components that carry traffic to an Actor authenticate each other with mutual Transport Layer Security (mTLS). The [kagent installation guide]({{< link path="setup/installation" >}}) covers creating the certificate authority pools and the JSON Web Token (JWT) authority pool that these identities are issued from, which is a required step that no Helm chart performs.
Expand Down
16 changes: 8 additions & 8 deletions docs-site/content/kagent/1.x/agents/agent-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Each memory is one row in the `memory` table, which the vector migration created
| Column | What it holds |
| ------ | ------------- |
| `content` | The text that the agent saved. Retrieval returns it to a later conversation. |
| `agent_name` | The agent that owns the memory, written as `<namespace>__NS__<agent>` with every hyphen replaced by an underscore. The name identifies one {{< gloss "Agent" >}}Agent{{< /gloss >}}, so the same AgentTemplate paired into two Agents owns two separate sets of memories. |
| `agent_name` | The agent that owns the memory, written as `<namespace>/<agent>`, such as `kagent/my-first-agent`. The name identifies one {{< gloss "Agent" >}}Agent{{< /gloss >}}, so the same AgentTemplate paired into two Agents owns two separate sets of memories. A memory that an earlier release saved keeps its original key, such as `kagent__NS__my_first_agent`, and kagent does not migrate it. The agent no longer retrieves that memory. To list or delete it, pass the original key. |
| `user_id` | The user that the memory belongs to. |
| `embedding` | The 768-dimensional vector that similarity search compares a query against. |
| `created_at` and `expires_at` | When kagent wrote the memory, and `ttlDays` after that. |
Expand All @@ -216,28 +216,28 @@ Each memory is one row in the `memory` table, which the vector migration created

The SQL query only reads the table. To list or clear memories, call the `MemoryService` that the kagent controller serves over gRPC.

No CLI command manages memories, so these examples call the service with [grpcurl](https://github.com/fullstorydev/grpcurl). Both calls take the `agent_name` exactly as the memory table stores it. Be sure to copy the value out of the table rather than assembling it by hand, because an incorrect name fails silently.
No CLI command manages memories, so these examples call the service with [grpcurl](https://github.com/fullstorydev/grpcurl). Each call acts on the memories of the user that the call authenticates as, and does not take a user ID. For how the controller resolves that user, see [Controller authentication modes]({{< link path="about/substrate-runtime/identity#controller-authentication-modes" >}}). In the default `insecure` mode, a call without an identity runs as `admin@kagent.dev`. In that case, the call returns an empty list for memories that belong to any other user, and a Delete call succeeds without deleting anything. To act on another user's memories in `insecure` mode, add `-H 'X-User-Id: <user_id>'` to each grpcurl call, with the value from the `user_id` column.

Each call also takes the `agent_name` exactly as the memory table stores it. An incorrect name fails silently, so copy the value from the table instead of typing it by hand.

1. Port-forward the controller's gRPC port, and confirm that your kagent installation sets `config.server.grpcReflection=true`.
```bash
kubectl port-forward -n kagent svc/kagent-controller 8083:8083
```

2. List the memories that an agent stores for one user.
2. List the memories that an agent stores.
```bash
grpcurl -plaintext -d '{
"agent_name": "kagent__NS__my_first_agent_my_first_harness",
"user_id": "admin@kagent.dev"
"agent_name": "kagent/my-first-agent"
}' localhost:8083 kagent.runtime.v1.MemoryService/List
```

Each entry returns the `id`, `content`, `access_count`, `created_at`, and `expires_at` fields. Results are ranked by how often retrieval has returned them, so the most-used memories appear first.

3. Delete the memories for an agent and user.
3. Delete the memories that an agent stores.
```bash
grpcurl -plaintext -d '{
"agent_name": "kagent__NS__my_first_agent_my_first_harness",
"user_id": "admin@kagent.dev"
"agent_name": "kagent/my-first-agent"
}' localhost:8083 kagent.runtime.v1.MemoryService/Delete
```

Expand Down
39 changes: 22 additions & 17 deletions docs-site/content/kagent/1.x/examples/skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,39 +20,44 @@ Because kagent fetches a skill this late, review the following considerations.
* **Each Actor mounts up to 29 distinct skill images.** Images shared by several skills or plugins count once. A revision that needs more fails when kagent builds its ActorTemplate.
* **Scripts run in the runtime image.** A skill's scripts get whatever the Harness image provides. The kagent runtime image is Alpine Linux with `bash`, `git`, and the standard Alpine utilities, and it does **not** include Python.

### Skill tools
### Skill tools and built-in tools

On a `kagent` Harness, attaching a skill adds seven tools to the agent, whether or not the skill ships a script. The first three read skills, and the rest let the agent act on their files. The `claude` and `codex` Harness runtimes take the same skills and expose them through their own coding agent's tools instead.
On a `kagent` Harness, every agent has kagent's built-in tools, even without a skill. A skill runs its scripts with the built-in `bash` tool. Attaching a skill also adds the skill tools, which read skills. The `claude` and `codex` Harness runtimes also take skills. They expose the skills through their own coding agent's tools.

| Tool | What it does |
| ---- | ------------ |
| `list_skills` | Lists the attached skills with their names and descriptions. |
| `load_skill` | Reads a skill's full `SKILL.md` instructions. |
| `load_skill_resource` | Reads one file inside a skill directory, such as a reference document. |
| `read_file` | Reads a file from the skills directory or the session directory. |
| `write_file` | Writes a file to the session directory. |
| `edit_file` | Replaces an exact string in a file that the agent has already read. |
| `bash` | Runs a shell command in the session directory `/tmp/kagent/<session-id>/`. Commands time out after 30 seconds. |
| Tool | Availability | What it does |
| ---- | ------------ | ------------ |
| `list_skills` | With a skill | Lists the attached skills with their names and descriptions. |
| `load_skill` | With a skill | Reads a skill's full `SKILL.md` instructions. |
| `load_skill_resource` | With a skill | Reads one file inside a skill directory, such as a reference document. |
| `read_file` | Built-in | Reads a file, with line numbers. |
| `write_file` | Built-in | Writes a file, and creates its parent directories. |
| `edit_file` | Built-in | Replaces an exact string in a file. The edit fails when the string occurs more than once, unless the agent asks to replace every occurrence. |
| `list_files` | Built-in | Lists the contents of a directory. |
| `grep_file` | Built-in | Searches a file, or a directory recursively, for a regular expression. |
| `bash` | Built-in | Runs a command in a new shell. A command stops after 60 seconds by default. The agent can raise that limit to 600 seconds for one call. The tool combines standard output and standard error, and truncates the result at 64 KiB. When the call returns, the tool stops every process that the command started. |

The `config.runtimeDefaults.skillTools` Helm values change this tool set for every agent in the installation, because a Harness has no per-agent equivalent.
The built-in tools accept an absolute path or a path relative to the workspace, `/data/workspace`. The root agent and its subagents share the workspace. The workspace starts empty, and its files survive when the Actor is [suspended and resumed]({{< link path="about/substrate-runtime/suspend-and-resume#what-a-snapshot-captures" >}}). A command that is still running does not survive.

A Harness does not have a per-agent setting for the built-in tools. The `config.runtimeDefaults.builtinTools` Helm values change the built-in tools for every agent in the installation.

```yaml
config:
runtimeDefaults:
skillTools:
fileSearchTools: true
builtinTools:
disableFileSearch: true
disableBash: true
```

| Setting | Description |
| ------- | ----------- |
| `fileSearchTools` | Set to `true` to add `list_files`, which lists the contents of a directory, and `grep_file`, which searches file contents for a pattern and can recurse. Both tools reach only the skills and session roots that `read_file` reads. These settings are off by default because they give an agent broad visibility of the filesystem. When `bash` is disabled, these tools keep that visibility available to the agent. |
| `disableBash` | Set to `true` to remove the `bash` tool from the root agent and from every subagent. The agent still loads skills and keeps the file tools. Defaults to `false`. |
| `disableFileSearch` | Set to `true` to remove `list_files` and `grep_file` from the root agent and from every subagent. Defaults to `false`. This value replaces `skillTools.fileSearchTools` from earlier releases, with the opposite meaning. |
| `disableBash` | Set to `true` to remove the `bash` tool from the root agent and from every subagent. The agent keeps the file tools, and still loads skills. Defaults to `false`. |
| `bashVenvPath` | The path to a Python virtual environment in the Harness image. The `bash` tool adds the environment's `bin` directory to the start of `PATH`, and sets `VIRTUAL_ENV`. The kagent runtime image does not include Python. To use this setting, build a Harness image that includes the environment. Defaults to empty. |

Attaching a skill also changes what the agent is told. The runtime appends the name and description of every attached skill to the model request, along with an instruction to call `load_skill` before acting on one, so a skill reaches the model even before any tool is called.

> [!IMPORTANT]
> The `bash` tool gives the agent shell access inside its own Actor sandbox, and the sandbox is the boundary that contains it. Review a skill before you attach it, and treat the [egress]({{< link path="about/substrate-runtime/sandboxing" >}}) that the Actor is granted as the reach that the skill has. Writes are confined to the session directory, so a skill cannot modify `/skills` or another skill's files.
> The `bash` tool gives the agent shell access inside its own Actor sandbox, and the sandbox is the boundary that contains the agent. The file tools are not limited to the workspace. They read and write anywhere in the sandbox, including `/skills`, so one skill's instructions can change another skill's files. Review a skill before you attach it, and treat the [egress]({{< link path="about/substrate-runtime/sandboxing" >}}) that you grant the Actor as the reach that the skill has.

## Before you begin

Expand Down
Loading
Loading