Skip to content

docs: update kagent 1.x docs for v1.0.0-rc1 - #652

Merged
Rachael-Graham merged 11 commits into
mainfrom
alpha18
Nov 2, 2026
Merged

Rachael-Graham merged 11 commits into
mainfrom
alpha18

Conversation

@Rachael-Graham

@Rachael-Graham Rachael-Graham commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Updates the 1.x docs for kagent v1.0.0-rc1. Each claim is checked against the rc1 source, and the behavioral ones are live-tested on a kind 1.37 cluster.

New rc1 features. This PR documents cross-namespace ModelConfig and MCP server references, Actor JWTs, service account callers and the agent identity lookup, push delivery settings, and the golden-build retry.

Pages that rc1 made wrong. These pages now cover:

  • The ListSubstrateActors, ListSubstrateWorkers, and GetSubstrateSummary methods that replace GetSubstrateStatus.
  • The ateworker-* image rename.
  • The reshaped SandboxConfig.
  • config.logging.level.
  • Session Agent UIDs.

New pages. "Run agents in multiple namespaces" takes the namespace sections from the installation page and adds the rc1 behavior. "Export a CLI installation to Helm" covers moving an installation to Helm.

Retired. The env-vars page is deleted (kagent#3434) and redirects to the Helm reference. The workflow change is in #674.

Worth a close look: the per-namespace credentialProvider.namespacePolicies requirement on multiple-namespaces.md. Without it an Agent goes Ready, but every model call returns 403. A selector-based share on a restricted installation also needs a Namespace ClusterRole.

Also: "Agent2Agent (A2A)" spelling throughout.

Merge #674, run the reference-docs workflow at v1.0.0-rc1, then merge this PR.

🤖 Generated with Claude Code

Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Signed-off-by: Rachael Graham <rachael.graham@solo.io>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Docs preview

Link Points at
Branch preview The newest push to this branch. Updates in place.
Commit preview 381e591 only. Frozen.

Both are uploaded Worker versions and serve no production traffic.

Signed-off-by: Rachael Graham <rachael.graham@solo.io>
@Rachael-Graham Rachael-Graham changed the title Docs for alpha18 Docs for rc1 Oct 30, 2026
Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Signed-off-by: Rachael Graham <rachael.graham@solo.io>

@Rachael-Graham Rachael-Graham left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline notes on changes a reviewer might pause on.

--out-dir "$KMCP_CLI_DIR" \
--url-prefix "$KMCP_CLI_URL_PREFIX"

- name: Generate environment variable reference

@Rachael-Graham Rachael-Graham Oct 30, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed because kagent#3434 deleted docs/env.md at v1.0.0-rc1 and declared env vars internal wiring, not a supported interface. This step exits 1 when that file is missing, so the env-vars page and generate-env-docs.py are retired with it.


A2A:
short: "The Agent-to-Agent protocol, which callers and other agents use to talk to an Agent. The conversation's context identifier is the Session ID, so a second message on the same ID continues the same conversation."
short: "The Agent2Agent protocol, which callers and other agents use to talk to an Agent. The conversation's context identifier is the Session ID, so a second message on the same ID continues the same conversation."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agent2Agent is the protocol's own name; this sweep replaced both agent-to-agent spellings. This glossary is shared with 0.x, so the 0.x A2A tooltip changes too.

}
```

The response contains the Agent's namespace, name, UID, labels, and annotations, and the ID of the Session and the revision that the Actor runs. The labels and annotations are the Agent's current values, returned unchanged. They include `kubectl.kubernetes.io/last-applied-configuration` when you applied the Agent with `kubectl apply`, so the service can read the Agent's full manifest. Do not put values in an Agent's labels or annotations that the receiving service must not see. The Session ID does not give the service access to the Session.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lookup (kagent#3362) was live-tested, and its response really does include last-applied-configuration, which is why the page warns about labels and annotations. A token without the kagent-agent-info audience returned Invalid Agent identity credential.

## 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.
{{< 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). `kagent install` creates the certificate authority pools and the JWT authority pool that these identities are issued from. No Helm chart creates these pools. For an installation that you manage with Helm, see [Export the installation to Helm]({{< link path="operations/export-to-helm" >}}).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factual fix: the old text said the installation guide covers creating these pools, but it no longer does. kagent install creates them now.

```

6. Let the Agent's namespace read Secrets in the shared namespace. Agent Substrate's credential provider controls which Secret namespaces each namespace's Agents can read, separately from `allowedNamespaces`. kagent does not widen this grant automatically.
1. Read the current namespace policies. The `credentialProvider.namespacePolicies` list that you set replaces the existing list, so you must include the entries that your installation already has.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this grant, the Agent goes Ready but every model call returns 403; verified live. The list replaces the existing value, so a reader who skips this read step drops the default kagent entry.

```

> [!IMPORTANT]
> `allowedNamespaces` gates compilation, not running agents. When you narrow the policy or remove a namespace label, the Agent reports `Ready=False`, but kagent keeps its last successful revision. New Sessions still start from that revision and use the shared ModelConfig's credential. To cut off a namespace completely, also remove its entry from `credentialProvider.namespacePolicies`.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security-relevant and verified live: after removing the namespace label, the Agent showed Ready=False, but a new Session still started on the last good revision. Only removing the Substrate grant actually cuts the namespace off.

- The server's `allowedNamespaces` field admits the AgentTemplate's namespace. Until the server admits the namespace, the controller cannot resolve the binding, and the Agent that runs that template does not become ready.
- The controller watches both namespaces.

The server sends no Secret-backed header, so an Agent in another namespace does not need an Agent Substrate Secret grant to reach it. For a RemoteMCPServer that does send one, see [Share an MCP server across namespaces]({{< link path="skills-and-mcp/about-tools#share-an-mcp-server-across-namespaces" >}}).

@Rachael-Graham Rachael-Graham Oct 30, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Live-tested at rc1: an Agent in another namespace called kagent-tool-server with no Agent Substrate grant to the kagent namespace, because the server sends no Secret-backed header. The Agent's namespace still needs its own namespacePolicies entry for its model Secret.

gvisor:
url: gs://gvisor/releases/release/20260803/aarch64/gvisor.tar.bz2
sha256: <sha256>
defaultVersion: v6

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Substrate 1.0.0-rc.1 reshaped SandboxConfig: defaultVersion plus versions[], and pauseImage is gone. The WorkerPool now resolves the config, not the ActorTemplate. This example matches the live gvisor-default with the digests elided.

loglevel: debug
config:
logging:
level: debug

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factual fix: controller.loglevel does not exist in the rc1 chart. The controller's level is config.logging.level.

@Rachael-Graham
Rachael-Graham marked this pull request as ready for review October 30, 2026 23:01
Signed-off-by: Rachael Graham <rachael.graham@solo.io>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New guide to explain swapping from a demo cli install to a helm-managed install

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved some existing namespace-scoping content out of the install page here, plus added some new rc1 functionality

@kristin-kronstain-brown kristin-kronstain-brown left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, Rachael. This is a big, careful release update, and the inline notes made it much easier to review. The anchor preservation, the conventions pass, and the live-tested security notes are especially good.

I checked the claims against the kagent and Agent Substrate source at v1.0.0-rc1. I did not run the procedures on a cluster. Labels on each comment: Blocking is wrong content, Should fix is before merge, and Nit is optional.

Order of merges (blocking). The version conrefs on this branch still pin kagent 1.0.0-alpha17, Agent Substrate 0.6.0-alpha3, and the Substrate chart 0.4.0-alpha1, but the pages describe rc1. The rc1 reference-docs run has not happened yet, and it fails until the env-docs step is removed. Could the update-ref-docs.yaml change and the generate-env-docs.py deletion move to their own PR? Then we merge that, run the reference-docs update at v1.0.0-rc1, and merge this PR.

Not inline, because the lines are outside the diff:

  • reference/env-vars.md is deleted without a redirect, so the published URL returns 404 after merge. An aliases: entry on reference/helm (or a similar page) would fix it.
  • The comment at update-ref-docs.yaml:263 still says "The CLI and env doc generators import PyYAML".
  • The PR description still calls this a draft for alpha18.

Overlapping automated drafts: #659, #661, #662, and #665 to #668 cover changes that this PR also makes. #664 (image pull secrets for the worker pool ServiceAccount) and #669 (the API breaks made before rc1) cover topics that I could not find here. Are those in scope for this PR?

Comment on lines +166 to +168
NAME AGE READY
my-agent 30s True
my-agent 30s True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (accuracy). At v1.0.0-rc1, the Agent CRD prints Ready before Age (helm/kagent-crds/templates/api.kagent.dev_agents.yaml). Each kubectl get command also prints its own header. This output came over from the old installation page, so the error is older than this PR.

Suggested change
NAME AGE READY
my-agent 30s True
my-agent 30s True
NAME READY AGE
my-agent True 30s
NAME READY AGE
my-agent True 30s

my-agent 30s True
```

4. Confirm that the Agent in the unwatched namespace stays unmanaged. The controller does not have a watch entry for that namespace. The Agent's `READY` value therefore stays `UNKNOWN`, and its conditions stay empty.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (accuracy). The Ready column is .status.conditions[?(@.type=='Ready')].status. An Agent with no conditions shows an empty cell, not UNKNOWN.

Suggested change
4. Confirm that the Agent in the unwatched namespace stays unmanaged. The controller does not have a watch entry for that namespace. The Agent's `READY` value therefore stays `UNKNOWN`, and its conditions stay empty.
4. Confirm that the Agent in the unwatched namespace stays unmanaged. The controller does not have a watch entry for that namespace. The Agent's `READY` value therefore stays empty, and its conditions stay empty.

Comment on lines +178 to +180
NAME AGE READY
my-agent 30s UNKNOWN
null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (accuracy). The READY cell is empty, and -o jsonpath='{.status.conditions}' on a missing field prints nothing, not null.

Suggested change
NAME AGE READY
my-agent 30s UNKNOWN
null
NAME READY AGE
my-agent 30s

* Kubernetes RBAC governs who can create Agents, Harnesses, AgentTemplates, and EgressPolicies in the namespace.
* The Agent Substrate credential policy limits which namespaces' Secrets the namespace's agents can read.
* An Agent or SandboxTemplate can select only the EgressPolicies in its own namespace. For more information, see [Access control]({{< link path="agents/egress-policies#access-control" >}}).
* A ModelConfig or RemoteMCPServer admits references only from the namespaces in its `allowedNamespaces` field.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking (accuracy). allowedNamespaces is not a list of namespaces. It is {from: All|Same|Selector, selector}, and defaults to Same (go/api/v1alpha3/common_types.go). As written, readers will try to write a list.

Suggested change
* A ModelConfig or RemoteMCPServer admits references only from the namespaces in its `allowedNamespaces` field.
* A ModelConfig or RemoteMCPServer admits references only from the namespaces that its `allowedNamespaces` field selects.

* Agent Substrate has one credential policy. The policy lets agents in `kagent` read Secrets in `kagent` only. Each namespace that you prepare gets a policy of its own.
* The `default-model-config` ModelConfig and the `kagent-tool-server` RemoteMCPServer admit references from the `kagent` namespace only. To use them from another namespace, see [Share configuration across namespaces](#share-configuration-across-namespaces).

When you install the charts directly with Helm, the installation sets up the following defaults:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix. Which install does this half of the section describe? I cannot find a page that documents installing the charts directly with Helm. identity.md also says that no Helm chart creates the identity pools, so a Helm-only install does not get far. An export applied with install.sh carries the CLI-generated values, so its defaults match the kagent install list instead. Should this half go, or should it say how a Helm-only install gets its pools?

If it stays, the list also leaves out default-model-config. The chart creates that ModelConfig by default, with providers.default: openAI in values.yaml.


```bash
kubectl port-forward -n kagent deployment/kagent-controller 8083:8083 &
TOKEN=$(kubectl create token scheduler -n ci-bots --audience kagent-invocation)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. This command assumes a scheduler ServiceAccount in a ci-bots namespace. A one-line kubectl create namespace ci-bots && kubectl create serviceaccount scheduler -n ci-bots before it would make the example runnable. The port-forward on line 63 also keeps running in the background after the example ends.

An agent can stop mid-task to ask a question or to request approval for a tool call. The task then reports `TASK_STATE_INPUT_REQUIRED` and waits until a caller answers it. By default, every agent on the `kagent` harness can raise the question kind, because the runtime gives each one a built-in `ask_user` tool. A system prompt that tells an agent to ask before it answers is therefore enough to see a pause.

Answering a pause needs the human-in-the-loop extension, which a caller requests per call. The extension is a versioned URI, and a request names it in two places: the `A2A-Extensions` header, and the message's own `extensions` list.
Answering a pause needs the human-in-the-loop extension, which a caller requests per call. The extension is a versioned URI. A request must include the URI in both the `A2A-Extensions` header and the message's own `extensions` list.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix (contradiction with human-in-the-loop.md). Activation reads only the A2A-Extensions header (go/adk/pkg/a2a/hitl.go:43). Only a response message must list the URI in message.extensions (go/api/a2a/hitl.go:115-116, 146). human-in-the-loop.md says that the header is enough. Suggest: "A request activates the extension through the A2A-Extensions header. A response that answers a pause must also list the URI in the message's own extensions list."

### Enable tool calling in vLLM

kagent sends a `tools` array with `tool_choice: "auto"` on every request. kagent's runtime registers a built-in `ask_user` tool on every agent, so that array is sent even when you bind no tools yourself. Launch vLLM with automatic tool choice enabled, or every agent turn fails.
kagent sends a `tools` array with `tool_choice: "auto"` on every request. By default, kagent's runtime registers a built-in `ask_user` tool on every agent, so kagent sends that array even when you do not bind any tools yourself. To prevent every agent turn from failing, launch vLLM with automatic tool choice enabled.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix. "By default" suggests that disableAskUser: true stops the tools array from being sent, but it does not. The runtime always registers read_file, write_file, edit_file, list_files, grep_file, and bash (upstream docs/architecture/process-configuration.md, lines 226-233). Suggest: "kagent's runtime always registers built-in tools, such as the file tools, on every agent, so kagent sends that array even when you do not bind any tools yourself."

```

3. Apply the converted resources.
3. Delete the ModelConfig fields that `v1alpha3` removed from the converted file. The conversion command does not delete them, and the apply fails while they remain. If the file includes the `kagent-grafana-mcp` RemoteMCPServer, delete it too, because 1.0 does not deploy the Grafana Model Context Protocol (MCP) server behind it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should fix. This step tells the reader to delete "the ModelConfig fields that v1alpha3 removed" without naming them. Could you list the fields, or add a yq del(...) to the conversion command in step 2, so that the reader does not have to find them by failing an apply?

```

The Agent's status reports two revision fields that answer a different question. `desiredRevision` is the {{< gloss "Revision" >}}revision{{< /gloss >}} that the current spec should produce, and `latestSuccessfulRevision` is the newest revision that finished preparing. A missing `latestSuccessfulRevision` means that the Agent was never ready, and two differing values mean that the newest edit is not yet prepared.
A failed golden snapshot is not final. When Agent Substrate fails to build the golden snapshot, kagent deletes the failed ActorTemplate and rebuilds it after 15 seconds, 1 minute, and 4 minutes, and then every 10 minutes indefinitely. While a rebuild waits, `Ready` is `False` with the reason `ActorTemplateRetrying` and a message such as `golden build failed (GoldenActorCrashed), retry 1 at <time>`. The message omits Agent Substrate's full error, because that error can quote your configuration. Read the full error in the controller log. When a configuration fault causes the failure, kagent retries until you edit the Agent or the SandboxTemplate.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit. These are base delays. Each one gets up to 20% jitter (maxJitterFraction: 0.2 in go/core/internal/controller/golden_retry.go:30-33). "About 15 seconds, 1 minute, and 4 minutes" would match better.

Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Signed-off-by: Rachael Graham <rachael.graham@solo.io>
@Rachael-Graham
Rachael-Graham merged commit 3b46ecc into main Nov 2, 2026
4 checks passed
@Rachael-Graham
Rachael-Graham deleted the alpha18 branch November 2, 2026 16:33
Rachael-Graham added a commit that referenced this pull request Nov 2, 2026
kagent#3434 deleted docs/env.md at v1.0.0-rc1 and declared environment
variables internal wiring rather than a supported interface. The
"Generate environment variable reference" step exits 1 when that file is
missing, so every rc1 reference-docs run fails until it is removed.

Remove the step, the WITH_ENV_DOCS and KAGENT_ENV_PAGE plumbing, the
ENV_DOCS_NOTE in the generated PR body, and scripts/generate-env-docs.py.

The helm.md write step now carries over an existing aliases: block from
the page it overwrites. The 1.x env-vars page is deleted in the alpha18
docs PR (#652) with an alias on reference/helm.md, and without this the
next regeneration would drop that alias and 404 the old URL.

Signed-off-by: Rachael Graham <rachael.graham@solo.io>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants