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
2 changes: 1 addition & 1 deletion docs-site/assets/kagent-docs/versions/agent-substrate.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{< version include-if="0.x" >}}0.0.9{{< /version >}}{{< version include-if="1.x" >}}0.4.0-alpha1{{< /version >}}
{{< version include-if="0.x" >}}0.0.9{{< /version >}}{{< version include-if="1.x" >}}0.5.0-alpha2{{< /version >}}
2 changes: 1 addition & 1 deletion docs-site/assets/kagent-docs/versions/kagent.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{< version include-if="0.x" >}}0.10.2{{< /version >}}{{< version include-if="1.x" >}}1.0.0-alpha9{{< /version >}}
{{< version include-if="0.x" >}}0.10.2{{< /version >}}{{< version include-if="1.x" >}}1.0.0-alpha12{{< /version >}}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ghcr.io/kagent-dev/kagent/claude-harness@sha256:e72d66d9f3b6eafbc59d18cef150fb5d31cb89ead83999a33c06264c21e86d4c
ghcr.io/kagent-dev/kagent/claude-harness@sha256:95a5f4839a337aaf78e0eeff480025ed5586d3cfec22277102318826236e3d74
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ghcr.io/kagent-dev/kagent/codex-harness@sha256:aef1e913671c65721af8003494afbeacc6c81e41309afbbb1e8d888e1868d8ce
ghcr.io/kagent-dev/kagent/codex-harness@sha256:7748610b7eccd94e556e0b9cd7bef93c8961e99d445519135b77513ead81f379
2 changes: 1 addition & 1 deletion docs-site/assets/kagent-docs/versions/runtime-image.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ghcr.io/kagent-dev/kagent/golang-adk@sha256:26ae5c772d4a59b24ecb3619c3499e106e3b28abbc239de25b4ff8d746f97e69
ghcr.io/kagent-dev/kagent/golang-adk@sha256:9c2e93b1dc6ac4bfa586cd2636891b5c17e91ca6978338fe02de307098147493
9 changes: 5 additions & 4 deletions docs-site/content/kagent/1.x/about/core-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ For the complete AgentTemplate schema, see the [API reference]({{< link path="re

## Agent

An **Agent** is a Kubernetes custom resource that pairs _one AgentTemplate with one Harness_. For each side, the Agent either names an existing resource or includes a complete spec inline, and it sets exactly one of the two.
An **Agent** is a Kubernetes custom resource that pairs _one AgentTemplate with one Harness_. Both sides are required. Under `spec.template`, the Agent sets exactly one of `ref`, which names an existing AgentTemplate, or `inline`, which carries a complete template spec. Under `spec.harnessRef`, the Agent names an existing Harness. A Harness has no inline form.

The two sides are independent, so an Agent can name both resources, inline both, or mix the two. An inline spec is a complete definition, not an override of a named resource, and kagent creates no Kubernetes resource to back one. Every name resolves in the Agent's own namespace, including a name nested inside an inline spec. For the fields that express each choice, see the [API reference]({{< link path="reference/api-ref#agent" >}}).
An inline template is a complete definition rather than an override of a named AgentTemplate, and kagent creates no Kubernetes resource to back one. Every name resolves in the Agent's own namespace, including a name nested inside an inline template. For the fields that express each choice, see the [API reference]({{< link path="reference/api-ref#agent" >}}).

The following Agent resource references both sides:

Expand All @@ -103,8 +103,9 @@ metadata:
name: assistant
namespace: kagent
spec:
templateRef:
name: shared-context
template:
ref:
name: shared-context
harnessRef:
name: kagent
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ A share carries one of two permissions.
- **`READ_ONLY`**: The holder can read the conversation. kagent refuses any call that is not a read before the request reaches the service.
- **`READ_WRITE`**: The holder can also send messages to the Session.

A client that creates a share can set `CreateSessionShareRequest.ttl` to a positive lifetime, which starts when the share is created. Once that lifetime ends, the token grants no access and a token lookup returns not found. The owner still sees the expired share in `ListSessionShares` and can revoke it.

The returned `SessionShare.expiresAt` field records when the token stops granting access. Omit `ttl` and `expiresAt` stays unset. The share then stays valid until it is revoked or the Session is deleted. An operator caps share lifetimes with `controller.sessionShareMaxTTL`. For more information, see [Expire idle Sessions]({{< link path="operations/operational-considerations#expire-idle-sessions" >}}).

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.

## The Agent Substrate plane
Expand Down
12 changes: 7 additions & 5 deletions docs-site/content/kagent/1.x/agents/agent-harness.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ EOF
| `substrate.workerPoolRef.name` | Yes | The {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} that this Harness's Actors are scheduled onto. An operator must provision one before any agent can run. |
| `substrate.snapshotPolicy.location` | Yes | The object storage location for Actor {{< gloss "Snapshot" >}}snapshots{{< /gloss >}}. |

A Harness names no AgentTemplate. An {{< gloss "Agent" >}}Agent{{< /gloss >}} pairs the two through either `spec.harnessRef` or an inline `spec.harness`, so whoever writes the Agent decides which template runs on which Harness. For more information about the pairing, see [Core concepts]({{< link path="about/core-concepts#agent" >}}).
A Harness names no AgentTemplate. An {{< gloss "Agent" >}}Agent{{< /gloss >}} pairs the two through `spec.harnessRef`, so whoever writes the Agent decides which template runs on which Harness. `spec.harnessRef` takes a reference only, so a Harness must exist before an Agent can name it. For more information about the pairing, see [Core concepts]({{< link path="about/core-concepts#agent" >}}).

A command or argument override belongs to the revision that kagent prepares. Changing one prepares a new revision rather than altering a running agent. A {{< gloss "Session" >}}Session{{< /gloss >}} pinned to an earlier revision keeps the command it was prepared with until it moves to the new one.

Expand Down Expand Up @@ -140,8 +140,9 @@ metadata:
name: codex-agent
namespace: kagent
spec:
templateRef:
name: codex-template
template:
ref:
name: codex-template
harnessRef:
name: codex-harness
EOF
Expand Down Expand Up @@ -194,8 +195,9 @@ metadata:
name: claude-agent
namespace: kagent
spec:
templateRef:
name: claude-template
template:
ref:
name: claude-template
harnessRef:
name: claude-harness
EOF
Expand Down
5 changes: 3 additions & 2 deletions docs-site/content/kagent/1.x/agents/bring-your-own-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ metadata:
name: my-byo-agent
namespace: kagent
spec:
templateRef:
name: my-byo-template
template:
ref:
name: my-byo-template
harnessRef:
name: my-byo-harness
EOF
Expand Down
10 changes: 6 additions & 4 deletions docs-site/content/kagent/1.x/agents/structured-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ Set `spec.outputSchema` to keep the schema in the AgentTemplate, so that the sch
name: structured-answer
namespace: kagent
spec:
templateRef:
name: structured-answer
template:
ref:
name: structured-answer
harnessRef:
name: my-first-harness
EOF
Expand Down Expand Up @@ -157,8 +158,9 @@ Use `outputSchemaFrom` to keep the schema outside the AgentTemplate, so that sev
name: structured-answer-shared
namespace: kagent
spec:
templateRef:
name: structured-answer-shared
template:
ref:
name: structured-answer-shared
harnessRef:
name: my-first-harness
EOF
Expand Down
5 changes: 3 additions & 2 deletions docs-site/content/kagent/1.x/examples/a2a-byo.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ A `byo` Harness carries two fields that the other runtimes do not need: an empty
name: byo-example-agent
namespace: kagent
spec:
templateRef:
name: byo-example-template
template:
ref:
name: byo-example-template
harnessRef:
name: byo-example
EOF
Expand Down
5 changes: 3 additions & 2 deletions docs-site/content/kagent/1.x/examples/agent-delegation.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,9 @@ Each binding renames the specialist that it points to, so the coordinator's syst
name: incident-coordinator
namespace: kagent
spec:
templateRef:
name: incident-coordinator
template:
ref:
name: incident-coordinator
harnessRef:
name: my-first-harness
EOF
Expand Down
5 changes: 3 additions & 2 deletions docs-site/content/kagent/1.x/examples/agentgateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,9 @@ Two paths are worth checking in order. Calling the gateway directly isolates the
name: support-triage
namespace: kagent
spec:
templateRef:
name: support-triage
template:
ref:
name: support-triage
harnessRef:
name: my-first-harness
EOF
Expand Down
5 changes: 3 additions & 2 deletions docs-site/content/kagent/1.x/examples/documentation-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,9 @@ The AgentTemplate binds the tools and sets the system prompt that makes the agen
name: docs-agent
namespace: kagent
spec:
templateRef:
name: docs-agent
template:
ref:
name: docs-agent
harnessRef:
name: my-first-harness
EOF
Expand Down
5 changes: 3 additions & 2 deletions docs-site/content/kagent/1.x/examples/skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ kagent pulls an `oci` source as a container image and unpacks its flattened file
name: release-writer
namespace: kagent
spec:
templateRef:
name: release-writer
template:
ref:
name: release-writer
harnessRef:
name: my-first-harness
EOF
Expand Down
7 changes: 4 additions & 3 deletions docs-site/content/kagent/1.x/get-started/your-first-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,14 @@ Three resources define a runnable agent: a Harness holds the runtime, an AgentTe
name: my-first-agent
namespace: kagent
spec:
templateRef:
name: my-first-template
template:
ref:
name: my-first-template
harnessRef:
name: my-first-harness
```
> [!NOTE]
> Each side of the pairing takes either a reference, as shown here, or a complete spec written inline under `spec.template` or `spec.harness`. The two choices are independent, so an Agent can reference one side and inline the other. An inline spec is a complete value rather than an override, and kagent creates no Kubernetes object to back it.
> `spec.template` takes either a reference, as shown here, or a complete AgentTemplate spec under `inline`. An inline template is a complete value rather than an override, and kagent creates no Kubernetes object to back it. `spec.harnessRef` takes a reference only, so a Harness must exist before an Agent can name it.

4. Confirm that the Agent is ready. `READY` reports whether kagent compiled and prepared a runtime {{< gloss "Revision" >}}revision{{< /gloss >}} for the pair.
```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,42 @@ Leader election keeps the replicas from conflicting. One replica takes a Kuberne
> [!IMPORTANT]
> If an installation runs on the development database, extra controller replicas do not make the installation highly available. That database is a single pod backed by one PersistentVolumeClaim, so losing it stops every replica at once. Run an external PostgreSQL instance before counting controller replicas toward availability.

## Sign push notification callbacks

Agent-to-Agent (A2A) push notifications are unsigned by default. A callback carries no `Authorization` header unless you supply an Ed25519 signing key, and the JSON Web Key Set (JWKS) endpoint returns `404`. Push notifications still work without a key, so sign them only where a receiver must verify that a callback came from your installation.

To sign callbacks, generate one unencrypted PKCS#8 Ed25519 key and store it in a Secret in the kagent namespace.

1. Generate the signing key.
```bash
openssl genpkey -algorithm ED25519 -out private-key.pem
```

2. Store the key in a Secret. The Secret must hold the key under the `private-key.pem` key.
```bash
kubectl create secret generic kagent-push-signing -n kagent \
--from-file=private-key.pem
```

Then name that Secret in your {{< reuse "kagent-docs/snippets/name-product.md" >}} Helm values.

```yaml
controller:
push:
signing:
secretName: kagent-push-signing
issuer: https://kagent.example.com
```

| Setting | Description |
| ------- | ----------- |
| `controller.push.signing.secretName` | The Secret that holds `private-key.pem`. Leave it empty to send push notifications without JSON Web Token (JWT) authentication. Helm references a Secret that you create, and neither generates nor rotates signing keys. An invalid key stops the controller from starting. |
| `controller.push.signing.issuer` | The stable URL that webhook receivers trust as the JWT issuer. Leave it empty to fall back to `ui.externalUrl`, and then to the in-cluster A2A gateway URL. |

With a signing key configured, each callback attempt carries a fresh five-minute Ed25519 JWT in an `Authorization: Bearer` header, and the `/.well-known/jwks.json` endpoint publishes the matching public key.

Every controller replica must load the same key. After you rotate the key, restart all controller pods together, because replicas that run on different keys publish different JSON Web Key Sets.

## Node operations

A {{< gloss "Worker" >}}Worker{{< /gloss >}} is an ordinary Kubernetes pod, so every node event reaches the {{< gloss "Actor" >}}Actors{{< /gloss >}} that this Worker hosts. What the event costs depends on what each Actor was doing when the node went away.
Expand Down Expand Up @@ -161,6 +197,13 @@ Work in progress is never deleted. A Session with a running task survives past t

<!-- REVIEW: the creation request ID behaviour belongs with the Session API rather than on an operations page, so it is parked here until a Sessions reference page exists. The behaviour: an expired Session releases its creation request ID, unlike an explicit client deletion, which keeps a tombstone, so the same caller can reuse that request ID to start a fresh Session. -->

A Session share carries its own lifetime, separate from the Session's idle limit. A client sets `CreateSessionShareRequest.ttl` when it creates a share, and `controller.sessionShareMaxTTL` caps what a client may ask for. A positive cap rejects any request that exceeds it, and supplies the lifetime for a request that omits `ttl`. The default `0` leaves a share unbounded unless the client sets `ttl`, and a negative value is rejected at startup.

```yaml
controller:
sessionShareMaxTTL: "24h"
```

To watch the sweep, scrape `kagent_session_expired_total`, which counts the Sessions that it removed. Each removal also logs `expired idle session` at debug level with the Session's ID and how long it had been idle.

## How configuration changes reach agents
Expand Down
57 changes: 57 additions & 0 deletions docs-site/content/kagent/1.x/operations/tune-agent-substrate.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,63 @@ The same `template` block also accepts `nodeSelector`, `tolerations`, `priorityC

<!-- REVIEW (WorkerPool owner): the CPU and memory figures above are illustrative rather than measured, and the chart ships no defaults to derive them from. Confirm a recommended request and limit per Worker for a pool that carries production traffic, and the scheduling guidance that goes with it, before this section presents either as a recommendation. -->

### Give Workers their own ServiceAccount

Worker pods run as a ServiceAccount that the chart creates, named after the pool. On a default install that name is `kagent-default`. The chart binds no Role or ClusterRole to the account. Its purpose is to keep Workers off the namespace's `default` ServiceAccount, and to give you a Worker identity that you can attach your own policy to, such as an IAM role or an admission rule.

To run Workers as an account that you manage outside the chart, stop the chart from creating one and name your own account instead. That account must already exist in the release namespace, because neither the chart nor Kubernetes creates it on demand.

```yaml
substrateWorkerPool:
serviceAccount:
create: false
name: my-worker-sa
```

| Field | Description |
| ----- | ----------- |
| `substrateWorkerPool.serviceAccount.create` | Whether the chart creates the Worker ServiceAccount. Defaults to `true`. Set it to `false` to use an account that you manage yourself. |
| `substrateWorkerPool.serviceAccount.name` | The ServiceAccount that Worker pods run as. Omit it to use the pool name. |

The chart writes `serviceAccountName` into the pool's pod template. A `serviceAccountName` that you set under `substrateWorkerPool.template` is overwritten rather than merged, so set the account through `substrateWorkerPool.serviceAccount.name`.

### Keep placement scoped to the pool's namespace {#workerpool-placement-labels}

kagent selects a WorkerPool by name and namespace when it compiles an ActorTemplate, and the generated ActorTemplate matches Workers on the `kagent.dev/worker-pool-name` and `kagent.dev/worker-pool-namespace` labels. Agent Substrate matches those labels across every pool rather than checking the WorkerPool's namespace, so a pool that carries only the name label can be selected from another namespace.

The chart sets both labels from the pool's name and namespace, and applies them after `substrateWorkerPool.labels`. An extra label that reuses either key is overwritten rather than honored.

```yaml
substrateWorkerPool:
name: kagent-default
labels:
environment: production
```

A pool that you manage outside the chart carries no labels of its own. Set both keys yourself, and match each value to the pool's name and namespace.

```yaml
apiVersion: ate.dev/v1alpha1
kind: WorkerPool
metadata:
name: external-pool
namespace: team-a
labels:
kagent.dev/worker-pool-name: external-pool
kagent.dev/worker-pool-namespace: team-a
spec:
replicas: 2
workerImage: "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}"
```

Earlier releases placed Actors with a single `kagent.dev/worker-pool` label, and the chart no longer sets it. A Session or Sandbox that is pinned to a revision from one of those releases still selects that key, so keep the old label on the pool until you recreate them.

```yaml
substrateWorkerPool:
labels:
kagent.dev/worker-pool: kagent-default
```

## Configure snapshot storage

Agent Substrate writes every suspended Actor to an object store, so the bucket stores the Session state that a resume restores. Two places decide where a snapshot lands:
Expand Down
Loading
Loading