From 898d4147ccd8e16a3eeb114dd886d7c62f6f0a46 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 15 Oct 2026 11:04:02 -0500 Subject: [PATCH 1/3] Skills and MCP wording cleanup Signed-off-by: Rachael Graham --- .../kagent-docs/snippets/artifact-sources.md | 6 +- .../content/kagent/1.x/about/core-concepts.md | 6 +- .../kagent/1.x/agents/structured-output.md | 45 ++++---- .../content/kagent/1.x/examples/skills.md | 36 +++---- .../content/kagent/1.x/operations/debug.md | 101 ++++++++++-------- .../kagent/1.x/reference/tools-ecosystem.md | 5 +- .../kagent/1.x/skills-and-mcp/about-tools.md | 57 ++++++---- .../kagent/1.x/skills-and-mcp/plugins.md | 101 +++++++++++++----- .../kagent/1.x/skills-and-mcp/skills.md | 34 ++---- docs-site/data/glossary.yaml | 8 +- 10 files changed, 228 insertions(+), 171 deletions(-) diff --git a/docs-site/assets/kagent-docs/snippets/artifact-sources.md b/docs-site/assets/kagent-docs/snippets/artifact-sources.md index 4f4643ab..c5ebd156 100644 --- a/docs-site/assets/kagent-docs/snippets/artifact-sources.md +++ b/docs-site/assets/kagent-docs/snippets/artifact-sources.md @@ -1,9 +1,11 @@ ## Every source is immutable -A skill or a plugin package changes what an agent does, so kagent only accepts artifact references that cannot shift underneath a running agent. Each source names exactly one of three kinds of artifact, and every kind must be pinned in its own way. +A skill or a plugin changes what an agent does, so kagent only accepts artifact references that cannot shift underneath a running agent. Each source specifies exactly one of three kinds of artifact, and every kind must be pinned in its own way. - **`oci`**: An image reference pinned to a digest, in the form `@sha256:`. A tag alone is rejected, because a tag can be moved to different content later. - **`git`**: A repository URL together with a full commit identifier. An abbreviated commit, a branch, or a tag is rejected. - **`bucket.s3`**: An endpoint, bucket, and key, together with the `versionId` of that exact object version. A region is included where the service requires one for request signing. -Pinning has a practical consequence worth planning for. Publishing a new version means updating the AgentTemplate to name the new digest, commit, or object version, which compiles a new revision. Agents that are already running keep the content that they started with. +If a source sets more than one kind, or none of them, the API server rejects the AgentTemplate with the error `exactly one of the fields in [oci git bucket] must be set`. + +Keep in mind that publishing a new version means updating the AgentTemplate to reference the new digest, commit, or object version, which produces a new revision. However, agents that are already running keep the content that they started with. diff --git a/docs-site/content/kagent/1.x/about/core-concepts.md b/docs-site/content/kagent/1.x/about/core-concepts.md index 04513cdf..9bc86f4d 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -169,9 +169,9 @@ Each Actor runs in its own sandbox, with its own filesystem and its own durable An agent tool binding can point at another AgentTemplate instead of an MCP server, so a broad-scope agent can hand part of a task to a specialist. For example, a release agent delegates a database question to another agent, gets the answer, and carries on. The specialist keeps its own prompt and its own tools, and the conversation stays with the agent that the caller addressed. -Each subagent binding sets `tools[].subAgent.templateRef` to name an AgentTemplate in the same namespace. The named template compiles under the parent Agent's Harness and runs inside the parent's Actor, so the two agents share one sandbox and the nesting does not create a second Actor. A subagent does not need an Agent of its own or a matching Harness reference. +Each subagent binding sets `tools[].subAgent.templateRef` to reference an AgentTemplate in the same namespace. The named template compiles under the parent Agent's Harness and runs inside the parent's Actor, so the two agents share one sandbox and the nesting does not create a second Actor. A subagent does not need an Agent of its own or a matching Harness reference. -Because a subagent runs inside its parent's runtime boundary, nesting stops at one level, and a bound template cannot bind a third. Every agent therefore runs either in its own Actor or in the Actor of the agent that bound it, never deeper. For the remaining rules that a tree must satisfy, see [What a subagent tree allows]({{< link path="skills-and-mcp/about-tools#what-a-subagent-tree-allows" >}}). +Because a subagent runs inside its parent's runtime boundary, nesting stops at one level, and a bound template cannot bind a third. Every agent therefore runs either in its own Actor or in the Actor of the agent that bound it, never deeper. For the remaining rules that a tree must meet, see [Subagent tree rules]({{< link path="skills-and-mcp/about-tools#subagent-tree-rules" >}}). > [!NOTE] -> Dedicated subagents, which would give a bound agent its own Harness, Session, and Actor and reach it over A2A, are not part of the served API. The `subAgent.agentRef` field that would select one is deferred until a dedicated subagent can create and invoke its own Session. +> Dedicated subagents, which would give a bound agent its own Harness, Session, and Actor and reach it over A2A, are not part of the served API. The `subAgent.agentRef` field that would select one is unavailable. diff --git a/docs-site/content/kagent/1.x/agents/structured-output.md b/docs-site/content/kagent/1.x/agents/structured-output.md index a502b69e..65835ce7 100644 --- a/docs-site/content/kagent/1.x/agents/structured-output.md +++ b/docs-site/content/kagent/1.x/agents/structured-output.md @@ -250,37 +250,34 @@ Error: Session task 01a0ec27-157f-7034-bb89-09855f485b2a ended in TASK_STATE_FAI ## Troubleshooting -A schema problem appears on the AgentTemplate's status, in the entry for each Harness under `status.harnesses`. `ResolvedRefs` reports a ConfigMap or key that kagent cannot find, and `Compatible` reports a schema that kagent found but cannot accept, or a Harness that does not use the `kagent` runtime. +A schema problem appears on the Agent's status conditions. `ResolvedRefs` reports a ConfigMap or key that kagent cannot find, and `Compatible` reports a schema that kagent found but cannot accept, or a Harness that does not use the `kagent` harness. ```bash -kubectl get agenttemplate structured-answer-shared -n kagent -o json \ - | jq '.status.harnesses[] | {harness, conditions: [.conditions[] | select(.type == "ResolvedRefs" or .type == "Compatible")]}' +kubectl get agent structured-answer-shared -n kagent -o json \ + | jq '[.status.conditions[] | select(.type == "ResolvedRefs" or .type == "Compatible")]' ``` For example, if the `shared-schemas` ConfigMap no longer has the `arithmetic-answer` key, the output is similar to the following. When `ResolvedRefs` fails, `Compatible` reports `Blocked` instead of a result of its own. ```json -{ - "harness": "my-first-harness", - "conditions": [ - { - "lastTransitionTime": "2026-09-29T07:52:08Z", - "message": "resolve output schema ConfigMap \"shared-schemas\": key \"arithmetic-answer\" not found", - "observedGeneration": 1, - "reason": "ReferenceResolutionFailed", - "status": "False", - "type": "ResolvedRefs" - }, - { - "lastTransitionTime": "2026-09-29T07:52:08Z", - "message": "blocked by ResolvedRefs", - "observedGeneration": 1, - "reason": "Blocked", - "status": "False", - "type": "Compatible" - } - ] -} +[ + { + "lastTransitionTime": "2026-09-29T07:52:08Z", + "message": "resolve output schema ConfigMap \"shared-schemas\": key \"arithmetic-answer\" not found", + "observedGeneration": 1, + "reason": "ReferenceResolutionFailed", + "status": "False", + "type": "ResolvedRefs" + }, + { + "lastTransitionTime": "2026-09-29T07:52:08Z", + "message": "blocked by ResolvedRefs", + "observedGeneration": 1, + "reason": "Blocked", + "status": "False", + "type": "Compatible" + } +] ``` | Message | Condition and reason | Cause | diff --git a/docs-site/content/kagent/1.x/examples/skills.md b/docs-site/content/kagent/1.x/examples/skills.md index c4290973..ca22807f 100644 --- a/docs-site/content/kagent/1.x/examples/skills.md +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -7,11 +7,11 @@ author: kagent.dev A {{< gloss "Skill" >}}skill{{< /gloss >}} packages know-how that an agent picks up at run time: a `SKILL.md` file of instructions, together with the scripts and reference files those instructions depend on. This example builds a skill that turns raw commit subjects into release notes, publishes it as an OCI image, and attaches it to an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}. -For the fields that attach a skill and the rules that govern their names, see [Skills]({{< link path="skills-and-mcp/skills" >}}). For the format of a multi-skill package, see [Plugins]({{< link path="skills-and-mcp/plugins" >}}). +For the fields that attach a skill and the rules that govern their names, see [Skills]({{< link path="skills-and-mcp/skills" >}}). For the format of a plugin, see [Plugins]({{< link path="skills-and-mcp/plugins" >}}). ## About skills at run time -kagent does not fetch a skill when you apply an AgentTemplate. The compiled revision records where each skill comes from, and the {{< gloss "Actor" >}}Actor{{< /gloss >}} fetches it when the agent starts. Every artifact is unpacked under `/plugins`, whether it holds one skill or a package of them, and each enabled skill is then copied to `/skills/`. The agent reads skills only from `/skills`. +kagent does not fetch a skill when you apply an AgentTemplate. The compiled revision records where each skill comes from, and the {{< gloss "Actor" >}}Actor{{< /gloss >}} fetches it when the agent starts. Every artifact is unpacked under `/plugins`, whether it contains a single skill or a plugin, and each enabled skill is then copied to `/skills/`. The agent reads skills only from `/skills`. Because kagent fetches a skill this late, review the following considerations. @@ -265,11 +265,11 @@ A source is immutable, so changing a skill is a two-step change: publish new con 4. Create a new Session. Conversations that are already running keep the skill content they started with, because their revision is pinned. -## Bundle the skill in a plugin package +## Bundle the skill in a plugin -A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin package{{< /gloss >}} carries several skills, and an AgentTemplate attaches the package once and names the skills it wants. Use a package when you ship a set of skills together, or when you want the same artifact to contribute [MCP servers]({{< link path="skills-and-mcp/plugins" >}}) as well. +While a standalone source carries one skill, a {{< gloss "Plugin" >}}plugin{{< /gloss >}} contains multiple skills. An AgentTemplate attaches the plugin once and lists the skills that it wants. Use a plugin when you ship a set of skills together, or when you want the same artifact to contribute [MCP servers]({{< link path="skills-and-mcp/plugins#mcp-servers" >}}) as well. -1. Restructure the directory so that each skill sits under `skills/`, and add the manifest that makes it a package. +1. Restructure the directory so that each skill sits under `skills/`, and add the manifest that makes it a plugin. ```bash cd .. mkdir -p release-tools/skills @@ -286,7 +286,7 @@ A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin pa > [!NOTE] > kagent compares the `$schema` value literally and rejects anything else, so copy it exactly. Of the remaining manifest fields, kagent reads only `name`. -2. Build and push the package, and read its digest. A package image is built the same way as a single skill, from `scratch`, so that the package root is the image root. +2. Build and push the plugin, and read its digest. A plugin image is built in the same way as a single skill from `scratch`, so that the plugin root is the image root. ```bash export PLUGIN_REPO=ghcr.io//release-tools mv skills/release-notes/Dockerfile . @@ -294,7 +294,7 @@ A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin pa export PLUGIN_OCI="$PLUGIN_REPO@$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' "$PLUGIN_REPO:1.0.0")" ``` -3. Attach the package with `plugins` instead of `skills`, and list the skills to enable. +3. Attach the plugin with `plugins` instead of `skills`, and list the skills to enable. ```bash kubectl apply -f - <}}plugin pa ``` > [!IMPORTANT] - > A package enables only the skills that you list. If you omit `plugins[].skills`, or leave it empty, the agent gets none of them, and kagent accepts that rather than reporting an error. For why an explicit list is the safer default, see [Skills]({{< link path="skills-and-mcp/skills" >}}). + > A plugin enables only the skills that you list. If you omit `plugins[].skills`, or leave it empty, the agent gets none of them, and kagent accepts an empty list rather than reporting an error. For why an explicit list is the safer default, see [Plugins]({{< link path="skills-and-mcp/plugins#skill-allowlist" >}}). 4. Create a Session on the new revision, and confirm that the agent still has the skill. The session from the previous section is pinned to the revision that carried the standalone skill. ```bash @@ -324,16 +324,16 @@ A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin pa kagent agent invoke --session $PLUGIN_SESSION_ID --task "What skills do you have?" ``` - The agent reports `release-notes` exactly as before. A skill behaves the same whether it arrives on its own or inside a package, because kagent copies both into `/skills` before the agent starts. + The agent reports `release-notes` exactly as before. A skill behaves the same whether it arrives on its own or inside a plugin, because kagent copies both into `/skills` before the agent starts. ## Troubleshoot a skill that does not load -A skill that kagent cannot fetch stops the agent from starting at all, rather than producing an agent without that skill. The runtime logs the failure and exits, and the AgentTemplate never becomes ready. +A skill that kagent cannot fetch stops the agent from starting at all, rather than producing an agent without that skill. The agent logs the failure and exits, and the Agent never becomes ready. -1. Check the AgentTemplate's `Ready` condition. A skill that cannot be fetched leaves it waiting, because the Actor that builds the template's golden snapshot is the Actor that fetches the skill. +1. Check the Agent's `Ready` condition. A skill that cannot be fetched leaves the Agent waiting, because the Actor that builds the golden snapshot is the Actor that fetches the skill. ```bash - kubectl get agenttemplate -n kagent \ - -o jsonpath='{range .status.harnesses[0].conditions[?(@.type=="Ready")]}{.status} {.reason} {.message}{end}' + kubectl get agent -n kagent \ + -o jsonpath='{range .status.conditions[?(@.type=="Ready")]}{.status} {.reason} {.message}{end}' ``` Example output: @@ -344,7 +344,7 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th > [!NOTE] > This condition does not name the skill, and reports the same reason for any Actor that has not yet produced a snapshot. An agent that is merely still starting looks identical to one whose skill cannot be fetched. -2. Find the WorkerPool that the Harness runs on, and read its Workers' logs. The Actor writes the failure there rather than to the AgentTemplate. +2. Find the WorkerPool that the Harness runs on, and read its Workers' logs. The Actor writes the failure there rather than to the Agent. ```bash export WORKER_POOL=$(kubectl get harness my-first-harness -n kagent \ -o jsonpath='{.spec.substrate.workerPoolRef.name}') @@ -367,14 +367,14 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th | `pull : ... x509` or a TLS error | The registry does not serve HTTPS with a certificate the runtime trusts. | | `SKILL.md is required` | The artifact was fetched, but no `SKILL.md` file sits at the root that `source.path` selects. | | `symlink "..." escapes artifact root` | A symlink in the artifact points outside it. | - | `artifact contains more than 10000 filesystem entries`, or `artifact exceeds 104857600 bytes` | The artifact is over one of the package limits. | + | `artifact contains more than 10000 filesystem entries`, or `artifact exceeds 104857600 bytes` | The artifact is over one of the plugin limits. | > [!TIP] > Build the skill image with `--platform` set to the architecture of your worker nodes. kagent asks the registry for the `linux/amd64` or `linux/arm64` manifest that matches the node it runs on, so an image published for one architecture alone fails on the other. ## Clean up -1. Delete the Sessions that you created. Deleting the Agent does not remove them. Skip the second command if you did not complete the plugin package section. +1. Delete the Sessions that you created. Deleting the Agent does not remove them. Skip the second command if you did not complete the plugin section. ```bash kagent agent session delete $SESSION_ID kagent agent session delete $PLUGIN_SESSION_ID @@ -386,7 +386,7 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th kubectl delete agenttemplate release-writer -n kagent ``` -3. Remove the skill directory from your machine. The directory is `release-notes`, or `release-tools` if you completed the plugin package section. +3. Remove the skill directory from your machine. The directory is `release-notes`, or `release-tools` if you completed the plugin section. ```bash cd .. rm -rf release-notes release-tools @@ -397,7 +397,7 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th ## Next steps {{< cards >}} - {{< card link=`{{< link path="skills-and-mcp/plugins" >}}` title="Plugins" subtitle="Bundle several skills, and MCP servers, into one package that an AgentTemplate attaches at once." >}} + {{< card link=`{{< link path="skills-and-mcp/plugins" >}}` title="Plugins" subtitle="Bundle several skills, and MCP servers, into one plugin that an AgentTemplate attaches at once." >}} {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Read the full set of skill fields, source kinds, and naming rules." >}} {{< card link=`{{< link path="get-started/your-first-mcp-tool" >}}` title="Your first MCP tool" subtitle="Give the same agent a tool from an MCP server alongside its skills." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/operations/debug.md b/docs-site/content/kagent/1.x/operations/debug.md index c7d7f52e..439a8955 100644 --- a/docs-site/content/kagent/1.x/operations/debug.md +++ b/docs-site/content/kagent/1.x/operations/debug.md @@ -5,13 +5,13 @@ weight: 30 author: kagent.dev --- -Most {{< reuse "kagent-docs/snippets/name-product.md" >}} failures surface in one place: the readiness conditions that a {{< gloss "Harness" >}}Harness{{< /gloss >}} writes onto the {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} that it admits. This page explains where to read those conditions, how to tell the real failure from the ones that follow it, and how to work back from the symptoms that report nothing useful on their own. +Most {{< reuse "kagent-docs/snippets/name-product.md" >}} failures surface in one place: the readiness conditions on the {{< gloss "Agent" >}}Agent{{< /gloss >}}. This page explains where to read those conditions, how to tell the real failure from the ones that follow it, and how to work back from the symptoms that report nothing useful on their own. ## Where kagent reports status Two habits from Kubernetes lead nowhere here, so it is worth knowing what reports nothing before you start. -A Harness carries **no status at all**. Its `READY` column is always blank, and the resource has no `status` key to read. +A {{< gloss "Harness" >}}Harness{{< /gloss >}} has a `READY` column, but because nothing writes the Harness status, the column is always empty. ```bash kubectl get harness -n kagent @@ -22,7 +22,7 @@ NAME READY AGE kagent 30h ``` -The AgentTemplate list view does not include a status column either, so a healthy template and a broken one look identical in it. +An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} has **no status at all**, and its list view has no status column, so a healthy template and a broken one look identical. ```bash kubectl get agenttemplate -n kagent @@ -33,19 +33,30 @@ NAME AGE assistant 30h ``` -The diagnostic surface is the AgentTemplate's `status.harnesses[]` array. Each entry covers one Harness that admits the template, and it holds that pairing's conditions and revisions. Read it directly. +The diagnostic surface is the Agent. An Agent pairs one AgentTemplate with one Harness, and its conditions cover that pairing. ```bash -kubectl get agenttemplate -n kagent \ - -o jsonpath='{range .status.harnesses[*]}{"Harness: "}{.harness}{"\n"}{range .conditions[*]}{" "}{.type}{"="}{.status}{" "}{.reason}{": "}{.message}{"\n"}{end}{end}' +kubectl get agent -n kagent ``` -Example output from a healthy pairing: +Example output: +```console +NAME READY AGE +assistant True 30h +``` + +The `READY` column reports the status of the `Ready` condition and nothing else. To find the condition's reason and message, read the Agent's conditions directly. + +```bash +kubectl get agent -n kagent \ + -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" "}{.reason}{": "}{.message}{"\n"}{end}' +``` + +Example output for a healthy Agent: ```console -Harness: kagent - Accepted=True Accepted: Harness admission selector matches the AgentTemplate - ResolvedRefs=True Resolved: All runtime references resolved - Compatible=True Compatible: Resolved configuration is compatible with the Harness - Ready=True Ready: ActorTemplate golden snapshot is ready +Accepted=True Accepted: Agent explicitly selects its template and harness +ResolvedRefs=True Resolved: All runtime references resolved +Compatible=True Compatible: Resolved configuration is compatible with the Harness +Ready=True Ready: ActorTemplate golden snapshot is ready ``` ## Read the readiness conditions @@ -56,10 +67,10 @@ Each condition covers one stage, and a stage runs only when the stage before it | Condition | Stage it covers | A failure here means | | --------- | --------------- | -------------------- | -| `Accepted` | The Harness admission selector matched this AgentTemplate. | Nothing. This condition is only ever written as `True`, so a template that fails admission has no entry rather than a false one. | -| `ResolvedRefs` | Every resource that the template names was found, including its ModelConfig and any tool servers. | A reference points at something that does not exist, or the controller cannot read it. | -| `Compatible` | The resolved configuration is valid for the Harness runtime. | The template asks for something that its Harness runtime does not support. | -| `Ready` | The ActorTemplate's golden {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} exists, so instances can start from it. | Agent Substrate has not finished capturing the golden snapshot, or capture failed. | +| `Accepted` | The Agent selects a template and a Harness. | Nothing. kagent writes this condition only as `True`, because an Agent references both resources explicitly. | +| `ResolvedRefs` | Every resource that the Agent references was found, including its AgentTemplate, its Harness, its ModelConfig, and any tool servers. | A reference points at something that does not exist, or the controller cannot read it. | +| `Compatible` | The resolved configuration is valid for the Harness. | The configuration asks for something that its Harness does not support. | +| `Ready` | The ActorTemplate's golden {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} exists, so Sessions can start from it. | Agent Substrate has not finished capturing the golden snapshot, or capture failed. | When a stage fails, kagent marks that stage `False` with the real reason and message, then marks **every later stage `False` with the reason `Blocked`**. Only the first failure describes an actual problem. @@ -68,58 +79,60 @@ When a stage fails, kagent marks that stage `False` with the real reason and mes In the following example, one missing ModelConfig is the whole problem, and the two conditions after it do not add independent information. ```console -Harness: kagent - Accepted=True Accepted: Harness admission selector matches the AgentTemplate - ResolvedRefs=False ReferenceResolutionFailed: resolve ModelConfig "does-not-exist": not found - Compatible=False Blocked: blocked by ResolvedRefs - Ready=False Blocked: blocked by ResolvedRefs +Accepted=True Accepted: Agent explicitly selects its template and harness +ResolvedRefs=False ReferenceResolutionFailed: resolve ModelConfig "does-not-exist": not found +Compatible=False Blocked: blocked by ResolvedRefs +Ready=False Blocked: blocked by ResolvedRefs ``` -The same entry carries 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 one that finished preparing. A missing `latestSuccessfulRevision` means the template has never been ready, and two differing values mean the newest edit has not prepared yet. - -## An AgentTemplate does not report conditions +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. -An AgentTemplate that no Harness admits gets no `status.harnesses[]` entry at all, so any command that ranges over that array prints nothing. +The status also reports a `warnings` list, which shows the compatibility decisions that kagent made without blocking the revision. A warning does not stop an Agent from becoming ready, so no condition reports it. -The status object holds an `observedGeneration` and nothing else. - -```console -status: - observedGeneration: 1 +```bash +kubectl get agent -n kagent -o jsonpath='{.status.warnings}' ``` -No error appears on either resource, because the Harness has no status to write one to and the AgentTemplate was never paired. The failure surfaces only when you try to use the template. +## A new AgentTemplate never runs + +When you create an AgentTemplate directly, it never becomes ready. This is because an AgentTemplate is not runnable by itself, and nothing prepares a template until an Agent references it. The template also has no status for a failure to appear on, so the problem surfaces only when you try to start a conversation. ```console ERROR: Code: FailedPrecondition - Message: AgentTemplate and Harness do not have a ready prepared revision + Message: Agent does not have a ready prepared revision ``` -The cause is almost always a missing admission label. A Harness admits AgentTemplates through `spec.allowedAgentTemplates.selector`, and the Harness that ships with kagent selects on one label. +Check which Agents exist and what each one references. ```bash -kubectl get harness kagent -n kagent -o jsonpath='{.spec.allowedAgentTemplates.selector}' +kubectl get agents -n kagent \ + -o jsonpath='{range .items[*]}{.metadata.name}{" template="}{.spec.template.ref.name}{" harness="}{.spec.harnessRef.name}{"\n"}{end}' ``` + Example output: ```console -{"matchLabels":{"kagent.dev/harness":"kagent"}} +assistant template=assistant harness=kagent ``` -If you add the label that the selector expects, the conditions appear within seconds. +An Agent that defines its behavior inline prints an empty `template=`, because it has no `spec.template.ref` to read. If no Agent references your template, create one. ```yaml apiVersion: api.kagent.dev/v1alpha3 -kind: AgentTemplate +kind: Agent metadata: name: assistant namespace: kagent - labels: - kagent.dev/harness: kagent +spec: + template: + ref: + name: assistant + harnessRef: + name: kagent ``` > [!NOTE] -> No entry in `status.harnesses[]` means admission never happened, so check the label first. An entry with a failing condition means admission succeeded and a later stage failed. +> An Agent with no conditions at all means that the controller did not reconcile it yet. An Agent with a failing condition means that reconciliation reached that stage and stopped. ## An agent turn times out @@ -146,13 +159,13 @@ Work through the causes in this order. ## An edit to an AgentTemplate has no effect -An edit that appears to do nothing has two possible causes, and the conditions distinguish them. +An edit that appears to do nothing has two possible causes, and the Agent's conditions distinguish them. -The first cause is a revision that never prepared. Compare the two revision fields on the AgentTemplate: when `desiredRevision` and `latestSuccessfulRevision` differ, the edit produced a new revision that has not become ready, and the conditions say why. +The first cause is a revision that never prepared. Compare the two revision fields on the Agent that references the template. When `desiredRevision` and `latestSuccessfulRevision` differ, the edit produces a new revision that is not ready, and the conditions say why. ```bash -kubectl get agenttemplate -n kagent \ - -o jsonpath='{range .status.harnesses[*]}{.harness}{" desired="}{.desiredRevision}{" latestSuccessful="}{.latestSuccessfulRevision}{"\n"}{end}' +kubectl get agent -n kagent \ + -o jsonpath='{"desired="}{.status.desiredRevision}{" latestSuccessful="}{.status.latestSuccessfulRevision}{"\n"}' ``` The second cause is deliberate. A {{< gloss "Session" >}}Session{{< /gloss >}} runs the revision that it was created from for its whole life, so editing an AgentTemplate never changes a conversation that already exists. Create a new Session to pick up the edit. diff --git a/docs-site/content/kagent/1.x/reference/tools-ecosystem.md b/docs-site/content/kagent/1.x/reference/tools-ecosystem.md index 8b3f4a4a..fc2b8c7b 100644 --- a/docs-site/content/kagent/1.x/reference/tools-ecosystem.md +++ b/docs-site/content/kagent/1.x/reference/tools-ecosystem.md @@ -274,12 +274,11 @@ kagent-tools: Because the settings are per-installation, they change what every agent sees. To give one agent a smaller set while leaving the server intact, list the tools on the tool binding instead, as described in [About tools]({{< link path="skills-and-mcp/about-tools#mcp-tools" >}}). -> [!WARNING] -> A tool binding's tool list does not narrow anything on the Claude {{< gloss "Harness" >}}Harness{{< /gloss >}}. The compiler exposes the whole server instead, and names the tools that you selected in a warning on the AgentTemplate's `status.harnesses[].warnings`. The kagent and Codex harnesses both honor the list. Where an agent runs on the Claude harness and must not reach a tool, narrow the server with `tools.enabledTools` or `--read-only` rather than with the binding. +The kagent and Codex harnesses both honor this tool list. On the Claude {{< gloss "Harness" >}}Harness{{< /gloss >}}, a tool binding's tool list does not narrow the server, so an agent on Claude reaches every tool that kagent-tool-server serves. Narrow the server with `tools.enabledTools` or `--read-only` instead. For more information about this behavior, see [Tool selection on the Claude harness]({{< link path="skills-and-mcp/about-tools#tool-selection-on-the-claude-harness" >}}). ## Reach kagent-tool-server from another namespace -The chart creates the `kagent-tool-server` RemoteMCPServer in the release namespace, and a RemoteMCPServer admits references from its own namespace only. Where an AgentTemplate in another namespace binds the server, the controller cannot resolve the binding and the AgentTemplate does not become ready. To admit another namespace, set `allowedNamespaces` on the RemoteMCPServer that the chart creates. +The chart creates the `kagent-tool-server` RemoteMCPServer in the release namespace, and a RemoteMCPServer admits references from its own namespace only. Where an AgentTemplate in another namespace binds the server, the controller cannot resolve the binding, and the Agent that runs that template does not become ready. To admit another namespace, set `allowedNamespaces` on the RemoteMCPServer that the chart creates. ```yaml kagent-tools: diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md index 822e5387..534ef9b8 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md @@ -5,16 +5,18 @@ weight: 10 author: kagent.dev --- -An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s `spec.tools` list defines what an agent can do beyond its system prompt. Each entry is a **{{< gloss "Tool binding" >}}tool binding{{< /gloss >}}**, and every binding selects exactly one source: a {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) server, or another AgentTemplate used as a tool. A binding that names both, or neither, is rejected. +An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s `spec.tools` list defines what an agent can do beyond its system prompt. Each entry is a **{{< gloss "Tool binding" >}}tool binding{{< /gloss >}}**, and each binding connects the agent to one source. -- `mcp`: Binds tools from an MCP server. -- `agent`: Binds another AgentTemplate, so that the agent can hand work to it. +- `mcp`: Tools from a {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) server. +- `subAgent`: Another agent that takes work from the agent that you are configuring. + +You must set exactly one of these fields on a binding. If you set both or neither fields, the API server rejects the AgentTemplate with the error `exactly one of the fields in [mcp subAgent] must be set`. Both kinds resolve within the AgentTemplate's own namespace, so a binding cannot reach a server or a template in another namespace. ## MCP tools -An `mcp` binding names a server, and optionally the tools to take from it. On the kagent and Codex harnesses, listing tools narrows the binding to those tools. Omitting the list, or leaving it empty, exposes every tool that the server offers. +An `mcp` binding references an MCP server in the AgentTemplate's namespace. The optional `tools` list limits which of that server's tools the agent gets. On the kagent and Codex harnesses, a list narrows the binding to the tools that you name. To give the agent every tool that the server offers, omit the list or leave it empty. ```yaml tools: @@ -32,22 +34,24 @@ tools: | ----- | ----------- | | `mcp.server.kind` | The kind of server resource. `RemoteMCPServer` is the only accepted value. | | `mcp.server.name` | The server's name, in the AgentTemplate's namespace. | -| `mcp.tools` | Optional. The names of the tools to bind, up to 50. Duplicates are collapsed. An omitted or empty list exposes every tool on the server, and so does any list on the Claude harness. | -| `mcp.requireApproval` | Optional. Pauses the agent for a person's approval before each call to a tool that this binding exposes. Omit to run the bound tools without approval. For more information, see [Human in the loop]({{< link path="agents/human-in-the-loop#require-approval-for-a-tool" >}}). | - -> [!WARNING] -> **The Claude {{< gloss "Harness" >}}Harness{{< /gloss >}} ignores `mcp.tools` and exposes the whole server.** Claude's MCP configuration has no per-tool allowlist, so kagent cannot narrow a server there. The compiler records the tools that you selected in a warning on the AgentTemplate's `status.harnesses[].warnings` and then admits the {{< gloss "Revision" >}}revision{{< /gloss >}} anyway, so the agent becomes ready with every tool that the server serves. Read the warning after you bind a server: -> -> ```sh -> kubectl get agenttemplate -n \ -> -o jsonpath='{range .status.harnesses[*]}{.harness}{": "}{.warnings}{"\n"}{end}' -> ``` -> -> Where an agent on the Claude harness must not reach a tool, narrow the server rather than the binding. Set `requireApproval: true`, which does apply on this harness and pauses every call to the server, or give the agent its own RemoteMCPServer that serves only the tools you intend. For the bundled tool server, see the installation-level settings that drop providers and write tools in [Tools ecosystem]({{< link path="reference/tools-ecosystem#narrow-what-kagent-tool-server-serves" >}}). +| `mcp.tools` | Optional. The names of the tools to bind, up to 50. Duplicates are collapsed. Omit the list, or leave it empty, to expose every tool on the server. On the Claude {{< gloss "Harness" >}}Harness{{< /gloss >}}, a list does not narrow the server. See [Tool selection on the Claude harness](#tool-selection-on-the-claude-harness). | +| `mcp.requireApproval` | Optional. Pauses the agent for a person's approval before each call to a tool that this binding exposes. On the Claude harness, the pause covers every tool on the server, because Claude approves one server at a time rather than one tool at a time. Omit to run the bound tools without approval. For more information, see [Human in the loop]({{< link path="agents/human-in-the-loop#require-approval-for-a-tool" >}}). | + +### Tool selection on the Claude harness + +Claude's MCP configuration has no per-tool allowlist. On the Claude harness, the `tools` list does not narrow a server, and the agent reaches every tool that the server serves. kagent admits the {{< gloss "Revision" >}}revision{{< /gloss >}} either way. If the list that you wrote does not already cover every tool that the server offers, kagent also records a warning on the Agent. + +```sh +kubectl get agent -n -o jsonpath='{.status.warnings}' +``` + +To keep an agent on the Claude harness away from a tool, limit what the server exposes rather than what the binding selects. For example, put the MCP server behind agentgateway and apply [tool access](https://agentgateway.dev/docs/kubernetes/latest/documentation/mcp/tool-access/) rules to the route. Those rules filter a disallowed tool out of the `tools/list` response, so the agent never sees it. Then point the RemoteMCPServer at that route. To put more than one MCP server behind one route, see [Virtual MCP](https://agentgateway.dev/docs/kubernetes/latest/documentation/mcp/virtual/). + +For the bundled tool server, see the installation-level settings that drop providers and write tools in [Tools ecosystem]({{< link path="reference/tools-ecosystem#narrow-what-kagent-tool-server-serves" >}}). ## Subagents as tools -A `subAgent` binding points at another AgentTemplate. The binding allows one agent to route work to another agent. The model reads the `description` when it decides whether to route work here. A description that states plainly what the bound agent is for therefore matters more than the detail of its configuration. +A `subAgent` binding points at another AgentTemplate in the same namespace so that one agent can route work to another agent. The model reads the `description` when it decides whether to route work here. A description that states plainly what the bound agent is for therefore matters more than the detail of its configuration. ```yaml tools: @@ -66,16 +70,25 @@ Every field is required. For the complete schema, see the [API reference]({{< li | `subAgent.description` | The text that tells the parent agent when to route work here. | | `subAgent.templateRef.name` | The AgentTemplate to bind, in the same namespace. | -A bound template compiles under the parent {{< gloss "Agent" >}}Agent{{< /gloss >}}'s Harness and runs inside the parent's {{< gloss "Actor" >}}Actor{{< /gloss >}}, so nesting does not add compute and the two agents share one sandbox. A subagent does not need an Agent of its own. +kagent compiles the bound template into the parent agent's own configuration, and both agents then run in the same place. A bound template is not an MCP server and has no endpoint of its own. A bound template also does not need an {{< gloss "Agent" >}}Agent{{< /gloss >}} resource because the parent's Agent runs it. > [!NOTE] -> Dedicated subagents, which would give a bound agent its own Harness, Session, and Actor and reach it over A2A, are not part of the served API. The `subAgent.agentRef` field that would select one is deferred until a dedicated subagent can create and invoke its own Session, so the only binding a reader can write today is `templateRef`. +> Dedicated subagents, which would give a bound agent its own Harness, Session, and {{< gloss "Actor" >}}Actor{{< /gloss >}}, are not part of the served API. The `subAgent.agentRef` field that would select one is unavailable, so `templateRef` is the only binding that you can write today. -### What a subagent tree allows +### Subagent tree rules -A subagent binding nests one agent inside another's runtime, so kagent constrains the shape of the resulting tree. The compiler enforces each of the following rules, and a violation surfaces as a failed {{< gloss "Revision" >}}revision{{< /gloss >}} rather than a failure at run time. +A bound agent runs inside its parent, so kagent constrains the shape of the resulting tree. kagent rejects a violation while it compiles the Agent, before any revision exists. -- **One level of nesting.** A bound agent cannot itself bind another agent. A second consecutive binding is rejected as exceeding the kagent runtime boundary. +- **One level of nesting.** A bound agent cannot bind another agent. - **No cycles.** An AgentTemplate cannot reach itself through a chain of bindings. - **No reuse within one tree.** The same AgentTemplate cannot appear twice in the same tree. - **Unique binding names.** Two bindings on one AgentTemplate cannot share a `name`. + +When kagent rejects a tree, the Agent's `Compatible` condition becomes `False`. The condition reports the reason as `UnsupportedConfiguration` and returns a message that identifies the rule that failed. Read both in the output of the following command. + +```sh +kubectl get agent -n \ + -o jsonpath='{range .status.conditions[?(@.type=="Compatible")]}{.reason}{": "}{.message}{"\n"}{end}' +``` + +The Claude and Codex harnesses apply further restrictions by not allowing a bound agent to have tools, skills, or plugins of its own. The bound agent must also use the same model provider and authentication as its parent. A tree that compiles on the kagent harness can therefore fail after you move it to a Harness that runs Claude or Codex. diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md b/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md index 41ed0f4d..9348fdb7 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md @@ -1,57 +1,108 @@ --- title: Plugins -description: Understand what a plugin package holds, and what kagent does with one when an agent starts. +description: Understand what a plugin contains, and what kagent does with one when an agent starts. weight: 30 author: kagent.dev --- -A **{{< gloss "Plugin package" >}}plugin package{{< /gloss >}}** is a bundle that an AgentTemplate attaches with `spec.plugins`. The package carries {{< gloss "Skill" >}}skills{{< /gloss >}} and can also declare {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) servers. Packages follow the [Agent Plugins](https://agent-plugins.org) 1.0.0 format, which kagent consumes rather than defines. This page covers what a package holds and how kagent handles it. To understand how to attach a plugin package with an AgentTemplate, see [Skills]({{< link path="skills-and-mcp/skills" >}}). +A **{{< gloss "Plugin" >}}plugin{{< /gloss >}}** is a bundle that an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} attaches with `spec.plugins`. A plugin contains {{< gloss "Skill" >}}skills{{< /gloss >}} and can also declare {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) servers. Plugins follow the [Agent Plugins](https://agent-plugins.org) 1.0.0 specification. To attach a skill that is published on its own, see [Skills]({{< link path="skills-and-mcp/skills#attach-skills-to-an-agenttemplate" >}}). -## What a package holds +## Plugin contents -A package root can hold up to three things. +A plugin root contains a manifest, and optionally the skills and the MCP servers that the plugin contributes. -- `plugin.json` (required): The manifest that names the package. -- `skills/`: One subdirectory per skill, each holding a `SKILL.md` file at its root. -- `mcp.json`: Declares MCP servers that kagent adds to the agent's tools. +- `plugin.json` (required): The manifest that gives the plugin its name. +- `skills/`: One subdirectory per skill, each with a `SKILL.md` file at its root. +- `mcp.json`: Declares MCP servers that kagent adds to the agent's [tools]({{< link path="skills-and-mcp/about-tools" >}}). -kagent reads `name` from the manifest and ignores the rest, so a package that carries `version`, `description`, `author`, `homepage`, `repository`, `license`, `keywords`, or `extensions` is accepted, but none of those fields change what the agent gets. The manifest's `$schema` must be exactly `https://agent-plugins.org/schemas/1.0.0/plugin.schema.json`. +kagent reads `name` from the manifest and ignores the rest. A manifest that sets `version`, `description`, `author`, `homepage`, `repository`, `license`, `keywords`, or `extensions` is accepted, but none of those fields change what the agent gets. -> [!NOTE] -> kagent compares that `$schema` value literally. It does not fetch the schema or validate the document against it, so a manifest that names the right schema and holds the wrong shape is rejected by the decoder rather than by schema validation. +The name must be at most 64 characters. It must start and end with a lowercase letter or a digit, and the characters between can be lowercase letters, digits, dots, and hyphens. A name that contains `--` or `..` is rejected. + +The manifest's `$schema` must be exactly `https://agent-plugins.org/schemas/1.0.0/plugin.schema.json`. kagent compares that value literally. kagent does not fetch the schema, and it does not check the manifest against the schema. + +## Attach a plugin to an AgentTemplate + +Use `spec.plugins` to attach a plugin and list the skills that the agent needs from it. + +```yaml +apiVersion: api.kagent.dev/v1alpha3 +kind: AgentTemplate +metadata: + name: incident-responder + namespace: kagent +spec: + modelConfig: + name: default-model-config + systemPrompt: You help engineers work through production incidents. + plugins: + - source: + git: + url: https://github.com/example/agent-plugins + commit: + path: bundles/observability + skills: + - log-search + - runbook-lookup +``` + +| Field | Description | +| ----- | ----------- | +| `plugins[].source` | The location to fetch the plugin from. The source root must contain a `plugin.json` manifest. | +| `plugins[].skills` | The names of the skills inside that plugin to enable, up to 50. Omit the list, or leave it empty, to enable none of them. | +| `source.path` | The directory to select inside the artifact, when the content is not at its root. The path must be relative, and it cannot climb out of the artifact with `..` segments. | + +One AgentTemplate accepts up to 20 plugins. + +### Skill allowlist + +List the name of each skill that you want in `plugins[].skills`. A skill's name is the name of its subdirectory under `skills/` in the plugin. + +Attaching a plugin does not enable the skills that it contains, and an empty list does not enable any of them. kagent accepts an empty list as a safe default rather than reporting an error. An explicit list also means that a later version of the plugin cannot add skills to your agent. To enable a new skill, add its name. + +Plugin names must be unique. If two entries in `plugins` declare the same name in their manifests, the agent fails to start. Skill names come from your AgentTemplate, so kagent checks them before it fetches anything. A plugin name comes from the plugin's own manifest, and kagent can only check that name as each plugin is fetched. + +## Claude-format plugins + +kagent reads `plugin.json` at the plugin root. A plugin that instead keeps its manifest at `.claude-plugin/plugin.json` is a Claude-format plugin. kagent handles a Claude-format plugin differently on each {{< gloss "Harness" >}}Harness{{< /gloss >}}. + +- On the Claude harness, kagent hands the whole plugin to the Claude CLI. The `plugins[].skills` allowlist does not apply, and the agent gets every skill in the plugin. +- On every other harness, the agent fails to start, with the error `plugin is Claude-format; only the Agent Plugins format (plugin.json at the plugin root) is supported here`. + +kagent also does not check the `$schema` value in a Claude-format manifest. ## MCP servers -A package that includes `mcp.json` contributes MCP servers to every agent that enables it, alongside any bound directly on the AgentTemplate (see [About tools]({{< link path="skills-and-mcp/about-tools" >}})). The file declares an `mcpServers` object, keyed by server name, and its `$schema` must be exactly `https://agent-plugins.org/schemas/1.0.0/mcp.schema.json`. +A plugin that includes `mcp.json` contributes MCP servers to every agent that enables it, alongside any bound directly on the AgentTemplate. The file has an `mcpServers` object, keyed by server name, and its `$schema` must be exactly `https://agent-plugins.org/schemas/1.0.0/mcp.schema.json`. -Each server names a transport in its `type` field, and the transport determines which other fields are allowed. +Each server specifies a transport in its `type` field, and the transport determines which other fields are allowed. | Transport | Fields | Description | | --------- | ------ | ----------- | -| `stdio` | `command`, `args`, `env`, `cwd` | Runs a process inside the agent's sandbox. Specifying `url` or `headers` is rejected. | +| `stdio` | `command`, `args`, `env`, `cwd` | Runs a process in the same place as the agent. Specifying `url` or `headers` is rejected. | | `streamable-http` | `url`, `headers` | Calls a remote server. Specifying `command`, `args`, `env`, or `cwd` is rejected. | | `sse` | `url`, `headers` | Calls a remote server over Server-Sent Events. Accepts the same fields as `streamable-http`. | -kagent enforces several rules on these servers, and each one exists to keep a package from reaching outside itself. +The path rules on a `stdio` server keep a plugin self-contained. A plugin can run only what it ships or what the agent's image already provides, and it can write only to its own data directory. -- A `stdio` command must be either a bare name resolved on the sandbox's path, or a package-relative path beginning with `./`. A command holding a path separator any other way or containing whitespace is rejected. -- A `cwd` must be package-relative or written with the `${PLUGIN_ROOT}` or `${PLUGIN_DATA}` [variables](#referring-to-package-files), and it is rejected if it resolves outside the package. -- A remote `url` must be `http` or `https`, and must not carry user information or fragments. Any host other than a loopback address must use HTTPS. +- A `stdio` command must be a bare name on the agent's `PATH`, or a path that begins with `./` and resolves inside the plugin directory. A command that uses a path separator any other way or that contains whitespace is rejected. +- A `cwd` must begin with `./`, `${PLUGIN_ROOT}`, or `${PLUGIN_DATA}`, and it must resolve inside the plugin directory or that plugin's data directory. Omit `cwd` to run the command in the plugin directory. If a `cwd` under `${PLUGIN_DATA}` does not exist yet, kagent creates it. +- A remote `url` must be `http` or `https`, and it must not carry user information or fragments. Any host other than a loopback address must use HTTPS. - Unrecognized fields are rejected rather than ignored. -An invalid server is skipped with a log entry, and the rest of the file still loads. An `mcp.json` that is invalid or that names an unexpected schema is ignored in full. +If one server in the file is invalid, kagent logs the problem and skips that server, but the rest of the file is still loaded. A whole `mcp.json` contributes nothing when it fails to parse, declares an unexpected `$schema`, or omits `mcpServers`. -### Referring to package files +### Referring to plugin files -A `stdio` server often needs to run something that the package ships, or to write somewhere durable. Two variables are expanded in `args`, `env` values, and `cwd`. +A `stdio` server often needs to run something that the plugin ships, or to write somewhere durable. kagent expands two variables in `args`, in `env` values, and in `cwd`. -- `${PLUGIN_ROOT}`: The directory the package was unpacked into. Read-only in practice, and shared by every Actor of the template. -- `${PLUGIN_DATA}`: A per-package data directory that kagent creates. Use it for anything the server writes. +- `${PLUGIN_ROOT}`: The directory that the plugin was unpacked into. Treat it as read-only. +- `${PLUGIN_DATA}`: The data directory that kagent creates for that plugin. Use it for anything that the server writes. -kagent also sets both as environment variables on every `stdio` server, so a server can read them without the package declaring them. A package cannot override either one: an `env` block that sets `PLUGIN_ROOT` or `PLUGIN_DATA` is rejected. +kagent also sets `PLUGIN_ROOT` and `PLUGIN_DATA` as environment variables on every `stdio` server, so a server can read them without the plugin declaring them. A plugin cannot override either variable. An `env` block that sets one of them is rejected. -## Package limits +## Plugin limits -kagent measures a package after fetching it and before mounting anything. A package is rejected if it holds more than 10,000 filesystem entries or more than 100 MB of regular files. A `.git` directory is skipped and counts toward neither. +kagent measures a plugin after fetching it and before mounting anything. A plugin is rejected if it contains more than 10,000 filesystem entries or more than 100 MB of regular files. A `.git` directory is skipped and counts toward neither. A symlink that resolves outside the artifact root is also rejected. {{< reuse "kagent-docs/snippets/artifact-sources.md" >}} diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/skills.md b/docs-site/content/kagent/1.x/skills-and-mcp/skills.md index f4a65377..cc53d05b 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/skills.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/skills.md @@ -5,19 +5,19 @@ weight: 20 author: kagent.dev --- -A **{{< gloss "Skill" >}}skill{{< /gloss >}}** packages a piece of know-how that an agent can pick up: a set of instructions, together with whatever scripts or reference files those instructions depend on. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} attaches skills by naming where each one comes from, and kagent fetches them and places them where the agent runtime can find them. +A **{{< gloss "Skill" >}}skill{{< /gloss >}}** packages a piece of know-how that an agent can pick up: a set of instructions, together with whatever scripts, command-line tools, or reference files those instructions depend on. You attach a skill to an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} by specifying where it comes from, and kagent fetches it and places it where the agent can find it. ## About A skill is a directory whose root holds a `SKILL.md` file. That file carries front matter naming the skill and describing what it is for, followed by the instructions themselves. -The description makes a skill usable. When an agent starts, the runtime reads the front matter of every skill that is attached to it, and offers those skills to the model as tools that it can call. The model chooses a skill from its description, in the same way that it chooses any other tool. This means that a description that states plainly when to use the skill matters more than the length of the instructions behind it. +The description makes a skill usable. When an agent starts, it reads the front matter of every skill that is attached to it. The agent then offers those skills to the model as tools that the model can call. The model chooses a skill from its description in the same way that it chooses any other tool. A description that states plainly when to use the skill therefore matters more than the length of the instructions behind it. -A skill can be published on its own, or bundled with other skills in a [plugin package]({{< link path="skills-and-mcp/plugins" >}}), which can also declare {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) servers that kagent adds to the agent's [tools]({{< link path="skills-and-mcp/about-tools" >}}). +A skill can be published on its own, or bundled with other skills in a {{< gloss "Plugin" >}}plugin{{< /gloss >}}. For what a plugin contains and how to attach one, see [Plugins]({{< link path="skills-and-mcp/plugins" >}}). ## Attach skills to an AgentTemplate -An AgentTemplate attaches skills in two ways, and it can use both at once. Use `spec.skills` for a standalone skill, and `spec.plugins` for a {{< gloss "Plugin package" >}}plugin package{{< /gloss >}}. +Use `spec.skills` to attach a standalone skill. Each entry gives the skill a name and an immutable source to fetch it from. ```yaml apiVersion: api.kagent.dev/v1alpha3 @@ -33,39 +33,21 @@ spec: - name: incident-triage source: oci: registry.example.com/skills/incident-triage@sha256: - plugins: - - source: - git: - url: https://github.com/example/agent-plugins - commit: - path: bundles/observability - skills: - - log-search - - runbook-lookup ``` | Field | Description | | ----- | ----------- | | `skills[].name` | The name that the skill is mounted under, and the name that the model sees. | -| `skills[].source` | The location to fetch this one skill from. The source root must hold a `SKILL.md` file. | -| `plugins[].source` | The location to fetch the plugin package from. The source root must hold a `plugin.json` manifest. | -| `plugins[].skills` | The names of the skills inside that package to enable. Omit or leave empty to enable none. | +| `skills[].source` | The location to fetch this one skill from. The source root must contain a `SKILL.md` file. | | `source.path` | The directory to select inside the artifact, when the content is not at its root. The path must be relative, and it cannot climb out of the artifact with `..` segments. | -### Plugin allowlist - -Attaching a plugin package does not enable any of the skills that it carries. Only the names listed in `plugins[].skills` are enabled. - -> [!IMPORTANT] -> An empty skills list enables nothing. Adding a plugin package and omitting its `skills` list gives the agent no skills from that package, which is the safe default rather than an error. Listing skills explicitly also means that a package gaining new skills in a later version does not silently grant them to your agent. +One AgentTemplate accepts up to 50 standalone skills. To give an agent the skills that a plugin contains, [use `spec.plugins` instead]({{< link path="skills-and-mcp/plugins#attach-a-plugin-to-an-agenttemplate" >}}). An AgentTemplate can use both fields at once. {{< reuse "kagent-docs/snippets/artifact-sources.md" >}} ## Naming rules -Skill names are checked before anything is fetched, and two rules apply across every skill on an AgentTemplate. +kagent checks skill names before it fetches anything. These rules apply to every skill on an AgentTemplate, whether the skill is standalone or comes from a plugin. - A name must be a single path component. A name containing a slash, or a name of `.` or `..`, is rejected. -- Names must be unique across the whole AgentTemplate. Because standalone skills and plugin skills are mounted into the same place, a standalone skill cannot reuse the name of an enabled plugin skill, and two plugin packages cannot both contribute the same name. - -Plugin package names must also be unique. Two entries in `plugins` whose manifests declare the same name are rejected. Unlike skill names, kagent checks this as each package is fetched, because the name comes from the package's `plugin.json` manifest rather than from your AgentTemplate. +- Names must be unique across the whole AgentTemplate. Because standalone skills and plugin skills are mounted into the same place, a standalone skill cannot reuse the name of an enabled plugin skill, and two plugins cannot both contribute the same name. diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index 9105618b..f9b22b25 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -111,15 +111,15 @@ Transcript: short: "The record of a Session's conversation, held server-side and append-only. It survives the Actor suspending between turns, and a resumed runtime cannot shrink it." Skill: - short: "A packaged piece of know-how that an agent can pick up: a directory holding a SKILL.md file of instructions, plus any scripts or reference files those instructions use. An AgentTemplate attaches skills by naming where each one comes from." + short: "A packaged piece of know-how that an agent can pick up: a directory holding a SKILL.md file of instructions, plus any scripts, command-line tools, or reference files those instructions use. You attach a skill to an AgentTemplate by specifying where it comes from." link: "/docs/kagent/1.x/skills-and-mcp/skills/" -Plugin package: - short: "A bundle that an AgentTemplate attaches with spec.plugins, carrying skills and optionally declaring Model Context Protocol servers. Packages follow the Agent Plugins format, which kagent consumes rather than defines." +Plugin: + short: "A bundle that an AgentTemplate attaches with spec.plugins. A plugin carries skills and can also declare Model Context Protocol servers. Plugins follow the Agent Plugins specification." link: "/docs/kagent/1.x/skills-and-mcp/plugins/" Tool binding: - short: "One entry in an AgentTemplate's spec.tools list. Each binding selects exactly one source: tools from a Model Context Protocol server, or another AgentTemplate used as a tool." + short: "One entry in an AgentTemplate's spec.tools list. Each binding connects the agent to one source: tools from a Model Context Protocol server, or another agent that takes work from it." link: "/docs/kagent/1.x/skills-and-mcp/about-tools/" Model Context Protocol: From d90a51d1481be906ef914696b4ca3ceb848b9806 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 15 Oct 2026 11:08:29 -0500 Subject: [PATCH 2/3] conventions sweep Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/agents/structured-output.md | 2 +- docs-site/content/kagent/1.x/examples/skills.md | 2 +- docs-site/content/kagent/1.x/operations/debug.md | 6 +++--- docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs-site/content/kagent/1.x/agents/structured-output.md b/docs-site/content/kagent/1.x/agents/structured-output.md index 65835ce7..1042befb 100644 --- a/docs-site/content/kagent/1.x/agents/structured-output.md +++ b/docs-site/content/kagent/1.x/agents/structured-output.md @@ -250,7 +250,7 @@ Error: Session task 01a0ec27-157f-7034-bb89-09855f485b2a ended in TASK_STATE_FAI ## Troubleshooting -A schema problem appears on the Agent's status conditions. `ResolvedRefs` reports a ConfigMap or key that kagent cannot find, and `Compatible` reports a schema that kagent found but cannot accept, or a Harness that does not use the `kagent` harness. +A schema problem appears on the Agent's status conditions. `ResolvedRefs` reports a ConfigMap or key that kagent cannot find. `Compatible` reports a schema that kagent found but cannot accept, or a Harness that does not use the `kagent` harness. ```bash kubectl get agent structured-answer-shared -n kagent -o json \ diff --git a/docs-site/content/kagent/1.x/examples/skills.md b/docs-site/content/kagent/1.x/examples/skills.md index ca22807f..609ad628 100644 --- a/docs-site/content/kagent/1.x/examples/skills.md +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -397,7 +397,7 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th ## Next steps {{< cards >}} - {{< card link=`{{< link path="skills-and-mcp/plugins" >}}` title="Plugins" subtitle="Bundle several skills, and MCP servers, into one plugin that an AgentTemplate attaches at once." >}} + {{< card link=`{{< link path="skills-and-mcp/plugins" >}}` title="Plugins" subtitle="Bundle skills and MCP servers into one plugin that an AgentTemplate attaches at once." >}} {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Read the full set of skill fields, source kinds, and naming rules." >}} {{< card link=`{{< link path="get-started/your-first-mcp-tool" >}}` title="Your first MCP tool" subtitle="Give the same agent a tool from an MCP server alongside its skills." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/operations/debug.md b/docs-site/content/kagent/1.x/operations/debug.md index 439a8955..17355d9d 100644 --- a/docs-site/content/kagent/1.x/operations/debug.md +++ b/docs-site/content/kagent/1.x/operations/debug.md @@ -87,7 +87,7 @@ Ready=False Blocked: blocked by ResolvedRefs 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. -The status also reports a `warnings` list, which shows the compatibility decisions that kagent made without blocking the revision. A warning does not stop an Agent from becoming ready, so no condition reports it. +The status also reports a `warnings` list, which shows the compatibility decisions that kagent made without blocking the revision. A warning does not stop an Agent from becoming ready, and the conditions do not report it. ```bash kubectl get agent -n kagent -o jsonpath='{.status.warnings}' @@ -95,7 +95,7 @@ kubectl get agent -n kagent -o jsonpath='{.status.warnings}' ## A new AgentTemplate never runs -When you create an AgentTemplate directly, it never becomes ready. This is because an AgentTemplate is not runnable by itself, and nothing prepares a template until an Agent references it. The template also has no status for a failure to appear on, so the problem surfaces only when you try to start a conversation. +When you create an AgentTemplate directly, it never becomes ready. An AgentTemplate is not runnable by itself, and nothing prepares a template until an Agent references it. The template also has no status for a failure to appear on, so the problem surfaces only when you try to start a conversation. ```console ERROR: @@ -132,7 +132,7 @@ spec: ``` > [!NOTE] -> An Agent with no conditions at all means that the controller did not reconcile it yet. An Agent with a failing condition means that reconciliation reached that stage and stopped. +> An Agent with no conditions at all means that the controller has not reconciled it yet. An Agent with a failing condition means that reconciliation reached that stage and stopped. ## An agent turn times out diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md index 534ef9b8..605052b0 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md @@ -84,7 +84,7 @@ A bound agent runs inside its parent, so kagent constrains the shape of the resu - **No reuse within one tree.** The same AgentTemplate cannot appear twice in the same tree. - **Unique binding names.** Two bindings on one AgentTemplate cannot share a `name`. -When kagent rejects a tree, the Agent's `Compatible` condition becomes `False`. The condition reports the reason as `UnsupportedConfiguration` and returns a message that identifies the rule that failed. Read both in the output of the following command. +When kagent rejects a tree, the Agent's `Compatible` condition becomes `False`. The condition reports the reason `UnsupportedConfiguration`, and its message identifies the rule that failed. Read both in the output of the following command. ```sh kubectl get agent -n \ From a600e80fbe5380be5772db63046bd219d6226dc2 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 15 Oct 2026 12:13:54 -0500 Subject: [PATCH 3/3] review comments Signed-off-by: Rachael Graham --- .../kagent-docs/snippets/artifact-sources.md | 2 +- .../content/kagent/1.x/agents/structured-output.md | 2 +- docs-site/content/kagent/1.x/examples/skills.md | 2 +- docs-site/content/kagent/1.x/operations/debug.md | 2 +- .../kagent/1.x/skills-and-mcp/about-tools.md | 14 +++++++------- .../content/kagent/1.x/skills-and-mcp/plugins.md | 6 +++--- docs-site/data/glossary.yaml | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs-site/assets/kagent-docs/snippets/artifact-sources.md b/docs-site/assets/kagent-docs/snippets/artifact-sources.md index c5ebd156..ae69ab2e 100644 --- a/docs-site/assets/kagent-docs/snippets/artifact-sources.md +++ b/docs-site/assets/kagent-docs/snippets/artifact-sources.md @@ -8,4 +8,4 @@ A skill or a plugin changes what an agent does, so kagent only accepts artifact If a source sets more than one kind, or none of them, the API server rejects the AgentTemplate with the error `exactly one of the fields in [oci git bucket] must be set`. -Keep in mind that publishing a new version means updating the AgentTemplate to reference the new digest, commit, or object version, which produces a new revision. However, agents that are already running keep the content that they started with. +Publishing a new version means updating the AgentTemplate to reference the new digest, commit, or object version. The update produces a new revision. Agents that are already running keep the content that they started with. diff --git a/docs-site/content/kagent/1.x/agents/structured-output.md b/docs-site/content/kagent/1.x/agents/structured-output.md index 1042befb..4223f161 100644 --- a/docs-site/content/kagent/1.x/agents/structured-output.md +++ b/docs-site/content/kagent/1.x/agents/structured-output.md @@ -250,7 +250,7 @@ Error: Session task 01a0ec27-157f-7034-bb89-09855f485b2a ended in TASK_STATE_FAI ## Troubleshooting -A schema problem appears on the Agent's status conditions. `ResolvedRefs` reports a ConfigMap or key that kagent cannot find. `Compatible` reports a schema that kagent found but cannot accept, or a Harness that does not use the `kagent` harness. +A schema problem appears on the Agent's status conditions. `ResolvedRefs` reports a ConfigMap or key that kagent cannot find. `Compatible` reports a schema that kagent found but cannot accept, or a Harness whose runtime is not `kagent`. ```bash kubectl get agent structured-answer-shared -n kagent -o json \ diff --git a/docs-site/content/kagent/1.x/examples/skills.md b/docs-site/content/kagent/1.x/examples/skills.md index 609ad628..94eaa477 100644 --- a/docs-site/content/kagent/1.x/examples/skills.md +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -332,7 +332,7 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th 1. Check the Agent's `Ready` condition. A skill that cannot be fetched leaves the Agent waiting, because the Actor that builds the golden snapshot is the Actor that fetches the skill. ```bash - kubectl get agent -n kagent \ + kubectl get agent release-writer -n kagent \ -o jsonpath='{range .status.conditions[?(@.type=="Ready")]}{.status} {.reason} {.message}{end}' ``` diff --git a/docs-site/content/kagent/1.x/operations/debug.md b/docs-site/content/kagent/1.x/operations/debug.md index 17355d9d..fc29d982 100644 --- a/docs-site/content/kagent/1.x/operations/debug.md +++ b/docs-site/content/kagent/1.x/operations/debug.md @@ -95,7 +95,7 @@ kubectl get agent -n kagent -o jsonpath='{.status.warnings}' ## A new AgentTemplate never runs -When you create an AgentTemplate directly, it never becomes ready. An AgentTemplate is not runnable by itself, and nothing prepares a template until an Agent references it. The template also has no status for a failure to appear on, so the problem surfaces only when you try to start a conversation. +When you create an AgentTemplate directly, nothing prepares it until an Agent references it. The template also has no status for a failure to appear on, so the problem surfaces only when you try to start a conversation. ```console ERROR: diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md index 605052b0..e31f61c8 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md @@ -8,7 +8,7 @@ author: kagent.dev An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s `spec.tools` list defines what an agent can do beyond its system prompt. Each entry is a **{{< gloss "Tool binding" >}}tool binding{{< /gloss >}}**, and each binding connects the agent to one source. - `mcp`: Tools from a {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) server. -- `subAgent`: Another agent that takes work from the agent that you are configuring. +- `subAgent`: Another AgentTemplate that takes work from the agent that you are configuring. You must set exactly one of these fields on a binding. If you set both or neither fields, the API server rejects the AgentTemplate with the error `exactly one of the fields in [mcp subAgent] must be set`. @@ -39,13 +39,13 @@ tools: ### Tool selection on the Claude harness -Claude's MCP configuration has no per-tool allowlist. On the Claude harness, the `tools` list does not narrow a server, and the agent reaches every tool that the server serves. kagent admits the {{< gloss "Revision" >}}revision{{< /gloss >}} either way. If the list that you wrote does not already cover every tool that the server offers, kagent also records a warning on the Agent. +Claude's MCP configuration has no per-tool allowlist. On the Claude harness, the `tools` list does not narrow a server, and the agent reaches every tool that the server serves. kagent admits the {{< gloss "Revision" >}}revision{{< /gloss >}} either way. Unless the list exactly matches the tools that kagent currently discovers on the server, kagent also records a warning on the Agent. ```sh kubectl get agent -n -o jsonpath='{.status.warnings}' ``` -To keep an agent on the Claude harness away from a tool, limit what the server exposes rather than what the binding selects. For example, put the MCP server behind agentgateway and apply [tool access](https://agentgateway.dev/docs/kubernetes/latest/documentation/mcp/tool-access/) rules to the route. Those rules filter a disallowed tool out of the `tools/list` response, so the agent never sees it. Then point the RemoteMCPServer at that route. To put more than one MCP server behind one route, see [Virtual MCP](https://agentgateway.dev/docs/kubernetes/latest/documentation/mcp/virtual/). +To keep an agent on the Claude harness away from a tool, limit what the server exposes rather than what the binding selects. Give the agent its own RemoteMCPServer that serves only the tools that you intend. Where you do not control what the server serves, put the MCP server behind agentgateway and apply [tool access](https://agentgateway.dev/docs/kubernetes/latest/documentation/mcp/tool-access/) rules to the route. Those rules filter a disallowed tool out of the `tools/list` response, so the agent never sees it. Then point the RemoteMCPServer at that route. To put more than one MCP server behind one route, see [Virtual MCP](https://agentgateway.dev/docs/kubernetes/latest/documentation/mcp/virtual/). For the bundled tool server, see the installation-level settings that drop providers and write tools in [Tools ecosystem]({{< link path="reference/tools-ecosystem#narrow-what-kagent-tool-server-serves" >}}). @@ -70,10 +70,10 @@ Every field is required. For the complete schema, see the [API reference]({{< li | `subAgent.description` | The text that tells the parent agent when to route work here. | | `subAgent.templateRef.name` | The AgentTemplate to bind, in the same namespace. | -kagent compiles the bound template into the parent agent's own configuration, and both agents then run in the same place. A bound template is not an MCP server and has no endpoint of its own. A bound template also does not need an {{< gloss "Agent" >}}Agent{{< /gloss >}} resource because the parent's Agent runs it. +kagent compiles the bound template into the parent agent's own configuration and runs it inside the parent's {{< gloss "Actor" >}}Actor{{< /gloss >}}, so the two agents share one sandbox. A bound template is not an MCP server and has no endpoint of its own. A bound template also does not need an {{< gloss "Agent" >}}Agent{{< /gloss >}} resource because the parent's Agent runs it. > [!NOTE] -> Dedicated subagents, which would give a bound agent its own Harness, Session, and {{< gloss "Actor" >}}Actor{{< /gloss >}}, are not part of the served API. The `subAgent.agentRef` field that would select one is unavailable, so `templateRef` is the only binding that you can write today. +> Dedicated subagents, which would give a bound agent its own Harness, Session, and Actor, are not part of the served API. The `subAgent.agentRef` field that would select one is unavailable, so `templateRef` is the only binding that you can write today. ### Subagent tree rules @@ -84,11 +84,11 @@ A bound agent runs inside its parent, so kagent constrains the shape of the resu - **No reuse within one tree.** The same AgentTemplate cannot appear twice in the same tree. - **Unique binding names.** Two bindings on one AgentTemplate cannot share a `name`. -When kagent rejects a tree, the Agent's `Compatible` condition becomes `False`. The condition reports the reason `UnsupportedConfiguration`, and its message identifies the rule that failed. Read both in the output of the following command. +When kagent rejects a tree, the Agent's `Compatible` condition becomes `False`. The condition reports the reason `UnsupportedConfiguration`, and its message identifies the rule that failed. A binding that names an AgentTemplate that does not exist fails before any rule is checked, so the Agent's `ResolvedRefs` condition reports `ReferenceResolutionFailed` instead. Read the conditions in the output of the following command. ```sh kubectl get agent -n \ - -o jsonpath='{range .status.conditions[?(@.type=="Compatible")]}{.reason}{": "}{.message}{"\n"}{end}' + -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" "}{.reason}{": "}{.message}{"\n"}{end}' ``` The Claude and Codex harnesses apply further restrictions by not allowing a bound agent to have tools, skills, or plugins of its own. The bound agent must also use the same model provider and authentication as its parent. A tree that compiles on the kagent harness can therefore fail after you move it to a Harness that runs Claude or Codex. diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md b/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md index 9348fdb7..580f6cac 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md @@ -58,7 +58,7 @@ One AgentTemplate accepts up to 20 plugins. List the name of each skill that you want in `plugins[].skills`. A skill's name is the name of its subdirectory under `skills/` in the plugin. -Attaching a plugin does not enable the skills that it contains, and an empty list does not enable any of them. kagent accepts an empty list as a safe default rather than reporting an error. An explicit list also means that a later version of the plugin cannot add skills to your agent. To enable a new skill, add its name. +Attaching a plugin does not enable the skills that it contains, and an empty list does not enable any of them. kagent accepts an empty list rather than reporting an error, and the agent starts with no skills from that plugin. An explicit list also means that a later version of the plugin cannot add skills to your agent. To enable a new skill, add its name. Plugin names must be unique. If two entries in `plugins` declare the same name in their manifests, the agent fails to start. Skill names come from your AgentTemplate, so kagent checks them before it fetches anything. A plugin name comes from the plugin's own manifest, and kagent can only check that name as each plugin is fetched. @@ -73,13 +73,13 @@ kagent also does not check the `$schema` value in a Claude-format manifest. ## MCP servers -A plugin that includes `mcp.json` contributes MCP servers to every agent that enables it, alongside any bound directly on the AgentTemplate. The file has an `mcpServers` object, keyed by server name, and its `$schema` must be exactly `https://agent-plugins.org/schemas/1.0.0/mcp.schema.json`. +A plugin that includes `mcp.json` contributes MCP servers alongside any bound directly on the AgentTemplate. Only the kagent harness reads `mcp.json`. On every other harness, an agent gets only the servers that its AgentTemplate binds. The file has an `mcpServers` object, keyed by server name, and its `$schema` must be exactly `https://agent-plugins.org/schemas/1.0.0/mcp.schema.json`. Each server specifies a transport in its `type` field, and the transport determines which other fields are allowed. | Transport | Fields | Description | | --------- | ------ | ----------- | -| `stdio` | `command`, `args`, `env`, `cwd` | Runs a process in the same place as the agent. Specifying `url` or `headers` is rejected. | +| `stdio` | `command`, `args`, `env`, `cwd` | Runs a process in the agent's sandbox. Specifying `url` or `headers` is rejected. | | `streamable-http` | `url`, `headers` | Calls a remote server. Specifying `command`, `args`, `env`, or `cwd` is rejected. | | `sse` | `url`, `headers` | Calls a remote server over Server-Sent Events. Accepts the same fields as `streamable-http`. | diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index f9b22b25..b47597e0 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -119,7 +119,7 @@ Plugin: link: "/docs/kagent/1.x/skills-and-mcp/plugins/" Tool binding: - short: "One entry in an AgentTemplate's spec.tools list. Each binding connects the agent to one source: tools from a Model Context Protocol server, or another agent that takes work from it." + short: "One entry in an AgentTemplate's spec.tools list. Each binding connects the agent to one source: tools from a Model Context Protocol server, or another AgentTemplate that takes work from it." link: "/docs/kagent/1.x/skills-and-mcp/about-tools/" Model Context Protocol: