From 6004e3e661bb2930bbbf610f923ad2bbf78a13d7 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 21 Aug 2026 16:18:08 -0500 Subject: [PATCH 01/70] Split kagent docs into versioned 0.x/1.x tree for the 1.0 rewrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the existing flat kagent doc set to content/kagent/0.x/ (frozen) and add content/kagent/1.x/ for the Agent Substrate/v1alpha3 rewrite, wired up with docs-theme-extras' version switcher via sections.kagent.versions. Scope the versions to the kagent section specifically (not site-wide) since this Hugo build also serves kmcp, which stays unversioned. That also required two local overrides of upstream partials (navbar.html, version-banner.html): upstream assumes a single-product site where the version sits directly after the baseURL, which breaks kagent's actual /docs/kagent//... shape (an extra section segment) and doesn't scope by section — both fixed here after empirically verifying with a real Hugo build. Also repoints the marketing site's hardcoded doc links and the nightly update-ref-docs.yaml job at 0.x so they keep working, and fixes a stale .docs-test.toml comment left over from the removed MDX pipeline. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Rachael Graham --- .github/workflows/update-ref-docs.yaml | 15 +- docs-site/.docs-test.toml | 21 +- docs-site/content/kagent/0.x/_index.md | 37 ++ .../kagent/{ => 0.x}/concepts/_index.md | 0 .../{ => 0.x}/concepts/agent-harness.md | 0 .../kagent/{ => 0.x}/concepts/agent-memory.md | 0 .../{ => 0.x}/concepts/agent-substrate.md | 0 .../kagent/{ => 0.x}/concepts/agents.md | 0 .../kagent/{ => 0.x}/concepts/architecture.md | 0 .../kagent/{ => 0.x}/concepts/mcp-apps.md | 0 .../kagent/{ => 0.x}/concepts/tools.md | 0 .../kagent/{ => 0.x}/examples/_index.md | 0 .../kagent/{ => 0.x}/examples/a2a-agents.md | 0 .../kagent/{ => 0.x}/examples/a2a-byo.md | 0 .../{ => 0.x}/examples/agent-harness.md | 0 .../{ => 0.x}/examples/agent-substrate.md | 0 .../kagent/{ => 0.x}/examples/agentgateway.md | 0 .../kagent/{ => 0.x}/examples/agents-mcp.md | 0 .../kagent/{ => 0.x}/examples/crewai-byo.md | 0 .../kagent/{ => 0.x}/examples/discord-a2a.md | 0 .../{ => 0.x}/examples/documentation.md | 0 .../{ => 0.x}/examples/human-in-the-loop.md | 0 .../{ => 0.x}/examples/langchain-byo.md | 0 .../kagent/{ => 0.x}/examples/skills.md | 0 .../kagent/{ => 0.x}/examples/slack-a2a.md | 0 .../kagent/{ => 0.x}/examples/telegram-bot.md | 0 .../{ => 0.x}/getting-started/_index.md | 0 .../{ => 0.x}/getting-started/first-agent.md | 0 .../getting-started/first-mcp-tool.md | 0 .../getting-started/local-development.md | 0 .../{ => 0.x}/getting-started/quickstart.md | 0 .../getting-started/system-prompts.md | 0 .../kagent/{ => 0.x}/introduction/_index.md | 0 .../kagent/{ => 0.x}/introduction/features.md | 0 .../{ => 0.x}/introduction/installation.md | 0 .../{ => 0.x}/introduction/what-is-kagent.md | 0 .../content/kagent/0.x/not-in-version.md | 8 + .../kagent/{ => 0.x}/observability/_index.md | 0 .../{ => 0.x}/observability/audit-prompts.md | 0 .../{ => 0.x}/observability/launch-ui.md | 0 .../kagent/{ => 0.x}/observability/tracing.md | 0 .../kagent/{ => 0.x}/operations/_index.md | 0 .../kagent/{ => 0.x}/operations/debug.md | 0 .../operations/operational-considerations.md | 0 .../kagent/{ => 0.x}/operations/uninstall.md | 0 .../kagent/{ => 0.x}/operations/upgrade.md | 0 .../kagent/{ => 0.x}/resources/_index.md | 0 .../kagent/{ => 0.x}/resources/api-ref.md | 0 .../kagent/{ => 0.x}/resources/cli/_index.md | 0 .../{ => 0.x}/resources/cli/kagent-add-mcp.md | 0 .../resources/cli/kagent-bug-report.md | 0 .../{ => 0.x}/resources/cli/kagent-build.md | 0 .../resources/cli/kagent-completion.md | 0 .../resources/cli/kagent-dashboard.md | 0 .../{ => 0.x}/resources/cli/kagent-deploy.md | 0 .../{ => 0.x}/resources/cli/kagent-get.md | 0 .../{ => 0.x}/resources/cli/kagent-help.md | 0 .../{ => 0.x}/resources/cli/kagent-init.md | 0 .../{ => 0.x}/resources/cli/kagent-install.md | 0 .../{ => 0.x}/resources/cli/kagent-invoke.md | 0 .../{ => 0.x}/resources/cli/kagent-mcp.md | 0 .../{ => 0.x}/resources/cli/kagent-run.md | 0 .../resources/cli/kagent-uninstall.md | 0 .../{ => 0.x}/resources/cli/kagent-version.md | 0 .../kagent/{ => 0.x}/resources/community.md | 0 .../content/kagent/{ => 0.x}/resources/faq.md | 0 .../kagent/{ => 0.x}/resources/helm.md | 0 .../{ => 0.x}/resources/release-notes.md | 0 .../{ => 0.x}/resources/tools-ecosystem.md | 0 .../kagent/{ => 0.x}/resources/versions.md | 0 .../{ => 0.x}/supported-providers/_index.md | 0 .../supported-providers/amazon-bedrock.md | 0 .../supported-providers/anthropic.md | 0 .../supported-providers/azure-ai-foundry.md | 0 .../supported-providers/azure-openai.md | 0 .../supported-providers/byo-agentgateway.md | 0 .../supported-providers/byo-openai.md | 0 .../{ => 0.x}/supported-providers/gemini.md | 0 .../supported-providers/google-vertexai.md | 0 .../{ => 0.x}/supported-providers/ollama.md | 0 .../{ => 0.x}/supported-providers/openai.md | 0 .../supported-providers/sap-ai-core.md | 0 .../{ => 0.x}/supported-providers/xai.md | 0 docs-site/content/kagent/1.x/_index.md | 13 + .../content/kagent/1.x/not-in-version.md | 8 + docs-site/content/kagent/_index.md | 31 +- docs-site/hugo.yaml | 24 ++ docs-site/layouts/_partials/navbar.html | 318 ++++++++++++++++++ .../layouts/partials/version-banner.html | 49 +++ src/app/page.tsx | 4 +- src/components/footer.tsx | 26 +- src/components/key-components.tsx | 2 +- 92 files changed, 499 insertions(+), 57 deletions(-) create mode 100644 docs-site/content/kagent/0.x/_index.md rename docs-site/content/kagent/{ => 0.x}/concepts/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/agent-harness.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/agent-memory.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/agent-substrate.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/agents.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/architecture.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/mcp-apps.md (100%) rename docs-site/content/kagent/{ => 0.x}/concepts/tools.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/a2a-agents.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/a2a-byo.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/agent-harness.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/agent-substrate.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/agentgateway.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/agents-mcp.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/crewai-byo.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/discord-a2a.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/documentation.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/human-in-the-loop.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/langchain-byo.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/skills.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/slack-a2a.md (100%) rename docs-site/content/kagent/{ => 0.x}/examples/telegram-bot.md (100%) rename docs-site/content/kagent/{ => 0.x}/getting-started/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/getting-started/first-agent.md (100%) rename docs-site/content/kagent/{ => 0.x}/getting-started/first-mcp-tool.md (100%) rename docs-site/content/kagent/{ => 0.x}/getting-started/local-development.md (100%) rename docs-site/content/kagent/{ => 0.x}/getting-started/quickstart.md (100%) rename docs-site/content/kagent/{ => 0.x}/getting-started/system-prompts.md (100%) rename docs-site/content/kagent/{ => 0.x}/introduction/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/introduction/features.md (100%) rename docs-site/content/kagent/{ => 0.x}/introduction/installation.md (100%) rename docs-site/content/kagent/{ => 0.x}/introduction/what-is-kagent.md (100%) create mode 100644 docs-site/content/kagent/0.x/not-in-version.md rename docs-site/content/kagent/{ => 0.x}/observability/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/observability/audit-prompts.md (100%) rename docs-site/content/kagent/{ => 0.x}/observability/launch-ui.md (100%) rename docs-site/content/kagent/{ => 0.x}/observability/tracing.md (100%) rename docs-site/content/kagent/{ => 0.x}/operations/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/operations/debug.md (100%) rename docs-site/content/kagent/{ => 0.x}/operations/operational-considerations.md (100%) rename docs-site/content/kagent/{ => 0.x}/operations/uninstall.md (100%) rename docs-site/content/kagent/{ => 0.x}/operations/upgrade.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/api-ref.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-add-mcp.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-bug-report.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-build.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-completion.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-dashboard.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-deploy.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-get.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-help.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-init.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-install.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-invoke.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-mcp.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-run.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-uninstall.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/cli/kagent-version.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/community.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/faq.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/helm.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/release-notes.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/tools-ecosystem.md (100%) rename docs-site/content/kagent/{ => 0.x}/resources/versions.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/_index.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/amazon-bedrock.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/anthropic.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/azure-ai-foundry.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/azure-openai.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/byo-agentgateway.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/byo-openai.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/gemini.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/google-vertexai.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/ollama.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/openai.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/sap-ai-core.md (100%) rename docs-site/content/kagent/{ => 0.x}/supported-providers/xai.md (100%) create mode 100644 docs-site/content/kagent/1.x/_index.md create mode 100644 docs-site/content/kagent/1.x/not-in-version.md create mode 100644 docs-site/layouts/_partials/navbar.html create mode 100644 docs-site/layouts/partials/version-banner.html diff --git a/.github/workflows/update-ref-docs.yaml b/.github/workflows/update-ref-docs.yaml index 5e4303fc..678b3b84 100644 --- a/.github/workflows/update-ref-docs.yaml +++ b/.github/workflows/update-ref-docs.yaml @@ -13,10 +13,17 @@ concurrency: # The docs are a Hugo site under docs-site/ (served at /docs). This workflow # generates the reference pages directly as Hugo markdown into docs-site/content: -# - kagent CRD API ref -> docs-site/content/kagent/resources/api-ref.md +# - kagent CRD API ref -> docs-site/content/kagent/0.x/resources/api-ref.md # - kmcp CRD API ref -> docs-site/content/kmcp/reference/api-ref.md -# - kagent Helm ref -> docs-site/content/kagent/resources/helm.md +# - kagent Helm ref -> docs-site/content/kagent/0.x/resources/helm.md # Each page uses plain Hugo YAML frontmatter (no MDX `export const metadata`). +# +# Targets the 0.x (current stable) tree only — v1alpha2, the API this job +# generates against, is what 0.x actually ships. The 1.x rewrite tracks +# v1alpha3 and gets its API/Helm reference hand-written for now (see the +# kagent 1.0 docs scope: Phase 4, blocked on the v1alpha3 schema settling); +# point a similar job at docs-site/content/kagent/1.x/resources/ once that's +# ready to automate. jobs: generate-api-docs: runs-on: ubuntu-latest @@ -27,9 +34,9 @@ jobs: # Target Hugo content paths (relative to the website checkout). env: - KAGENT_API_PAGE: docs-site/content/kagent/resources/api-ref.md + KAGENT_API_PAGE: docs-site/content/kagent/0.x/resources/api-ref.md KMCP_API_PAGE: docs-site/content/kmcp/reference/api-ref.md - HELM_PAGE: docs-site/content/kagent/resources/helm.md + HELM_PAGE: docs-site/content/kagent/0.x/resources/helm.md steps: - name: Checkout kagent repository diff --git a/docs-site/.docs-test.toml b/docs-site/.docs-test.toml index fdde7f01..84abaf8a 100644 --- a/docs-site/.docs-test.toml +++ b/docs-site/.docs-test.toml @@ -6,11 +6,10 @@ # against this file's directory (docs-site/). The harness does NOT build the # site — `hugo --config hugo.yaml` runs first and writes to builtRoot. # -# NOTE: docs-site/content is GENERATED from the Next.js MDX source under -# src/app/docs by `make gen-docs` (scripts/mdx-to-hugo.mjs --out docs-site/content). -# These checks run against the generated Hugo output, which is the right place -# to catch shortcode/rendering breaks — but a content fix must land in the MDX -# source (or the converter), not in docs-site/content, or `gen-docs` overwrites it. +# docs-site/content is hand-authored Markdown and is the source of truth (the +# former MDX source under src/app/docs and its mdx-to-hugo.mjs converter were +# removed once the one-time conversion landed — see "Remove the src/apps/docs +# directory"). Edit pages directly under docs-site/content. version = "1" name = "kagent-oss" @@ -35,10 +34,14 @@ scanRoots = [ "./content", ] -# NOTE: kagent docs are a flat, unversioned set (/
//) with no -# version segment. There is intentionally no [versioning] block — version-aware -# specs detect the absence and skip gracefully (same mechanism agentregistry's -# and ambientmesh's flat docs rely on). +# kagent docs are versioned (0.x frozen, 1.x in-progress rewrite), nested +# under /docs/kagent//... . kmcp, the other product built into this +# same Hugo site, stays flat/unversioned — see the sections.kagent.versions +# comment in hugo.yaml for why versions are scoped per-section rather than +# site-wide. +[versioning] +versionFromPath = "^/docs/kagent/(?[^/]+)/" +versions = ["0.x", "1.x"] # All checks default to enabled. No [checks] overrides are needed: kagent runs # the full default set. (The former `smoke`/`crossBrowser` toggles were removed diff --git a/docs-site/content/kagent/0.x/_index.md b/docs-site/content/kagent/0.x/_index.md new file mode 100644 index 00000000..489502ad --- /dev/null +++ b/docs-site/content/kagent/0.x/_index.md @@ -0,0 +1,37 @@ +--- +title: kagent +linkTitle: "kagent 0.x" +description: Concepts, guides, and reference docs for running declarative AI agents on Kubernetes, from install through day-two operations. +weight: 1 +author: kagent.dev +--- + +Your complete guide to the AI agent platform for Kubernetes + +## What is kagent? + +kagent is an innovative AI agent platform designed specifically for Kubernetes environments. +It empowers developers and operations teams to create intelligent, autonomous agents that can +monitor, manage, and automate complex Kubernetes workloads using the power of large language models (LLMs). + +kagent was created at [Solo.io](https://www.solo.io) in 2025 and is a [Cloud Native Computing Foundation](https://www.cncf.io) sandbox project. + +## Key Features + +- **AI-Powered Automation** - Create intelligent agents that understand natural language and can perform complex Kubernetes operations +- **Multi-Provider Support** - Works with OpenAI, Anthropic, Google Vertex AI, Azure OpenAI, Ollama, and custom models +- **Tool Integration** - Supports Model Context Protocol (MCP) tools, built-in Kubernetes tools, and custom HTTP tools +- **Agent-to-Agent Communication** - Enable sophisticated workflows through A2A (Agent-to-Agent) interactions +- **Comprehensive Observability** - Built-in tracing and monitoring to understand agent behavior and performance +- **Cloud Native** - Designed from the ground up to run natively in Kubernetes environments + +## Why Choose kagent? + +Whether you're looking to automate routine operations, implement intelligent monitoring, +or create sophisticated multi-agent workflows, kagent provides the tools and framework +to bring AI to your Kubernetes infrastructure. Start with simple automation and scale +to complex, intelligent systems that can reason about your cluster's state and make +informed decisions. + +## Explore the Documentation + diff --git a/docs-site/content/kagent/concepts/_index.md b/docs-site/content/kagent/0.x/concepts/_index.md similarity index 100% rename from docs-site/content/kagent/concepts/_index.md rename to docs-site/content/kagent/0.x/concepts/_index.md diff --git a/docs-site/content/kagent/concepts/agent-harness.md b/docs-site/content/kagent/0.x/concepts/agent-harness.md similarity index 100% rename from docs-site/content/kagent/concepts/agent-harness.md rename to docs-site/content/kagent/0.x/concepts/agent-harness.md diff --git a/docs-site/content/kagent/concepts/agent-memory.md b/docs-site/content/kagent/0.x/concepts/agent-memory.md similarity index 100% rename from docs-site/content/kagent/concepts/agent-memory.md rename to docs-site/content/kagent/0.x/concepts/agent-memory.md diff --git a/docs-site/content/kagent/concepts/agent-substrate.md b/docs-site/content/kagent/0.x/concepts/agent-substrate.md similarity index 100% rename from docs-site/content/kagent/concepts/agent-substrate.md rename to docs-site/content/kagent/0.x/concepts/agent-substrate.md diff --git a/docs-site/content/kagent/concepts/agents.md b/docs-site/content/kagent/0.x/concepts/agents.md similarity index 100% rename from docs-site/content/kagent/concepts/agents.md rename to docs-site/content/kagent/0.x/concepts/agents.md diff --git a/docs-site/content/kagent/concepts/architecture.md b/docs-site/content/kagent/0.x/concepts/architecture.md similarity index 100% rename from docs-site/content/kagent/concepts/architecture.md rename to docs-site/content/kagent/0.x/concepts/architecture.md diff --git a/docs-site/content/kagent/concepts/mcp-apps.md b/docs-site/content/kagent/0.x/concepts/mcp-apps.md similarity index 100% rename from docs-site/content/kagent/concepts/mcp-apps.md rename to docs-site/content/kagent/0.x/concepts/mcp-apps.md diff --git a/docs-site/content/kagent/concepts/tools.md b/docs-site/content/kagent/0.x/concepts/tools.md similarity index 100% rename from docs-site/content/kagent/concepts/tools.md rename to docs-site/content/kagent/0.x/concepts/tools.md diff --git a/docs-site/content/kagent/examples/_index.md b/docs-site/content/kagent/0.x/examples/_index.md similarity index 100% rename from docs-site/content/kagent/examples/_index.md rename to docs-site/content/kagent/0.x/examples/_index.md diff --git a/docs-site/content/kagent/examples/a2a-agents.md b/docs-site/content/kagent/0.x/examples/a2a-agents.md similarity index 100% rename from docs-site/content/kagent/examples/a2a-agents.md rename to docs-site/content/kagent/0.x/examples/a2a-agents.md diff --git a/docs-site/content/kagent/examples/a2a-byo.md b/docs-site/content/kagent/0.x/examples/a2a-byo.md similarity index 100% rename from docs-site/content/kagent/examples/a2a-byo.md rename to docs-site/content/kagent/0.x/examples/a2a-byo.md diff --git a/docs-site/content/kagent/examples/agent-harness.md b/docs-site/content/kagent/0.x/examples/agent-harness.md similarity index 100% rename from docs-site/content/kagent/examples/agent-harness.md rename to docs-site/content/kagent/0.x/examples/agent-harness.md diff --git a/docs-site/content/kagent/examples/agent-substrate.md b/docs-site/content/kagent/0.x/examples/agent-substrate.md similarity index 100% rename from docs-site/content/kagent/examples/agent-substrate.md rename to docs-site/content/kagent/0.x/examples/agent-substrate.md diff --git a/docs-site/content/kagent/examples/agentgateway.md b/docs-site/content/kagent/0.x/examples/agentgateway.md similarity index 100% rename from docs-site/content/kagent/examples/agentgateway.md rename to docs-site/content/kagent/0.x/examples/agentgateway.md diff --git a/docs-site/content/kagent/examples/agents-mcp.md b/docs-site/content/kagent/0.x/examples/agents-mcp.md similarity index 100% rename from docs-site/content/kagent/examples/agents-mcp.md rename to docs-site/content/kagent/0.x/examples/agents-mcp.md diff --git a/docs-site/content/kagent/examples/crewai-byo.md b/docs-site/content/kagent/0.x/examples/crewai-byo.md similarity index 100% rename from docs-site/content/kagent/examples/crewai-byo.md rename to docs-site/content/kagent/0.x/examples/crewai-byo.md diff --git a/docs-site/content/kagent/examples/discord-a2a.md b/docs-site/content/kagent/0.x/examples/discord-a2a.md similarity index 100% rename from docs-site/content/kagent/examples/discord-a2a.md rename to docs-site/content/kagent/0.x/examples/discord-a2a.md diff --git a/docs-site/content/kagent/examples/documentation.md b/docs-site/content/kagent/0.x/examples/documentation.md similarity index 100% rename from docs-site/content/kagent/examples/documentation.md rename to docs-site/content/kagent/0.x/examples/documentation.md diff --git a/docs-site/content/kagent/examples/human-in-the-loop.md b/docs-site/content/kagent/0.x/examples/human-in-the-loop.md similarity index 100% rename from docs-site/content/kagent/examples/human-in-the-loop.md rename to docs-site/content/kagent/0.x/examples/human-in-the-loop.md diff --git a/docs-site/content/kagent/examples/langchain-byo.md b/docs-site/content/kagent/0.x/examples/langchain-byo.md similarity index 100% rename from docs-site/content/kagent/examples/langchain-byo.md rename to docs-site/content/kagent/0.x/examples/langchain-byo.md diff --git a/docs-site/content/kagent/examples/skills.md b/docs-site/content/kagent/0.x/examples/skills.md similarity index 100% rename from docs-site/content/kagent/examples/skills.md rename to docs-site/content/kagent/0.x/examples/skills.md diff --git a/docs-site/content/kagent/examples/slack-a2a.md b/docs-site/content/kagent/0.x/examples/slack-a2a.md similarity index 100% rename from docs-site/content/kagent/examples/slack-a2a.md rename to docs-site/content/kagent/0.x/examples/slack-a2a.md diff --git a/docs-site/content/kagent/examples/telegram-bot.md b/docs-site/content/kagent/0.x/examples/telegram-bot.md similarity index 100% rename from docs-site/content/kagent/examples/telegram-bot.md rename to docs-site/content/kagent/0.x/examples/telegram-bot.md diff --git a/docs-site/content/kagent/getting-started/_index.md b/docs-site/content/kagent/0.x/getting-started/_index.md similarity index 100% rename from docs-site/content/kagent/getting-started/_index.md rename to docs-site/content/kagent/0.x/getting-started/_index.md diff --git a/docs-site/content/kagent/getting-started/first-agent.md b/docs-site/content/kagent/0.x/getting-started/first-agent.md similarity index 100% rename from docs-site/content/kagent/getting-started/first-agent.md rename to docs-site/content/kagent/0.x/getting-started/first-agent.md diff --git a/docs-site/content/kagent/getting-started/first-mcp-tool.md b/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md similarity index 100% rename from docs-site/content/kagent/getting-started/first-mcp-tool.md rename to docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md diff --git a/docs-site/content/kagent/getting-started/local-development.md b/docs-site/content/kagent/0.x/getting-started/local-development.md similarity index 100% rename from docs-site/content/kagent/getting-started/local-development.md rename to docs-site/content/kagent/0.x/getting-started/local-development.md diff --git a/docs-site/content/kagent/getting-started/quickstart.md b/docs-site/content/kagent/0.x/getting-started/quickstart.md similarity index 100% rename from docs-site/content/kagent/getting-started/quickstart.md rename to docs-site/content/kagent/0.x/getting-started/quickstart.md diff --git a/docs-site/content/kagent/getting-started/system-prompts.md b/docs-site/content/kagent/0.x/getting-started/system-prompts.md similarity index 100% rename from docs-site/content/kagent/getting-started/system-prompts.md rename to docs-site/content/kagent/0.x/getting-started/system-prompts.md diff --git a/docs-site/content/kagent/introduction/_index.md b/docs-site/content/kagent/0.x/introduction/_index.md similarity index 100% rename from docs-site/content/kagent/introduction/_index.md rename to docs-site/content/kagent/0.x/introduction/_index.md diff --git a/docs-site/content/kagent/introduction/features.md b/docs-site/content/kagent/0.x/introduction/features.md similarity index 100% rename from docs-site/content/kagent/introduction/features.md rename to docs-site/content/kagent/0.x/introduction/features.md diff --git a/docs-site/content/kagent/introduction/installation.md b/docs-site/content/kagent/0.x/introduction/installation.md similarity index 100% rename from docs-site/content/kagent/introduction/installation.md rename to docs-site/content/kagent/0.x/introduction/installation.md diff --git a/docs-site/content/kagent/introduction/what-is-kagent.md b/docs-site/content/kagent/0.x/introduction/what-is-kagent.md similarity index 100% rename from docs-site/content/kagent/introduction/what-is-kagent.md rename to docs-site/content/kagent/0.x/introduction/what-is-kagent.md diff --git a/docs-site/content/kagent/0.x/not-in-version.md b/docs-site/content/kagent/0.x/not-in-version.md new file mode 100644 index 00000000..306e4dc5 --- /dev/null +++ b/docs-site/content/kagent/0.x/not-in-version.md @@ -0,0 +1,8 @@ +--- +title: Topic not available in this version +description: This topic isn't available in this version of the documentation. +build: + list: never +--- + +This topic doesn't exist in this version of the kagent docs. Use the version switcher above to go back to a version where it's available, or browse the [kagent docs]({{< relref "/kagent/0.x" >}}) landing page. diff --git a/docs-site/content/kagent/observability/_index.md b/docs-site/content/kagent/0.x/observability/_index.md similarity index 100% rename from docs-site/content/kagent/observability/_index.md rename to docs-site/content/kagent/0.x/observability/_index.md diff --git a/docs-site/content/kagent/observability/audit-prompts.md b/docs-site/content/kagent/0.x/observability/audit-prompts.md similarity index 100% rename from docs-site/content/kagent/observability/audit-prompts.md rename to docs-site/content/kagent/0.x/observability/audit-prompts.md diff --git a/docs-site/content/kagent/observability/launch-ui.md b/docs-site/content/kagent/0.x/observability/launch-ui.md similarity index 100% rename from docs-site/content/kagent/observability/launch-ui.md rename to docs-site/content/kagent/0.x/observability/launch-ui.md diff --git a/docs-site/content/kagent/observability/tracing.md b/docs-site/content/kagent/0.x/observability/tracing.md similarity index 100% rename from docs-site/content/kagent/observability/tracing.md rename to docs-site/content/kagent/0.x/observability/tracing.md diff --git a/docs-site/content/kagent/operations/_index.md b/docs-site/content/kagent/0.x/operations/_index.md similarity index 100% rename from docs-site/content/kagent/operations/_index.md rename to docs-site/content/kagent/0.x/operations/_index.md diff --git a/docs-site/content/kagent/operations/debug.md b/docs-site/content/kagent/0.x/operations/debug.md similarity index 100% rename from docs-site/content/kagent/operations/debug.md rename to docs-site/content/kagent/0.x/operations/debug.md diff --git a/docs-site/content/kagent/operations/operational-considerations.md b/docs-site/content/kagent/0.x/operations/operational-considerations.md similarity index 100% rename from docs-site/content/kagent/operations/operational-considerations.md rename to docs-site/content/kagent/0.x/operations/operational-considerations.md diff --git a/docs-site/content/kagent/operations/uninstall.md b/docs-site/content/kagent/0.x/operations/uninstall.md similarity index 100% rename from docs-site/content/kagent/operations/uninstall.md rename to docs-site/content/kagent/0.x/operations/uninstall.md diff --git a/docs-site/content/kagent/operations/upgrade.md b/docs-site/content/kagent/0.x/operations/upgrade.md similarity index 100% rename from docs-site/content/kagent/operations/upgrade.md rename to docs-site/content/kagent/0.x/operations/upgrade.md diff --git a/docs-site/content/kagent/resources/_index.md b/docs-site/content/kagent/0.x/resources/_index.md similarity index 100% rename from docs-site/content/kagent/resources/_index.md rename to docs-site/content/kagent/0.x/resources/_index.md diff --git a/docs-site/content/kagent/resources/api-ref.md b/docs-site/content/kagent/0.x/resources/api-ref.md similarity index 100% rename from docs-site/content/kagent/resources/api-ref.md rename to docs-site/content/kagent/0.x/resources/api-ref.md diff --git a/docs-site/content/kagent/resources/cli/_index.md b/docs-site/content/kagent/0.x/resources/cli/_index.md similarity index 100% rename from docs-site/content/kagent/resources/cli/_index.md rename to docs-site/content/kagent/0.x/resources/cli/_index.md diff --git a/docs-site/content/kagent/resources/cli/kagent-add-mcp.md b/docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-add-mcp.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md diff --git a/docs-site/content/kagent/resources/cli/kagent-bug-report.md b/docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-bug-report.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md diff --git a/docs-site/content/kagent/resources/cli/kagent-build.md b/docs-site/content/kagent/0.x/resources/cli/kagent-build.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-build.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-build.md diff --git a/docs-site/content/kagent/resources/cli/kagent-completion.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-completion.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-completion.md diff --git a/docs-site/content/kagent/resources/cli/kagent-dashboard.md b/docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-dashboard.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md diff --git a/docs-site/content/kagent/resources/cli/kagent-deploy.md b/docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-deploy.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md diff --git a/docs-site/content/kagent/resources/cli/kagent-get.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-get.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-get.md diff --git a/docs-site/content/kagent/resources/cli/kagent-help.md b/docs-site/content/kagent/0.x/resources/cli/kagent-help.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-help.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-help.md diff --git a/docs-site/content/kagent/resources/cli/kagent-init.md b/docs-site/content/kagent/0.x/resources/cli/kagent-init.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-init.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-init.md diff --git a/docs-site/content/kagent/resources/cli/kagent-install.md b/docs-site/content/kagent/0.x/resources/cli/kagent-install.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-install.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-install.md diff --git a/docs-site/content/kagent/resources/cli/kagent-invoke.md b/docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-invoke.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-mcp.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md diff --git a/docs-site/content/kagent/resources/cli/kagent-run.md b/docs-site/content/kagent/0.x/resources/cli/kagent-run.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-run.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-run.md diff --git a/docs-site/content/kagent/resources/cli/kagent-uninstall.md b/docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-uninstall.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md diff --git a/docs-site/content/kagent/resources/cli/kagent-version.md b/docs-site/content/kagent/0.x/resources/cli/kagent-version.md similarity index 100% rename from docs-site/content/kagent/resources/cli/kagent-version.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-version.md diff --git a/docs-site/content/kagent/resources/community.md b/docs-site/content/kagent/0.x/resources/community.md similarity index 100% rename from docs-site/content/kagent/resources/community.md rename to docs-site/content/kagent/0.x/resources/community.md diff --git a/docs-site/content/kagent/resources/faq.md b/docs-site/content/kagent/0.x/resources/faq.md similarity index 100% rename from docs-site/content/kagent/resources/faq.md rename to docs-site/content/kagent/0.x/resources/faq.md diff --git a/docs-site/content/kagent/resources/helm.md b/docs-site/content/kagent/0.x/resources/helm.md similarity index 100% rename from docs-site/content/kagent/resources/helm.md rename to docs-site/content/kagent/0.x/resources/helm.md diff --git a/docs-site/content/kagent/resources/release-notes.md b/docs-site/content/kagent/0.x/resources/release-notes.md similarity index 100% rename from docs-site/content/kagent/resources/release-notes.md rename to docs-site/content/kagent/0.x/resources/release-notes.md diff --git a/docs-site/content/kagent/resources/tools-ecosystem.md b/docs-site/content/kagent/0.x/resources/tools-ecosystem.md similarity index 100% rename from docs-site/content/kagent/resources/tools-ecosystem.md rename to docs-site/content/kagent/0.x/resources/tools-ecosystem.md diff --git a/docs-site/content/kagent/resources/versions.md b/docs-site/content/kagent/0.x/resources/versions.md similarity index 100% rename from docs-site/content/kagent/resources/versions.md rename to docs-site/content/kagent/0.x/resources/versions.md diff --git a/docs-site/content/kagent/supported-providers/_index.md b/docs-site/content/kagent/0.x/supported-providers/_index.md similarity index 100% rename from docs-site/content/kagent/supported-providers/_index.md rename to docs-site/content/kagent/0.x/supported-providers/_index.md diff --git a/docs-site/content/kagent/supported-providers/amazon-bedrock.md b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md similarity index 100% rename from docs-site/content/kagent/supported-providers/amazon-bedrock.md rename to docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md diff --git a/docs-site/content/kagent/supported-providers/anthropic.md b/docs-site/content/kagent/0.x/supported-providers/anthropic.md similarity index 100% rename from docs-site/content/kagent/supported-providers/anthropic.md rename to docs-site/content/kagent/0.x/supported-providers/anthropic.md diff --git a/docs-site/content/kagent/supported-providers/azure-ai-foundry.md b/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md similarity index 100% rename from docs-site/content/kagent/supported-providers/azure-ai-foundry.md rename to docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md diff --git a/docs-site/content/kagent/supported-providers/azure-openai.md b/docs-site/content/kagent/0.x/supported-providers/azure-openai.md similarity index 100% rename from docs-site/content/kagent/supported-providers/azure-openai.md rename to docs-site/content/kagent/0.x/supported-providers/azure-openai.md diff --git a/docs-site/content/kagent/supported-providers/byo-agentgateway.md b/docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md similarity index 100% rename from docs-site/content/kagent/supported-providers/byo-agentgateway.md rename to docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md diff --git a/docs-site/content/kagent/supported-providers/byo-openai.md b/docs-site/content/kagent/0.x/supported-providers/byo-openai.md similarity index 100% rename from docs-site/content/kagent/supported-providers/byo-openai.md rename to docs-site/content/kagent/0.x/supported-providers/byo-openai.md diff --git a/docs-site/content/kagent/supported-providers/gemini.md b/docs-site/content/kagent/0.x/supported-providers/gemini.md similarity index 100% rename from docs-site/content/kagent/supported-providers/gemini.md rename to docs-site/content/kagent/0.x/supported-providers/gemini.md diff --git a/docs-site/content/kagent/supported-providers/google-vertexai.md b/docs-site/content/kagent/0.x/supported-providers/google-vertexai.md similarity index 100% rename from docs-site/content/kagent/supported-providers/google-vertexai.md rename to docs-site/content/kagent/0.x/supported-providers/google-vertexai.md diff --git a/docs-site/content/kagent/supported-providers/ollama.md b/docs-site/content/kagent/0.x/supported-providers/ollama.md similarity index 100% rename from docs-site/content/kagent/supported-providers/ollama.md rename to docs-site/content/kagent/0.x/supported-providers/ollama.md diff --git a/docs-site/content/kagent/supported-providers/openai.md b/docs-site/content/kagent/0.x/supported-providers/openai.md similarity index 100% rename from docs-site/content/kagent/supported-providers/openai.md rename to docs-site/content/kagent/0.x/supported-providers/openai.md diff --git a/docs-site/content/kagent/supported-providers/sap-ai-core.md b/docs-site/content/kagent/0.x/supported-providers/sap-ai-core.md similarity index 100% rename from docs-site/content/kagent/supported-providers/sap-ai-core.md rename to docs-site/content/kagent/0.x/supported-providers/sap-ai-core.md diff --git a/docs-site/content/kagent/supported-providers/xai.md b/docs-site/content/kagent/0.x/supported-providers/xai.md similarity index 100% rename from docs-site/content/kagent/supported-providers/xai.md rename to docs-site/content/kagent/0.x/supported-providers/xai.md diff --git a/docs-site/content/kagent/1.x/_index.md b/docs-site/content/kagent/1.x/_index.md new file mode 100644 index 00000000..f68c8997 --- /dev/null +++ b/docs-site/content/kagent/1.x/_index.md @@ -0,0 +1,13 @@ +--- +title: kagent 1.0 +linkTitle: "kagent 1.x (preview)" +description: Preview documentation for the kagent 1.0 release, built on Agent Substrate. +weight: 1 +author: kagent.dev +--- + +# kagent 1.0 (preview) + +kagent 1.0 moves the runtime from Kubernetes Deployments to [Agent Substrate](https://github.com/agent-substrate/substrate), introducing Harness, AgentTemplate, and AgentInstance as the new API surface. + +This section is under active development ahead of the 1.0 release. Pages here may be incomplete, and content may change without notice. See the [0.x docs]({{< relref "/kagent/0.x" >}}) for the current stable release. diff --git a/docs-site/content/kagent/1.x/not-in-version.md b/docs-site/content/kagent/1.x/not-in-version.md new file mode 100644 index 00000000..b4d3437f --- /dev/null +++ b/docs-site/content/kagent/1.x/not-in-version.md @@ -0,0 +1,8 @@ +--- +title: Topic not available in this version +description: This topic isn't available in this version of the documentation. +build: + list: never +--- + +This topic doesn't exist in this version of the kagent docs yet. Use the version switcher above to go back to a version where it's available, or browse the [kagent 1.0 (preview)]({{< relref "/kagent/1.x" >}}) landing page. diff --git a/docs-site/content/kagent/_index.md b/docs-site/content/kagent/_index.md index 1a4f7505..bc8c3517 100644 --- a/docs-site/content/kagent/_index.md +++ b/docs-site/content/kagent/_index.md @@ -3,34 +3,9 @@ title: kagent description: Concepts, guides, and reference docs for running declarative AI agents on Kubernetes, from install through day-two operations. weight: 1 author: kagent.dev +disableCards: true --- -Your complete guide to the AI agent platform for Kubernetes - -## What is kagent? - -kagent is an innovative AI agent platform designed specifically for Kubernetes environments. -It empowers developers and operations teams to create intelligent, autonomous agents that can -monitor, manage, and automate complex Kubernetes workloads using the power of large language models (LLMs). - -kagent was created at [Solo.io](https://www.solo.io) in 2025 and is a [Cloud Native Computing Foundation](https://www.cncf.io) sandbox project. - -## Key Features - -- **AI-Powered Automation** - Create intelligent agents that understand natural language and can perform complex Kubernetes operations -- **Multi-Provider Support** - Works with OpenAI, Anthropic, Google Vertex AI, Azure OpenAI, Ollama, and custom models -- **Tool Integration** - Supports Model Context Protocol (MCP) tools, built-in Kubernetes tools, and custom HTTP tools -- **Agent-to-Agent Communication** - Enable sophisticated workflows through A2A (Agent-to-Agent) interactions -- **Comprehensive Observability** - Built-in tracing and monitoring to understand agent behavior and performance -- **Cloud Native** - Designed from the ground up to run natively in Kubernetes environments - -## Why Choose kagent? - -Whether you're looking to automate routine operations, implement intelligent monitoring, -or create sophisticated multi-agent workflows, kagent provides the tools and framework -to bring AI to your Kubernetes infrastructure. Start with simple automation and scale -to complex, intelligent systems that can reason about your cluster's state and make -informed decisions. - -## Explore the Documentation +# kagent docs +{{< version-cards desc="Select a version of the kagent docs." >}} diff --git a/docs-site/hugo.yaml b/docs-site/hugo.yaml index fa93f101..7b2114e2 100644 --- a/docs-site/hugo.yaml +++ b/docs-site/hugo.yaml @@ -108,6 +108,30 @@ params: # Auto-render the light/dark toggle in the navbar displayToggle: true + # Per-section version lists, consumed by the local navbar.html override + # (layouts/_partials/navbar.html) and by docs-theme-extras' version-cards + # shortcode. Scoped under sections.kagent rather than the top-level + # `versions` key so kmcp — the other product built into this same Hugo + # site — never picks up kagent's version dropdown. See the navbar.html + # override's header comment for why that scoping is necessary here. + # + # 0.x is the frozen pre-1.0 doc set (moved verbatim from the former flat + # content/kagent/ tree); 1.x is the in-progress v1alpha3/Agent Substrate + # rewrite and carries an in-development banner until it's ready to become + # the default. + sections: + kagent: + versions: + - version: "0.x" + dropdown: "0.x (current)" + linkVersion: "0.x" + url: "/kagent/0.x" + - version: "1.x" + dropdown: "1.x (preview)" + linkVersion: "1.x" + url: "/kagent/1.x" + banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." + # Top nav — mirrors kagent.dev. Docs is local; the marketing/blog sections stay # on the Next.js site, so those link out to absolute kagent.dev URLs. menu: diff --git a/docs-site/layouts/_partials/navbar.html b/docs-site/layouts/_partials/navbar.html new file mode 100644 index 00000000..bd13da2f --- /dev/null +++ b/docs-site/layouts/_partials/navbar.html @@ -0,0 +1,318 @@ +{{- /* Custom navbar override: adds version dropdown from [[params.versions]] */ -}} +{{- $navWidth := "hx:max-w-[90rem]" -}} +{{- with .Site.Params.navbar.width -}} + {{ if eq . "normal" -}} + {{ $navWidth = "hx:max-w-screen-xl" -}} + {{ else if eq . "full" -}} + {{ $navWidth = "max-w-full" -}} + {{ end -}} +{{- end -}} + +{{- $page := . -}} +{{- $iconHeight := 24 -}} + +
+
+ + +
diff --git a/docs-site/layouts/partials/version-banner.html b/docs-site/layouts/partials/version-banner.html new file mode 100644 index 00000000..be3f790f --- /dev/null +++ b/docs-site/layouts/partials/version-banner.html @@ -0,0 +1,49 @@ +{{- /* kagent override of docs-theme-extras' version-banner.html. + + Why this exists: upstream matches against `.FirstSection.RelPermalink` + (always the top-level section, e.g. "/kagent/") checked as a substring + against `.linkVersion`, which can't see a version segment nested a + level deeper (content/kagent/0.x/…) — the substring check would never + fire. It also reads only the site-wide Site.Params.versions, which + kagent leaves unset (see the navbar.html override) since this build + also serves kmcp, an unrelated, unversioned product. + + Fix: resolve versions the same way navbar.html's override and + version-cards.html do (Site.Params.sections..versions, + falling back to the site-wide list), and match by checking whether any + exact path segment of the current page's own RelPermalink equals + `.linkVersion` — correct regardless of nesting depth, folder prefix, + or language prefix, and still no-ops on kmcp pages since none of their + segments will ever equal "0.x"/"1.x". + + Everything below the resolution step (the bannerID/i18n handling, + markdownify, markup) matches upstream. */ -}} +{{- $currentSection := .Section -}} +{{- $versions := slice -}} +{{- if and $currentSection (isset .Site.Params.sections $currentSection) -}} + {{- with (index .Site.Params.sections $currentSection).versions -}} + {{- $versions = . -}} + {{- end -}} +{{- end -}} +{{- if eq (len $versions) 0 -}} + {{- with .Site.Params.versions -}} + {{- $versions = . -}} + {{- end -}} +{{- end -}} + +{{- $segments := split (strings.Trim .RelPermalink "/") "/" -}} +{{- $bannerText := "" -}} +{{- range $versions -}} + {{- if and (not $bannerText) .banner (in $segments .linkVersion) -}} + {{- $bannerText = .banner -}} + {{- if .bannerID -}} + {{- $translated := i18n .bannerID . -}} + {{- if $translated -}}{{- $bannerText = $translated -}}{{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- with $bannerText }} +
+ {{ . | markdownify }} +
+{{- end -}} diff --git a/src/app/page.tsx b/src/app/page.tsx index 66289ba6..2c2aeacb 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -264,7 +264,7 @@ export default function RedesignPage() { already trusts. Open source. Production grade. Built by the founders of Istio.

- + Get Started @@ -680,7 +680,7 @@ export default function RedesignPage() {

Run your first agent on Kubernetes today.

One Helm chart. One CRD. One namespace. You'll be looking at agent traces before your coffee gets cold.

- + Get Started diff --git a/src/components/footer.tsx b/src/components/footer.tsx index d9c03ec9..1fe8874c 100644 --- a/src/components/footer.tsx +++ b/src/components/footer.tsx @@ -18,22 +18,22 @@ export default function Footer() {

Getting Started

  • - + Installing kagent
  • - + Quick Start
  • - + First Agent Guide
  • - + First MCP Tool
  • @@ -45,22 +45,22 @@ export default function Footer() {

    Documentation

    • - + What is kagent
    • - + Architecture
    • - + Core Concepts
    • - + Configuring LLM Providers
    • @@ -82,22 +82,22 @@ export default function Footer() {
    • - + A2A Agents
    • - + Documentation Agent
    • - + Slack and A2A
    • - + Discord and A2A
    • @@ -129,7 +129,7 @@ export default function Footer() {
    • - + FAQ
    • diff --git a/src/components/key-components.tsx b/src/components/key-components.tsx index 571454bc..5fddd49c 100644 --- a/src/components/key-components.tsx +++ b/src/components/key-components.tsx @@ -20,7 +20,7 @@ const keyComponents = [ { title: "Framework", icon: Code, - link: "/docs/kagent/concepts", + link: "/docs/kagent/0.x/concepts", description: "Simple CLI and UI interface to run agents, with full extensibility for custom solutions", }, ]; From 99e7077c66d7679b4474adf2ec713e5495ae5518 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 21 Aug 2026 16:25:56 -0500 Subject: [PATCH 02/70] Scope the docs sidebar to the current kagent doc version The sidebar override rooted its tree at the kagent product section via .FirstSection, which was fine when kagent was flat. Now that 0.x and 1.x are both direct children of that section, it showed both versions' full trees at once regardless of which one the version switcher pointed at. Resolve the current page's own version page and root the tree there instead, falling back to hiding the sidebar on the bare version-picker landing page where there's no single version to root at. kmcp, which has no versions config, is unaffected. Verified against a real Hugo build. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Rachael Graham --- docs-site/layouts/_partials/sidebar.html | 72 +++++++++++++++++++----- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/docs-site/layouts/_partials/sidebar.html b/docs-site/layouts/_partials/sidebar.html index fd2a0d40..3c50bbdd 100644 --- a/docs-site/layouts/_partials/sidebar.html +++ b/docs-site/layouts/_partials/sidebar.html @@ -7,17 +7,29 @@ at the current section, so kagent's nav "drills down" as you navigate deeper instead of showing the whole product tree. - kagent docs are flat + unversioned but split across two products (kagent + kmcp, - each a top-level content section). This override roots the tree at the product - section via .FirstSection — the current page's top-level section ancestor — so - every page in a product shows that product's full, expandable tree with the - active branch auto-expanded. Using .FirstSection (rather than parsing the URL - for a /docs/ prefix) keeps this correct regardless of the baseURL + kagent docs are split across two top-level content sections, kagent and + kmcp. This override roots the tree at the product section via .FirstSection + — the current page's top-level section ancestor — so every page in a + product shows that product's full, expandable tree with the active branch + auto-expanded. Using .FirstSection (rather than parsing the URL for a + /docs/ prefix) keeps this correct regardless of the baseURL subpath the site is served under. It reuses the same CSS classes / data-attributes as extras' sidebar (sidebar-link, sidebar-toggle, sidebar-children, data-sidebar-item, sidebar-mobile-panel) so the toggle JS and mobile drawer in docs-theme-extras keep working. + kagent (unlike kmcp) is also versioned (0.x, 1.x — see + sections.kagent.versions in hugo.yaml). .FirstSection alone would root the + tree at the "kagent" product page, whose direct children are now the 0.x + and 1.x version pages themselves — so BOTH versions' full trees would + render side by side, and the version switcher (navbar.html) would have no + effect on the sidebar at all. For a versioned product, this override + instead resolves the CURRENT page's version page (e.g. "/kagent/0.x") and + roots the tree there, so only that version's sections show. On the bare + product landing page (the version-picker itself, with no version segment + in its own URL) there's no single version to root at, so the sidebar is + suppressed there rather than showing every version. + Called by extras' docs/single.html + docs/list.html as: {{ partial "sidebar.html" (dict "context" .) }} */ -}} @@ -29,17 +41,47 @@ {{- else -}} {{- $navRoot := $context.FirstSection -}} + {{- $suppress := false -}} - - + {{- end -}} + {{- if $versionPage -}} + {{- $navRoot = $versionPage -}} + {{- else -}} + {{- $suppress = true -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if $suppress -}} + + {{- else -}} + + + {{- end -}} {{- end -}} {{- /* Recursive tree renderer — mirrors extras' render-sidebar-tree markup. */ -}} From 94eda0d4ff82515568a7e14e9800a6b803b91b79 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 21 Aug 2026 16:26:12 -0500 Subject: [PATCH 03/70] Convert internal kagent 0.x links to relref shortcodes The 0.x content had 124 internal cross-links hardcoded as absolute /docs/kagent/... paths, written before the version split. They all 404 now that the same content lives under /docs/kagent/0.x/... Convert them to {{< relref >}} shortcodes pointing at /kagent/0.x/... instead of just patching in the version segment as a literal string, so they resolve against the actual content graph and Hugo's build fails loudly (relref is strict) if a target ever moves again, rather than silently 404ing. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Rachael Graham --- .../content/kagent/0.x/concepts/_index.md | 2 +- .../kagent/0.x/concepts/agent-harness.md | 6 +++--- .../kagent/0.x/concepts/agent-memory.md | 6 +++--- .../kagent/0.x/concepts/agent-substrate.md | 10 +++++----- .../content/kagent/0.x/concepts/agents.md | 14 ++++++------- .../kagent/0.x/concepts/architecture.md | 4 ++-- .../content/kagent/0.x/concepts/mcp-apps.md | 2 +- .../content/kagent/0.x/concepts/tools.md | 4 ++-- .../content/kagent/0.x/examples/a2a-agents.md | 4 ++-- .../content/kagent/0.x/examples/a2a-byo.md | 6 +++--- .../kagent/0.x/examples/agent-harness.md | 10 +++++----- .../kagent/0.x/examples/agent-substrate.md | 6 +++--- .../kagent/0.x/examples/agentgateway.md | 4 ++-- .../content/kagent/0.x/examples/crewai-byo.md | 6 +++--- .../kagent/0.x/examples/discord-a2a.md | 4 ++-- .../kagent/0.x/examples/langchain-byo.md | 4 ++-- .../content/kagent/0.x/examples/skills.md | 10 +++++----- .../content/kagent/0.x/examples/slack-a2a.md | 2 +- .../kagent/0.x/examples/telegram-bot.md | 2 +- .../kagent/0.x/getting-started/first-agent.md | 4 ++-- .../0.x/getting-started/first-mcp-tool.md | 6 +++--- .../0.x/getting-started/local-development.md | 4 ++-- .../kagent/0.x/getting-started/quickstart.md | 6 +++--- .../content/kagent/0.x/introduction/_index.md | 2 +- .../kagent/0.x/introduction/installation.md | 16 +++++++-------- .../kagent/0.x/introduction/what-is-kagent.md | 4 ++-- .../kagent/0.x/observability/audit-prompts.md | 2 +- .../kagent/0.x/observability/launch-ui.md | 6 +++--- .../kagent/0.x/observability/tracing.md | 10 +++++----- .../operations/operational-considerations.md | 2 +- .../kagent/0.x/operations/uninstall.md | 2 +- .../content/kagent/0.x/operations/upgrade.md | 10 +++++----- .../content/kagent/0.x/resources/_index.md | 2 +- docs-site/content/kagent/0.x/resources/faq.md | 2 +- .../kagent/0.x/resources/release-notes.md | 20 +++++++++---------- .../0.x/supported-providers/amazon-bedrock.md | 2 +- .../supported-providers/azure-ai-foundry.md | 2 +- .../0.x/supported-providers/azure-openai.md | 2 +- 38 files changed, 105 insertions(+), 105 deletions(-) diff --git a/docs-site/content/kagent/0.x/concepts/_index.md b/docs-site/content/kagent/0.x/concepts/_index.md index 0f67b0a6..41b4b4f6 100644 --- a/docs-site/content/kagent/0.x/concepts/_index.md +++ b/docs-site/content/kagent/0.x/concepts/_index.md @@ -7,4 +7,4 @@ author: kagent.dev Learn about the AI agent and kagent concepts. -The [Agents](/docs/kagent/concepts/agents) page also covers [prompt templates](/docs/kagent/concepts/agents#prompt-templates), [Git-based skills](/docs/kagent/concepts/agents#git-based-skills), and [context management](/docs/kagent/concepts/agents#context-management). For related material, see [What is kagent](/docs/kagent/introduction/what-is-kagent), the [Tools Ecosystem](/docs/kagent/resources/tools-ecosystem) catalog, [Human-in-the-Loop](/docs/kagent/examples/human-in-the-loop) configuration, and the [examples](/docs/kagent/examples), which include both the Go and Python runtimes. +The [Agents]({{< relref "/kagent/0.x/concepts/agents" >}}) page also covers [prompt templates]({{< relref "/kagent/0.x/concepts/agents#prompt-templates" >}}), [Git-based skills]({{< relref "/kagent/0.x/concepts/agents#git-based-skills" >}}), and [context management]({{< relref "/kagent/0.x/concepts/agents#context-management" >}}). For related material, see [What is kagent]({{< relref "/kagent/0.x/introduction/what-is-kagent" >}}), the [Tools Ecosystem]({{< relref "/kagent/0.x/resources/tools-ecosystem" >}}) catalog, [Human-in-the-Loop]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) configuration, and the [examples]({{< relref "/kagent/0.x/examples" >}}), which include both the Go and Python runtimes. diff --git a/docs-site/content/kagent/0.x/concepts/agent-harness.md b/docs-site/content/kagent/0.x/concepts/agent-harness.md index ab4455fe..a5043d18 100644 --- a/docs-site/content/kagent/0.x/concepts/agent-harness.md +++ b/docs-site/content/kagent/0.x/concepts/agent-harness.md @@ -5,7 +5,7 @@ weight: 4 author: kagent.dev --- -An `AgentHarness` is a Kubernetes custom resource that asks kagent to provision a long-running remote execution environment on [Agent Substrate](/docs/kagent/concepts/agent-substrate). It is useful when you want a managed sandbox that runs a coding agent (such as OpenClaw or Hermes) that you can chat with and connect to messaging channels, but you do not want kagent to package and run a full agent runtime inside the workload. +An `AgentHarness` is a Kubernetes custom resource that asks kagent to provision a long-running remote execution environment on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). It is useful when you want a managed sandbox that runs a coding agent (such as OpenClaw or Hermes) that you can chat with and connect to messaging channels, but you do not want kagent to package and run a full agent runtime inside the workload. `AgentHarness` resources appear alongside agents in kagent APIs and status views, but they are not the same thing as `Agent` or `SandboxAgent`. @@ -30,7 +30,7 @@ All backends use the same top-level `AgentHarness` shape: `backend`, `substrate` ## Runtime: Agent Substrate -Every `AgentHarness` runs on [Agent Substrate](/docs/kagent/concepts/agent-substrate). The `spec.substrate` field is required and configures the Substrate provisioning stack: +Every `AgentHarness` runs on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). The `spec.substrate` field is required and configures the Substrate provisioning stack: - `workerPoolRef` — references an existing `WorkerPool` in the harness namespace. When unset, the controller uses its configured default WorkerPool. - `snapshotsConfig` — configures where actor memory snapshots are stored. Defaults to `gs://ate-snapshots//` when unset. @@ -94,4 +94,4 @@ The API uses CEL validation to ensure Slack settings match the selected backend. ## Next steps -For enabling Agent Substrate so the controller can provision harnesses, see [Enable AgentHarness support](/docs/kagent/introduction/installation#enable-agentharness-support). For complete YAML examples, including Slack token references and backend-specific Slack settings, see the [Agent Harness example](/docs/kagent/examples/agent-harness). For the generated schema, see the [API reference](/docs/kagent/resources/api-ref#agentharness). +For enabling Agent Substrate so the controller can provision harnesses, see [Enable AgentHarness support]({{< relref "/kagent/0.x/introduction/installation#enable-agentharness-support" >}}). For complete YAML examples, including Slack token references and backend-specific Slack settings, see the [Agent Harness example]({{< relref "/kagent/0.x/examples/agent-harness" >}}). For the generated schema, see the [API reference]({{< relref "/kagent/0.x/resources/api-ref#agentharness" >}}). diff --git a/docs-site/content/kagent/0.x/concepts/agent-memory.md b/docs-site/content/kagent/0.x/concepts/agent-memory.md index 3e85e470..88db2e76 100644 --- a/docs-site/content/kagent/0.x/concepts/agent-memory.md +++ b/docs-site/content/kagent/0.x/concepts/agent-memory.md @@ -22,7 +22,7 @@ Agent memory provides the following capabilities. ### Install kagent with Postgres -To use memory, you must install kagent with a Postgres database that has the `pgvector` extension installed and vector enabled. For more information, see the [Database configuration](/docs/kagent/operations/operational-considerations#database-configuration) section. +To use memory, you must install kagent with a Postgres database that has the `pgvector` extension installed and vector enabled. For more information, see the [Database configuration]({{< relref "/kagent/0.x/operations/operational-considerations#database-configuration" >}}) section. Example Helm configuration for your own external Postgres: @@ -71,7 +71,7 @@ The embedding `ModelConfig` does not have to use the same provider as the agent' To use [Amazon Bedrock Titan embedding models](https://docs.aws.amazon.com/bedrock/latest/userguide/titan-embedding-models.html), create a `ModelConfig` with `provider: Bedrock`. -The Bedrock provider uses the standard AWS credential chain, so no API key secret is required. The agent's pod must have AWS credentials with the `bedrock:InvokeModel` permission for the chosen model. On Kubernetes, the recommended setup is [EKS IRSA on the agent ServiceAccount](/docs/kagent/supported-providers/amazon-bedrock#step-3-configure-the-agent-to-use-an-iam-role). +The Bedrock provider uses the standard AWS credential chain, so no API key secret is required. The agent's pod must have AWS credentials with the `bedrock:InvokeModel` permission for the chosen model. On Kubernetes, the recommended setup is [EKS IRSA on the agent ServiceAccount]({{< relref "/kagent/0.x/supported-providers/amazon-bedrock#step-3-configure-the-agent-to-use-an-iam-role" >}}). ```yaml apiVersion: kagent.dev/v1alpha2 @@ -184,5 +184,5 @@ DELETE /api/memories?agent_name=X&user_id=Y - **No per-memory deletion.** You can delete all memories for an agent, but you cannot delete individual memory entries. - **No cross-agent memory sharing.** Each agent has its own isolated memory store. You cannot share memories across agents. -- **Not pluggable.** Memory is built on the Google ADK memory implementation and cannot be swapped for an alternative memory solution (such as Cognee). However, if an alternative memory solution exposes an [MCP server](/docs/kagent/concepts/tools#mcp-tools), you can add it as a tool and instruct the agent to use it instead of the built-in memory. +- **Not pluggable.** Memory is built on the Google ADK memory implementation and cannot be swapped for an alternative memory solution (such as Cognee). However, if an alternative memory solution exposes an [MCP server]({{< relref "/kagent/0.x/concepts/tools#mcp-tools" >}}), you can add it as a tool and instruct the agent to use it instead of the built-in memory. diff --git a/docs-site/content/kagent/0.x/concepts/agent-substrate.md b/docs-site/content/kagent/0.x/concepts/agent-substrate.md index 85e7ff20..8ae021dd 100644 --- a/docs-site/content/kagent/0.x/concepts/agent-substrate.md +++ b/docs-site/content/kagent/0.x/concepts/agent-substrate.md @@ -9,8 +9,8 @@ Agent Substrate is a Kubernetes-native runtime for running AI agents and other s kagent can run workloads on Agent Substrate in two ways: -- **Declarative agents** — A declarative `Agent` describes its model, instructions, and tools (see [Agents](/docs/kagent/concepts/agents)). Its sandboxed variant, the [`SandboxAgent`](/docs/kagent/resources/api-ref) CRD, lets you run a (Go) declarative agent on Agent Substrate. -- **AgentHarness** — The [`AgentHarness`](/docs/kagent/concepts/agent-harness) CRD provisions a long-running execution environment for a coding agent (OpenClaw or Hermes). It always runs on Agent Substrate: kagent generates a per-harness `ActorTemplate` and creates an `Actor` from it on demand, referencing a `WorkerPool` for capacity. +- **Declarative agents** — A declarative `Agent` describes its model, instructions, and tools (see [Agents]({{< relref "/kagent/0.x/concepts/agents" >}})). Its sandboxed variant, the [`SandboxAgent`]({{< relref "/kagent/0.x/resources/api-ref" >}}) CRD, lets you run a (Go) declarative agent on Agent Substrate. +- **AgentHarness** — The [`AgentHarness`]({{< relref "/kagent/0.x/concepts/agent-harness" >}}) CRD provisions a long-running execution environment for a coding agent (OpenClaw or Hermes). It always runs on Agent Substrate: kagent generates a per-harness `ActorTemplate` and creates an `Actor` from it on demand, referencing a `WorkerPool` for capacity. ## Why Agent Substrate @@ -66,11 +66,11 @@ An `AgentHarness` always runs on Agent Substrate; `spec.substrate` is required. - `snapshotsConfig` — configures where actor memory snapshots are stored. Defaults to `gs://ate-snapshots//` when unset. - `workloadImage` — overrides the default OpenClaw or Hermes sandbox image used in the generated ActorTemplate. -kagent talks to the harness over the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) so you can chat with it from the kagent UI. See the [Agent Harness concept page](/docs/kagent/concepts/agent-harness) for details. +kagent talks to the harness over the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) so you can chat with it from the kagent UI. See the [Agent Harness concept page]({{< relref "/kagent/0.x/concepts/agent-harness" >}}) for details. -See the [API reference](/docs/kagent/resources/api-ref) for the full `AgentHarnessSubstrateSpec` schema. +See the [API reference]({{< relref "/kagent/0.x/resources/api-ref" >}}) for the full `AgentHarnessSubstrateSpec` schema. ## Learn more -- [Run a declarative agent on Agent Substrate](/docs/kagent/examples/agent-substrate) — end-to-end walkthrough on a kind cluster. +- [Run a declarative agent on Agent Substrate]({{< relref "/kagent/0.x/examples/agent-substrate" >}}) — end-to-end walkthrough on a kind cluster. - For a deeper dive into the runtime internals, see the [Agent Substrate documentation](https://learn.agentsubstrate.dev/). diff --git a/docs-site/content/kagent/0.x/concepts/agents.md b/docs-site/content/kagent/0.x/concepts/agents.md index 9cd432b2..f366ea08 100644 --- a/docs-site/content/kagent/0.x/concepts/agents.md +++ b/docs-site/content/kagent/0.x/concepts/agents.md @@ -24,7 +24,7 @@ Your responses should be clear and concise; you should provide helpful informati Instructions are an important part of the agent's behavior. They define the agent's role and capabilities and help the agent understand its environment and the tasks it can perform. -Writing good instructions is an art and a science. It requires a good understanding of the task at hand, the tools available, and the user's needs. In order to make it easier to write good instructions, we've created a [system prompt tutorial](/docs/kagent/getting-started/system-prompts) that can help you get started. +Writing good instructions is an art and a science. It requires a good understanding of the task at hand, the tools available, and the user's needs. In order to make it easier to write good instructions, we've created a [system prompt tutorial]({{< relref "/kagent/0.x/getting-started/system-prompts" >}}) that can help you get started. ### Prompt templates @@ -98,7 +98,7 @@ kagent comes with a set of built-in tools that you can use to interact with your kagent supports Human-in-the-Loop (HITL) to keep humans in control of agent actions. You can require user approval before an agent executes sensitive tools, and agents can ask users questions when they need clarification. -For a hands-on tutorial that walks through setting up HITL with tool approval and the `ask_user` tool, see the [Human-in-the-Loop example](/docs/kagent/examples/human-in-the-loop). +For a hands-on tutorial that walks through setting up HITL with tool approval and the `ask_user` tool, see the [Human-in-the-Loop example]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}). ### Tool approval @@ -226,7 +226,7 @@ When creating skills for your agents, consider the following best practices. Age 4. **Align with tools**: Ensure your skills align with the tools available to the agent. If you have a skill that centers around writing docs in markdown, you might want to align it with the `write-markdown` tool (as opposed to a `generate-pdf` tool). 5. **Keep skills focused**: Each skill should have a clear, focused purpose. For example, a document-generating skill might be too broad, but a skill that focuses on creating a specific type of document, such as a `.docx` file or alternatively a genre like a getting started guide, might be more appropriate. -To learn more about using skills in your agents, see the [Skills example guide](/docs/kagent/examples/skills). +To learn more about using skills in your agents, see the [Skills example guide]({{< relref "/kagent/0.x/examples/skills" >}}). ## Runtime @@ -263,7 +263,7 @@ For more benchmarks and details, see the [Go vs Python runtime blog post](https: Your agents can save and retrieve relevant context across conversations using vector similarity search. When you enable memory on an agent, it receives three additional tools (`save_memory`, `load_memory`, `prefetch_memory`) and automatically extracts key information every 5th user message. -For configuration details, supported storage backends, API endpoints, and limitations, see [Agent Memory](/docs/kagent/concepts/agent-memory). +For configuration details, supported storage backends, API endpoints, and limitations, see [Agent Memory]({{< relref "/kagent/0.x/concepts/agent-memory" >}}). ## Context Management @@ -292,9 +292,9 @@ Compaction removes older conversation events to free up space in the context win ## Sandboxed Agents -You can run a declarative agent in an isolated sandbox by creating a `SandboxAgent` resource instead of a regular `Agent`. A `SandboxAgent` runs on [Agent Substrate](/docs/kagent/concepts/agent-substrate): the kagent controller runs it as a gVisor-sandboxed actor instead of a Deployment, snapshotting it to object storage when idle and rehydrating it on demand. The spec mirrors the `Agent` spec, with a few constraints: sandboxed agents always use the Go ADK runtime, and `spec.skills` and `BYO` agents are not supported. Configure substrate placement with the optional `spec.substrate` field (for example, `workerPoolRef`). +You can run a declarative agent in an isolated sandbox by creating a `SandboxAgent` resource instead of a regular `Agent`. A `SandboxAgent` runs on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}): the kagent controller runs it as a gVisor-sandboxed actor instead of a Deployment, snapshotting it to object storage when idle and rehydrating it on demand. The spec mirrors the `Agent` spec, with a few constraints: sandboxed agents always use the Go ADK runtime, and `spec.skills` and `BYO` agents are not supported. Configure substrate placement with the optional `spec.substrate` field (for example, `workerPoolRef`). -For setup steps, see the [Agent Substrate example](/docs/kagent/examples/agent-substrate). +For setup steps, see the [Agent Substrate example]({{< relref "/kagent/0.x/examples/agent-substrate" >}}). ## Agents as Tools @@ -330,4 +330,4 @@ Here's how you could reference an existing agent (`promql-agent`) as a tool: A2A-enabled agents are automatically exposed as an MCP server on the kagent controller. The MCP endpoint is available at `/mcp` on the same port as the A2A endpoint (default 8083). -For more information, see the [MCP tools](/docs/kagent/examples/agents-mcp) guide. +For more information, see the [MCP tools]({{< relref "/kagent/0.x/examples/agents-mcp" >}}) guide. diff --git a/docs-site/content/kagent/0.x/concepts/architecture.md b/docs-site/content/kagent/0.x/concepts/architecture.md index e6dd9deb..0f38b86b 100644 --- a/docs-site/content/kagent/0.x/concepts/architecture.md +++ b/docs-site/content/kagent/0.x/concepts/architecture.md @@ -24,7 +24,7 @@ The kagent engine is the core component of kagent. It runs the agent's conversat - **Python ADK** (default) — Built on top of the [Google ADK](https://google.github.io/adk-docs/) framework. Supports Google ADK-native features and integrations with CrewAI, LangGraph, and OpenAI frameworks. - **Go ADK** — A native Go implementation that provides faster startup (~2 seconds vs ~15 seconds) and lower resource consumption. -Select the runtime by setting the `runtime` field in the agent spec (e.g., `runtime: go`). Both runtimes support MCP tools, HITL, and agent memory. For more details, see [Agents](/docs/kagent/concepts/agents#runtime). +Select the runtime by setting the `runtime` field in the agent spec (e.g., `runtime: go`). Both runtimes support MCP tools, HITL, and agent memory. For more details, see [Agents]({{< relref "/kagent/0.x/concepts/agents#runtime" >}}). For more information on the Google ADK framework: @@ -63,5 +63,5 @@ kagent dashboard provides a web interface for managing and working with AI agent ## Next Steps -- Try [building your own agent](/docs/kagent/getting-started/first-agent) +- Try [building your own agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) diff --git a/docs-site/content/kagent/0.x/concepts/mcp-apps.md b/docs-site/content/kagent/0.x/concepts/mcp-apps.md index f0cb1f61..d1bf1044 100644 --- a/docs-site/content/kagent/0.x/concepts/mcp-apps.md +++ b/docs-site/content/kagent/0.x/concepts/mcp-apps.md @@ -60,4 +60,4 @@ A complete example, including a demo agent, is available in the kagent repositor - [MCP Apps extension](https://github.com/modelcontextprotocol/ext-apps) - [Model Context Protocol](https://modelcontextprotocol.io/) -- [Tools in kagent](/docs/kagent/concepts/tools) +- [Tools in kagent]({{< relref "/kagent/0.x/concepts/tools" >}}) diff --git a/docs-site/content/kagent/0.x/concepts/tools.md b/docs-site/content/kagent/0.x/concepts/tools.md index c2bfdb73..6573a194 100644 --- a/docs-site/content/kagent/0.x/concepts/tools.md +++ b/docs-site/content/kagent/0.x/concepts/tools.md @@ -11,7 +11,7 @@ kagent comes with a set of built-in tools that you can use to interact with your ## Built-in Tools -You can check out the full list of [built-in tools](https://kagent.dev/tools), or see the [Tools Ecosystem](/docs/kagent/resources/tools-ecosystem) reference for a detailed catalog of tools organized by MCP server. +You can check out the full list of [built-in tools](https://kagent.dev/tools), or see the [Tools Ecosystem]({{< relref "/kagent/0.x/resources/tools-ecosystem" >}}) reference for a detailed catalog of tools organized by MCP server. The built-in tools are meant as a good starting point for any agents running in kubernetes, however we don't envision them covering all possible use-cases, so we support multiple tool extension points to allow you to bring in your own tools. @@ -78,7 +78,7 @@ MCP stands for [Model Context Protocol](https://modelcontextprotocol.io/introduc ### MCP Apps -Some MCP tools ship an interactive UI with their results. kagent detects these tools automatically and renders their widgets inline in the chat, and the dashboard lists them alongside a server's regular tools so you can test them directly. See [MCP Apps](/docs/kagent/concepts/mcp-apps) for details. +Some MCP tools ship an interactive UI with their results. kagent detects these tools automatically and renders their widgets inline in the chat, and the dashboard lists them alongside a server's regular tools so you can test them directly. See [MCP Apps]({{< relref "/kagent/0.x/concepts/mcp-apps" >}}) for details. ## HTTP Tools diff --git a/docs-site/content/kagent/0.x/examples/a2a-agents.md b/docs-site/content/kagent/0.x/examples/a2a-agents.md index 08fb2670..272cd49f 100644 --- a/docs-site/content/kagent/0.x/examples/a2a-agents.md +++ b/docs-site/content/kagent/0.x/examples/a2a-agents.md @@ -12,7 +12,7 @@ Let's look at how this works in kagent! ## Prerequisites -Install kagent by following the [quick start](/docs/kagent/getting-started/quickstart) guide. +Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. ## Creating an AI agent that supports A2A @@ -135,7 +135,7 @@ You can invoke the agent in several ways, including the kagent dashboard, kagent ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `k8s-a2a-agent`, and start chatting. For complete steps, see the [Your First Agent](/docs/kagent/getting-started/first-agent) guide. +Launch the dashboard with `kagent dashboard`, find your `k8s-a2a-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. ### kagent CLI diff --git a/docs-site/content/kagent/0.x/examples/a2a-byo.md b/docs-site/content/kagent/0.x/examples/a2a-byo.md index 532a9892..2000a7f3 100644 --- a/docs-site/content/kagent/0.x/examples/a2a-byo.md +++ b/docs-site/content/kagent/0.x/examples/a2a-byo.md @@ -6,13 +6,13 @@ weight: 1 author: kagent.dev --- -Bring your own custom agents. This example uses the [Agent Development Kit (ADK)](https://google.github.io/adk-docs/), but you can also try out the [LangGraph guide](/docs/kagent/examples/langchain-byo/). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. +Bring your own custom agents. This example uses the [Agent Development Kit (ADK)](https://google.github.io/adk-docs/), but you can also try out the [LangGraph guide]({{< relref "/kagent/0.x/examples/langchain-byo/" >}}). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. Unlike declarative agents that are defined by kagent resources with components such as system instructions, models, and tools written inline, these BYO agents give you full control over agent logic. If you have your own agent, no need to decompose its functions into separate kagent resources. kagent can invoke your agent directly through the A2A protocol. ## Prerequisites -1. Install kagent by following the [quick start](/docs/kagent/getting-started/quickstart) guide. +1. Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. 2. Use [Google ADK](https://github.com/google/adk-python) version 1.22.1 or later. ## Building a custom agent @@ -162,7 +162,7 @@ You can invoke the agent in several ways, including the kagent dashboard, kagent ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `basic-agent`, and start chatting. For complete steps, see the [Your First Agent](/docs/kagent/getting-started/first-agent) guide. +Launch the dashboard with `kagent dashboard`, find your `basic-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. ![BYO Agent](/images/byo-basic.png "Chat with your basic agent") diff --git a/docs-site/content/kagent/0.x/examples/agent-harness.md b/docs-site/content/kagent/0.x/examples/agent-harness.md index 7272b3fe..4be4b4f1 100644 --- a/docs-site/content/kagent/0.x/examples/agent-harness.md +++ b/docs-site/content/kagent/0.x/examples/agent-harness.md @@ -5,14 +5,14 @@ weight: 8 author: kagent.dev --- -`AgentHarness` creates a long-running remote execution environment on [Agent Substrate](/docs/kagent/concepts/agent-substrate). Unlike an `Agent` or `SandboxAgent`, it does not package a kagent runtime into the workload. The backend provisions a sandbox that runs a coding agent (OpenClaw or Hermes), which you can chat with from the kagent UI and wire into messaging channels. +`AgentHarness` creates a long-running remote execution environment on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). Unlike an `Agent` or `SandboxAgent`, it does not package a kagent runtime into the workload. The backend provisions a sandbox that runs a coding agent (OpenClaw or Hermes), which you can chat with from the kagent UI and wire into messaging channels. Use `AgentHarness` when you want kagent to manage the lifecycle of an OpenClaw or Hermes sandbox and surface it in the kagent API/UI alongside regular agents. ## Before you begin -1. Install kagent v0.9.9 or later by following the [quick start](/docs/kagent/getting-started/quickstart) guide. -2. Install Agent Substrate and enable the substrate integration in kagent. For Helm-based setup instructions, see [Enable AgentHarness support](/docs/kagent/introduction/installation#enable-agentharness-support) and the [Agent Substrate example](/docs/kagent/examples/agent-substrate). +1. Install kagent v0.9.9 or later by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. +2. Install Agent Substrate and enable the substrate integration in kagent. For Helm-based setup instructions, see [Enable AgentHarness support]({{< relref "/kagent/0.x/introduction/installation#enable-agentharness-support" >}}) and the [Agent Substrate example]({{< relref "/kagent/0.x/examples/agent-substrate" >}}). When the substrate integration is not enabled, the controller cannot provision AgentHarness resources. @@ -204,7 +204,7 @@ Once the harness is `Ready`, it appears in the kagent UI alongside your other ag 2. Open [http://localhost:8001](http://localhost:8001), select your harness (for example `kagent/openclaw-shell`) from the Agents list, and send a message. -The first chat connection creates a shared Substrate actor from the harness template; every chat is multiplexed as an ACP session inside that actor. You see streamed tool activity, and any tool-approval prompts the backend raises are surfaced through kagent's [human-in-the-loop](/docs/kagent/examples/human-in-the-loop) flow. +The first chat connection creates a shared Substrate actor from the harness template; every chat is multiplexed as an ACP session inside that actor. You see streamed tool activity, and any tool-approval prompts the backend raises are surfaced through kagent's [human-in-the-loop]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) flow. ## Troubleshooting @@ -217,4 +217,4 @@ If the harness is not accepted or ready, check these common causes. - A Slack channel has the wrong backend settings, such as `slack.hermes` on an OpenClaw harness or `slack.openclaw` on a Hermes harness. - A Slack credential uses neither `value` nor `valueFrom`, or sets both. -For the complete generated schema, see the [API reference](/docs/kagent/resources/api-ref#agentharness). +For the complete generated schema, see the [API reference]({{< relref "/kagent/0.x/resources/api-ref#agentharness" >}}). diff --git a/docs-site/content/kagent/0.x/examples/agent-substrate.md b/docs-site/content/kagent/0.x/examples/agent-substrate.md index 312048d2..53af1c5f 100644 --- a/docs-site/content/kagent/0.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/0.x/examples/agent-substrate.md @@ -13,7 +13,7 @@ By the end, you will have: - kagent v0.9.7 or later installed with the substrate integration enabled. Earlier kagent releases do not include the controller wiring that lets a `SandboxAgent` target substrate. - A `SandboxAgent` running on substrate, reachable from the kagent UI. -For background on what substrate is and how it differs from a per-pod agent runtime, see the [Agent Substrate concept page](/docs/kagent/concepts/agent-substrate). This guide does not cover the `AgentHarness` path on substrate. +For background on what substrate is and how it differs from a per-pod agent runtime, see the [Agent Substrate concept page]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). This guide does not cover the `AgentHarness` path on substrate. ## Before you begin @@ -213,5 +213,5 @@ kind delete cluster --name kagent-substrate ## Next steps -- [Agent Substrate concept page](/docs/kagent/concepts/agent-substrate) — runtime architecture and how snapshots, actors, and worker pools fit together. -- [AgentHarness](/docs/kagent/examples/agent-harness) — provision long-running OpenClaw and Hermes coding-agent sandboxes on Agent Substrate and chat with them over ACP. +- [Agent Substrate concept page]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}) — runtime architecture and how snapshots, actors, and worker pools fit together. +- [AgentHarness]({{< relref "/kagent/0.x/examples/agent-harness" >}}) — provision long-running OpenClaw and Hermes coding-agent sandboxes on Agent Substrate and chat with them over ACP. diff --git a/docs-site/content/kagent/0.x/examples/agentgateway.md b/docs-site/content/kagent/0.x/examples/agentgateway.md index 010a4554..196be566 100644 --- a/docs-site/content/kagent/0.x/examples/agentgateway.md +++ b/docs-site/content/kagent/0.x/examples/agentgateway.md @@ -10,7 +10,7 @@ As your kagent deployment grows, you might need governance over how your agents ## Prerequisites -1. A running kagent installation. If you haven't installed kagent yet, follow the [quick start](/docs/kagent/getting-started/quickstart) guide first. +1. A running kagent installation. If you haven't installed kagent yet, follow the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide first. 2. Follow the [agentgateway installation guide](https://agentgateway.dev/docs/kubernetes/latest/quickstart/install/) to install agentgateway in your cluster. 3. Set up an LLM provider with agentgateway. This guide uses [the Ollama setup](https://agentgateway.dev/docs/kubernetes/latest/llm/providers/ollama/) as an example. @@ -86,7 +86,7 @@ With agentgateway installed, point kagent at the agentgateway proxy instead of d {{< /tab >}} {{< /tabs >}} -4. [Open the kagent UI](/docs/kagent/observability/launch-ui). +4. [Open the kagent UI]({{< relref "/kagent/0.x/observability/launch-ui" >}}). 5. Start a chat with an agent such as `k8s-agent` to confirm that requests flow through agentgateway. ![kagent default k8s-agent UI](/images/kagent-default-k8s-agent.png "kagent default k8s-agent UI") diff --git a/docs-site/content/kagent/0.x/examples/crewai-byo.md b/docs-site/content/kagent/0.x/examples/crewai-byo.md index 322ba174..a0f763b9 100644 --- a/docs-site/content/kagent/0.x/examples/crewai-byo.md +++ b/docs-site/content/kagent/0.x/examples/crewai-byo.md @@ -6,13 +6,13 @@ weight: 1 author: kagent.dev --- -Bring your own custom agents. This example uses [CrewAI](https://www.crewai.com/), but you can also try out the [ADK guide](/docs/kagent/examples/a2a-byo/) or [LangGraph guide](/docs/kagent/examples/langchain-byo/). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. +Bring your own custom agents. This example uses [CrewAI](https://www.crewai.com/), but you can also try out the [ADK guide]({{< relref "/kagent/0.x/examples/a2a-byo/" >}}) or [LangGraph guide]({{< relref "/kagent/0.x/examples/langchain-byo/" >}}). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. Unlike declarative agents that are defined by kagent resources with components such as system instructions, models, and tools written inline, these BYO agents give you full control over agent logic. If you have your own agent, no need to decompose its functions into separate kagent resources. kagent can invoke your agent directly through the A2A protocol. ## Prerequisites -Install kagent by following the [quick start](/docs/kagent/getting-started/quickstart) guide. +Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. ## Building a custom agent @@ -148,7 +148,7 @@ You can invoke the agent in several ways, including the kagent dashboard, kagent ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `research-crew`, and start chatting. For complete steps, see the [Your First Agent](/docs/kagent/getting-started/first-agent) guide. +Launch the dashboard with `kagent dashboard`, find your `research-crew`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. ### kagent CLI diff --git a/docs-site/content/kagent/0.x/examples/discord-a2a.md b/docs-site/content/kagent/0.x/examples/discord-a2a.md index 283c44ff..7ef4e775 100644 --- a/docs-site/content/kagent/0.x/examples/discord-a2a.md +++ b/docs-site/content/kagent/0.x/examples/discord-a2a.md @@ -8,7 +8,7 @@ author: kagent.dev }; -kagent enables you to create AI agents that run inside your Kubernetes cluster. They can access a variety of [built-in tools](/docs/kagent/concepts/tools) and use other [external tools via MCP](/docs/kagent/examples/documentation). +kagent enables you to create AI agents that run inside your Kubernetes cluster. They can access a variety of [built-in tools]({{< relref "/kagent/0.x/concepts/tools" >}}) and use other [external tools via MCP]({{< relref "/kagent/0.x/examples/documentation" >}}). This guide shows how to connect a Discord bot to one of your agents using the A2A protocol, enabling natural conversations and command execution inside Discord. @@ -129,7 +129,7 @@ When a message is received, it’s sent to the A2A endpoint (`KAGENT_A2A_URL`), ## Agent Setup -If you haven’t deployed your agent yet, follow the instructions in [Deploying an Agent](/docs/kagent/examples/slack-a2a#deploying-an-agent). You can reuse the same agent across Slack and Discord integrations. +If you haven’t deployed your agent yet, follow the instructions in [Deploying an Agent]({{< relref "/kagent/0.x/examples/slack-a2a#deploying-an-agent" >}}). You can reuse the same agent across Slack and Discord integrations. Be sure to port-forward your agent if running locally: diff --git a/docs-site/content/kagent/0.x/examples/langchain-byo.md b/docs-site/content/kagent/0.x/examples/langchain-byo.md index 10d33c0e..b5a8ea39 100644 --- a/docs-site/content/kagent/0.x/examples/langchain-byo.md +++ b/docs-site/content/kagent/0.x/examples/langchain-byo.md @@ -10,7 +10,7 @@ You can bring your own LangGraph agent to kagent by configuring the kagentCheckp ## Prerequisites -Install kagent by following the [quick start](/docs/kagent/getting-started/quickstart) guide. +Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. ## Building a LangGraph agent @@ -125,7 +125,7 @@ You can invoke the agent through the kagent dashboard or kagent CLI. ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `langgraph-agent`, and start chatting. For complete steps, see the [Your First Agent](/docs/kagent/getting-started/first-agent) guide. +Launch the dashboard with `kagent dashboard`, find your `langgraph-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. ![BYO Agent](/images/byo-langgraph.png "Chat with your LangGraph agent") diff --git a/docs-site/content/kagent/0.x/examples/skills.md b/docs-site/content/kagent/0.x/examples/skills.md index fd66647f..5fcab664 100644 --- a/docs-site/content/kagent/0.x/examples/skills.md +++ b/docs-site/content/kagent/0.x/examples/skills.md @@ -15,9 +15,9 @@ In this guide, you learn how to add container-based skills to your agents in kag ## Before you begin -1. Install kagent by following the [quick start](/docs/kagent/getting-started/quickstart) guide. +1. Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. -2. Review the concepts of [agents and skills](/docs/kagent/concepts/agents) in kagent. +2. Review the concepts of [agents and skills]({{< relref "/kagent/0.x/concepts/agents" >}}) in kagent. ## Container-based skills @@ -372,6 +372,6 @@ When you're done, you can clean up the resources that you created. ## Next steps -- Learn more about [agents](/docs/kagent/concepts/agents) and their components -- Explore [tools](/docs/kagent/concepts/tools) available in kagent -- Check out other [examples](/docs/kagent/examples) to see different agent configurations +- Learn more about [agents]({{< relref "/kagent/0.x/concepts/agents" >}}) and their components +- Explore [tools]({{< relref "/kagent/0.x/concepts/tools" >}}) available in kagent +- Check out other [examples]({{< relref "/kagent/0.x/examples" >}}) to see different agent configurations diff --git a/docs-site/content/kagent/0.x/examples/slack-a2a.md b/docs-site/content/kagent/0.x/examples/slack-a2a.md index 01ed5c7e..22e63fc9 100644 --- a/docs-site/content/kagent/0.x/examples/slack-a2a.md +++ b/docs-site/content/kagent/0.x/examples/slack-a2a.md @@ -8,7 +8,7 @@ author: kagent.dev }; -kagent enables you to create AI agents that run inside your Kubernetes cluster. They have access to a variety of [built-in tools](/docs/kagent/concepts/tools) like Kubernetes, Istio, Grafana, Prometheus, Argo and can be extended with any other tools [using MCP](/docs/kagent/examples/documentation). +kagent enables you to create AI agents that run inside your Kubernetes cluster. They have access to a variety of [built-in tools]({{< relref "/kagent/0.x/concepts/tools" >}}) like Kubernetes, Istio, Grafana, Prometheus, Argo and can be extended with any other tools [using MCP]({{< relref "/kagent/0.x/examples/documentation" >}}). ![Slack - A2A - MCP - kagent](/images/slack-a2a/slack-a2a-kagent.png) diff --git a/docs-site/content/kagent/0.x/examples/telegram-bot.md b/docs-site/content/kagent/0.x/examples/telegram-bot.md index dd3ecf81..bb3af6c3 100644 --- a/docs-site/content/kagent/0.x/examples/telegram-bot.md +++ b/docs-site/content/kagent/0.x/examples/telegram-bot.md @@ -98,7 +98,7 @@ spec: EOF ``` -Notice `requireApproval` — anything destructive (deleting resources, applying manifests, Helm upgrades) goes through [Human-in-the-Loop](/docs/kagent/examples/human-in-the-loop) approval in the kagent UI first. Nobody's accidentally nuking prod from a Telegram chat. +Notice `requireApproval` — anything destructive (deleting resources, applying manifests, Helm upgrades) goes through [Human-in-the-Loop]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) approval in the kagent UI first. Nobody's accidentally nuking prod from a Telegram chat. Verify it's working: diff --git a/docs-site/content/kagent/0.x/getting-started/first-agent.md b/docs-site/content/kagent/0.x/getting-started/first-agent.md index 8083bfba..3e2f4a10 100644 --- a/docs-site/content/kagent/0.x/getting-started/first-agent.md +++ b/docs-site/content/kagent/0.x/getting-started/first-agent.md @@ -10,7 +10,7 @@ In this guide, you'll learn how to create your first AI agent using the kagent d ## Prerequisites -Before you begin make sure you have a Kubernetes cluster with kagent installed. If you haven't done this yet, check out the [installation guide](/docs/kagent/introduction/installation) or the [quickstart guide](/docs/kagent/getting-started/quickstart). +Before you begin make sure you have a Kubernetes cluster with kagent installed. If you haven't done this yet, check out the [installation guide]({{< relref "/kagent/0.x/introduction/installation" >}}) or the [quickstart guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). We'll be working in the kagent dashboard, so use the kagent CLI to open the dashboard: @@ -90,5 +90,5 @@ Now that you set up all the details for your agent, you're ready to finish creat ## Next Steps -- Learn more about [Core Concepts](/docs/kagent/concepts) +- Learn more about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) diff --git a/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md b/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md index 40e4c890..7781acd1 100644 --- a/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md +++ b/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md @@ -12,7 +12,7 @@ In this guide, you'll learn how to add an MCP tool to your first AI agent using ## Prerequisites -1. Install kagent in a Kubernetes cluster. If you haven't done this yet, check out the [installation guide](/docs/kagent/introduction/installation) or the [quickstart guide](/docs/kagent/getting-started/quickstart). +1. Install kagent in a Kubernetes cluster. If you haven't done this yet, check out the [installation guide]({{< relref "/kagent/0.x/introduction/installation" >}}) or the [quickstart guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). 2. Make sure that you have the kagent custom resources in your cluster. @@ -22,7 +22,7 @@ In this guide, you'll learn how to add an MCP tool to your first AI agent using ## Creating an agent -To create an agent, follow the [Your First Agent guide](/docs/kagent/getting-started/first-agent). +To create an agent, follow the [Your First Agent guide]({{< relref "/kagent/0.x/getting-started/first-agent" >}}). Take a look at the Agent custom resource for your first agent, such as with the following command. @@ -177,5 +177,5 @@ Now let's try our agent out with the fetch tool. ## Next Steps -- Learn more about [Core Concepts](/docs/kagent/concepts) +- Learn more about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) diff --git a/docs-site/content/kagent/0.x/getting-started/local-development.md b/docs-site/content/kagent/0.x/getting-started/local-development.md index 04a300f4..da2ec1b8 100644 --- a/docs-site/content/kagent/0.x/getting-started/local-development.md +++ b/docs-site/content/kagent/0.x/getting-started/local-development.md @@ -6,13 +6,13 @@ weight: 4 author: kagent.dev --- -In this guide, you'll learn how to develop, build and run an AI agent locally using kagent CLI, without a Kubernetes cluster. This guide is meant for developers familiar with Python. You can also create declarative agents without writing a single line of code, by following the [Your First Agent](/docs/kagent/getting-started/first-agent) guide. +In this guide, you'll learn how to develop, build and run an AI agent locally using kagent CLI, without a Kubernetes cluster. This guide is meant for developers familiar with Python. You can also create declarative agents without writing a single line of code, by following the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. ## Prerequisites Before you begin make sure you have the following prerequisites installed: -- [kagent CLI](/docs/kagent/introduction/installation) +- [kagent CLI]({{< relref "/kagent/0.x/introduction/installation" >}}) - [Python](https://www.python.org/) - [Docker](https://www.docker.com/) and [Docker compose](https://docs.docker.com/compose/) diff --git a/docs-site/content/kagent/0.x/getting-started/quickstart.md b/docs-site/content/kagent/0.x/getting-started/quickstart.md index de8cc6c0..cd91017f 100644 --- a/docs-site/content/kagent/0.x/getting-started/quickstart.md +++ b/docs-site/content/kagent/0.x/getting-started/quickstart.md @@ -141,12 +141,12 @@ Interact with kagent in your terminal. ## Next Steps -- Create your [first agent](/docs/kagent/getting-started/first-agent) -- Learn about [Core Concepts](/docs/kagent/concepts) +- Create your [first agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) +- Learn about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) ## Need Help? - Visit our [GitHub repository](https://github.com/kagent-dev/kagent) - Ask a question on [Discord](https://discord.gg/Fu3k65f2k3) -- Check out the [FAQ](/docs/kagent/resources/faq) \ No newline at end of file +- Check out the [FAQ]({{< relref "/kagent/0.x/resources/faq" >}}) \ No newline at end of file diff --git a/docs-site/content/kagent/0.x/introduction/_index.md b/docs-site/content/kagent/0.x/introduction/_index.md index 15a86baf..1f86319e 100644 --- a/docs-site/content/kagent/0.x/introduction/_index.md +++ b/docs-site/content/kagent/0.x/introduction/_index.md @@ -5,4 +5,4 @@ weight: 1 author: kagent.dev --- -Welcome to kagent! Start here to understand what kagent is and how to install it. To follow the roadmap or help improve kagent, see [Community and Contributing](/docs/kagent/resources/community). +Welcome to kagent! Start here to understand what kagent is and how to install it. To follow the roadmap or help improve kagent, see [Community and Contributing]({{< relref "/kagent/0.x/resources/community" >}}). diff --git a/docs-site/content/kagent/0.x/introduction/installation.md b/docs-site/content/kagent/0.x/introduction/installation.md index 2e9b7609..7aa93038 100644 --- a/docs-site/content/kagent/0.x/introduction/installation.md +++ b/docs-site/content/kagent/0.x/introduction/installation.md @@ -5,13 +5,13 @@ weight: 1 author: kagent.dev --- -This guide covers ways to install and configure kagent in your Kubernetes environment. For a quick setup, check out our [Quick Start Guide](/docs/kagent/getting-started/quickstart). For enterpise offerings, check out [Solo Enterprise for kagent](/docs/kagent/introduction/what-is-kagent/#enterprise-distributions). +This guide covers ways to install and configure kagent in your Kubernetes environment. For a quick setup, check out our [Quick Start Guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). For enterpise offerings, check out [Solo Enterprise for kagent]({{< relref "/kagent/0.x/introduction/what-is-kagent/#enterprise-distributions" >}}). ## Installation Methods Install kagent by using the kagent CLI or Helm. -> **Note**: As of [version 0.7](/docs/kagent/resources/release-notes#kmcp-installed-by-default), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. +> **Note**: As of [version 0.7]({{< relref "/kagent/0.x/resources/release-notes#kmcp-installed-by-default" >}}), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. ### Using kagent CLI (Recommended) @@ -66,7 +66,7 @@ Another way to install kagent is using Helm. --create-namespace ``` -2. Optionally prepare a Helm values file or `--set` flags to use for your installation. For example, you might set up your default LLM provider, or configure resource requests and limits or disable the default agents. For options, refer to the [Helm reference docs](/docs/kagent/resources/helm). +2. Optionally prepare a Helm values file or `--set` flags to use for your installation. For example, you might set up your default LLM provider, or configure resource requests and limits or disable the default agents. For options, refer to the [Helm reference docs]({{< relref "/kagent/0.x/resources/helm" >}}). {{< tabs >}} {{< tab name="OpenAI" >}} @@ -185,7 +185,7 @@ Review the following advanced configuration options that you might want to set u ### Enable AgentHarness support -`AgentHarness` resources run on [Agent Substrate](/docs/kagent/concepts/agent-substrate). To enable them, install Agent Substrate and turn on the substrate integration in kagent. When the integration is disabled, the controller cannot provision AgentHarness resources. +`AgentHarness` resources run on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). To enable them, install Agent Substrate and turn on the substrate integration in kagent. When the integration is disabled, the controller cannot provision AgentHarness resources. 1. Install Agent Substrate (CRDs, then the control plane and data plane). @@ -228,11 +228,11 @@ Review the following advanced configuration options that you might want to set u Pin the kagent chart to v0.9.9 or later — earlier versions do not include the `controller.substrate.*` and `substrateWorkerPool.*` values. -For an end-to-end walkthrough on a kind cluster, see the [Agent Substrate example](/docs/kagent/examples/agent-substrate). For more information about creating harness resources, see [Agent Harness](/docs/kagent/examples/agent-harness). +For an end-to-end walkthrough on a kind cluster, see the [Agent Substrate example]({{< relref "/kagent/0.x/examples/agent-substrate" >}}). For more information about creating harness resources, see [Agent Harness]({{< relref "/kagent/0.x/examples/agent-harness" >}}). ### Database configuration -For production environments, set up kagent with an external PostgreSQL instance. For more information, see the [Database configuration guide](/docs/kagent/operations/operational-considerations/#database-configuration). +For production environments, set up kagent with an external PostgreSQL instance. For more information, see the [Database configuration guide]({{< relref "/kagent/0.x/operations/operational-considerations/#database-configuration" >}}). ### Configure controller environment variables @@ -303,9 +303,9 @@ This example loads all key-value pairs from the `controller-secrets` secret as e ## Uninstallation -Refer to the [Uninstall](/docs/kagent/operations/uninstall) guide. +Refer to the [Uninstall]({{< relref "/kagent/0.x/operations/uninstall" >}}) guide. ## Next Steps -- [Create your first agent](/docs/kagent/getting-started/first-agent) +- [Create your first agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) - [Explore available agents](https://kagent.dev/agents) diff --git a/docs-site/content/kagent/0.x/introduction/what-is-kagent.md b/docs-site/content/kagent/0.x/introduction/what-is-kagent.md index c17818c7..c61b9728 100644 --- a/docs-site/content/kagent/0.x/introduction/what-is-kagent.md +++ b/docs-site/content/kagent/0.x/introduction/what-is-kagent.md @@ -62,7 +62,7 @@ Check out [Solo Enterprise for kagent](https://www.solo.io/products/kagent-enter ## Getting Started -To start using kagent in your environment, check out the [Quick Start Guide](/docs/kagent/getting-started/quickstart) guide. For a deeper understanding of how kagent works, refer to the [kagent architecture](/docs/kagent/concepts/architecture). +To start using kagent in your environment, check out the [Quick Start Guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. For a deeper understanding of how kagent works, refer to the [kagent architecture]({{< relref "/kagent/0.x/concepts/architecture" >}}). Ready to contribute? Visit our [Github repository](https://github.com/kagent-dev) to learn how you can help expand the ecosystem of cloud-native AI agents. @@ -71,5 +71,5 @@ Ready to contribute? Visit our [Github repository](https://github.com/kagent-dev Join the kagent community: - Explore our repositories on [GitHub](https://github.com/kagent-dev) - Join the discussion in the #kagent channel on CNCF Slack -- Check our [FAQ](/docs/kagent/resources/faq) for common questions +- Check our [FAQ]({{< relref "/kagent/0.x/resources/faq" >}}) for common questions - Follow our [Feature Roadmap](https://github.com/kagent-dev/kagent/blob/main/README.md#roadmap) for upcoming developments diff --git a/docs-site/content/kagent/0.x/observability/audit-prompts.md b/docs-site/content/kagent/0.x/observability/audit-prompts.md index c4301fc3..73cdd9a8 100644 --- a/docs-site/content/kagent/0.x/observability/audit-prompts.md +++ b/docs-site/content/kagent/0.x/observability/audit-prompts.md @@ -20,7 +20,7 @@ kagent supports logging input/output messages for the following LLM providers: ## Before you begin -1. [Install kagent](/docs/kagent/introduction/installation) in your cluster. +1. [Install kagent]({{< relref "/kagent/0.x/introduction/installation" >}}) in your cluster. 2. Add the OpenTelemetry Helm repository. diff --git a/docs-site/content/kagent/0.x/observability/launch-ui.md b/docs-site/content/kagent/0.x/observability/launch-ui.md index 66308306..edc687da 100644 --- a/docs-site/content/kagent/0.x/observability/launch-ui.md +++ b/docs-site/content/kagent/0.x/observability/launch-ui.md @@ -51,6 +51,6 @@ If you prefer to manually set up port-forwarding, or if you're on a platform whe You can use the UI to view and manage your agents, tools, and models. For more information, see the following guides: -- [Create your first agent](/docs/kagent/getting-started/first-agent) -- [Add MCP tools to your agents](/docs/kagent/getting-started/first-mcp-tool) -- [Configure LLM providers](/docs/kagent/supported-providers) +- [Create your first agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) +- [Add MCP tools to your agents]({{< relref "/kagent/0.x/getting-started/first-mcp-tool" >}}) +- [Configure LLM providers]({{< relref "/kagent/0.x/supported-providers" >}}) diff --git a/docs-site/content/kagent/0.x/observability/tracing.md b/docs-site/content/kagent/0.x/observability/tracing.md index 3792cec5..00886605 100644 --- a/docs-site/content/kagent/0.x/observability/tracing.md +++ b/docs-site/content/kagent/0.x/observability/tracing.md @@ -9,7 +9,7 @@ Set up tracing for your kagent agents. ## Before you begin -[Install kagent](/docs/kagent/introduction/installation). +[Install kagent]({{< relref "/kagent/0.x/introduction/installation" >}}). ## Install Jaeger @@ -82,7 +82,7 @@ Now that you installed kagent with Jaeger, learn how to trace requests to an age ### Generate tracing data -To generate tracing data, you can chat with a pre-configured agent such as `k8s-agent`. For more information about agents, see the [Your First Agent](/docs/kagent/getting-started/first-agent) guide. +To generate tracing data, you can chat with a pre-configured agent such as `k8s-agent`. For more information about agents, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. 1. Launch the kagent dashboard. @@ -135,11 +135,11 @@ That's it! You've now traced your first agent. ## Next Steps -- Learn about [Core Concepts](/docs/kagent/concepts) -- Try out some [Example](/docs/kagent/examples) guides +- Learn about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) +- Try out some [Example]({{< relref "/kagent/0.x/examples" >}}) guides ## Need Help? - Visit our [GitHub repository](https://github.com/kagent-dev/kagent) - Ask a question on [Discord](https://discord.gg/Fu3k65f2k3) -- Check out the [FAQ](/docs/kagent/resources/faq) \ No newline at end of file +- Check out the [FAQ]({{< relref "/kagent/0.x/resources/faq" >}}) \ No newline at end of file diff --git a/docs-site/content/kagent/0.x/operations/operational-considerations.md b/docs-site/content/kagent/0.x/operations/operational-considerations.md index 9e2cd8b5..d768ff64 100644 --- a/docs-site/content/kagent/0.x/operations/operational-considerations.md +++ b/docs-site/content/kagent/0.x/operations/operational-considerations.md @@ -89,7 +89,7 @@ urlFile > url > bundled connection string The bundled PostgreSQL instance is deployed by default (`database.postgres.bundled.enabled: true`). The database name, username, and password are all hardcoded to `kagent`. Credentials are stored in a Kubernetes Secret. -You can customize the storage size and image of the bundled instance when you [install](/docs/kagent/introduction/installation) or upgrade kagent. +You can customize the storage size and image of the bundled instance when you [install]({{< relref "/kagent/0.x/introduction/installation" >}}) or upgrade kagent. 1. Add the bundled database settings to your Helm values file for kagent. diff --git a/docs-site/content/kagent/0.x/operations/uninstall.md b/docs-site/content/kagent/0.x/operations/uninstall.md index cca768ac..a66074fa 100644 --- a/docs-site/content/kagent/0.x/operations/uninstall.md +++ b/docs-site/content/kagent/0.x/operations/uninstall.md @@ -17,7 +17,7 @@ Remove kagent from your Kubernetes cluster using the kagent CLI or Helm. ## Uninstall with the kagent CLI -Remove kagent by using the CLI. For more options, see the [`kagent uninstall` command reference](/docs/kagent/resources/cli/kagent-uninstall). +Remove kagent by using the CLI. For more options, see the [`kagent uninstall` command reference]({{< relref "/kagent/0.x/resources/cli/kagent-uninstall" >}}). ```bash kagent uninstall diff --git a/docs-site/content/kagent/0.x/operations/upgrade.md b/docs-site/content/kagent/0.x/operations/upgrade.md index 30159929..0c7099cb 100644 --- a/docs-site/content/kagent/0.x/operations/upgrade.md +++ b/docs-site/content/kagent/0.x/operations/upgrade.md @@ -15,12 +15,12 @@ Follow these steps to upgrade kagent to the latest version and keep your cluster export NEW_VERSION= ``` -2. Read the [release notes](/docs/kagent/resources/release-notes) for the version you are upgrading to. Pay attention to any breaking changes or deprecations that might affect your configuration. +2. Read the [release notes]({{< relref "/kagent/0.x/resources/release-notes" >}}) for the version you are upgrading to. Pay attention to any breaking changes or deprecations that might affect your configuration. 3. Back up your current configuration, including the following: - Agent definitions - Any custom settings - - PostgreSQL database: You can take a snapshot now so that you have a restore point if the upgrade fails. For the database connection string, see [Database configuration](/docs/kagent/operations/operational-considerations#database-configuration). + - PostgreSQL database: You can take a snapshot now so that you have a restore point if the upgrade fails. For the database connection string, see [Database configuration]({{< relref "/kagent/0.x/operations/operational-considerations#database-configuration" >}}). ```bash pg_dump "postgres://:@:5432/" \ @@ -28,7 +28,7 @@ Follow these steps to upgrade kagent to the latest version and keep your cluster --file=kagent-pre-upgrade-snapshot.dump ``` -4. **v0.9.0 and later**: You must be running at least v0.8.0 before upgrading to v0.9.0. Check the [release notes](/docs/kagent/resources/release-notes#v09) for 0.9-specific upgrades related to database migrations and RBAC scope. +4. **v0.9.0 and later**: You must be running at least v0.8.0 before upgrading to v0.9.0. Check the [release notes]({{< relref "/kagent/0.x/resources/release-notes#v09" >}}) for 0.9-specific upgrades related to database migrations and RBAC scope. ## Upgrade kagent @@ -56,7 +56,7 @@ Follow these steps to upgrade kagent to the latest version and keep your cluster 3. Make any changes that you want by editing your `values.yaml` Helm values file or preparing `--set` flags for the upgrade commands. - > **Note**: As of [version 0.7](/docs/kagent/resources/release-notes#kmcp-installed-by-default), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. + > **Note**: As of [version 0.7]({{< relref "/kagent/0.x/resources/release-notes#kmcp-installed-by-default" >}}), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. 4. Upgrade the kagent-crds chart. @@ -171,7 +171,7 @@ For example, `v0.9.9` has migrations up to `000005_a2a_protocol_version.up.sql` export ROLLBACK_MIGRATION_VERSION= ``` -5. Reset the core track. The `github://` source references the migration files directly from the release tag without a local checkout. For the database connection string, see [Database configuration](/docs/kagent/operations/operational-considerations#database-configuration). +5. Reset the core track. The `github://` source references the migration files directly from the release tag without a local checkout. For the database connection string, see [Database configuration]({{< relref "/kagent/0.x/operations/operational-considerations#database-configuration" >}}). ```bash migrate \ -source "github://kagent-dev/kagent/go/core/pkg/migrations/core#v$CURRENT_VERSION" \ diff --git a/docs-site/content/kagent/0.x/resources/_index.md b/docs-site/content/kagent/0.x/resources/_index.md index a1fb1b51..659c77ad 100644 --- a/docs-site/content/kagent/0.x/resources/_index.md +++ b/docs-site/content/kagent/0.x/resources/_index.md @@ -5,4 +5,4 @@ weight: 7 author: kagent.dev --- -Find helpful resources and FAQs for kagent. New to kagent? Start with the [Quick Start Guide](/docs/kagent/getting-started/quickstart). +Find helpful resources and FAQs for kagent. New to kagent? Start with the [Quick Start Guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). diff --git a/docs-site/content/kagent/0.x/resources/faq.md b/docs-site/content/kagent/0.x/resources/faq.md index 9d554b22..822fa07a 100644 --- a/docs-site/content/kagent/0.x/resources/faq.md +++ b/docs-site/content/kagent/0.x/resources/faq.md @@ -8,7 +8,7 @@ author: kagent.dev ## What's the best way to get started with kagent? -The best way to get started with kagent is to follow the [quickstart guide](/docs/kagent/getting-started/quickstart). This will give you a basic understanding of how kagent works and how to use it. +The best way to get started with kagent is to follow the [quickstart guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). This will give you a basic understanding of how kagent works and how to use it. ## What differentiates kagent from other LLM frameworks? diff --git a/docs-site/content/kagent/0.x/resources/release-notes.md b/docs-site/content/kagent/0.x/resources/release-notes.md index 35c37174..fbe12d16 100644 --- a/docs-site/content/kagent/0.x/resources/release-notes.md +++ b/docs-site/content/kagent/0.x/resources/release-notes.md @@ -16,7 +16,7 @@ Review this summary of significant changes from kagent version 0.8 to v0.9. **Before you upgrade:** * You must be running at least v0.8.0 before upgrading to v0.9.0. -* Back up your PostgreSQL database before upgrading. For details on your database configuration, see the [Database configuration guide](/docs/kagent/operations/operational-considerations/#database-configuration). +* Back up your PostgreSQL database before upgrading. For details on your database configuration, see the [Database configuration guide]({{< relref "/kagent/0.x/operations/operational-considerations/#database-configuration" >}}). * The `rbac.clusterScoped` Helm value is removed. RBAC scope is now derived from `rbac.namespaces`. If you set `rbac.clusterScoped` in your Helm values, update your configuration to use `rbac.namespaces` instead. **What's included:** @@ -159,7 +159,7 @@ You can now use two Human-in-the-Loop mechanisms that can pause agent execution **Ask User** — A built-in `ask_user` tool is automatically added to every agent. Agents can pose questions to users with predefined choices (single-select, multi-select) or free-text input during execution. -For more information, see the [Human-in-the-Loop example](/docs/kagent/examples/human-in-the-loop) and the [blog post](https://kagent.dev/blog/human-in-the-loop-kagent). +For more information, see the [Human-in-the-Loop example]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) and the [blog post](https://kagent.dev/blog/human-in-the-loop-kagent). ### Agent Memory @@ -169,7 +169,7 @@ When you enable memory on an agent, it receives three additional tools: `save_me You can configure memory in the Agent CR or through the UI when you create or edit an agent by selecting an embedding model and TTL. -For more information, see [Agent Memory](/docs/kagent/concepts/agent-memory). +For more information, see [Agent Memory]({{< relref "/kagent/0.x/concepts/agent-memory" >}}). ### Go ADK Runtime @@ -186,7 +186,7 @@ spec: The Go ADK includes built-in tools: `SkillsTool`, `BashTool`, `ReadFile`, `WriteFile`, and `EditFile`. -For more information, see [Agents](/docs/kagent/concepts/agents#runtime) and the [blog post](https://kagent.dev/blog/go-vs-python-runtime). +For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#runtime" >}}) and the [blog post](https://kagent.dev/blog/go-vs-python-runtime). ### Agents as MCP Servers @@ -201,7 +201,7 @@ You can load skills from two sources. - **OCI images.** Container images containing skill files. - **Git repositories.** Clone skills directly from Git repos, with support for private repos via HTTPS token or SSH key authentication. -For more information, see [Agents](/docs/kagent/concepts/agents#git-based-skills). +For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#git-based-skills" >}}). ### Go Workspace Restructure @@ -219,13 +219,13 @@ Agent system messages now support Go `text/template` syntax. You can store commo The `kagent-builtin-prompts` ConfigMap ships with five reusable templates: `skills-usage`, `tool-usage-best-practices`, `safety-guardrails`, `kubernetes-context`, and `a2a-communication`. -For more information, see [Agents](/docs/kagent/concepts/agents#prompt-templates). +For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#prompt-templates" >}}). ### Context Management Long conversations can now be automatically compacted to stay within LLM context windows. You can configure the `context.compaction` field to enable periodic summarization of older events while preserving key information. -For more information, see [Agents](/docs/kagent/concepts/agents#context-management). +For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#context-management" >}}). ### AWS Bedrock Support @@ -252,7 +252,7 @@ SQLite support has been removed from kagent. PostgreSQL is now the only supporte **Migration:** -If you were using the default SQLite backend, no migration is needed. The bundled PostgreSQL is deployed automatically. You can optionally customize the bundled instance via `database.postgres.bundled.*` (storage size, image) as needed. See the [Database configuration guide](/docs/kagent/operations/operational-considerations/#database-configuration) for details. +If you were using the default SQLite backend, no migration is needed. The bundled PostgreSQL is deployed automatically. You can optionally customize the bundled instance via `database.postgres.bundled.*` (storage size, image) as needed. See the [Database configuration guide]({{< relref "/kagent/0.x/operations/operational-considerations/#database-configuration" >}}) for details. Note that for production deployments, use your own external PostgreSQL instance. If you already are, you can keep your `database.postgres.url` or `database.postgres.urlFile` settings as before. If your external PostgreSQL has the pgvector extension and you were using vector-based memory features, set `database.postgres.vectorEnabled: true` since the default has changed to `false`. @@ -306,7 +306,7 @@ helm upgrade --install kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \ Develop and test agents locally on your machine without needing a Kubernetes cluster. As part of this feature, the `kagent` CLI includes new commands to scaffold, build, run, and deploy agents. -For more information, see the [local development](/docs/kagent/getting-started/local-development) guide. +For more information, see the [local development]({{< relref "/kagent/0.x/getting-started/local-development" >}}) guide. ### Discovery label @@ -654,7 +654,7 @@ This change supports the new type for BYO agents. A new agent type has been added to the Agents API so that you can bring your own (BYO) agent. The agent must be written in ADK, with other frameworks under development. -BYO Agent example configuration. For more information, see the [BYO Agent](/docs/kagent/examples/a2a-byo) guide. +BYO Agent example configuration. For more information, see the [BYO Agent]({{< relref "/kagent/0.x/examples/a2a-byo" >}}) guide. ```yaml apiVersion: kagent.dev/v1alpha2 diff --git a/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md index 72f329de..7d63fbc6 100644 --- a/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md +++ b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md @@ -97,7 +97,7 @@ spec: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/kagent-bedrock ``` -If you want to use one shared ServiceAccount for multiple agents, you can also set `controller.agentDeployment.serviceAccountName` in the [Helm chart configuration](/docs/kagent/resources/helm). +If you want to use one shared ServiceAccount for multiple agents, you can also set `controller.agentDeployment.serviceAccountName` in the [Helm chart configuration]({{< relref "/kagent/0.x/resources/helm" >}}). ## Option 2: OpenAI-compatible API diff --git a/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md b/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md index 2f8edd63..40782510 100644 --- a/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md +++ b/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md @@ -248,7 +248,7 @@ spec: # No API key: use Azure Workload Identity. ``` -For the complete memory and embedding configuration and model requirements, see [Agent Memory](/docs/kagent/concepts/agent-memory). +For the complete memory and embedding configuration and model requirements, see [Agent Memory]({{< relref "/kagent/0.x/concepts/agent-memory" >}}). ## Troubleshooting diff --git a/docs-site/content/kagent/0.x/supported-providers/azure-openai.md b/docs-site/content/kagent/0.x/supported-providers/azure-openai.md index ff10dc02..b9ec49e8 100644 --- a/docs-site/content/kagent/0.x/supported-providers/azure-openai.md +++ b/docs-site/content/kagent/0.x/supported-providers/azure-openai.md @@ -66,4 +66,4 @@ Omit `apiKeySecret` and `apiKeyPassthrough` to use Azure Workload Identity. For Follow the [AKS Workload Identity deployment guide](https://learn.microsoft.com/azure/aks/workload-identity-deploy-cluster) and grant the managed identity the `Cognitive Services User` role. -The kagent pod and ServiceAccount settings are provider-independent. Follow [Configure the agent for Azure Workload Identity](/docs/kagent/supported-providers/azure-ai-foundry#configure-the-agent-for-azure-workload-identity) and set the agent's `modelConfig` to `azure-openai`. +The kagent pod and ServiceAccount settings are provider-independent. Follow [Configure the agent for Azure Workload Identity]({{< relref "/kagent/0.x/supported-providers/azure-ai-foundry#configure-the-agent-for-azure-workload-identity" >}}) and set the agent's `modelConfig` to `azure-openai`. From 9ed386215d5646dcf75ddec5aeeaf3ce0429d2ab Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 21 Aug 2026 16:28:29 -0500 Subject: [PATCH 04/70] Use the link shortcode instead of relref for internal kagent links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit relref works but isn't the convention this theme actually uses for same-product cross-links — docs-theme-extras ships a `link` shortcode for exactly this. Swap the previous relref conversion over to it. Upstream's link shortcode resolves relative to .Page.FirstSection, which lands on the product root ("/docs/kagent/") and drops the version segment — the same class of bug already fixed in navbar.html, sidebar.html, and version-banner.html. Added a local override (layouts/_shortcodes/link.html) that resolves relative to the current page's own version instead, and verified against a real Hugo build (plain links, a fragment-bearing link, and the not-in-version self-links all resolve correctly). The one cross-version link (1.x's landing page pointing back at 0.x) stays on relref, since `link` is inherently relative to the current page's own version and can't express "the other version" — relref targeting an absolute content path is the right tool for that one case. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Rachael Graham --- .../content/kagent/0.x/concepts/_index.md | 2 +- .../kagent/0.x/concepts/agent-harness.md | 6 +- .../kagent/0.x/concepts/agent-memory.md | 6 +- .../kagent/0.x/concepts/agent-substrate.md | 10 +-- .../content/kagent/0.x/concepts/agents.md | 14 ++-- .../kagent/0.x/concepts/architecture.md | 4 +- .../content/kagent/0.x/concepts/mcp-apps.md | 2 +- .../content/kagent/0.x/concepts/tools.md | 4 +- .../content/kagent/0.x/examples/a2a-agents.md | 4 +- .../content/kagent/0.x/examples/a2a-byo.md | 6 +- .../kagent/0.x/examples/agent-harness.md | 10 +-- .../kagent/0.x/examples/agent-substrate.md | 6 +- .../kagent/0.x/examples/agentgateway.md | 4 +- .../content/kagent/0.x/examples/crewai-byo.md | 6 +- .../kagent/0.x/examples/discord-a2a.md | 4 +- .../kagent/0.x/examples/langchain-byo.md | 4 +- .../content/kagent/0.x/examples/skills.md | 10 +-- .../content/kagent/0.x/examples/slack-a2a.md | 2 +- .../kagent/0.x/examples/telegram-bot.md | 2 +- .../kagent/0.x/getting-started/first-agent.md | 4 +- .../0.x/getting-started/first-mcp-tool.md | 6 +- .../0.x/getting-started/local-development.md | 4 +- .../kagent/0.x/getting-started/quickstart.md | 6 +- .../content/kagent/0.x/introduction/_index.md | 2 +- .../kagent/0.x/introduction/installation.md | 16 ++--- .../kagent/0.x/introduction/what-is-kagent.md | 4 +- .../content/kagent/0.x/not-in-version.md | 2 +- .../kagent/0.x/observability/audit-prompts.md | 2 +- .../kagent/0.x/observability/launch-ui.md | 6 +- .../kagent/0.x/observability/tracing.md | 10 +-- .../operations/operational-considerations.md | 2 +- .../kagent/0.x/operations/uninstall.md | 2 +- .../content/kagent/0.x/operations/upgrade.md | 10 +-- .../content/kagent/0.x/resources/_index.md | 2 +- docs-site/content/kagent/0.x/resources/faq.md | 2 +- .../kagent/0.x/resources/release-notes.md | 20 +++--- .../0.x/supported-providers/amazon-bedrock.md | 2 +- .../supported-providers/azure-ai-foundry.md | 2 +- .../0.x/supported-providers/azure-openai.md | 2 +- .../content/kagent/1.x/not-in-version.md | 2 +- docs-site/layouts/_shortcodes/link.html | 72 +++++++++++++++++++ 41 files changed, 179 insertions(+), 107 deletions(-) create mode 100644 docs-site/layouts/_shortcodes/link.html diff --git a/docs-site/content/kagent/0.x/concepts/_index.md b/docs-site/content/kagent/0.x/concepts/_index.md index 41b4b4f6..d195c405 100644 --- a/docs-site/content/kagent/0.x/concepts/_index.md +++ b/docs-site/content/kagent/0.x/concepts/_index.md @@ -7,4 +7,4 @@ author: kagent.dev Learn about the AI agent and kagent concepts. -The [Agents]({{< relref "/kagent/0.x/concepts/agents" >}}) page also covers [prompt templates]({{< relref "/kagent/0.x/concepts/agents#prompt-templates" >}}), [Git-based skills]({{< relref "/kagent/0.x/concepts/agents#git-based-skills" >}}), and [context management]({{< relref "/kagent/0.x/concepts/agents#context-management" >}}). For related material, see [What is kagent]({{< relref "/kagent/0.x/introduction/what-is-kagent" >}}), the [Tools Ecosystem]({{< relref "/kagent/0.x/resources/tools-ecosystem" >}}) catalog, [Human-in-the-Loop]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) configuration, and the [examples]({{< relref "/kagent/0.x/examples" >}}), which include both the Go and Python runtimes. +The [Agents]({{< link path="concepts/agents" >}}) page also covers [prompt templates]({{< link path="concepts/agents#prompt-templates" >}}), [Git-based skills]({{< link path="concepts/agents#git-based-skills" >}}), and [context management]({{< link path="concepts/agents#context-management" >}}). For related material, see [What is kagent]({{< link path="introduction/what-is-kagent" >}}), the [Tools Ecosystem]({{< link path="resources/tools-ecosystem" >}}) catalog, [Human-in-the-Loop]({{< link path="examples/human-in-the-loop" >}}) configuration, and the [examples]({{< link path="examples" >}}), which include both the Go and Python runtimes. diff --git a/docs-site/content/kagent/0.x/concepts/agent-harness.md b/docs-site/content/kagent/0.x/concepts/agent-harness.md index a5043d18..bd07c01d 100644 --- a/docs-site/content/kagent/0.x/concepts/agent-harness.md +++ b/docs-site/content/kagent/0.x/concepts/agent-harness.md @@ -5,7 +5,7 @@ weight: 4 author: kagent.dev --- -An `AgentHarness` is a Kubernetes custom resource that asks kagent to provision a long-running remote execution environment on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). It is useful when you want a managed sandbox that runs a coding agent (such as OpenClaw or Hermes) that you can chat with and connect to messaging channels, but you do not want kagent to package and run a full agent runtime inside the workload. +An `AgentHarness` is a Kubernetes custom resource that asks kagent to provision a long-running remote execution environment on [Agent Substrate]({{< link path="concepts/agent-substrate" >}}). It is useful when you want a managed sandbox that runs a coding agent (such as OpenClaw or Hermes) that you can chat with and connect to messaging channels, but you do not want kagent to package and run a full agent runtime inside the workload. `AgentHarness` resources appear alongside agents in kagent APIs and status views, but they are not the same thing as `Agent` or `SandboxAgent`. @@ -30,7 +30,7 @@ All backends use the same top-level `AgentHarness` shape: `backend`, `substrate` ## Runtime: Agent Substrate -Every `AgentHarness` runs on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). The `spec.substrate` field is required and configures the Substrate provisioning stack: +Every `AgentHarness` runs on [Agent Substrate]({{< link path="concepts/agent-substrate" >}}). The `spec.substrate` field is required and configures the Substrate provisioning stack: - `workerPoolRef` — references an existing `WorkerPool` in the harness namespace. When unset, the controller uses its configured default WorkerPool. - `snapshotsConfig` — configures where actor memory snapshots are stored. Defaults to `gs://ate-snapshots//` when unset. @@ -94,4 +94,4 @@ The API uses CEL validation to ensure Slack settings match the selected backend. ## Next steps -For enabling Agent Substrate so the controller can provision harnesses, see [Enable AgentHarness support]({{< relref "/kagent/0.x/introduction/installation#enable-agentharness-support" >}}). For complete YAML examples, including Slack token references and backend-specific Slack settings, see the [Agent Harness example]({{< relref "/kagent/0.x/examples/agent-harness" >}}). For the generated schema, see the [API reference]({{< relref "/kagent/0.x/resources/api-ref#agentharness" >}}). +For enabling Agent Substrate so the controller can provision harnesses, see [Enable AgentHarness support]({{< link path="introduction/installation#enable-agentharness-support" >}}). For complete YAML examples, including Slack token references and backend-specific Slack settings, see the [Agent Harness example]({{< link path="examples/agent-harness" >}}). For the generated schema, see the [API reference]({{< link path="resources/api-ref#agentharness" >}}). diff --git a/docs-site/content/kagent/0.x/concepts/agent-memory.md b/docs-site/content/kagent/0.x/concepts/agent-memory.md index 88db2e76..bace41e6 100644 --- a/docs-site/content/kagent/0.x/concepts/agent-memory.md +++ b/docs-site/content/kagent/0.x/concepts/agent-memory.md @@ -22,7 +22,7 @@ Agent memory provides the following capabilities. ### Install kagent with Postgres -To use memory, you must install kagent with a Postgres database that has the `pgvector` extension installed and vector enabled. For more information, see the [Database configuration]({{< relref "/kagent/0.x/operations/operational-considerations#database-configuration" >}}) section. +To use memory, you must install kagent with a Postgres database that has the `pgvector` extension installed and vector enabled. For more information, see the [Database configuration]({{< link path="operations/operational-considerations#database-configuration" >}}) section. Example Helm configuration for your own external Postgres: @@ -71,7 +71,7 @@ The embedding `ModelConfig` does not have to use the same provider as the agent' To use [Amazon Bedrock Titan embedding models](https://docs.aws.amazon.com/bedrock/latest/userguide/titan-embedding-models.html), create a `ModelConfig` with `provider: Bedrock`. -The Bedrock provider uses the standard AWS credential chain, so no API key secret is required. The agent's pod must have AWS credentials with the `bedrock:InvokeModel` permission for the chosen model. On Kubernetes, the recommended setup is [EKS IRSA on the agent ServiceAccount]({{< relref "/kagent/0.x/supported-providers/amazon-bedrock#step-3-configure-the-agent-to-use-an-iam-role" >}}). +The Bedrock provider uses the standard AWS credential chain, so no API key secret is required. The agent's pod must have AWS credentials with the `bedrock:InvokeModel` permission for the chosen model. On Kubernetes, the recommended setup is [EKS IRSA on the agent ServiceAccount]({{< link path="supported-providers/amazon-bedrock#step-3-configure-the-agent-to-use-an-iam-role" >}}). ```yaml apiVersion: kagent.dev/v1alpha2 @@ -184,5 +184,5 @@ DELETE /api/memories?agent_name=X&user_id=Y - **No per-memory deletion.** You can delete all memories for an agent, but you cannot delete individual memory entries. - **No cross-agent memory sharing.** Each agent has its own isolated memory store. You cannot share memories across agents. -- **Not pluggable.** Memory is built on the Google ADK memory implementation and cannot be swapped for an alternative memory solution (such as Cognee). However, if an alternative memory solution exposes an [MCP server]({{< relref "/kagent/0.x/concepts/tools#mcp-tools" >}}), you can add it as a tool and instruct the agent to use it instead of the built-in memory. +- **Not pluggable.** Memory is built on the Google ADK memory implementation and cannot be swapped for an alternative memory solution (such as Cognee). However, if an alternative memory solution exposes an [MCP server]({{< link path="concepts/tools#mcp-tools" >}}), you can add it as a tool and instruct the agent to use it instead of the built-in memory. diff --git a/docs-site/content/kagent/0.x/concepts/agent-substrate.md b/docs-site/content/kagent/0.x/concepts/agent-substrate.md index 8ae021dd..86c95802 100644 --- a/docs-site/content/kagent/0.x/concepts/agent-substrate.md +++ b/docs-site/content/kagent/0.x/concepts/agent-substrate.md @@ -9,8 +9,8 @@ Agent Substrate is a Kubernetes-native runtime for running AI agents and other s kagent can run workloads on Agent Substrate in two ways: -- **Declarative agents** — A declarative `Agent` describes its model, instructions, and tools (see [Agents]({{< relref "/kagent/0.x/concepts/agents" >}})). Its sandboxed variant, the [`SandboxAgent`]({{< relref "/kagent/0.x/resources/api-ref" >}}) CRD, lets you run a (Go) declarative agent on Agent Substrate. -- **AgentHarness** — The [`AgentHarness`]({{< relref "/kagent/0.x/concepts/agent-harness" >}}) CRD provisions a long-running execution environment for a coding agent (OpenClaw or Hermes). It always runs on Agent Substrate: kagent generates a per-harness `ActorTemplate` and creates an `Actor` from it on demand, referencing a `WorkerPool` for capacity. +- **Declarative agents** — A declarative `Agent` describes its model, instructions, and tools (see [Agents]({{< link path="concepts/agents" >}})). Its sandboxed variant, the [`SandboxAgent`]({{< link path="resources/api-ref" >}}) CRD, lets you run a (Go) declarative agent on Agent Substrate. +- **AgentHarness** — The [`AgentHarness`]({{< link path="concepts/agent-harness" >}}) CRD provisions a long-running execution environment for a coding agent (OpenClaw or Hermes). It always runs on Agent Substrate: kagent generates a per-harness `ActorTemplate` and creates an `Actor` from it on demand, referencing a `WorkerPool` for capacity. ## Why Agent Substrate @@ -66,11 +66,11 @@ An `AgentHarness` always runs on Agent Substrate; `spec.substrate` is required. - `snapshotsConfig` — configures where actor memory snapshots are stored. Defaults to `gs://ate-snapshots//` when unset. - `workloadImage` — overrides the default OpenClaw or Hermes sandbox image used in the generated ActorTemplate. -kagent talks to the harness over the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) so you can chat with it from the kagent UI. See the [Agent Harness concept page]({{< relref "/kagent/0.x/concepts/agent-harness" >}}) for details. +kagent talks to the harness over the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) so you can chat with it from the kagent UI. See the [Agent Harness concept page]({{< link path="concepts/agent-harness" >}}) for details. -See the [API reference]({{< relref "/kagent/0.x/resources/api-ref" >}}) for the full `AgentHarnessSubstrateSpec` schema. +See the [API reference]({{< link path="resources/api-ref" >}}) for the full `AgentHarnessSubstrateSpec` schema. ## Learn more -- [Run a declarative agent on Agent Substrate]({{< relref "/kagent/0.x/examples/agent-substrate" >}}) — end-to-end walkthrough on a kind cluster. +- [Run a declarative agent on Agent Substrate]({{< link path="examples/agent-substrate" >}}) — end-to-end walkthrough on a kind cluster. - For a deeper dive into the runtime internals, see the [Agent Substrate documentation](https://learn.agentsubstrate.dev/). diff --git a/docs-site/content/kagent/0.x/concepts/agents.md b/docs-site/content/kagent/0.x/concepts/agents.md index f366ea08..474768cf 100644 --- a/docs-site/content/kagent/0.x/concepts/agents.md +++ b/docs-site/content/kagent/0.x/concepts/agents.md @@ -24,7 +24,7 @@ Your responses should be clear and concise; you should provide helpful informati Instructions are an important part of the agent's behavior. They define the agent's role and capabilities and help the agent understand its environment and the tasks it can perform. -Writing good instructions is an art and a science. It requires a good understanding of the task at hand, the tools available, and the user's needs. In order to make it easier to write good instructions, we've created a [system prompt tutorial]({{< relref "/kagent/0.x/getting-started/system-prompts" >}}) that can help you get started. +Writing good instructions is an art and a science. It requires a good understanding of the task at hand, the tools available, and the user's needs. In order to make it easier to write good instructions, we've created a [system prompt tutorial]({{< link path="getting-started/system-prompts" >}}) that can help you get started. ### Prompt templates @@ -98,7 +98,7 @@ kagent comes with a set of built-in tools that you can use to interact with your kagent supports Human-in-the-Loop (HITL) to keep humans in control of agent actions. You can require user approval before an agent executes sensitive tools, and agents can ask users questions when they need clarification. -For a hands-on tutorial that walks through setting up HITL with tool approval and the `ask_user` tool, see the [Human-in-the-Loop example]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}). +For a hands-on tutorial that walks through setting up HITL with tool approval and the `ask_user` tool, see the [Human-in-the-Loop example]({{< link path="examples/human-in-the-loop" >}}). ### Tool approval @@ -226,7 +226,7 @@ When creating skills for your agents, consider the following best practices. Age 4. **Align with tools**: Ensure your skills align with the tools available to the agent. If you have a skill that centers around writing docs in markdown, you might want to align it with the `write-markdown` tool (as opposed to a `generate-pdf` tool). 5. **Keep skills focused**: Each skill should have a clear, focused purpose. For example, a document-generating skill might be too broad, but a skill that focuses on creating a specific type of document, such as a `.docx` file or alternatively a genre like a getting started guide, might be more appropriate. -To learn more about using skills in your agents, see the [Skills example guide]({{< relref "/kagent/0.x/examples/skills" >}}). +To learn more about using skills in your agents, see the [Skills example guide]({{< link path="examples/skills" >}}). ## Runtime @@ -263,7 +263,7 @@ For more benchmarks and details, see the [Go vs Python runtime blog post](https: Your agents can save and retrieve relevant context across conversations using vector similarity search. When you enable memory on an agent, it receives three additional tools (`save_memory`, `load_memory`, `prefetch_memory`) and automatically extracts key information every 5th user message. -For configuration details, supported storage backends, API endpoints, and limitations, see [Agent Memory]({{< relref "/kagent/0.x/concepts/agent-memory" >}}). +For configuration details, supported storage backends, API endpoints, and limitations, see [Agent Memory]({{< link path="concepts/agent-memory" >}}). ## Context Management @@ -292,9 +292,9 @@ Compaction removes older conversation events to free up space in the context win ## Sandboxed Agents -You can run a declarative agent in an isolated sandbox by creating a `SandboxAgent` resource instead of a regular `Agent`. A `SandboxAgent` runs on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}): the kagent controller runs it as a gVisor-sandboxed actor instead of a Deployment, snapshotting it to object storage when idle and rehydrating it on demand. The spec mirrors the `Agent` spec, with a few constraints: sandboxed agents always use the Go ADK runtime, and `spec.skills` and `BYO` agents are not supported. Configure substrate placement with the optional `spec.substrate` field (for example, `workerPoolRef`). +You can run a declarative agent in an isolated sandbox by creating a `SandboxAgent` resource instead of a regular `Agent`. A `SandboxAgent` runs on [Agent Substrate]({{< link path="concepts/agent-substrate" >}}): the kagent controller runs it as a gVisor-sandboxed actor instead of a Deployment, snapshotting it to object storage when idle and rehydrating it on demand. The spec mirrors the `Agent` spec, with a few constraints: sandboxed agents always use the Go ADK runtime, and `spec.skills` and `BYO` agents are not supported. Configure substrate placement with the optional `spec.substrate` field (for example, `workerPoolRef`). -For setup steps, see the [Agent Substrate example]({{< relref "/kagent/0.x/examples/agent-substrate" >}}). +For setup steps, see the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). ## Agents as Tools @@ -330,4 +330,4 @@ Here's how you could reference an existing agent (`promql-agent`) as a tool: A2A-enabled agents are automatically exposed as an MCP server on the kagent controller. The MCP endpoint is available at `/mcp` on the same port as the A2A endpoint (default 8083). -For more information, see the [MCP tools]({{< relref "/kagent/0.x/examples/agents-mcp" >}}) guide. +For more information, see the [MCP tools]({{< link path="examples/agents-mcp" >}}) guide. diff --git a/docs-site/content/kagent/0.x/concepts/architecture.md b/docs-site/content/kagent/0.x/concepts/architecture.md index 0f38b86b..7d40b4a5 100644 --- a/docs-site/content/kagent/0.x/concepts/architecture.md +++ b/docs-site/content/kagent/0.x/concepts/architecture.md @@ -24,7 +24,7 @@ The kagent engine is the core component of kagent. It runs the agent's conversat - **Python ADK** (default) — Built on top of the [Google ADK](https://google.github.io/adk-docs/) framework. Supports Google ADK-native features and integrations with CrewAI, LangGraph, and OpenAI frameworks. - **Go ADK** — A native Go implementation that provides faster startup (~2 seconds vs ~15 seconds) and lower resource consumption. -Select the runtime by setting the `runtime` field in the agent spec (e.g., `runtime: go`). Both runtimes support MCP tools, HITL, and agent memory. For more details, see [Agents]({{< relref "/kagent/0.x/concepts/agents#runtime" >}}). +Select the runtime by setting the `runtime` field in the agent spec (e.g., `runtime: go`). Both runtimes support MCP tools, HITL, and agent memory. For more details, see [Agents]({{< link path="concepts/agents#runtime" >}}). For more information on the Google ADK framework: @@ -63,5 +63,5 @@ kagent dashboard provides a web interface for managing and working with AI agent ## Next Steps -- Try [building your own agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) +- Try [building your own agent]({{< link path="getting-started/first-agent" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) diff --git a/docs-site/content/kagent/0.x/concepts/mcp-apps.md b/docs-site/content/kagent/0.x/concepts/mcp-apps.md index d1bf1044..1668554e 100644 --- a/docs-site/content/kagent/0.x/concepts/mcp-apps.md +++ b/docs-site/content/kagent/0.x/concepts/mcp-apps.md @@ -60,4 +60,4 @@ A complete example, including a demo agent, is available in the kagent repositor - [MCP Apps extension](https://github.com/modelcontextprotocol/ext-apps) - [Model Context Protocol](https://modelcontextprotocol.io/) -- [Tools in kagent]({{< relref "/kagent/0.x/concepts/tools" >}}) +- [Tools in kagent]({{< link path="concepts/tools" >}}) diff --git a/docs-site/content/kagent/0.x/concepts/tools.md b/docs-site/content/kagent/0.x/concepts/tools.md index 6573a194..0ea813fe 100644 --- a/docs-site/content/kagent/0.x/concepts/tools.md +++ b/docs-site/content/kagent/0.x/concepts/tools.md @@ -11,7 +11,7 @@ kagent comes with a set of built-in tools that you can use to interact with your ## Built-in Tools -You can check out the full list of [built-in tools](https://kagent.dev/tools), or see the [Tools Ecosystem]({{< relref "/kagent/0.x/resources/tools-ecosystem" >}}) reference for a detailed catalog of tools organized by MCP server. +You can check out the full list of [built-in tools](https://kagent.dev/tools), or see the [Tools Ecosystem]({{< link path="resources/tools-ecosystem" >}}) reference for a detailed catalog of tools organized by MCP server. The built-in tools are meant as a good starting point for any agents running in kubernetes, however we don't envision them covering all possible use-cases, so we support multiple tool extension points to allow you to bring in your own tools. @@ -78,7 +78,7 @@ MCP stands for [Model Context Protocol](https://modelcontextprotocol.io/introduc ### MCP Apps -Some MCP tools ship an interactive UI with their results. kagent detects these tools automatically and renders their widgets inline in the chat, and the dashboard lists them alongside a server's regular tools so you can test them directly. See [MCP Apps]({{< relref "/kagent/0.x/concepts/mcp-apps" >}}) for details. +Some MCP tools ship an interactive UI with their results. kagent detects these tools automatically and renders their widgets inline in the chat, and the dashboard lists them alongside a server's regular tools so you can test them directly. See [MCP Apps]({{< link path="concepts/mcp-apps" >}}) for details. ## HTTP Tools diff --git a/docs-site/content/kagent/0.x/examples/a2a-agents.md b/docs-site/content/kagent/0.x/examples/a2a-agents.md index 272cd49f..b41fd043 100644 --- a/docs-site/content/kagent/0.x/examples/a2a-agents.md +++ b/docs-site/content/kagent/0.x/examples/a2a-agents.md @@ -12,7 +12,7 @@ Let's look at how this works in kagent! ## Prerequisites -Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. +Install kagent by following the [quick start]({{< link path="getting-started/quickstart" >}}) guide. ## Creating an AI agent that supports A2A @@ -135,7 +135,7 @@ You can invoke the agent in several ways, including the kagent dashboard, kagent ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `k8s-a2a-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. +Launch the dashboard with `kagent dashboard`, find your `k8s-a2a-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< link path="getting-started/first-agent" >}}) guide. ### kagent CLI diff --git a/docs-site/content/kagent/0.x/examples/a2a-byo.md b/docs-site/content/kagent/0.x/examples/a2a-byo.md index 2000a7f3..0bfc740e 100644 --- a/docs-site/content/kagent/0.x/examples/a2a-byo.md +++ b/docs-site/content/kagent/0.x/examples/a2a-byo.md @@ -6,13 +6,13 @@ weight: 1 author: kagent.dev --- -Bring your own custom agents. This example uses the [Agent Development Kit (ADK)](https://google.github.io/adk-docs/), but you can also try out the [LangGraph guide]({{< relref "/kagent/0.x/examples/langchain-byo/" >}}). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. +Bring your own custom agents. This example uses the [Agent Development Kit (ADK)](https://google.github.io/adk-docs/), but you can also try out the [LangGraph guide]({{< link path="examples/langchain-byo/" >}}). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. Unlike declarative agents that are defined by kagent resources with components such as system instructions, models, and tools written inline, these BYO agents give you full control over agent logic. If you have your own agent, no need to decompose its functions into separate kagent resources. kagent can invoke your agent directly through the A2A protocol. ## Prerequisites -1. Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. +1. Install kagent by following the [quick start]({{< link path="getting-started/quickstart" >}}) guide. 2. Use [Google ADK](https://github.com/google/adk-python) version 1.22.1 or later. ## Building a custom agent @@ -162,7 +162,7 @@ You can invoke the agent in several ways, including the kagent dashboard, kagent ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `basic-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. +Launch the dashboard with `kagent dashboard`, find your `basic-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< link path="getting-started/first-agent" >}}) guide. ![BYO Agent](/images/byo-basic.png "Chat with your basic agent") diff --git a/docs-site/content/kagent/0.x/examples/agent-harness.md b/docs-site/content/kagent/0.x/examples/agent-harness.md index 4be4b4f1..98e27e10 100644 --- a/docs-site/content/kagent/0.x/examples/agent-harness.md +++ b/docs-site/content/kagent/0.x/examples/agent-harness.md @@ -5,14 +5,14 @@ weight: 8 author: kagent.dev --- -`AgentHarness` creates a long-running remote execution environment on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). Unlike an `Agent` or `SandboxAgent`, it does not package a kagent runtime into the workload. The backend provisions a sandbox that runs a coding agent (OpenClaw or Hermes), which you can chat with from the kagent UI and wire into messaging channels. +`AgentHarness` creates a long-running remote execution environment on [Agent Substrate]({{< link path="concepts/agent-substrate" >}}). Unlike an `Agent` or `SandboxAgent`, it does not package a kagent runtime into the workload. The backend provisions a sandbox that runs a coding agent (OpenClaw or Hermes), which you can chat with from the kagent UI and wire into messaging channels. Use `AgentHarness` when you want kagent to manage the lifecycle of an OpenClaw or Hermes sandbox and surface it in the kagent API/UI alongside regular agents. ## Before you begin -1. Install kagent v0.9.9 or later by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. -2. Install Agent Substrate and enable the substrate integration in kagent. For Helm-based setup instructions, see [Enable AgentHarness support]({{< relref "/kagent/0.x/introduction/installation#enable-agentharness-support" >}}) and the [Agent Substrate example]({{< relref "/kagent/0.x/examples/agent-substrate" >}}). +1. Install kagent v0.9.9 or later by following the [quick start]({{< link path="getting-started/quickstart" >}}) guide. +2. Install Agent Substrate and enable the substrate integration in kagent. For Helm-based setup instructions, see [Enable AgentHarness support]({{< link path="introduction/installation#enable-agentharness-support" >}}) and the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). When the substrate integration is not enabled, the controller cannot provision AgentHarness resources. @@ -204,7 +204,7 @@ Once the harness is `Ready`, it appears in the kagent UI alongside your other ag 2. Open [http://localhost:8001](http://localhost:8001), select your harness (for example `kagent/openclaw-shell`) from the Agents list, and send a message. -The first chat connection creates a shared Substrate actor from the harness template; every chat is multiplexed as an ACP session inside that actor. You see streamed tool activity, and any tool-approval prompts the backend raises are surfaced through kagent's [human-in-the-loop]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) flow. +The first chat connection creates a shared Substrate actor from the harness template; every chat is multiplexed as an ACP session inside that actor. You see streamed tool activity, and any tool-approval prompts the backend raises are surfaced through kagent's [human-in-the-loop]({{< link path="examples/human-in-the-loop" >}}) flow. ## Troubleshooting @@ -217,4 +217,4 @@ If the harness is not accepted or ready, check these common causes. - A Slack channel has the wrong backend settings, such as `slack.hermes` on an OpenClaw harness or `slack.openclaw` on a Hermes harness. - A Slack credential uses neither `value` nor `valueFrom`, or sets both. -For the complete generated schema, see the [API reference]({{< relref "/kagent/0.x/resources/api-ref#agentharness" >}}). +For the complete generated schema, see the [API reference]({{< link path="resources/api-ref#agentharness" >}}). diff --git a/docs-site/content/kagent/0.x/examples/agent-substrate.md b/docs-site/content/kagent/0.x/examples/agent-substrate.md index 53af1c5f..ffd6acc4 100644 --- a/docs-site/content/kagent/0.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/0.x/examples/agent-substrate.md @@ -13,7 +13,7 @@ By the end, you will have: - kagent v0.9.7 or later installed with the substrate integration enabled. Earlier kagent releases do not include the controller wiring that lets a `SandboxAgent` target substrate. - A `SandboxAgent` running on substrate, reachable from the kagent UI. -For background on what substrate is and how it differs from a per-pod agent runtime, see the [Agent Substrate concept page]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). This guide does not cover the `AgentHarness` path on substrate. +For background on what substrate is and how it differs from a per-pod agent runtime, see the [Agent Substrate concept page]({{< link path="concepts/agent-substrate" >}}). This guide does not cover the `AgentHarness` path on substrate. ## Before you begin @@ -213,5 +213,5 @@ kind delete cluster --name kagent-substrate ## Next steps -- [Agent Substrate concept page]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}) — runtime architecture and how snapshots, actors, and worker pools fit together. -- [AgentHarness]({{< relref "/kagent/0.x/examples/agent-harness" >}}) — provision long-running OpenClaw and Hermes coding-agent sandboxes on Agent Substrate and chat with them over ACP. +- [Agent Substrate concept page]({{< link path="concepts/agent-substrate" >}}) — runtime architecture and how snapshots, actors, and worker pools fit together. +- [AgentHarness]({{< link path="examples/agent-harness" >}}) — provision long-running OpenClaw and Hermes coding-agent sandboxes on Agent Substrate and chat with them over ACP. diff --git a/docs-site/content/kagent/0.x/examples/agentgateway.md b/docs-site/content/kagent/0.x/examples/agentgateway.md index 196be566..801d69f6 100644 --- a/docs-site/content/kagent/0.x/examples/agentgateway.md +++ b/docs-site/content/kagent/0.x/examples/agentgateway.md @@ -10,7 +10,7 @@ As your kagent deployment grows, you might need governance over how your agents ## Prerequisites -1. A running kagent installation. If you haven't installed kagent yet, follow the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide first. +1. A running kagent installation. If you haven't installed kagent yet, follow the [quick start]({{< link path="getting-started/quickstart" >}}) guide first. 2. Follow the [agentgateway installation guide](https://agentgateway.dev/docs/kubernetes/latest/quickstart/install/) to install agentgateway in your cluster. 3. Set up an LLM provider with agentgateway. This guide uses [the Ollama setup](https://agentgateway.dev/docs/kubernetes/latest/llm/providers/ollama/) as an example. @@ -86,7 +86,7 @@ With agentgateway installed, point kagent at the agentgateway proxy instead of d {{< /tab >}} {{< /tabs >}} -4. [Open the kagent UI]({{< relref "/kagent/0.x/observability/launch-ui" >}}). +4. [Open the kagent UI]({{< link path="observability/launch-ui" >}}). 5. Start a chat with an agent such as `k8s-agent` to confirm that requests flow through agentgateway. ![kagent default k8s-agent UI](/images/kagent-default-k8s-agent.png "kagent default k8s-agent UI") diff --git a/docs-site/content/kagent/0.x/examples/crewai-byo.md b/docs-site/content/kagent/0.x/examples/crewai-byo.md index a0f763b9..5033e7d8 100644 --- a/docs-site/content/kagent/0.x/examples/crewai-byo.md +++ b/docs-site/content/kagent/0.x/examples/crewai-byo.md @@ -6,13 +6,13 @@ weight: 1 author: kagent.dev --- -Bring your own custom agents. This example uses [CrewAI](https://www.crewai.com/), but you can also try out the [ADK guide]({{< relref "/kagent/0.x/examples/a2a-byo/" >}}) or [LangGraph guide]({{< relref "/kagent/0.x/examples/langchain-byo/" >}}). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. +Bring your own custom agents. This example uses [CrewAI](https://www.crewai.com/), but you can also try out the [ADK guide]({{< link path="examples/a2a-byo/" >}}) or [LangGraph guide]({{< link path="examples/langchain-byo/" >}}). Such frameworks give you more control over the agent behavior and are well-suited for complex workflows and integration with external systems and APIs. Unlike declarative agents that are defined by kagent resources with components such as system instructions, models, and tools written inline, these BYO agents give you full control over agent logic. If you have your own agent, no need to decompose its functions into separate kagent resources. kagent can invoke your agent directly through the A2A protocol. ## Prerequisites -Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. +Install kagent by following the [quick start]({{< link path="getting-started/quickstart" >}}) guide. ## Building a custom agent @@ -148,7 +148,7 @@ You can invoke the agent in several ways, including the kagent dashboard, kagent ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `research-crew`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. +Launch the dashboard with `kagent dashboard`, find your `research-crew`, and start chatting. For complete steps, see the [Your First Agent]({{< link path="getting-started/first-agent" >}}) guide. ### kagent CLI diff --git a/docs-site/content/kagent/0.x/examples/discord-a2a.md b/docs-site/content/kagent/0.x/examples/discord-a2a.md index 7ef4e775..5dc298f3 100644 --- a/docs-site/content/kagent/0.x/examples/discord-a2a.md +++ b/docs-site/content/kagent/0.x/examples/discord-a2a.md @@ -8,7 +8,7 @@ author: kagent.dev }; -kagent enables you to create AI agents that run inside your Kubernetes cluster. They can access a variety of [built-in tools]({{< relref "/kagent/0.x/concepts/tools" >}}) and use other [external tools via MCP]({{< relref "/kagent/0.x/examples/documentation" >}}). +kagent enables you to create AI agents that run inside your Kubernetes cluster. They can access a variety of [built-in tools]({{< link path="concepts/tools" >}}) and use other [external tools via MCP]({{< link path="examples/documentation" >}}). This guide shows how to connect a Discord bot to one of your agents using the A2A protocol, enabling natural conversations and command execution inside Discord. @@ -129,7 +129,7 @@ When a message is received, it’s sent to the A2A endpoint (`KAGENT_A2A_URL`), ## Agent Setup -If you haven’t deployed your agent yet, follow the instructions in [Deploying an Agent]({{< relref "/kagent/0.x/examples/slack-a2a#deploying-an-agent" >}}). You can reuse the same agent across Slack and Discord integrations. +If you haven’t deployed your agent yet, follow the instructions in [Deploying an Agent]({{< link path="examples/slack-a2a#deploying-an-agent" >}}). You can reuse the same agent across Slack and Discord integrations. Be sure to port-forward your agent if running locally: diff --git a/docs-site/content/kagent/0.x/examples/langchain-byo.md b/docs-site/content/kagent/0.x/examples/langchain-byo.md index b5a8ea39..1a898790 100644 --- a/docs-site/content/kagent/0.x/examples/langchain-byo.md +++ b/docs-site/content/kagent/0.x/examples/langchain-byo.md @@ -10,7 +10,7 @@ You can bring your own LangGraph agent to kagent by configuring the kagentCheckp ## Prerequisites -Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. +Install kagent by following the [quick start]({{< link path="getting-started/quickstart" >}}) guide. ## Building a LangGraph agent @@ -125,7 +125,7 @@ You can invoke the agent through the kagent dashboard or kagent CLI. ### Dashboard -Launch the dashboard with `kagent dashboard`, find your `langgraph-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. +Launch the dashboard with `kagent dashboard`, find your `langgraph-agent`, and start chatting. For complete steps, see the [Your First Agent]({{< link path="getting-started/first-agent" >}}) guide. ![BYO Agent](/images/byo-langgraph.png "Chat with your LangGraph agent") diff --git a/docs-site/content/kagent/0.x/examples/skills.md b/docs-site/content/kagent/0.x/examples/skills.md index 5fcab664..897cf325 100644 --- a/docs-site/content/kagent/0.x/examples/skills.md +++ b/docs-site/content/kagent/0.x/examples/skills.md @@ -15,9 +15,9 @@ In this guide, you learn how to add container-based skills to your agents in kag ## Before you begin -1. Install kagent by following the [quick start]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. +1. Install kagent by following the [quick start]({{< link path="getting-started/quickstart" >}}) guide. -2. Review the concepts of [agents and skills]({{< relref "/kagent/0.x/concepts/agents" >}}) in kagent. +2. Review the concepts of [agents and skills]({{< link path="concepts/agents" >}}) in kagent. ## Container-based skills @@ -372,6 +372,6 @@ When you're done, you can clean up the resources that you created. ## Next steps -- Learn more about [agents]({{< relref "/kagent/0.x/concepts/agents" >}}) and their components -- Explore [tools]({{< relref "/kagent/0.x/concepts/tools" >}}) available in kagent -- Check out other [examples]({{< relref "/kagent/0.x/examples" >}}) to see different agent configurations +- Learn more about [agents]({{< link path="concepts/agents" >}}) and their components +- Explore [tools]({{< link path="concepts/tools" >}}) available in kagent +- Check out other [examples]({{< link path="examples" >}}) to see different agent configurations diff --git a/docs-site/content/kagent/0.x/examples/slack-a2a.md b/docs-site/content/kagent/0.x/examples/slack-a2a.md index 22e63fc9..82b6f922 100644 --- a/docs-site/content/kagent/0.x/examples/slack-a2a.md +++ b/docs-site/content/kagent/0.x/examples/slack-a2a.md @@ -8,7 +8,7 @@ author: kagent.dev }; -kagent enables you to create AI agents that run inside your Kubernetes cluster. They have access to a variety of [built-in tools]({{< relref "/kagent/0.x/concepts/tools" >}}) like Kubernetes, Istio, Grafana, Prometheus, Argo and can be extended with any other tools [using MCP]({{< relref "/kagent/0.x/examples/documentation" >}}). +kagent enables you to create AI agents that run inside your Kubernetes cluster. They have access to a variety of [built-in tools]({{< link path="concepts/tools" >}}) like Kubernetes, Istio, Grafana, Prometheus, Argo and can be extended with any other tools [using MCP]({{< link path="examples/documentation" >}}). ![Slack - A2A - MCP - kagent](/images/slack-a2a/slack-a2a-kagent.png) diff --git a/docs-site/content/kagent/0.x/examples/telegram-bot.md b/docs-site/content/kagent/0.x/examples/telegram-bot.md index bb3af6c3..c145d0f9 100644 --- a/docs-site/content/kagent/0.x/examples/telegram-bot.md +++ b/docs-site/content/kagent/0.x/examples/telegram-bot.md @@ -98,7 +98,7 @@ spec: EOF ``` -Notice `requireApproval` — anything destructive (deleting resources, applying manifests, Helm upgrades) goes through [Human-in-the-Loop]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) approval in the kagent UI first. Nobody's accidentally nuking prod from a Telegram chat. +Notice `requireApproval` — anything destructive (deleting resources, applying manifests, Helm upgrades) goes through [Human-in-the-Loop]({{< link path="examples/human-in-the-loop" >}}) approval in the kagent UI first. Nobody's accidentally nuking prod from a Telegram chat. Verify it's working: diff --git a/docs-site/content/kagent/0.x/getting-started/first-agent.md b/docs-site/content/kagent/0.x/getting-started/first-agent.md index 3e2f4a10..308cd9c4 100644 --- a/docs-site/content/kagent/0.x/getting-started/first-agent.md +++ b/docs-site/content/kagent/0.x/getting-started/first-agent.md @@ -10,7 +10,7 @@ In this guide, you'll learn how to create your first AI agent using the kagent d ## Prerequisites -Before you begin make sure you have a Kubernetes cluster with kagent installed. If you haven't done this yet, check out the [installation guide]({{< relref "/kagent/0.x/introduction/installation" >}}) or the [quickstart guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). +Before you begin make sure you have a Kubernetes cluster with kagent installed. If you haven't done this yet, check out the [installation guide]({{< link path="introduction/installation" >}}) or the [quickstart guide]({{< link path="getting-started/quickstart" >}}). We'll be working in the kagent dashboard, so use the kagent CLI to open the dashboard: @@ -90,5 +90,5 @@ Now that you set up all the details for your agent, you're ready to finish creat ## Next Steps -- Learn more about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) +- Learn more about [Core Concepts]({{< link path="concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) diff --git a/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md b/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md index 7781acd1..1c6cd1eb 100644 --- a/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md +++ b/docs-site/content/kagent/0.x/getting-started/first-mcp-tool.md @@ -12,7 +12,7 @@ In this guide, you'll learn how to add an MCP tool to your first AI agent using ## Prerequisites -1. Install kagent in a Kubernetes cluster. If you haven't done this yet, check out the [installation guide]({{< relref "/kagent/0.x/introduction/installation" >}}) or the [quickstart guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). +1. Install kagent in a Kubernetes cluster. If you haven't done this yet, check out the [installation guide]({{< link path="introduction/installation" >}}) or the [quickstart guide]({{< link path="getting-started/quickstart" >}}). 2. Make sure that you have the kagent custom resources in your cluster. @@ -22,7 +22,7 @@ In this guide, you'll learn how to add an MCP tool to your first AI agent using ## Creating an agent -To create an agent, follow the [Your First Agent guide]({{< relref "/kagent/0.x/getting-started/first-agent" >}}). +To create an agent, follow the [Your First Agent guide]({{< link path="getting-started/first-agent" >}}). Take a look at the Agent custom resource for your first agent, such as with the following command. @@ -177,5 +177,5 @@ Now let's try our agent out with the fetch tool. ## Next Steps -- Learn more about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) +- Learn more about [Core Concepts]({{< link path="concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) diff --git a/docs-site/content/kagent/0.x/getting-started/local-development.md b/docs-site/content/kagent/0.x/getting-started/local-development.md index da2ec1b8..47c3e9cd 100644 --- a/docs-site/content/kagent/0.x/getting-started/local-development.md +++ b/docs-site/content/kagent/0.x/getting-started/local-development.md @@ -6,13 +6,13 @@ weight: 4 author: kagent.dev --- -In this guide, you'll learn how to develop, build and run an AI agent locally using kagent CLI, without a Kubernetes cluster. This guide is meant for developers familiar with Python. You can also create declarative agents without writing a single line of code, by following the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. +In this guide, you'll learn how to develop, build and run an AI agent locally using kagent CLI, without a Kubernetes cluster. This guide is meant for developers familiar with Python. You can also create declarative agents without writing a single line of code, by following the [Your First Agent]({{< link path="getting-started/first-agent" >}}) guide. ## Prerequisites Before you begin make sure you have the following prerequisites installed: -- [kagent CLI]({{< relref "/kagent/0.x/introduction/installation" >}}) +- [kagent CLI]({{< link path="introduction/installation" >}}) - [Python](https://www.python.org/) - [Docker](https://www.docker.com/) and [Docker compose](https://docs.docker.com/compose/) diff --git a/docs-site/content/kagent/0.x/getting-started/quickstart.md b/docs-site/content/kagent/0.x/getting-started/quickstart.md index cd91017f..6f0c76ae 100644 --- a/docs-site/content/kagent/0.x/getting-started/quickstart.md +++ b/docs-site/content/kagent/0.x/getting-started/quickstart.md @@ -141,12 +141,12 @@ Interact with kagent in your terminal. ## Next Steps -- Create your [first agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) -- Learn about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) +- Create your [first agent]({{< link path="getting-started/first-agent" >}}) +- Learn about [Core Concepts]({{< link path="concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) ## Need Help? - Visit our [GitHub repository](https://github.com/kagent-dev/kagent) - Ask a question on [Discord](https://discord.gg/Fu3k65f2k3) -- Check out the [FAQ]({{< relref "/kagent/0.x/resources/faq" >}}) \ No newline at end of file +- Check out the [FAQ]({{< link path="resources/faq" >}}) \ No newline at end of file diff --git a/docs-site/content/kagent/0.x/introduction/_index.md b/docs-site/content/kagent/0.x/introduction/_index.md index 1f86319e..119de4c9 100644 --- a/docs-site/content/kagent/0.x/introduction/_index.md +++ b/docs-site/content/kagent/0.x/introduction/_index.md @@ -5,4 +5,4 @@ weight: 1 author: kagent.dev --- -Welcome to kagent! Start here to understand what kagent is and how to install it. To follow the roadmap or help improve kagent, see [Community and Contributing]({{< relref "/kagent/0.x/resources/community" >}}). +Welcome to kagent! Start here to understand what kagent is and how to install it. To follow the roadmap or help improve kagent, see [Community and Contributing]({{< link path="resources/community" >}}). diff --git a/docs-site/content/kagent/0.x/introduction/installation.md b/docs-site/content/kagent/0.x/introduction/installation.md index 7aa93038..8eba5679 100644 --- a/docs-site/content/kagent/0.x/introduction/installation.md +++ b/docs-site/content/kagent/0.x/introduction/installation.md @@ -5,13 +5,13 @@ weight: 1 author: kagent.dev --- -This guide covers ways to install and configure kagent in your Kubernetes environment. For a quick setup, check out our [Quick Start Guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). For enterpise offerings, check out [Solo Enterprise for kagent]({{< relref "/kagent/0.x/introduction/what-is-kagent/#enterprise-distributions" >}}). +This guide covers ways to install and configure kagent in your Kubernetes environment. For a quick setup, check out our [Quick Start Guide]({{< link path="getting-started/quickstart" >}}). For enterpise offerings, check out [Solo Enterprise for kagent]({{< link path="introduction/what-is-kagent/#enterprise-distributions" >}}). ## Installation Methods Install kagent by using the kagent CLI or Helm. -> **Note**: As of [version 0.7]({{< relref "/kagent/0.x/resources/release-notes#kmcp-installed-by-default" >}}), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. +> **Note**: As of [version 0.7]({{< link path="resources/release-notes#kmcp-installed-by-default" >}}), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. ### Using kagent CLI (Recommended) @@ -66,7 +66,7 @@ Another way to install kagent is using Helm. --create-namespace ``` -2. Optionally prepare a Helm values file or `--set` flags to use for your installation. For example, you might set up your default LLM provider, or configure resource requests and limits or disable the default agents. For options, refer to the [Helm reference docs]({{< relref "/kagent/0.x/resources/helm" >}}). +2. Optionally prepare a Helm values file or `--set` flags to use for your installation. For example, you might set up your default LLM provider, or configure resource requests and limits or disable the default agents. For options, refer to the [Helm reference docs]({{< link path="resources/helm" >}}). {{< tabs >}} {{< tab name="OpenAI" >}} @@ -185,7 +185,7 @@ Review the following advanced configuration options that you might want to set u ### Enable AgentHarness support -`AgentHarness` resources run on [Agent Substrate]({{< relref "/kagent/0.x/concepts/agent-substrate" >}}). To enable them, install Agent Substrate and turn on the substrate integration in kagent. When the integration is disabled, the controller cannot provision AgentHarness resources. +`AgentHarness` resources run on [Agent Substrate]({{< link path="concepts/agent-substrate" >}}). To enable them, install Agent Substrate and turn on the substrate integration in kagent. When the integration is disabled, the controller cannot provision AgentHarness resources. 1. Install Agent Substrate (CRDs, then the control plane and data plane). @@ -228,11 +228,11 @@ Review the following advanced configuration options that you might want to set u Pin the kagent chart to v0.9.9 or later — earlier versions do not include the `controller.substrate.*` and `substrateWorkerPool.*` values. -For an end-to-end walkthrough on a kind cluster, see the [Agent Substrate example]({{< relref "/kagent/0.x/examples/agent-substrate" >}}). For more information about creating harness resources, see [Agent Harness]({{< relref "/kagent/0.x/examples/agent-harness" >}}). +For an end-to-end walkthrough on a kind cluster, see the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). For more information about creating harness resources, see [Agent Harness]({{< link path="examples/agent-harness" >}}). ### Database configuration -For production environments, set up kagent with an external PostgreSQL instance. For more information, see the [Database configuration guide]({{< relref "/kagent/0.x/operations/operational-considerations/#database-configuration" >}}). +For production environments, set up kagent with an external PostgreSQL instance. For more information, see the [Database configuration guide]({{< link path="operations/operational-considerations/#database-configuration" >}}). ### Configure controller environment variables @@ -303,9 +303,9 @@ This example loads all key-value pairs from the `controller-secrets` secret as e ## Uninstallation -Refer to the [Uninstall]({{< relref "/kagent/0.x/operations/uninstall" >}}) guide. +Refer to the [Uninstall]({{< link path="operations/uninstall" >}}) guide. ## Next Steps -- [Create your first agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) +- [Create your first agent]({{< link path="getting-started/first-agent" >}}) - [Explore available agents](https://kagent.dev/agents) diff --git a/docs-site/content/kagent/0.x/introduction/what-is-kagent.md b/docs-site/content/kagent/0.x/introduction/what-is-kagent.md index c61b9728..72dc0706 100644 --- a/docs-site/content/kagent/0.x/introduction/what-is-kagent.md +++ b/docs-site/content/kagent/0.x/introduction/what-is-kagent.md @@ -62,7 +62,7 @@ Check out [Solo Enterprise for kagent](https://www.solo.io/products/kagent-enter ## Getting Started -To start using kagent in your environment, check out the [Quick Start Guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}) guide. For a deeper understanding of how kagent works, refer to the [kagent architecture]({{< relref "/kagent/0.x/concepts/architecture" >}}). +To start using kagent in your environment, check out the [Quick Start Guide]({{< link path="getting-started/quickstart" >}}) guide. For a deeper understanding of how kagent works, refer to the [kagent architecture]({{< link path="concepts/architecture" >}}). Ready to contribute? Visit our [Github repository](https://github.com/kagent-dev) to learn how you can help expand the ecosystem of cloud-native AI agents. @@ -71,5 +71,5 @@ Ready to contribute? Visit our [Github repository](https://github.com/kagent-dev Join the kagent community: - Explore our repositories on [GitHub](https://github.com/kagent-dev) - Join the discussion in the #kagent channel on CNCF Slack -- Check our [FAQ]({{< relref "/kagent/0.x/resources/faq" >}}) for common questions +- Check our [FAQ]({{< link path="resources/faq" >}}) for common questions - Follow our [Feature Roadmap](https://github.com/kagent-dev/kagent/blob/main/README.md#roadmap) for upcoming developments diff --git a/docs-site/content/kagent/0.x/not-in-version.md b/docs-site/content/kagent/0.x/not-in-version.md index 306e4dc5..30a0b1be 100644 --- a/docs-site/content/kagent/0.x/not-in-version.md +++ b/docs-site/content/kagent/0.x/not-in-version.md @@ -5,4 +5,4 @@ build: list: never --- -This topic doesn't exist in this version of the kagent docs. Use the version switcher above to go back to a version where it's available, or browse the [kagent docs]({{< relref "/kagent/0.x" >}}) landing page. +This topic doesn't exist in this version of the kagent docs. Use the version switcher above to go back to a version where it's available, or browse the [kagent docs]({{< link path="" >}}) landing page. diff --git a/docs-site/content/kagent/0.x/observability/audit-prompts.md b/docs-site/content/kagent/0.x/observability/audit-prompts.md index 73cdd9a8..d04b306d 100644 --- a/docs-site/content/kagent/0.x/observability/audit-prompts.md +++ b/docs-site/content/kagent/0.x/observability/audit-prompts.md @@ -20,7 +20,7 @@ kagent supports logging input/output messages for the following LLM providers: ## Before you begin -1. [Install kagent]({{< relref "/kagent/0.x/introduction/installation" >}}) in your cluster. +1. [Install kagent]({{< link path="introduction/installation" >}}) in your cluster. 2. Add the OpenTelemetry Helm repository. diff --git a/docs-site/content/kagent/0.x/observability/launch-ui.md b/docs-site/content/kagent/0.x/observability/launch-ui.md index edc687da..50905474 100644 --- a/docs-site/content/kagent/0.x/observability/launch-ui.md +++ b/docs-site/content/kagent/0.x/observability/launch-ui.md @@ -51,6 +51,6 @@ If you prefer to manually set up port-forwarding, or if you're on a platform whe You can use the UI to view and manage your agents, tools, and models. For more information, see the following guides: -- [Create your first agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) -- [Add MCP tools to your agents]({{< relref "/kagent/0.x/getting-started/first-mcp-tool" >}}) -- [Configure LLM providers]({{< relref "/kagent/0.x/supported-providers" >}}) +- [Create your first agent]({{< link path="getting-started/first-agent" >}}) +- [Add MCP tools to your agents]({{< link path="getting-started/first-mcp-tool" >}}) +- [Configure LLM providers]({{< link path="supported-providers" >}}) diff --git a/docs-site/content/kagent/0.x/observability/tracing.md b/docs-site/content/kagent/0.x/observability/tracing.md index 00886605..30b176f7 100644 --- a/docs-site/content/kagent/0.x/observability/tracing.md +++ b/docs-site/content/kagent/0.x/observability/tracing.md @@ -9,7 +9,7 @@ Set up tracing for your kagent agents. ## Before you begin -[Install kagent]({{< relref "/kagent/0.x/introduction/installation" >}}). +[Install kagent]({{< link path="introduction/installation" >}}). ## Install Jaeger @@ -82,7 +82,7 @@ Now that you installed kagent with Jaeger, learn how to trace requests to an age ### Generate tracing data -To generate tracing data, you can chat with a pre-configured agent such as `k8s-agent`. For more information about agents, see the [Your First Agent]({{< relref "/kagent/0.x/getting-started/first-agent" >}}) guide. +To generate tracing data, you can chat with a pre-configured agent such as `k8s-agent`. For more information about agents, see the [Your First Agent]({{< link path="getting-started/first-agent" >}}) guide. 1. Launch the kagent dashboard. @@ -135,11 +135,11 @@ That's it! You've now traced your first agent. ## Next Steps -- Learn about [Core Concepts]({{< relref "/kagent/0.x/concepts" >}}) -- Try out some [Example]({{< relref "/kagent/0.x/examples" >}}) guides +- Learn about [Core Concepts]({{< link path="concepts" >}}) +- Try out some [Example]({{< link path="examples" >}}) guides ## Need Help? - Visit our [GitHub repository](https://github.com/kagent-dev/kagent) - Ask a question on [Discord](https://discord.gg/Fu3k65f2k3) -- Check out the [FAQ]({{< relref "/kagent/0.x/resources/faq" >}}) \ No newline at end of file +- Check out the [FAQ]({{< link path="resources/faq" >}}) \ No newline at end of file diff --git a/docs-site/content/kagent/0.x/operations/operational-considerations.md b/docs-site/content/kagent/0.x/operations/operational-considerations.md index d768ff64..ee83341a 100644 --- a/docs-site/content/kagent/0.x/operations/operational-considerations.md +++ b/docs-site/content/kagent/0.x/operations/operational-considerations.md @@ -89,7 +89,7 @@ urlFile > url > bundled connection string The bundled PostgreSQL instance is deployed by default (`database.postgres.bundled.enabled: true`). The database name, username, and password are all hardcoded to `kagent`. Credentials are stored in a Kubernetes Secret. -You can customize the storage size and image of the bundled instance when you [install]({{< relref "/kagent/0.x/introduction/installation" >}}) or upgrade kagent. +You can customize the storage size and image of the bundled instance when you [install]({{< link path="introduction/installation" >}}) or upgrade kagent. 1. Add the bundled database settings to your Helm values file for kagent. diff --git a/docs-site/content/kagent/0.x/operations/uninstall.md b/docs-site/content/kagent/0.x/operations/uninstall.md index a66074fa..ecf6fb83 100644 --- a/docs-site/content/kagent/0.x/operations/uninstall.md +++ b/docs-site/content/kagent/0.x/operations/uninstall.md @@ -17,7 +17,7 @@ Remove kagent from your Kubernetes cluster using the kagent CLI or Helm. ## Uninstall with the kagent CLI -Remove kagent by using the CLI. For more options, see the [`kagent uninstall` command reference]({{< relref "/kagent/0.x/resources/cli/kagent-uninstall" >}}). +Remove kagent by using the CLI. For more options, see the [`kagent uninstall` command reference]({{< link path="resources/cli/kagent-uninstall" >}}). ```bash kagent uninstall diff --git a/docs-site/content/kagent/0.x/operations/upgrade.md b/docs-site/content/kagent/0.x/operations/upgrade.md index 0c7099cb..52fbc59d 100644 --- a/docs-site/content/kagent/0.x/operations/upgrade.md +++ b/docs-site/content/kagent/0.x/operations/upgrade.md @@ -15,12 +15,12 @@ Follow these steps to upgrade kagent to the latest version and keep your cluster export NEW_VERSION= ``` -2. Read the [release notes]({{< relref "/kagent/0.x/resources/release-notes" >}}) for the version you are upgrading to. Pay attention to any breaking changes or deprecations that might affect your configuration. +2. Read the [release notes]({{< link path="resources/release-notes" >}}) for the version you are upgrading to. Pay attention to any breaking changes or deprecations that might affect your configuration. 3. Back up your current configuration, including the following: - Agent definitions - Any custom settings - - PostgreSQL database: You can take a snapshot now so that you have a restore point if the upgrade fails. For the database connection string, see [Database configuration]({{< relref "/kagent/0.x/operations/operational-considerations#database-configuration" >}}). + - PostgreSQL database: You can take a snapshot now so that you have a restore point if the upgrade fails. For the database connection string, see [Database configuration]({{< link path="operations/operational-considerations#database-configuration" >}}). ```bash pg_dump "postgres://:@:5432/" \ @@ -28,7 +28,7 @@ Follow these steps to upgrade kagent to the latest version and keep your cluster --file=kagent-pre-upgrade-snapshot.dump ``` -4. **v0.9.0 and later**: You must be running at least v0.8.0 before upgrading to v0.9.0. Check the [release notes]({{< relref "/kagent/0.x/resources/release-notes#v09" >}}) for 0.9-specific upgrades related to database migrations and RBAC scope. +4. **v0.9.0 and later**: You must be running at least v0.8.0 before upgrading to v0.9.0. Check the [release notes]({{< link path="resources/release-notes#v09" >}}) for 0.9-specific upgrades related to database migrations and RBAC scope. ## Upgrade kagent @@ -56,7 +56,7 @@ Follow these steps to upgrade kagent to the latest version and keep your cluster 3. Make any changes that you want by editing your `values.yaml` Helm values file or preparing `--set` flags for the upgrade commands. - > **Note**: As of [version 0.7]({{< relref "/kagent/0.x/resources/release-notes#kmcp-installed-by-default" >}}), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. + > **Note**: As of [version 0.7]({{< link path="resources/release-notes#kmcp-installed-by-default" >}}), the kmcp subproject is included by default with kagent. To use an existing kmcp installation that you already set up separately, set `kmcp.enabled=false` in your `values.yaml` file or `--set` commands for both the `kagent` and `kagent-crds` charts. 4. Upgrade the kagent-crds chart. @@ -171,7 +171,7 @@ For example, `v0.9.9` has migrations up to `000005_a2a_protocol_version.up.sql` export ROLLBACK_MIGRATION_VERSION= ``` -5. Reset the core track. The `github://` source references the migration files directly from the release tag without a local checkout. For the database connection string, see [Database configuration]({{< relref "/kagent/0.x/operations/operational-considerations#database-configuration" >}}). +5. Reset the core track. The `github://` source references the migration files directly from the release tag without a local checkout. For the database connection string, see [Database configuration]({{< link path="operations/operational-considerations#database-configuration" >}}). ```bash migrate \ -source "github://kagent-dev/kagent/go/core/pkg/migrations/core#v$CURRENT_VERSION" \ diff --git a/docs-site/content/kagent/0.x/resources/_index.md b/docs-site/content/kagent/0.x/resources/_index.md index 659c77ad..789e3b5c 100644 --- a/docs-site/content/kagent/0.x/resources/_index.md +++ b/docs-site/content/kagent/0.x/resources/_index.md @@ -5,4 +5,4 @@ weight: 7 author: kagent.dev --- -Find helpful resources and FAQs for kagent. New to kagent? Start with the [Quick Start Guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). +Find helpful resources and FAQs for kagent. New to kagent? Start with the [Quick Start Guide]({{< link path="getting-started/quickstart" >}}). diff --git a/docs-site/content/kagent/0.x/resources/faq.md b/docs-site/content/kagent/0.x/resources/faq.md index 822fa07a..948151f8 100644 --- a/docs-site/content/kagent/0.x/resources/faq.md +++ b/docs-site/content/kagent/0.x/resources/faq.md @@ -8,7 +8,7 @@ author: kagent.dev ## What's the best way to get started with kagent? -The best way to get started with kagent is to follow the [quickstart guide]({{< relref "/kagent/0.x/getting-started/quickstart" >}}). This will give you a basic understanding of how kagent works and how to use it. +The best way to get started with kagent is to follow the [quickstart guide]({{< link path="getting-started/quickstart" >}}). This will give you a basic understanding of how kagent works and how to use it. ## What differentiates kagent from other LLM frameworks? diff --git a/docs-site/content/kagent/0.x/resources/release-notes.md b/docs-site/content/kagent/0.x/resources/release-notes.md index fbe12d16..3344497f 100644 --- a/docs-site/content/kagent/0.x/resources/release-notes.md +++ b/docs-site/content/kagent/0.x/resources/release-notes.md @@ -16,7 +16,7 @@ Review this summary of significant changes from kagent version 0.8 to v0.9. **Before you upgrade:** * You must be running at least v0.8.0 before upgrading to v0.9.0. -* Back up your PostgreSQL database before upgrading. For details on your database configuration, see the [Database configuration guide]({{< relref "/kagent/0.x/operations/operational-considerations/#database-configuration" >}}). +* Back up your PostgreSQL database before upgrading. For details on your database configuration, see the [Database configuration guide]({{< link path="operations/operational-considerations/#database-configuration" >}}). * The `rbac.clusterScoped` Helm value is removed. RBAC scope is now derived from `rbac.namespaces`. If you set `rbac.clusterScoped` in your Helm values, update your configuration to use `rbac.namespaces` instead. **What's included:** @@ -159,7 +159,7 @@ You can now use two Human-in-the-Loop mechanisms that can pause agent execution **Ask User** — A built-in `ask_user` tool is automatically added to every agent. Agents can pose questions to users with predefined choices (single-select, multi-select) or free-text input during execution. -For more information, see the [Human-in-the-Loop example]({{< relref "/kagent/0.x/examples/human-in-the-loop" >}}) and the [blog post](https://kagent.dev/blog/human-in-the-loop-kagent). +For more information, see the [Human-in-the-Loop example]({{< link path="examples/human-in-the-loop" >}}) and the [blog post](https://kagent.dev/blog/human-in-the-loop-kagent). ### Agent Memory @@ -169,7 +169,7 @@ When you enable memory on an agent, it receives three additional tools: `save_me You can configure memory in the Agent CR or through the UI when you create or edit an agent by selecting an embedding model and TTL. -For more information, see [Agent Memory]({{< relref "/kagent/0.x/concepts/agent-memory" >}}). +For more information, see [Agent Memory]({{< link path="concepts/agent-memory" >}}). ### Go ADK Runtime @@ -186,7 +186,7 @@ spec: The Go ADK includes built-in tools: `SkillsTool`, `BashTool`, `ReadFile`, `WriteFile`, and `EditFile`. -For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#runtime" >}}) and the [blog post](https://kagent.dev/blog/go-vs-python-runtime). +For more information, see [Agents]({{< link path="concepts/agents#runtime" >}}) and the [blog post](https://kagent.dev/blog/go-vs-python-runtime). ### Agents as MCP Servers @@ -201,7 +201,7 @@ You can load skills from two sources. - **OCI images.** Container images containing skill files. - **Git repositories.** Clone skills directly from Git repos, with support for private repos via HTTPS token or SSH key authentication. -For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#git-based-skills" >}}). +For more information, see [Agents]({{< link path="concepts/agents#git-based-skills" >}}). ### Go Workspace Restructure @@ -219,13 +219,13 @@ Agent system messages now support Go `text/template` syntax. You can store commo The `kagent-builtin-prompts` ConfigMap ships with five reusable templates: `skills-usage`, `tool-usage-best-practices`, `safety-guardrails`, `kubernetes-context`, and `a2a-communication`. -For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#prompt-templates" >}}). +For more information, see [Agents]({{< link path="concepts/agents#prompt-templates" >}}). ### Context Management Long conversations can now be automatically compacted to stay within LLM context windows. You can configure the `context.compaction` field to enable periodic summarization of older events while preserving key information. -For more information, see [Agents]({{< relref "/kagent/0.x/concepts/agents#context-management" >}}). +For more information, see [Agents]({{< link path="concepts/agents#context-management" >}}). ### AWS Bedrock Support @@ -252,7 +252,7 @@ SQLite support has been removed from kagent. PostgreSQL is now the only supporte **Migration:** -If you were using the default SQLite backend, no migration is needed. The bundled PostgreSQL is deployed automatically. You can optionally customize the bundled instance via `database.postgres.bundled.*` (storage size, image) as needed. See the [Database configuration guide]({{< relref "/kagent/0.x/operations/operational-considerations/#database-configuration" >}}) for details. +If you were using the default SQLite backend, no migration is needed. The bundled PostgreSQL is deployed automatically. You can optionally customize the bundled instance via `database.postgres.bundled.*` (storage size, image) as needed. See the [Database configuration guide]({{< link path="operations/operational-considerations/#database-configuration" >}}) for details. Note that for production deployments, use your own external PostgreSQL instance. If you already are, you can keep your `database.postgres.url` or `database.postgres.urlFile` settings as before. If your external PostgreSQL has the pgvector extension and you were using vector-based memory features, set `database.postgres.vectorEnabled: true` since the default has changed to `false`. @@ -306,7 +306,7 @@ helm upgrade --install kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \ Develop and test agents locally on your machine without needing a Kubernetes cluster. As part of this feature, the `kagent` CLI includes new commands to scaffold, build, run, and deploy agents. -For more information, see the [local development]({{< relref "/kagent/0.x/getting-started/local-development" >}}) guide. +For more information, see the [local development]({{< link path="getting-started/local-development" >}}) guide. ### Discovery label @@ -654,7 +654,7 @@ This change supports the new type for BYO agents. A new agent type has been added to the Agents API so that you can bring your own (BYO) agent. The agent must be written in ADK, with other frameworks under development. -BYO Agent example configuration. For more information, see the [BYO Agent]({{< relref "/kagent/0.x/examples/a2a-byo" >}}) guide. +BYO Agent example configuration. For more information, see the [BYO Agent]({{< link path="examples/a2a-byo" >}}) guide. ```yaml apiVersion: kagent.dev/v1alpha2 diff --git a/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md index 7d63fbc6..7d6c60b4 100644 --- a/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md +++ b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md @@ -97,7 +97,7 @@ spec: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/kagent-bedrock ``` -If you want to use one shared ServiceAccount for multiple agents, you can also set `controller.agentDeployment.serviceAccountName` in the [Helm chart configuration]({{< relref "/kagent/0.x/resources/helm" >}}). +If you want to use one shared ServiceAccount for multiple agents, you can also set `controller.agentDeployment.serviceAccountName` in the [Helm chart configuration]({{< link path="resources/helm" >}}). ## Option 2: OpenAI-compatible API diff --git a/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md b/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md index 40782510..b5c90041 100644 --- a/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md +++ b/docs-site/content/kagent/0.x/supported-providers/azure-ai-foundry.md @@ -248,7 +248,7 @@ spec: # No API key: use Azure Workload Identity. ``` -For the complete memory and embedding configuration and model requirements, see [Agent Memory]({{< relref "/kagent/0.x/concepts/agent-memory" >}}). +For the complete memory and embedding configuration and model requirements, see [Agent Memory]({{< link path="concepts/agent-memory" >}}). ## Troubleshooting diff --git a/docs-site/content/kagent/0.x/supported-providers/azure-openai.md b/docs-site/content/kagent/0.x/supported-providers/azure-openai.md index b9ec49e8..dfc02b0e 100644 --- a/docs-site/content/kagent/0.x/supported-providers/azure-openai.md +++ b/docs-site/content/kagent/0.x/supported-providers/azure-openai.md @@ -66,4 +66,4 @@ Omit `apiKeySecret` and `apiKeyPassthrough` to use Azure Workload Identity. For Follow the [AKS Workload Identity deployment guide](https://learn.microsoft.com/azure/aks/workload-identity-deploy-cluster) and grant the managed identity the `Cognitive Services User` role. -The kagent pod and ServiceAccount settings are provider-independent. Follow [Configure the agent for Azure Workload Identity]({{< relref "/kagent/0.x/supported-providers/azure-ai-foundry#configure-the-agent-for-azure-workload-identity" >}}) and set the agent's `modelConfig` to `azure-openai`. +The kagent pod and ServiceAccount settings are provider-independent. Follow [Configure the agent for Azure Workload Identity]({{< link path="supported-providers/azure-ai-foundry#configure-the-agent-for-azure-workload-identity" >}}) and set the agent's `modelConfig` to `azure-openai`. diff --git a/docs-site/content/kagent/1.x/not-in-version.md b/docs-site/content/kagent/1.x/not-in-version.md index b4d3437f..2380ad55 100644 --- a/docs-site/content/kagent/1.x/not-in-version.md +++ b/docs-site/content/kagent/1.x/not-in-version.md @@ -5,4 +5,4 @@ build: list: never --- -This topic doesn't exist in this version of the kagent docs yet. Use the version switcher above to go back to a version where it's available, or browse the [kagent 1.0 (preview)]({{< relref "/kagent/1.x" >}}) landing page. +This topic doesn't exist in this version of the kagent docs yet. Use the version switcher above to go back to a version where it's available, or browse the [kagent 1.0 (preview)]({{< link path="" >}}) landing page. diff --git a/docs-site/layouts/_shortcodes/link.html b/docs-site/layouts/_shortcodes/link.html new file mode 100644 index 00000000..5131d9c4 --- /dev/null +++ b/docs-site/layouts/_shortcodes/link.html @@ -0,0 +1,72 @@ +{{- /* kagent override of docs-theme-extras' link shortcode. + + Why this exists: upstream resolves relative to + .Page.FirstSection.RelPermalink — the product's top-level section + (e.g. "/docs/kagent/"). kagent is now versioned (0.x, 1.x — see + sections.kagent.versions in hugo.yaml), so content lives one level + deeper than that; a plain FirstSection-relative path would drop the + version segment entirely, the same class of bug already fixed in + this repo's navbar.html, sidebar.html, and version-banner.html + overrides. + + Fix: when the current page's section has a versions list, resolve + relative to the CURRENT VERSION's own page (e.g. "/kagent/0.x") — + found by locating $sectionKey within this page's own URL segments and + taking the page one level deeper — instead of the top-level section. + Unversioned sections (kmcp) fall through to upstream's behavior + unchanged. + + Everything else (translation-export mode, slash cleanup) is + byte-for-byte identical to upstream. */ -}} +{{- $path := .Get "path" -}} +{{- if eq hugo.Environment "translation" -}} + {{- $reg := .Page.Store.Get "transReg" | default slice -}} + {{- $ph := printf "XTRANSPH%dX" (len $reg) -}} + {{- $reg = $reg | append (dict "ph" $ph "text" (printf "{{< link path=\"%s\" >}}" $path)) -}} + {{- .Page.Store.Set "transReg" $reg -}} + {{- $ph -}} +{{- else -}} +{{- $page := .Page -}} +{{- $root := $page.FirstSection -}} +{{- $sectionKey := $page.Section -}} +{{- if and $sectionKey (isset $page.Site.Params.sections $sectionKey) -}} + {{- with (index $page.Site.Params.sections $sectionKey).versions -}} + {{- $segments := split (strings.Trim $page.RelPermalink "/") "/" -}} + {{- $sectionIdx := -1 -}} + {{- range $i, $seg := $segments -}} + {{- if and (eq $sectionIdx -1) (eq $seg $sectionKey) -}} + {{- $sectionIdx = $i -}} + {{- end -}} + {{- end -}} + {{- if ge $sectionIdx 0 -}} + {{- $versionIdx := add $sectionIdx 1 -}} + {{- if lt $versionIdx (len $segments) -}} + {{- $versionPage := site.GetPage (printf "/%s/%s" $sectionKey (index $segments $versionIdx)) -}} + {{- if $versionPage -}} + {{- $root = $versionPage -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{- $finalURL := printf "/%s/%s" $root.RelPermalink $path -}} + +{{- /* Append a slash if the link is not a fragment */ -}} +{{- if not (strings.Contains $finalURL "#") -}} + {{- $finalURL = printf "%s/" $finalURL -}} +{{- end -}} + +{{- /* Replace all double slashes with single slashes as a safety measure */ -}} +{{- /* Preserve the protocol separator (://) by temporarily replacing it */ -}} +{{- $finalURL = replace $finalURL "://" "__PROTOCOL_SEPARATOR__" -}} +{{- /* Loop until no more double slashes exist (max 10 iterations for safety) */ -}} +{{- range $i := (seq 10) -}} + {{- if (strings.Contains $finalURL "//") -}} + {{- $finalURL = replace $finalURL "//" "/" -}} + {{- end -}} +{{- end -}} +{{- /* Restore the protocol separator */ -}} +{{- $finalURL = replace $finalURL "__PROTOCOL_SEPARATOR__" "://" -}} +{{- $finalURL -}} +{{- end -}} From cc5db939a7cc0ecea495886222fb7f9d06b76a1c Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 21 Aug 2026 17:33:25 -0500 Subject: [PATCH 05/70] Write Phase 1 kagent 1.0 docs: About and Get started sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the five Phase 1 pages from the docs scope: What is kagent, Core concepts, Architecture, Architecture: Agent Substrate, and Your first agent, plus the About and Get started section landing pages. Grounded against the actual kagent-private v1alpha3 code and the substrate repo rather than the design vault alone, which caught several places where the vault (and the original docs scope) had drifted from what's actually implemented — Hermes/OpenClaw living in a separate AgentHarness CRD rather than as Harness runtime variants, the v1alpha3 CRD version not covering the gRPC control plane (that's v1alpha1), and Harness/AgentTemplate attachment being a one-way label selector rather than a bilateral handshake. "Your first agent" uses kubectl + grpcurl directly, verified end-to-end against real e2e test code and the actual a2a-go proto, since the kagent CLI doesn't support this flow yet. Reviewed against solo.io's shared docs writing conventions (voice, sentence-case titles/headings, full-sentence descriptions, no contractions) and a Vale pass borrowing the docs repo's real Solo style rules. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/_index.md | 2 +- docs-site/content/kagent/1.x/about/_index.md | 8 ++ .../kagent/1.x/about/agent-substrate.md | 47 +++++++ .../content/kagent/1.x/about/architecture.md | 63 +++++++++ .../content/kagent/1.x/about/core-concepts.md | 96 +++++++++++++ .../kagent/1.x/about/what-is-kagent.md | 77 ++++++++++ .../content/kagent/1.x/get-started/_index.md | 8 ++ .../1.x/get-started/your-first-agent.md | 133 ++++++++++++++++++ docs-site/content/kagent/_index.md | 2 +- 9 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 docs-site/content/kagent/1.x/about/_index.md create mode 100644 docs-site/content/kagent/1.x/about/agent-substrate.md create mode 100644 docs-site/content/kagent/1.x/about/architecture.md create mode 100644 docs-site/content/kagent/1.x/about/core-concepts.md create mode 100644 docs-site/content/kagent/1.x/about/what-is-kagent.md create mode 100644 docs-site/content/kagent/1.x/get-started/_index.md create mode 100644 docs-site/content/kagent/1.x/get-started/your-first-agent.md diff --git a/docs-site/content/kagent/1.x/_index.md b/docs-site/content/kagent/1.x/_index.md index f68c8997..abd552db 100644 --- a/docs-site/content/kagent/1.x/_index.md +++ b/docs-site/content/kagent/1.x/_index.md @@ -1,7 +1,7 @@ --- title: kagent 1.0 linkTitle: "kagent 1.x (preview)" -description: Preview documentation for the kagent 1.0 release, built on Agent Substrate. +description: Preview the kagent 1.0 documentation, built on Agent Substrate. weight: 1 author: kagent.dev --- diff --git a/docs-site/content/kagent/1.x/about/_index.md b/docs-site/content/kagent/1.x/about/_index.md new file mode 100644 index 00000000..e2b34a46 --- /dev/null +++ b/docs-site/content/kagent/1.x/about/_index.md @@ -0,0 +1,8 @@ +--- +title: About +description: Learn the core concepts and architecture behind kagent 1.0. +weight: 2 +author: kagent.dev +--- + +Learn what changed in kagent 1.0 and the vocabulary the rest of these docs build on. diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md new file mode 100644 index 00000000..768cc52c --- /dev/null +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -0,0 +1,47 @@ +--- +title: "Architecture: Agent Substrate" +description: See how Agent Substrate runs, suspends, and resumes the Actors behind every AgentInstance. +weight: 4 +author: kagent.dev +--- + +[Architecture]({{< link path="about/architecture" >}}) covers where an Actor fits between an AgentInstance and a running conversation. This page covers how Agent Substrate itself runs that Actor: on what compute, inside what sandbox, and how it suspends and resumes without staying resident the whole time. + +## Workers and WorkerPools + +A **WorkerPool** is a Kubernetes custom resource that an operator provisions before any Harness can create AgentInstances. It defines a pool of pre-started sandbox pods, called **Workers**, along with the sandbox technology those Workers use. + +A Worker is not something an operator creates directly. Substrate manages Workers itself, keeping enough of them ready in each WorkerPool so that an Actor can start or resume on one immediately, without waiting on the Kubernetes scheduler to place a new Pod. + +## Sandboxing + +Because an Actor often runs a model-directed agent that calls tools and executes commands, Substrate runs each Actor in an isolated sandbox rather than a plain container. A WorkerPool's `sandboxClass` field selects the sandbox technology for its Workers: [gVisor](https://gvisor.dev) or a micro-VM technology such as [Kata Containers](https://katacontainers.io). Both technologies isolate an Actor from its Worker's host kernel, and both support the suspend and resume operations that the rest of this page covers. + +## ActorTemplate + +An **ActorTemplate** is the compiled, immutable definition that a new Actor is created from. [Architecture]({{< link path="about/architecture" >}}) covers how the kagent controller compiles a Harness and AgentTemplate pair into one. Substrate rejects any change to an ActorTemplate's spec after creation, so the kagent controller creates a new ActorTemplate for every compiled revision rather than editing an existing one, and reclaims old ones once no AgentInstance references them. + +## Suspend, snapshot, and resume + +Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming this way lets a WorkerPool run far more Actors than it has Workers for at any one moment. + +The diagram below follows an Actor through one suspend-and-resume cycle. Read it left to right: a WorkerPool hosts Workers, a Worker hosts a running Actor, suspending that Actor produces a snapshot, and a tag on that snapshot lets a later Actor resume from it on whichever Worker is free. + +```mermaid +flowchart LR + pool["WorkerPool"] --> worker1["Worker"] + pool --> worker2["Worker"] + worker1 -->|hosts| actor["Actor
      (running)"] + actor -->|suspend| snapshot["ActorSnapshot
      (immutable)"] + snapshot -->|tag| tag["ActorSnapshotTag
      (stable handle)"] + tag -->|resume| worker2 +``` + +Suspending an Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker it was running on. An **ActorSnapshotTag** gives that snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag's target can be updated to point at a newer snapshot without changing the tag's own name, and a snapshot cannot be deleted while any tag still points to it. Resuming reads the tagged snapshot and restores it onto whichever Worker in the pool is free, not necessarily the Worker the Actor originally ran on. + +Substrate's own target for this cycle is 100ms at the 95th percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. + +## Next steps + +- [Your first agent]({{< link path="get-started/your-first-agent" >}}): apply a Harness and AgentTemplate, and watch the Actor they produce suspend and resume. +- [Substrate operations]({{< link path="operations/substrate-operations" >}}): size a WorkerPool and choose a sandbox class for your cluster. diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md new file mode 100644 index 00000000..0228ab2f --- /dev/null +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -0,0 +1,63 @@ +--- +title: Architecture +description: See how a Harness and AgentTemplate become a running conversation, across kagent's two authorization planes. +weight: 3 +author: kagent.dev +--- + +[Core concepts]({{< link path="about/core-concepts" >}}) defines Harness, AgentTemplate, AgentInstance, and Actor on their own. This page connects them into one system: how applying a Harness and AgentTemplate leads to a running conversation, and which parts of that path Kubernetes governs versus which parts kagent governs itself. + +kagent 1.0 splits authorization across two planes, not one: + +- The **Kubernetes plane** governs the Harness and AgentTemplate custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit them, exactly as it would for any other Custom Resource Definition (CRD). +- The **kagent plane** governs AgentInstances: creating one, suspending or resuming it, sharing it, deleting it, and holding a conversation with it. kagent's own gRPC authentication and authorization decide who can do these things, independent of Kubernetes RBAC. + +Someone with RBAC access to apply a Harness and AgentTemplate does not automatically get access to create or talk to AgentInstances that use them, and the reverse is also true. The diagram below shows where the boundary between the two planes falls, and the walkthrough after it follows a request across that boundary from start to finish. + +```mermaid +flowchart TB + subgraph k8s["Kubernetes plane (RBAC)"] + operator["Operator
      kubectl apply"] + harness["Harness"] + template["AgentTemplate"] + controller["kagent controller"] + actortemplate["ActorTemplate
      (Substrate)"] + operator --> harness + operator --> template + harness --> controller + template --> controller + controller -->|compiles the pair into| actortemplate + end + + subgraph kagentplane["kagent plane (gRPC auth)"] + caller["Caller"] + instance["AgentInstance"] + gateway["A2A gateway"] + actor["Actor
      (Substrate)"] + caller -->|CreateAgentInstance| instance + instance -->|created from| actortemplate + instance -->|runs on| actor + caller -->|A2A conversation| gateway + gateway -->|routes to| actor + end + + classDef crd stroke:#a78bfa,fill:transparent + class harness,template crd +``` + +Follow the Kubernetes plane first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair, one whose `allowedAgentTemplates` selector matches, and compiles it into an ActorTemplate on Substrate. + +The kagent plane starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the latest compiled ActorTemplate, and that AgentInstance runs on an Actor. + +From there, the caller holds a conversation with the AgentInstance over the A2A (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance, so the caller only ever needs to know an AgentInstance's identity, never which Actor or Worker is behind it. + +## Why two planes + +Kubernetes RBAC is designed to authorize configuration changes: who can create a Deployment, edit a ConfigMap, or in this case, apply a Harness or AgentTemplate. It is not designed to authorize a running conversation, share access to it with another user, or scope who can suspend it. kagent's gRPC plane exists to authorize exactly those actions, at the granularity of a single AgentInstance rather than a namespace or a resource kind. + +This split also keeps the two lifecycles independent. Editing a Harness or AgentTemplate does not affect AgentInstances already running against the ActorTemplate they were created from. It only affects new AgentInstances, created after the edit is compiled. + +## Next steps + +- [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}): what an Actor actually runs on, and how it suspends and resumes. +- [Your first agent]({{< link path="get-started/your-first-agent" >}}): apply a Harness and AgentTemplate, and create the AgentInstance they produce. diff --git a/docs-site/content/kagent/1.x/about/core-concepts.md b/docs-site/content/kagent/1.x/about/core-concepts.md new file mode 100644 index 00000000..c9f77d58 --- /dev/null +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -0,0 +1,96 @@ +--- +title: Core concepts +description: Learn the Harness, AgentTemplate, AgentInstance, and Actor model that kagent 1.0 is built on. +weight: 2 +author: kagent.dev +--- + +kagent 1.0 replaces the Deployment-based `Agent` custom resource with a new model built around **Harness**, **AgentTemplate**, and **AgentInstance**, running on [Agent Substrate]({{< link path="about/agent-substrate" >}}) instead of plain Kubernetes Deployments. This page defines the vocabulary the rest of these docs use. If your existing kagent installation is on 0.x, see the [0.x docs]({{< relref "/kagent/0.x" >}}). This page and everything under it describes the 1.0 model only. + +The new model separates what an agent can do from how it is allowed to run: + +- A **Harness** defines how an agent is allowed to run. It picks a runtime and the infrastructure policy around it. +- An **AgentTemplate** defines what an agent can do: its model, prompt, and tools. +- An **AgentInstance** is a running conversation, created by pairing the two. +- An **Actor** is the sandboxed process, provided by Substrate, that an AgentInstance runs on. + +The diagram below shows how a Harness and an AgentTemplate become a running conversation. Follow the arrows from left to right: the kagent controller compiles the Harness and AgentTemplate pair into an ActorTemplate, and each AgentInstance is created from that ActorTemplate and runs on an Actor. + +```mermaid +flowchart LR + harness["Harness
      (CRD)"] + template["AgentTemplate
      (CRD)"] + controller["kagent controller"] + actortemplate["ActorTemplate
      (compiled, immutable)"] + instance["AgentInstance
      (gRPC + database)"] + actor["Actor
      (Substrate)"] + + harness --> controller + template --> controller + controller -->|compiles the pair into| actortemplate + instance -->|created from| actortemplate + instance -->|runs on| actor + + classDef crd stroke:#a78bfa,fill:transparent + class harness,template crd +``` + +The Harness and AgentTemplate are the only two resources an operator applies directly. The kagent controller watches for a valid pair and compiles it into an ActorTemplate. From there, each AgentInstance created from that ActorTemplate gets its own Actor to run on. The rest of this page defines each of these terms in more detail. + +## Harness + +A **Harness** is a Kubernetes custom resource that defines how an agent is allowed to run. It specifies: + +- **Runtime**: the engine that executes the agent. This is either kagent's own Go or Python runtime, or a bring-your-own coding agent such as Claude Code or Codex. +- **Workload**: the container image and environment the runtime runs in. +- **Substrate policy**: the [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their snapshots are stored. +- **Allowed AgentTemplates**: a selector that names which AgentTemplates are permitted to run on this Harness. + +That last point is a one-way match, not a mutual handshake. An AgentTemplate has no field naming a Harness. Instead, a Harness's `allowedAgentTemplates` selector matches on labels, and any AgentTemplate in the same namespace carrying a matching label becomes eligible to run on it. Whoever controls a Harness's selector decides which AgentTemplates it accepts. + +A Harness owns no running compute by itself. Applying one registers a runtime and policy that an AgentTemplate can pair with. + +## AgentTemplate + +An **AgentTemplate** is a Kubernetes custom resource that defines what an agent does. It specifies: + +- **Model configuration**: the large language model (LLM) provider and model the agent uses. This is the only field an AgentTemplate strictly requires. +- **System prompt**: a literal prompt, or a Go-templated one that can `include` shared ConfigMaps. +- **Tools**: a list of tool bindings the agent can call. Each binding is either a Model Context Protocol (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated) below). +- **Skills** and **plugins**: reusable capability packages, sourced from an Open Container Initiative (OCI) registry, Git, or S3. + +An AgentTemplate does nothing on its own. It becomes runnable once it is paired with a Harness whose `allowedAgentTemplates` selector accepts it. + +## AgentInstance + +An **AgentInstance** is a running, conversational pairing of a Harness and an AgentTemplate. Unlike Harness and AgentTemplate, an AgentInstance is not a Kubernetes custom resource. It does not live in etcd. kagent's own gRPC API creates it, and kagent's PostgreSQL database tracks it. + +This split is deliberate, not an implementation detail to work around: + +- Applying a Harness or AgentTemplate is a **Kubernetes-native operation**, governed by Kubernetes RBAC, exactly like any other CRD. +- Creating, suspending, resuming, sharing, or deleting an AgentInstance, and holding a conversation with it, are **kagent-native operations**, governed by kagent's own gRPC authentication and authorization, independent of who can `kubectl apply` a Harness or AgentTemplate. + +Under the hood, the kagent controller watches for valid Harness and AgentTemplate pairs and compiles each one into an immutable `ActorTemplate`, a Substrate resource keyed by a digest of the compiled revision. Creating an AgentInstance resolves to the latest successfully compiled ActorTemplate for that pair and creates an Actor from it. If you edit the Harness or AgentTemplate, existing AgentInstances keep running against the ActorTemplate they were created from. New AgentInstances pick up the new revision. + +Once created, an AgentInstance talks to callers over the A2A (Agent-to-Agent) protocol, through kagent's A2A gateway. The gateway resolves each request to the right AgentInstance and forwards it to the Actor running behind it. + +## Actor + +An **Actor** is the sandboxed unit of compute, provided by [Agent Substrate]({{< link path="about/agent-substrate" >}}), that runs an AgentInstance's conversation loop. Every AgentInstance is backed by an Actor. + +Actors are why AgentInstances can suspend and resume cheaply instead of staying resident: an idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}) covers the full mechanics (Workers, WorkerPools, ActorTemplates, and snapshotting). For this page, an Actor is simply the sandbox that an AgentInstance's conversation runs inside. + +## Agent tools: Shared vs. Dedicated + +An AgentTemplate's tools are not limited to MCP servers. A tool binding can also point at another AgentTemplate, letting one agent call another agent as a tool. Each agent-tool binding picks an isolation mode: + +- **Shared** (the default): the child agent runs inside the same Actor as its parent. This is cheaper, and the child shares its parent's fate. If the parent's Actor is suspended or crashes, so does the child. +- **Dedicated**: the child agent gets its own Actor, isolated from its parent. This is more expensive, but a crash or a long-running task in the child cannot take down the parent, and the child can be scaled, suspended, or resumed independently. + +A Shared agent tool can itself have Dedicated agent tools underneath it, but a Shared agent tool cannot contain another Shared one. Sharing a single Actor only ever goes one level deep. Restricting Shared nesting this way keeps the isolation model easy to reason about: at any point in an agent's tool tree, you can tell exactly which Actor a given call executes in just by walking up to the nearest Dedicated boundary, or the root. + +## Next steps + +- [Architecture]({{< link path="about/architecture" >}}): how these pieces fit together end to end, from `kubectl apply` to a live conversation. +- [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}): Workers, WorkerPools, ActorTemplates, and how Actors suspend and resume. +- [Your first agent]({{< link path="get-started/your-first-agent" >}}): apply a Harness and AgentTemplate, and talk to the AgentInstance they create. diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md new file mode 100644 index 00000000..4956b9b3 --- /dev/null +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -0,0 +1,77 @@ +--- +title: Introducing kagent +linkTitle: What is kagent +description: Understand what kagent is and its core purpose. +weight: 1 +author: kagent.dev +--- + +kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with coding-agent runtimes such as Claude Code and Codex, agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and every major large language model (LLM) provider. + +kagent was created at [Solo.io](https://www.solo.io) in 2025 and is a [Cloud Native Computing Foundation](https://www.cncf.io) sandbox project. + +## What is kagent? + +Unlike a traditional chatbot, kagent uses advanced reasoning and iterative planning to autonomously handle multi-step problems in cloud-native environments. It turns AI insight into concrete action, helping teams tackle common operational challenges such as: + +- Diagnosing connectivity issues across multiple service hops +- Troubleshooting application performance degradation +- Automating alert generation from Prometheus metrics +- Debugging Gateway and HTTPRoute configurations +- Managing progressive rollouts with Argo Rollouts + +## Core model + +kagent 1.0 separates an agent's capabilities from its runtime, then runs the two together as a conversation: + +- A **Harness** and an **AgentTemplate** are the Kubernetes custom resources you author. Together they say how an agent is allowed to run and what it can do. +- An **AgentInstance** is the running conversation those two resources produce, backed by an **Actor** on Agent Substrate. + +[Core concepts]({{< link path="about/core-concepts" >}}) defines each of these in detail, and [Architecture]({{< link path="about/architecture" >}}) walks through how they connect end to end. + +## Why kagent? + +kagent addresses the growing complexity of cloud-native operations by: + +- Automating routine troubleshooting and operational tasks +- Reducing the need for specialist intervention in common scenarios +- Enabling teams to formalize and share their operational expertise +- Providing a platform for building and sharing custom AI agents + +## Platform features + +Everything works with a single `helm install`. No add-ons, no extra databases, no waiting for enterprise. + +{{< feature-cards >}} +{{< feature-card title="Agent lifecycle via CRDs" desc="Define, version, and roll out Harnesses and AgentTemplates with kubectl and GitOps, the same workflow as every other workload." >}} +{{< feature-card title="Sandboxed by default" desc="Every AgentInstance runs on a Substrate Actor, sandboxed with gVisor or a micro-VM. Run untrusted, model-directed code safely." >}} +{{< feature-card title="Suspend and resume" desc="Idle AgentInstances suspend and free their compute, then resume on demand. Run far more agents than you have capacity for at any one moment." >}} +{{< feature-card title="Bring your own runtime" desc="Run kagent's native Go or Python engine, or bring Claude Code or Codex as the runtime behind a Harness." >}} +{{< feature-card title="Agent tools" desc="Compose agents from other agents. Choose Shared isolation for cheap nesting, or Dedicated isolation to give a nested agent its own Actor." >}} +{{< feature-card title="Long-term memory" desc="Persistent, vector-backed memory across sessions. Agents remember context, not just the last prompt." >}} +{{< feature-card title="Human-in-the-loop" desc="Tool approval gates and agent-initiated questions keep a person in control of consequential actions." >}} +{{< feature-card title="Agent-to-Agent (A2A)" desc="AgentInstances talk to callers, and to each other, over the A2A protocol." >}} +{{< feature-card title="Skills and plugins" desc="Load skills and capability packages from an Open Container Initiative (OCI) registry, Git, or S3 at startup." >}} +{{< feature-card title="Prompt templates" desc="Reusable prompt fragments stored as ConfigMaps. Keep system prompts consistent across agents." >}} +{{< feature-card title="Full observability" desc="OpenTelemetry tracing, Prometheus metrics, and structured logs. See every prompt, every tool call, every token." >}} +{{< feature-card title="Postgres storage" desc="AgentInstances are tracked in production-grade, Postgres-backed storage with reviewable migrations." >}} +{{< /feature-cards >}} + +## Enterprise distributions + +Check out [Solo Enterprise for kagent](https://www.solo.io/products/kagent-enterprise), a comprehensive agent management interface for creating, validating, debugging, deploying, and monitoring AI agents across federated Kubernetes clusters. Solo Enterprise for kagent adds enterprise-grade capabilities on top of the kagent open source project, including advanced management features, observability tools, and multicluster federation support. + +## Getting started + +To start using kagent, see [Your first agent]({{< link path="get-started/your-first-agent" >}}). For a deeper understanding of how kagent works, see [Architecture]({{< link path="about/architecture" >}}). + +Ready to contribute? Visit the [GitHub repository](https://github.com/kagent-dev) to learn how you can help expand the ecosystem of cloud-native AI agents. + +## Community + +Join the kagent community: + +- Explore the repositories on [GitHub](https://github.com/kagent-dev) +- Join the discussion in the #kagent channel on CNCF Slack +- Check the [FAQ]({{< link path="reference/faq" >}}) for common questions +- Follow the [feature roadmap](https://github.com/kagent-dev/kagent/blob/main/README.md#roadmap) for upcoming developments diff --git a/docs-site/content/kagent/1.x/get-started/_index.md b/docs-site/content/kagent/1.x/get-started/_index.md new file mode 100644 index 00000000..6b754904 --- /dev/null +++ b/docs-site/content/kagent/1.x/get-started/_index.md @@ -0,0 +1,8 @@ +--- +title: Get started +description: Install kagent and create your first agent. +weight: 1 +author: kagent.dev +--- + +Install kagent, then create and talk to your first agent. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md new file mode 100644 index 00000000..6ec94ddf --- /dev/null +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -0,0 +1,133 @@ +--- +title: Your first agent +description: Apply a Harness and AgentTemplate, then create and talk to the AgentInstance they produce. +weight: 1 +author: kagent.dev +--- + +This guide walks through the full path from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance they produce. [Core concepts]({{< link path="about/core-concepts" >}}) defines each of these terms, and [Architecture]({{< link path="about/architecture" >}}) covers how they fit together. + +## Before you begin creating your first agent + +- Install kagent with a WorkerPool provisioned. See [Installation]({{< link path="setup/installation" >}}). +- Install [grpcurl](https://github.com/fullstorydev/grpcurl). +- Enable gRPC reflection on the controller, so grpcurl can discover its methods without a local copy of kagent's proto files. Add `--set controller.grpc.reflection=true` to your Helm install or upgrade command. +- Port-forward the controller's gRPC port to your local machine: + + ```shell + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + +The kagent CLI does not yet have commands for Harness, AgentTemplate, or AgentInstance. Until it does, this guide uses `kubectl` and `grpcurl` directly. + +## Apply a Harness and an AgentTemplate + +1. Apply a `ModelConfig` that names your model provider: + + ```yaml + apiVersion: kagent.dev/v1alpha3 + kind: ModelConfig + metadata: + name: default-model-config + namespace: kagent + spec: + provider: "OpenAI" + model: "gpt-4.1-mini" + apiKeySecret: kagent-openai + apiKeySecretKey: OPENAI_API_KEY + ``` + + If you installed kagent with the Helm chart's default model provider settings, this `ModelConfig` already exists. Skip this step in that case. + +2. Apply a `Harness` that uses kagent's native runtime: + + ```yaml + apiVersion: kagent.dev/v1alpha3 + kind: Harness + metadata: + name: my-first-harness + namespace: kagent + spec: + kagent: {} + workload: + image: @sha256: # pin this to your kagent release's runtime image + substrate: + workerPoolRef: + name: kagent-default + snapshotPolicy: + location: gs:///kagent/ + allowedAgentTemplates: + selector: + matchLabels: + kagent.dev/harness: my-first-harness + ``` + +3. Apply an `AgentTemplate` labeled to match that selector: + + ```yaml + apiVersion: kagent.dev/v1alpha3 + kind: AgentTemplate + metadata: + name: my-first-agent + namespace: kagent + labels: + kagent.dev/harness: my-first-harness + spec: + description: My first kagent agent + modelConfig: + name: default-model-config + systemPrompt: You are a concise, helpful assistant. + ``` + + An `AgentTemplate` has no field naming a Harness. The `kagent.dev/harness` label is only a convention this guide uses to match the selector above. Choose any label key and value, as long as the Harness selector and the AgentTemplate's labels agree. + +4. Confirm the pair is ready: + + ```shell + kubectl get agenttemplate my-first-agent -n kagent -o jsonpath='{.status.harnesses}' + ``` + + A ready pair reports a `Ready` condition for `my-first-harness`. If the status is empty, wait a few seconds for the kagent controller to reconcile, then check again. + +## Create the AgentInstance + +Once the pair is ready, create an AgentInstance from it: + +```shell +grpcurl -plaintext \ + -d '{"namespace":"kagent","harness":"my-first-harness","agentTemplate":"my-first-agent","requestId":"'"$(uuidgen)"'"}' \ + localhost:8084 kagent.api.v1alpha1.AgentInstanceService/CreateAgentInstance +``` + +The response includes an `id` field. Save it. The next step needs it to address the AgentInstance you just created. + +## Talk to your agent + +Send a message to the AgentInstance over the A2A (Agent-to-Agent) protocol, using the `id` from the previous step: + +```shell +grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: " \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"What is 2+2?"}]}}' \ + localhost:8084 lf.a2a.v1.A2AService/SendMessage +``` + +The response carries the agent's reply in the same `parts` shape as the request. + +A future kagent CLI release will wrap the create-and-converse steps above into a single command. + +## Clean up your first agent + +```shell +kubectl delete agenttemplate my-first-agent -n kagent +kubectl delete harness my-first-harness -n kagent +``` + +Deleting the Harness and AgentTemplate does not delete the AgentInstance you created from them. Delete it directly through the same `AgentInstanceService` you used to create it. + +## Next steps + +- [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}): what happens to your AgentInstance's Actor when it sits idle. +- [Agent harness]({{< link path="agents/agent-harness" >}}): the full set of Harness runtime options, including Claude Code and Codex. +- [Skills]({{< link path="skills-mcp/skills" >}}): give your agent capabilities beyond its system prompt. diff --git a/docs-site/content/kagent/_index.md b/docs-site/content/kagent/_index.md index bc8c3517..485b2cd8 100644 --- a/docs-site/content/kagent/_index.md +++ b/docs-site/content/kagent/_index.md @@ -1,6 +1,6 @@ --- title: kagent -description: Concepts, guides, and reference docs for running declarative AI agents on Kubernetes, from install through day-two operations. +description: Explore concepts, guides, and reference docs for running declarative AI agents on Kubernetes, from install through day-two operations. weight: 1 author: kagent.dev disableCards: true From de7f422757142af12409b39e0abd4569524bb8e6 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 24 Aug 2026 13:31:35 -0500 Subject: [PATCH 06/70] Phase 1, review 1 Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/_index.md | 6 +- docs-site/content/kagent/1.x/about/_index.md | 2 +- .../kagent/1.x/about/agent-substrate.md | 8 +- .../content/kagent/1.x/about/architecture.md | 8 +- .../content/kagent/1.x/about/core-concepts.md | 10 +- .../kagent/1.x/about/what-is-kagent.md | 2 +- .../content/kagent/1.x/get-started/_index.md | 6 +- .../1.x/get-started/your-first-agent.md | 163 +++++++++++------- 8 files changed, 125 insertions(+), 80 deletions(-) diff --git a/docs-site/content/kagent/1.x/_index.md b/docs-site/content/kagent/1.x/_index.md index abd552db..d7e05c80 100644 --- a/docs-site/content/kagent/1.x/_index.md +++ b/docs-site/content/kagent/1.x/_index.md @@ -1,13 +1,11 @@ --- -title: kagent 1.0 +title: kagent 1.0 (preview) linkTitle: "kagent 1.x (preview)" description: Preview the kagent 1.0 documentation, built on Agent Substrate. -weight: 1 +weight: 10 author: kagent.dev --- -# kagent 1.0 (preview) - kagent 1.0 moves the runtime from Kubernetes Deployments to [Agent Substrate](https://github.com/agent-substrate/substrate), introducing Harness, AgentTemplate, and AgentInstance as the new API surface. This section is under active development ahead of the 1.0 release. Pages here may be incomplete, and content may change without notice. See the [0.x docs]({{< relref "/kagent/0.x" >}}) for the current stable release. diff --git a/docs-site/content/kagent/1.x/about/_index.md b/docs-site/content/kagent/1.x/about/_index.md index e2b34a46..e2c087a0 100644 --- a/docs-site/content/kagent/1.x/about/_index.md +++ b/docs-site/content/kagent/1.x/about/_index.md @@ -1,7 +1,7 @@ --- title: About description: Learn the core concepts and architecture behind kagent 1.0. -weight: 2 +weight: 20 author: kagent.dev --- diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 768cc52c..9b459ce0 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -1,7 +1,7 @@ --- title: "Architecture: Agent Substrate" description: See how Agent Substrate runs, suspends, and resumes the Actors behind every AgentInstance. -weight: 4 +weight: 40 author: kagent.dev --- @@ -43,5 +43,7 @@ Substrate's own target for this cycle is 100ms at the 95th percentile, measured ## Next steps -- [Your first agent]({{< link path="get-started/your-first-agent" >}}): apply a Harness and AgentTemplate, and watch the Actor they produce suspend and resume. -- [Substrate operations]({{< link path="operations/substrate-operations" >}}): size a WorkerPool and choose a sandbox class for your cluster. +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} + {{< card link=`{{< link path="operations/substrate-operations" >}}` title="Substrate operations" subtitle="Size a WorkerPool and choose a sandbox class for your cluster." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 0228ab2f..dc59fd5d 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -1,7 +1,7 @@ --- title: Architecture description: See how a Harness and AgentTemplate become a running conversation, across kagent's two authorization planes. -weight: 3 +weight: 30 author: kagent.dev --- @@ -59,5 +59,7 @@ This split also keeps the two lifecycles independent. Editing a Harness or Agent ## Next steps -- [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}): what an Actor actually runs on, and how it suspends and resumes. -- [Your first agent]({{< link path="get-started/your-first-agent" >}}): apply a Harness and AgentTemplate, and create the AgentInstance they produce. +{{< cards >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="See what an Actor actually runs on, and how it suspends and resumes." >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} +{{< /cards >}} 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 c9f77d58..e8a7bc25 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -1,7 +1,7 @@ --- title: Core concepts description: Learn the Harness, AgentTemplate, AgentInstance, and Actor model that kagent 1.0 is built on. -weight: 2 +weight: 20 author: kagent.dev --- @@ -91,6 +91,8 @@ A Shared agent tool can itself have Dedicated agent tools underneath it, but a S ## Next steps -- [Architecture]({{< link path="about/architecture" >}}): how these pieces fit together end to end, from `kubectl apply` to a live conversation. -- [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}): Workers, WorkerPools, ActorTemplates, and how Actors suspend and resume. -- [Your first agent]({{< link path="get-started/your-first-agent" >}}): apply a Harness and AgentTemplate, and talk to the AgentInstance they create. +{{< cards >}} + {{< card link=`{{< link path="about/architecture" >}}` title="Architecture" subtitle="See how these pieces fit together end to end, from `kubectl apply` to a live conversation." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Learn about Workers, WorkerPools, ActorTemplates, and how Actors suspend and resume." >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md index 4956b9b3..40904e17 100644 --- a/docs-site/content/kagent/1.x/about/what-is-kagent.md +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -2,7 +2,7 @@ title: Introducing kagent linkTitle: What is kagent description: Understand what kagent is and its core purpose. -weight: 1 +weight: 10 author: kagent.dev --- diff --git a/docs-site/content/kagent/1.x/get-started/_index.md b/docs-site/content/kagent/1.x/get-started/_index.md index 6b754904..91326661 100644 --- a/docs-site/content/kagent/1.x/get-started/_index.md +++ b/docs-site/content/kagent/1.x/get-started/_index.md @@ -1,8 +1,6 @@ --- title: Get started description: Install kagent and create your first agent. -weight: 1 +weight: 10 author: kagent.dev ---- - -Install kagent, then create and talk to your first agent. +--- \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 6ec94ddf..340530eb 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -1,46 +1,27 @@ --- title: Your first agent -description: Apply a Harness and AgentTemplate, then create and talk to the AgentInstance they produce. -weight: 1 +description: Create and communicate with your first agent by using the kagent project. +weight: 10 author: kagent.dev --- -This guide walks through the full path from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance they produce. [Core concepts]({{< link path="about/core-concepts" >}}) defines each of these terms, and [Architecture]({{< link path="about/architecture" >}}) covers how they fit together. +This guide walks you through creating an agent, from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance that they produce. For definitions of each of these components, review the [core concepts]({{< link path="about/core-concepts" >}}). For an overview of how each component fits together in kagent, review the [architecture]({{< link path="about/architecture" >}}). -## Before you begin creating your first agent +## Before you begin -- Install kagent with a WorkerPool provisioned. See [Installation]({{< link path="setup/installation" >}}). -- Install [grpcurl](https://github.com/fullstorydev/grpcurl). -- Enable gRPC reflection on the controller, so grpcurl can discover its methods without a local copy of kagent's proto files. Add `--set controller.grpc.reflection=true` to your Helm install or upgrade command. -- Port-forward the controller's gRPC port to your local machine: - - ```shell - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 - ``` - -The kagent CLI does not yet have commands for Harness, AgentTemplate, or AgentInstance. Until it does, this guide uses `kubectl` and `grpcurl` directly. - -## Apply a Harness and an AgentTemplate - -1. Apply a `ModelConfig` that names your model provider: - - ```yaml - apiVersion: kagent.dev/v1alpha3 - kind: ModelConfig - metadata: - name: default-model-config - namespace: kagent - spec: - provider: "OpenAI" - model: "gpt-4.1-mini" - apiKeySecret: kagent-openai - apiKeySecretKey: OPENAI_API_KEY +1. [Install kagent with a WorkerPool provisioned]({{< link path="setup/installation" >}}). Be sure to add `--set controller.grpc.reflection=true` to the Helm install command so that grpcurl can discover the controller's gRPC methods without a local copy of kagent's proto files. +2. Install [grpcurl](https://github.com/fullstorydev/grpcurl). +3. Port-forward the controller's gRPC port to your local machine. + ```shell + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 ``` - If you installed kagent with the Helm chart's default model provider settings, this `ModelConfig` already exists. Skip this step in that case. +> [!NOTE] +> This guide uses `kubectl` and `grpcurl` directly, as the kagent CLI does not yet have commands for Harness, AgentTemplate, or AgentInstance. -2. Apply a `Harness` that uses kagent's native runtime: +## Create a Harness and an AgentTemplate +1. Apply a `Harness` that uses kagent's native runtime. ```yaml apiVersion: kagent.dev/v1alpha3 kind: Harness @@ -50,20 +31,24 @@ The kagent CLI does not yet have commands for Harness, AgentTemplate, or AgentIn spec: kagent: {} workload: - image: @sha256: # pin this to your kagent release's runtime image + # Your kagent release's runtime image + image: @sha256: substrate: workerPoolRef: name: kagent-default snapshotPolicy: + # The object storage location your cluster's Substrate installation uses for Actor snapshots location: gs:///kagent/ allowedAgentTemplates: selector: matchLabels: + # Selector to match the AgentTemplate label kagent.dev/harness: my-first-harness ``` + > [!NOTE] + > An `AgentTemplate` has no field naming this Harness. The `kagent.dev/harness: my-first-harness` selector is a convention that this guide uses to match the `kagent.dev/harness` label in the next step. However, you can choose any label key and value, as long as the Harness selector and the AgentTemplate's labels match. -3. Apply an `AgentTemplate` labeled to match that selector: - +2. Apply an `AgentTemplate` that is labeled to match the Harness's `allowedAgentTemplates` selector. The `ModelConfig` field references the `default-model-config` that was automatically created for the model provider API key that you provided during kagent installation. ```yaml apiVersion: kagent.dev/v1alpha3 kind: AgentTemplate @@ -71,63 +56,121 @@ The kagent CLI does not yet have commands for Harness, AgentTemplate, or AgentIn name: my-first-agent namespace: kagent labels: + # Label matching the Harness selector kagent.dev/harness: my-first-harness spec: description: My first kagent agent modelConfig: + # Default config created by the kagent install guide name: default-model-config systemPrompt: You are a concise, helpful assistant. ``` - An `AgentTemplate` has no field naming a Harness. The `kagent.dev/harness` label is only a convention this guide uses to match the selector above. Choose any label key and value, as long as the Harness selector and the AgentTemplate's labels agree. - -4. Confirm the pair is ready: - +3. Confirm that the pair is ready. ```shell - kubectl get agenttemplate my-first-agent -n kagent -o jsonpath='{.status.harnesses}' + kubectl get agenttemplate my-first-agent -n kagent -o jsonpath='{.status.harnesses}' | jq . ``` A ready pair reports a `Ready` condition for `my-first-harness`. If the status is empty, wait a few seconds for the kagent controller to reconcile, then check again. + ```json + [ + { + "harness": "my-first-harness", + "desiredRevision": "sha256:5f2b3c1a9e8d", + "latestSuccessfulRevision": "sha256:5f2b3c1a9e8d", + "conditions": [ + { + "type": "Ready", + "status": "True", + "reason": "Ready", + "message": "ActorTemplate is ready", + "lastTransitionTime": "2026-08-24T15:02:10Z" + } + ] + } + ] + ``` ## Create the AgentInstance -Once the pair is ready, create an AgentInstance from it: +1. Create an AgentInstance from the Harness and AgentTemplate pair. + ```shell + RESPONSE=$(grpcurl -plaintext \ + -d '{"namespace":"kagent","harness":"my-first-harness","agentTemplate":"my-first-agent","requestId":"'"$(uuidgen)"'"}' \ + localhost:8084 kagent.api.v1alpha1.AgentInstanceService/CreateAgentInstance) + echo "$RESPONSE" + ``` -```shell -grpcurl -plaintext \ - -d '{"namespace":"kagent","harness":"my-first-harness","agentTemplate":"my-first-agent","requestId":"'"$(uuidgen)"'"}' \ - localhost:8084 kagent.api.v1alpha1.AgentInstanceService/CreateAgentInstance -``` + A successful response includes the new AgentInstance and its `id`. + ```json + { + "agentInstance": { + "id": "8f14e45f-ceea-4a37-b0f1-2b5c4d3a9c6e", + "namespace": "kagent", + "harness": { + "namespace": "kagent", + "name": "my-first-harness" + }, + "agentTemplate": { + "namespace": "kagent", + "name": "my-first-agent" + }, + "state": "AGENT_INSTANCE_STATE_READY" + } + } + ``` -The response includes an `id` field. Save it. The next step needs it to address the AgentInstance you just created. +2. Save the AgentInstance's `id` to an environment variable. The next step needs it to address the AgentInstance you created. + ```shell + export INSTANCE_ID=$(echo "$RESPONSE" | jq -r '.agentInstance.id') + ``` ## Talk to your agent -Send a message to the AgentInstance over the A2A (Agent-to-Agent) protocol, using the `id` from the previous step: +Send a message to the AgentInstance over the A2A (Agent-to-Agent) protocol. ```shell grpcurl -plaintext \ -H "x-kagent-agent-instance-namespace: kagent" \ - -H "x-kagent-agent-instance-id: " \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"What is 2+2?"}]}}' \ localhost:8084 lf.a2a.v1.A2AService/SendMessage ``` The response carries the agent's reply in the same `parts` shape as the request. +```json +{ + "message": { + "messageId": "b2b1e2b4-5c3a-4f8e-9d1a-7e6f5c4b3a2d", + "role": "ROLE_AGENT", + "parts": [ + { + "text": "4" + } + ] + } +} +``` -A future kagent CLI release will wrap the create-and-converse steps above into a single command. - -## Clean up your first agent +## Clean up -```shell -kubectl delete agenttemplate my-first-agent -n kagent -kubectl delete harness my-first-harness -n kagent -``` +1. Delete the Harness and AgentTemplate. + ```shell + kubectl delete agenttemplate my-first-agent -n kagent + kubectl delete harness my-first-harness -n kagent + ``` -Deleting the Harness and AgentTemplate does not delete the AgentInstance you created from them. Delete it directly through the same `AgentInstanceService` you used to create it. +2. Delete the AgentInstance directly through the same `AgentInstanceService` you used to create it, as deleting the Harness and AgentTemplate does not delete the AgentInstance you created from them. + ```shell + grpcurl -plaintext \ + -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'"}' \ + localhost:8084 kagent.api.v1alpha1.AgentInstanceService/DeleteAgentInstance + ``` ## Next steps -- [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}): what happens to your AgentInstance's Actor when it sits idle. -- [Agent harness]({{< link path="agents/agent-harness" >}}): the full set of Harness runtime options, including Claude Code and Codex. -- [Skills]({{< link path="skills-mcp/skills" >}}): give your agent capabilities beyond its system prompt. +{{< cards >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Understand what happens to your AgentInstance's Actor when it sits idle." >}} + {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Choose from the full set of Harness runtime options, including Claude Code and Codex." >}} + {{< card link=`{{< link path="skills-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities beyond its system prompt." >}} +{{< /cards >}} From 835c9b4220c47de993558e9700f012a20307eb42 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 24 Aug 2026 15:12:26 -0500 Subject: [PATCH 07/70] Phase 1, review 2 Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 2 +- .../content/kagent/1.x/about/architecture.md | 2 +- .../content/kagent/1.x/about/core-concepts.md | 10 +++--- .../kagent/1.x/about/what-is-kagent.md | 33 +++++++++---------- .../1.x/get-started/your-first-agent.md | 4 +-- .../content/kagent/1.x/not-in-version.md | 2 +- 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 9b459ce0..fc508f34 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -25,7 +25,7 @@ An **ActorTemplate** is the compiled, immutable definition that a new Actor is c Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming this way lets a WorkerPool run far more Actors than it has Workers for at any one moment. -The diagram below follows an Actor through one suspend-and-resume cycle. Read it left to right: a WorkerPool hosts Workers, a Worker hosts a running Actor, suspending that Actor produces a snapshot, and a tag on that snapshot lets a later Actor resume from it on whichever Worker is free. +The following diagram traces an Actor through one suspend-and-resume cycle. Read it left to right: a WorkerPool hosts Workers, a Worker hosts a running Actor, suspending that Actor produces a snapshot, and a tag on that snapshot lets a later Actor resume from it on whichever Worker is free. ```mermaid flowchart LR diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index dc59fd5d..aaa2872a 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -12,7 +12,7 @@ kagent 1.0 splits authorization across two planes, not one: - The **Kubernetes plane** governs the Harness and AgentTemplate custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit them, exactly as it would for any other Custom Resource Definition (CRD). - The **kagent plane** governs AgentInstances: creating one, suspending or resuming it, sharing it, deleting it, and holding a conversation with it. kagent's own gRPC authentication and authorization decide who can do these things, independent of Kubernetes RBAC. -Someone with RBAC access to apply a Harness and AgentTemplate does not automatically get access to create or talk to AgentInstances that use them, and the reverse is also true. The diagram below shows where the boundary between the two planes falls, and the walkthrough after it follows a request across that boundary from start to finish. +Someone with RBAC access to apply a Harness and AgentTemplate does not automatically get access to create or talk to AgentInstances that use them, and the reverse is also true. The following diagram shows where the boundary between the two planes falls, and the walkthrough after it follows a request across that boundary from start to finish. ```mermaid flowchart TB 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 e8a7bc25..f00a81e6 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -5,7 +5,7 @@ weight: 20 author: kagent.dev --- -kagent 1.0 replaces the Deployment-based `Agent` custom resource with a new model built around **Harness**, **AgentTemplate**, and **AgentInstance**, running on [Agent Substrate]({{< link path="about/agent-substrate" >}}) instead of plain Kubernetes Deployments. This page defines the vocabulary the rest of these docs use. If your existing kagent installation is on 0.x, see the [0.x docs]({{< relref "/kagent/0.x" >}}). This page and everything under it describes the 1.0 model only. +kagent 1.0 replaces the Deployment-based `Agent` custom resource with a new model built around **Harness**, **AgentTemplate**, and **AgentInstance**, running on [Agent Substrate]({{< link path="about/agent-substrate" >}}) instead of the plain Kubernetes Deployments that the 0.x model uses. This page defines the vocabulary that the rest of the 1.0 model docs use. The new model separates what an agent can do from how it is allowed to run: @@ -14,7 +14,7 @@ The new model separates what an agent can do from how it is allowed to run: - An **AgentInstance** is a running conversation, created by pairing the two. - An **Actor** is the sandboxed process, provided by Substrate, that an AgentInstance runs on. -The diagram below shows how a Harness and an AgentTemplate become a running conversation. Follow the arrows from left to right: the kagent controller compiles the Harness and AgentTemplate pair into an ActorTemplate, and each AgentInstance is created from that ActorTemplate and runs on an Actor. +The following diagram shows how a Harness and an AgentTemplate become a running conversation. Follow the arrows from left to right: the kagent controller compiles the Harness and AgentTemplate pair into an ActorTemplate, and each AgentInstance is created from that ActorTemplate and runs on an Actor. ```mermaid flowchart LR @@ -35,7 +35,7 @@ flowchart LR class harness,template crd ``` -The Harness and AgentTemplate are the only two resources an operator applies directly. The kagent controller watches for a valid pair and compiles it into an ActorTemplate. From there, each AgentInstance created from that ActorTemplate gets its own Actor to run on. The rest of this page defines each of these terms in more detail. +The Harness and AgentTemplate are the only two resources that an operator applies directly. The kagent controller watches for a valid pair and compiles it into an ActorTemplate. From there, each AgentInstance created from that ActorTemplate gets its own Actor to run on. The rest of this page defines each of these terms in more detail. ## Harness @@ -56,7 +56,7 @@ An **AgentTemplate** is a Kubernetes custom resource that defines what an agent - **Model configuration**: the large language model (LLM) provider and model the agent uses. This is the only field an AgentTemplate strictly requires. - **System prompt**: a literal prompt, or a Go-templated one that can `include` shared ConfigMaps. -- **Tools**: a list of tool bindings the agent can call. Each binding is either a Model Context Protocol (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated) below). +- **Tools**: a list of tool bindings the agent can call. Each binding is either a Model Context Protocol (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated)). - **Skills** and **plugins**: reusable capability packages, sourced from an Open Container Initiative (OCI) registry, Git, or S3. An AgentTemplate does nothing on its own. It becomes runnable once it is paired with a Harness whose `allowedAgentTemplates` selector accepts it. @@ -70,7 +70,7 @@ This split is deliberate, not an implementation detail to work around: - Applying a Harness or AgentTemplate is a **Kubernetes-native operation**, governed by Kubernetes RBAC, exactly like any other CRD. - Creating, suspending, resuming, sharing, or deleting an AgentInstance, and holding a conversation with it, are **kagent-native operations**, governed by kagent's own gRPC authentication and authorization, independent of who can `kubectl apply` a Harness or AgentTemplate. -Under the hood, the kagent controller watches for valid Harness and AgentTemplate pairs and compiles each one into an immutable `ActorTemplate`, a Substrate resource keyed by a digest of the compiled revision. Creating an AgentInstance resolves to the latest successfully compiled ActorTemplate for that pair and creates an Actor from it. If you edit the Harness or AgentTemplate, existing AgentInstances keep running against the ActorTemplate they were created from. New AgentInstances pick up the new revision. +Under the hood, the kagent controller watches for valid Harness and AgentTemplate pairs and compiles each one into an immutable `ActorTemplate`, a Substrate resource keyed by a digest of the compiled revision. Creating an AgentInstance resolves to the latest successfully compiled ActorTemplate for that pair and creates an Actor from it. If you edit the Harness or AgentTemplate, existing AgentInstances keep running against the ActorTemplate that they were created from. New AgentInstances pick up the new revision. Once created, an AgentInstance talks to callers over the A2A (Agent-to-Agent) protocol, through kagent's A2A gateway. The gateway resolves each request to the right AgentInstance and forwards it to the Actor running behind it. diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md index 40904e17..42362f61 100644 --- a/docs-site/content/kagent/1.x/about/what-is-kagent.md +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -1,16 +1,15 @@ --- -title: Introducing kagent -linkTitle: What is kagent -description: Understand what kagent is and its core purpose. +title: What is kagent? +description: Understand what the kagent platform is and its core purpose. weight: 10 author: kagent.dev --- -kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with coding-agent runtimes such as Claude Code and Codex, agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and every major large language model (LLM) provider. +kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability that you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with coding-agent runtimes such as Claude Code and Codex, agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and every major large language model (LLM) provider. kagent was created at [Solo.io](https://www.solo.io) in 2025 and is a [Cloud Native Computing Foundation](https://www.cncf.io) sandbox project. -## What is kagent? +## How kagent works Unlike a traditional chatbot, kagent uses advanced reasoning and iterative planning to autonomously handle multi-step problems in cloud-native environments. It turns AI insight into concrete action, helping teams tackle common operational challenges such as: @@ -25,18 +24,18 @@ Unlike a traditional chatbot, kagent uses advanced reasoning and iterative plann kagent 1.0 separates an agent's capabilities from its runtime, then runs the two together as a conversation: - A **Harness** and an **AgentTemplate** are the Kubernetes custom resources you author. Together they say how an agent is allowed to run and what it can do. -- An **AgentInstance** is the running conversation those two resources produce, backed by an **Actor** on Agent Substrate. +- An **AgentInstance** is the running conversation that those two resources produce, backed by an **Actor** on Agent Substrate. -[Core concepts]({{< link path="about/core-concepts" >}}) defines each of these in detail, and [Architecture]({{< link path="about/architecture" >}}) walks through how they connect end to end. +[Core concepts]({{< link path="about/core-concepts" >}}) define each of these in detail, and the [architecture]({{< link path="about/architecture" >}}) walks through how they connect end to end. -## Why kagent? +## Benefits kagent addresses the growing complexity of cloud-native operations by: -- Automating routine troubleshooting and operational tasks -- Reducing the need for specialist intervention in common scenarios -- Enabling teams to formalize and share their operational expertise -- Providing a platform for building and sharing custom AI agents +- Automating routine troubleshooting and operational tasks. +- Reducing the need for specialist intervention in common scenarios. +- Enabling teams to formalize and share their operational expertise. +- Providing a platform for building and sharing custom AI agents. ## Platform features @@ -69,9 +68,9 @@ Ready to contribute? Visit the [GitHub repository](https://github.com/kagent-dev ## Community -Join the kagent community: +Join the kagent community! -- Explore the repositories on [GitHub](https://github.com/kagent-dev) -- Join the discussion in the #kagent channel on CNCF Slack -- Check the [FAQ]({{< link path="reference/faq" >}}) for common questions -- Follow the [feature roadmap](https://github.com/kagent-dev/kagent/blob/main/README.md#roadmap) for upcoming developments +- Explore the repositories on [GitHub](https://github.com/kagent-dev). +- Join the discussion in the #kagent channel on CNCF Slack. +- Check the [FAQ]({{< link path="reference/faq" >}}) for common questions. +- Follow the [feature roadmap](https://github.com/kagent-dev/kagent/blob/main/README.md#roadmap) for upcoming developments. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 340530eb..584ca0bf 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -120,7 +120,7 @@ This guide walks you through creating an agent, from applying a Harness and an A } ``` -2. Save the AgentInstance's `id` to an environment variable. The next step needs it to address the AgentInstance you created. +2. Save the AgentInstance's `id` to an environment variable. The next step needs it to address the AgentInstance that you created. ```shell export INSTANCE_ID=$(echo "$RESPONSE" | jq -r '.agentInstance.id') ``` @@ -160,7 +160,7 @@ The response carries the agent's reply in the same `parts` shape as the request. kubectl delete harness my-first-harness -n kagent ``` -2. Delete the AgentInstance directly through the same `AgentInstanceService` you used to create it, as deleting the Harness and AgentTemplate does not delete the AgentInstance you created from them. +2. Delete the AgentInstance directly through the same `AgentInstanceService` that you used to create it, as deleting the Harness and AgentTemplate does not delete the AgentInstance that you created from them. ```shell grpcurl -plaintext \ -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'"}' \ diff --git a/docs-site/content/kagent/1.x/not-in-version.md b/docs-site/content/kagent/1.x/not-in-version.md index 2380ad55..7f96bd52 100644 --- a/docs-site/content/kagent/1.x/not-in-version.md +++ b/docs-site/content/kagent/1.x/not-in-version.md @@ -5,4 +5,4 @@ build: list: never --- -This topic doesn't exist in this version of the kagent docs yet. Use the version switcher above to go back to a version where it's available, or browse the [kagent 1.0 (preview)]({{< link path="" >}}) landing page. +This topic doesn't exist in this version of the kagent docs yet. Use the version switcher to go back to a version where it's available, or browse the [kagent 1.0 (preview)]({{< link path="" >}}) landing page. From b98a32ad54c545a3e1f40f59e7b8dea264d2a93a Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 15:32:02 -0500 Subject: [PATCH 08/70] Phase 1, review 3 Signed-off-by: Rachael Graham --- .../content/kagent/1.x/about/core-concepts.md | 65 ++++++++++++------- .../1.x/get-started/your-first-agent.md | 6 +- 2 files changed, 43 insertions(+), 28 deletions(-) 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 f00a81e6..6f314293 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -9,12 +9,12 @@ kagent 1.0 replaces the Deployment-based `Agent` custom resource with a new mode The new model separates what an agent can do from how it is allowed to run: -- A **Harness** defines how an agent is allowed to run. It picks a runtime and the infrastructure policy around it. -- An **AgentTemplate** defines what an agent can do: its model, prompt, and tools. -- An **AgentInstance** is a running conversation, created by pairing the two. -- An **Actor** is the sandboxed process, provided by Substrate, that an AgentInstance runs on. +- A [**Harness**](#harness) defines how an agent is allowed to run. It picks a runtime and the infrastructure policy around it. +- An [**AgentTemplate**](#agenttemplate) defines what an agent can do: its model, prompt, and tools. +- An [**AgentInstance**](#agentinstance) is a running conversation, created by pairing the two. +- An [**Actor**](#actor) is the sandboxed process, provided by Substrate, that an AgentInstance runs on. -The following diagram shows how a Harness and an AgentTemplate become a running conversation. Follow the arrows from left to right: the kagent controller compiles the Harness and AgentTemplate pair into an ActorTemplate, and each AgentInstance is created from that ActorTemplate and runs on an Actor. +The following diagram shows how a Harness and an AgentTemplate become a running conversation. The kagent controller compiles the Harness and AgentTemplate pair into an ActorTemplate, and each AgentInstance is created from that ActorTemplate and runs on an Actor. ```mermaid flowchart LR @@ -28,71 +28,86 @@ flowchart LR harness --> controller template --> controller controller -->|compiles the pair into| actortemplate - instance -->|created from| actortemplate + actortemplate -->|instantiated as| instance instance -->|runs on| actor classDef crd stroke:#a78bfa,fill:transparent class harness,template crd ``` -The Harness and AgentTemplate are the only two resources that an operator applies directly. The kagent controller watches for a valid pair and compiles it into an ActorTemplate. From there, each AgentInstance created from that ActorTemplate gets its own Actor to run on. The rest of this page defines each of these terms in more detail. +The Harness and AgentTemplate are the only two resources that an operator applies directly. The kagent controller watches for a valid pair and compiles it into an ActorTemplate. From there, each AgentInstance created from that ActorTemplate gets its own Actor to run on. ## Harness -A **Harness** is a Kubernetes custom resource that defines how an agent is allowed to run. It specifies: +A **Harness** is a Kubernetes custom resource that defines _how an agent is allowed to run_. It specifies: -- **Runtime**: the engine that executes the agent. This is either kagent's own Go or Python runtime, or a bring-your-own coding agent such as Claude Code or Codex. -- **Workload**: the container image and environment the runtime runs in. -- **Substrate policy**: the [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their snapshots are stored. -- **Allowed AgentTemplates**: a selector that names which AgentTemplates are permitted to run on this Harness. +- **Runtime**: The engine that executes the agent. This is either kagent's own Go or Python runtime, or a bring-your-own coding agent such as Claude Code or Codex. +- **Workload**: The container image and environment the runtime runs in. +- **Substrate policy**: The [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their snapshots are stored. +- **Allowed AgentTemplates**: A selector that names which AgentTemplates are permitted to run on this Harness. That last point is a one-way match, not a mutual handshake. An AgentTemplate has no field naming a Harness. Instead, a Harness's `allowedAgentTemplates` selector matches on labels, and any AgentTemplate in the same namespace carrying a matching label becomes eligible to run on it. Whoever controls a Harness's selector decides which AgentTemplates it accepts. A Harness owns no running compute by itself. Applying one registers a runtime and policy that an AgentTemplate can pair with. +For the complete Harness schema, see the [API reference]({{< link path="reference/api-ref#harness" >}}). + +> [!IMPORTANT] +> This `Harness` is unrelated to 0.x's `AgentHarness` resource, which provisions OpenClaw or Hermes coding-agent sandboxes. `Harness` is a different resource that covers how any agent is allowed to run, not a renamed or expanded version of `AgentHarness`. + ## AgentTemplate -An **AgentTemplate** is a Kubernetes custom resource that defines what an agent does. It specifies: +An **AgentTemplate** is a Kubernetes custom resource that defines _what an agent does_. It specifies: -- **Model configuration**: the large language model (LLM) provider and model the agent uses. This is the only field an AgentTemplate strictly requires. -- **System prompt**: a literal prompt, or a Go-templated one that can `include` shared ConfigMaps. -- **Tools**: a list of tool bindings the agent can call. Each binding is either a Model Context Protocol (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated)). -- **Skills** and **plugins**: reusable capability packages, sourced from an Open Container Initiative (OCI) registry, Git, or S3. +- **Model configuration**: The large language model (LLM) provider and model the agent uses. This is the only field an AgentTemplate strictly requires. +- **System prompt**: A literal prompt, or a Go-templated one that can `include` shared ConfigMaps. +- **Tools**: A list of tool bindings the agent can call. Each binding is either a Model Context Protocol (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated)). +- **Skills** and **plugins**: Reusable capability packages, sourced from an Open Container Initiative (OCI) registry, Git, or S3. An AgentTemplate does nothing on its own. It becomes runnable once it is paired with a Harness whose `allowedAgentTemplates` selector accepts it. +For the complete AgentTemplate schema, see the [API reference]({{< link path="reference/api-ref#agenttemplate" >}}). + ## AgentInstance -An **AgentInstance** is a running, conversational pairing of a Harness and an AgentTemplate. Unlike Harness and AgentTemplate, an AgentInstance is not a Kubernetes custom resource. It does not live in etcd. kagent's own gRPC API creates it, and kagent's PostgreSQL database tracks it. +An **AgentInstance** is a _running, conversational pairing_ of a Harness and an AgentTemplate. Unlike Harness and AgentTemplate, an AgentInstance is not a Kubernetes custom resource, and does not live in etcd. kagent's own gRPC API creates it, and kagent's PostgreSQL database tracks it. This split is deliberate, not an implementation detail to work around: - Applying a Harness or AgentTemplate is a **Kubernetes-native operation**, governed by Kubernetes RBAC, exactly like any other CRD. - Creating, suspending, resuming, sharing, or deleting an AgentInstance, and holding a conversation with it, are **kagent-native operations**, governed by kagent's own gRPC authentication and authorization, independent of who can `kubectl apply` a Harness or AgentTemplate. -Under the hood, the kagent controller watches for valid Harness and AgentTemplate pairs and compiles each one into an immutable `ActorTemplate`, a Substrate resource keyed by a digest of the compiled revision. Creating an AgentInstance resolves to the latest successfully compiled ActorTemplate for that pair and creates an Actor from it. If you edit the Harness or AgentTemplate, existing AgentInstances keep running against the ActorTemplate that they were created from. New AgentInstances pick up the new revision. +Under the hood, the kagent controller watches for valid Harness and AgentTemplate pairs and compiles each pair into an `ActorTemplate`, a Substrate resource that holds everything Substrate needs to start an Actor. + +Each compile produces one **revision**, identified by a digest: a SHA-256 hash of the compiled configuration. Because that digest is derived from the configuration itself, editing a Harness or AgentTemplate compiles to a different digest, and therefore becomes a separate ActorTemplate. kagent never rewrites an existing one. + +That immutability is what keeps running conversations stable. When you create an AgentInstance, kagent looks up the newest revision that compiled successfully for that Harness and AgentTemplate pair, and then creates an Actor from that revision. Editing the Harness or AgentTemplate afterward does not disturb that AgentInstance, which keeps running on the revision that it was created from. Only AgentInstances created after the edit use the new revision. Once created, an AgentInstance talks to callers over the A2A (Agent-to-Agent) protocol, through kagent's A2A gateway. The gateway resolves each request to the right AgentInstance and forwards it to the Actor running behind it. +For the AgentInstance gRPC service definition, see the [API reference]({{< link path="reference/api-ref" >}}). + ## Actor -An **Actor** is the sandboxed unit of compute, provided by [Agent Substrate]({{< link path="about/agent-substrate" >}}), that runs an AgentInstance's conversation loop. Every AgentInstance is backed by an Actor. +An **Actor** is the sandboxed unit of compute, provided by [Agent Substrate]({{< link path="about/agent-substrate" >}}), that _runs an AgentInstance's conversation loop_. Every AgentInstance is backed by an Actor. -Actors are why AgentInstances can suspend and resume cheaply instead of staying resident: an idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}) covers the full mechanics (Workers, WorkerPools, ActorTemplates, and snapshotting). For this page, an Actor is simply the sandbox that an AgentInstance's conversation runs inside. +Actors are the reason why AgentInstances can suspend and resume cheaply instead of staying resident. An idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. To understand the full mechanics (Workers, WorkerPools, ActorTemplates, and snapshotting), see [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}). ## Agent tools: Shared vs. Dedicated An AgentTemplate's tools are not limited to MCP servers. A tool binding can also point at another AgentTemplate, letting one agent call another agent as a tool. Each agent-tool binding picks an isolation mode: -- **Shared** (the default): the child agent runs inside the same Actor as its parent. This is cheaper, and the child shares its parent's fate. If the parent's Actor is suspended or crashes, so does the child. -- **Dedicated**: the child agent gets its own Actor, isolated from its parent. This is more expensive, but a crash or a long-running task in the child cannot take down the parent, and the child can be scaled, suspended, or resumed independently. +- **Shared** (default): The child agent runs inside the same Actor as its parent. This option is cheaper, but the child shares its parent's fate: if the parent's Actor is suspended or crashes, so does the child. +- **Dedicated**: The child agent gets its own Actor, isolated from its parent. This option is more expensive, but a crash or a long-running task in the child cannot take down the parent, and the child can be scaled, suspended, or resumed independently. + +Shared nesting never goes more than one level deep. A Shared agent tool can have Dedicated agent tools beneath it, but it cannot contain another Shared one. -A Shared agent tool can itself have Dedicated agent tools underneath it, but a Shared agent tool cannot contain another Shared one. Sharing a single Actor only ever goes one level deep. Restricting Shared nesting this way keeps the isolation model easy to reason about: at any point in an agent's tool tree, you can tell exactly which Actor a given call executes in just by walking up to the nearest Dedicated boundary, or the root. +This limit keeps the model predictable. A Dedicated binding gives the child its own Actor. A Shared binding puts the child in its parent's Actor, and because Shared bindings cannot chain, that parent always has an Actor of its own. Working out where any agent runs is therefore never more than a single step. ## Next steps {{< cards >}} {{< card link=`{{< link path="about/architecture" >}}` title="Architecture" subtitle="See how these pieces fit together end to end, from `kubectl apply` to a live conversation." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Learn about Workers, WorkerPools, ActorTemplates, and how Actors suspend and resume." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Learn about Workers, WorkerPools, and ActorTemplates, and how Actors suspend and resume." >}} {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 584ca0bf..10fd20f4 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -5,7 +5,7 @@ weight: 10 author: kagent.dev --- -This guide walks you through creating an agent, from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance that they produce. For definitions of each of these components, review the [core concepts]({{< link path="about/core-concepts" >}}). For an overview of how each component fits together in kagent, review the [architecture]({{< link path="about/architecture" >}}). +This guide walks you through creating an agent, from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance that they produce. For definitions of each of these components, review the [core concepts]({{< link path="about/core-concepts" >}}). For an overview of how each component fits together in kagent, review the [architecture]({{< link path="about/architecture" >}}). For the complete schema of every field that this guide sets, see the [API reference]({{< link path="reference/api-ref" >}}). ## Before you begin @@ -76,8 +76,8 @@ This guide walks you through creating an agent, from applying a Harness and an A [ { "harness": "my-first-harness", - "desiredRevision": "sha256:5f2b3c1a9e8d", - "latestSuccessfulRevision": "sha256:5f2b3c1a9e8d", + "desiredRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b", + "latestSuccessfulRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b", "conditions": [ { "type": "Ready", From cb9032323d0d51fb075e957052c92f0e7d1cc31a Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 15:44:13 -0500 Subject: [PATCH 09/70] Render the docs preview server to memory Hugo's server renders to disk and serves from docs-site/public, the same directory build-docs writes and clean removes. Emptying it mid-session strands the running server: later saves re-render only the touched pages, so pages return but stylesheets do not, and the preview degrades with each edit. --renderToMemory removes the shared directory. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7ed431cf..e0f08aa9 100644 --- a/Makefile +++ b/Makefile @@ -47,8 +47,15 @@ inject-docs: ## Copy built docs into public/docs (preserves tracked assets, e.g. $(DOCS_OUT)/ $(WEB_DOCS)/ .PHONY: serve-docs +# --renderToMemory keeps the preview out of $(DOCS_OUT) entirely. Hugo's server +# otherwise renders to disk and serves from there, so it shares one directory +# with `build-docs`/`clean`. Anything that empties that directory mid-session -- +# a `make clean` or `make build` in a second terminal -- strands the running +# server: each later save re-renders only the pages it touched, so pages come +# back but the stylesheets never do, and the preview degrades edit by edit +# instead of failing outright. Rendering to memory removes the shared directory. serve-docs: ## Preview the docs alone at http://localhost:1313/docs/ - cd $(DOCS_DIR) && $(HUGO) server --config hugo.yaml -D --disableFastRender + cd $(DOCS_DIR) && $(HUGO) server --config hugo.yaml -D --disableFastRender --renderToMemory # ── Web (Next.js) ────────────────────────────────────────────────────────── .PHONY: serve-web From 2d6b28394cc22db0149e8493c659fc1f5b82451d Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 16:56:25 -0500 Subject: [PATCH 10/70] Phase 1, review 4 Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 33 ++++++++++----- .../content/kagent/1.x/about/architecture.md | 41 ++++++++++++------- .../1.x/get-started/your-first-agent.md | 6 ++- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index fc508f34..d77054a2 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -5,27 +5,36 @@ weight: 40 author: kagent.dev --- -[Architecture]({{< link path="about/architecture" >}}) covers where an Actor fits between an AgentInstance and a running conversation. This page covers how Agent Substrate itself runs that Actor: on what compute, inside what sandbox, and how it suspends and resumes without staying resident the whole time. +[Architecture]({{< link path="about/architecture" >}}) established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate it is created from, the compute that hosts it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand. -## Workers and WorkerPools +## ActorTemplate -A **WorkerPool** is a Kubernetes custom resource that an operator provisions before any Harness can create AgentInstances. It defines a pool of pre-started sandbox pods, called **Workers**, along with the sandbox technology those Workers use. +Every Actor is created from an **ActorTemplate**, the compiled definition that the kagent controller produces from a Harness and AgentTemplate pair. -A Worker is not something an operator creates directly. Substrate manages Workers itself, keeping enough of them ready in each WorkerPool so that an Actor can start or resume on one immediately, without waiting on the Kubernetes scheduler to place a new Pod. +What Substrate adds is enforcement. Substrate rejects any change to an ActorTemplate's spec after it is created, so immutability is a property of the resource itself rather than a convention that the controller follows. That immutability requires the controller to create a new ActorTemplate for every compiled revision instead of editing an existing one, and allows the controller to safely reclaim an old ActorTemplate once no AgentInstance references it. -## Sandboxing +## Workers and WorkerPools -Because an Actor often runs a model-directed agent that calls tools and executes commands, Substrate runs each Actor in an isolated sandbox rather than a plain container. A WorkerPool's `sandboxClass` field selects the sandbox technology for its Workers: [gVisor](https://gvisor.dev) or a micro-VM technology such as [Kata Containers](https://katacontainers.io). Both technologies isolate an Actor from its Worker's host kernel, and both support the suspend and resume operations that the rest of this page covers. +An Actor needs somewhere to run. Each Actor runs on a **Worker**: a pre-started, sandboxed pod that hosts at most one Actor at a time. Instead of starting a new pod each time an AgentInstance needs an Actor, Substrate schedules that Actor onto a Worker that is already running and waiting. -## ActorTemplate +Workers come from a **WorkerPool**, a Kubernetes custom resource that an operator provisions before any Harness can create AgentInstances. A WorkerPool declares how many Workers to keep running and which sandbox technology those Workers use. -An **ActorTemplate** is the compiled, immutable definition that a new Actor is created from. [Architecture]({{< link path="about/architecture" >}}) covers how the kagent controller compiles a Harness and AgentTemplate pair into one. Substrate rejects any change to an ActorTemplate's spec after creation, so the kagent controller creates a new ActorTemplate for every compiled revision rather than editing an existing one, and reclaims old ones once no AgentInstance references them. +An operator never creates a Worker directly. Substrate manages them, keeping enough ready in each WorkerPool so that an Actor can start or resume on one immediately, without waiting on the Kubernetes scheduler to place a new Pod. + +## Sandboxing + +Because an Actor often runs a model-directed agent that calls tools and executes commands, Substrate runs each Actor in an isolated sandbox rather than a plain container. A WorkerPool's `sandboxClass` field selects the sandbox technology for its Workers: [gVisor](https://gvisor.dev) or a micro-VM technology such as [Kata Containers](https://katacontainers.io). Both technologies isolate an Actor from its Worker's host kernel, and both support suspend and resume operations. ## Suspend, snapshot, and resume -Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming this way lets a WorkerPool run far more Actors than it has Workers for at any one moment. +Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming allows a WorkerPool to run far more Actors than it has Workers for at any given moment. -The following diagram traces an Actor through one suspend-and-resume cycle. Read it left to right: a WorkerPool hosts Workers, a Worker hosts a running Actor, suspending that Actor produces a snapshot, and a tag on that snapshot lets a later Actor resume from it on whichever Worker is free. +The following diagram traces an Actor through one suspend-and-resume cycle. +1. A WorkerPool hosts Workers. +2. A Worker hosts a running Actor. +3. Suspending that Actor produces a snapshot. +4. That snapshot is tagged. +5. A later Actor uses the tag to resume from the snapshot on whichever Worker is free. ```mermaid flowchart LR @@ -37,7 +46,9 @@ flowchart LR tag -->|resume| worker2 ``` -Suspending an Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker it was running on. An **ActorSnapshotTag** gives that snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag's target can be updated to point at a newer snapshot without changing the tag's own name, and a snapshot cannot be deleted while any tag still points to it. Resuming reads the tagged snapshot and restores it onto whichever Worker in the pool is free, not necessarily the Worker the Actor originally ran on. +Suspending an Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker that it was running on. Resuming reads that snapshot back and restores the Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that it originally ran on. Because the snapshot captures the Actor's full state, the conversation continues from where it left off. + +An **ActorSnapshotTag** gives a snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag can be repointed at a newer snapshot without its own name changing, and Substrate does not delete a snapshot while any tag still points to it. Substrate's own target for this cycle is 100ms at the 95th percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index aaa2872a..68e6e15f 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -5,23 +5,27 @@ weight: 30 author: kagent.dev --- -[Core concepts]({{< link path="about/core-concepts" >}}) defines Harness, AgentTemplate, AgentInstance, and Actor on their own. This page connects them into one system: how applying a Harness and AgentTemplate leads to a running conversation, and which parts of that path Kubernetes governs versus which parts kagent governs itself. +The previous page defined the [core concepts]({{< link path="about/core-concepts" >}}) of Harness, AgentTemplate, AgentInstance, and Actor. This page connects them into one system: how applying a Harness and AgentTemplate leads to a running conversation, and which parts of that path Kubernetes governs versus which parts kagent governs itself. -kagent 1.0 splits authorization across two planes, not one: +## Two authorization planes -- The **Kubernetes plane** governs the Harness and AgentTemplate custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit them, exactly as it would for any other Custom Resource Definition (CRD). -- The **kagent plane** governs AgentInstances: creating one, suspending or resuming it, sharing it, deleting it, and holding a conversation with it. kagent's own gRPC authentication and authorization decide who can do these things, independent of Kubernetes RBAC. +kagent 1.0 splits authorization across two planes: -Someone with RBAC access to apply a Harness and AgentTemplate does not automatically get access to create or talk to AgentInstances that use them, and the reverse is also true. The following diagram shows where the boundary between the two planes falls, and the walkthrough after it follows a request across that boundary from start to finish. +- The **Kubernetes plane** governs the Harness and AgentTemplate custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit the resources, exactly as it would for any other Custom Resource Definition (CRD). +- The **kagent plane** governs any interactions involving AgentInstances, such as creating, suspending, resuming, sharing, deleting, and holding a conversation with an AgentInstance. kagent's own gRPC authentication and authorization decide who can complete these interactions, independent of Kubernetes RBAC. + +Someone with Kubernetes RBAC access to apply a Harness and AgentTemplate does not automatically have access to create or talk to AgentInstances that use them, and the reverse is also true. The following diagram shows where the boundary between the two planes falls. +

      ```mermaid flowchart TB + subgraph k8s["Kubernetes plane (RBAC)"] operator["Operator
      kubectl apply"] harness["Harness"] template["AgentTemplate"] controller["kagent controller"] - actortemplate["ActorTemplate
      (Substrate)"] + actortemplate["ActorTemplate (Substrate)"] operator --> harness operator --> template harness --> controller @@ -31,31 +35,38 @@ flowchart TB subgraph kagentplane["kagent plane (gRPC auth)"] caller["Caller"] - instance["AgentInstance"] gateway["A2A gateway"] - actor["Actor
      (Substrate)"] - caller -->|CreateAgentInstance| instance - instance -->|created from| actortemplate - instance -->|runs on| actor + instance["AgentInstance"] + actor["Actor (Substrate)"] caller -->|A2A conversation| gateway + caller -->|CreateAgentInstance| instance gateway -->|routes to| actor + instance -->|runs on| actor end + %% Declared outside both subgraphs on purpose: a node belongs to whichever + %% subgraph first references it, so putting this edge inside the kagent plane + %% would pull ActorTemplate out of the Kubernetes plane. + actortemplate -->|instantiated as| instance + %% Invisible link: forces the kagent plane to sit fully below the Kubernetes + %% plane. Without it, the layout engine staggers the two planes diagonally. + %% actortemplate ~~~ caller + classDef crd stroke:#a78bfa,fill:transparent class harness,template crd ``` -Follow the Kubernetes plane first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair, one whose `allowedAgentTemplates` selector matches, and compiles it into an ActorTemplate on Substrate. +Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an ActorTemplate on Substrate. -The kagent plane starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the latest compiled ActorTemplate, and that AgentInstance runs on an Actor. +The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an Actor. -From there, the caller holds a conversation with the AgentInstance over the A2A (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance, so the caller only ever needs to know an AgentInstance's identity, never which Actor or Worker is behind it. +From there, the caller holds a conversation with the AgentInstance over the A2A (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance. This means that the caller only ever needs to know an AgentInstance's identity, never which Actor or Worker is behind it. ## Why two planes Kubernetes RBAC is designed to authorize configuration changes: who can create a Deployment, edit a ConfigMap, or in this case, apply a Harness or AgentTemplate. It is not designed to authorize a running conversation, share access to it with another user, or scope who can suspend it. kagent's gRPC plane exists to authorize exactly those actions, at the granularity of a single AgentInstance rather than a namespace or a resource kind. -This split also keeps the two lifecycles independent. Editing a Harness or AgentTemplate does not affect AgentInstances already running against the ActorTemplate they were created from. It only affects new AgentInstances, created after the edit is compiled. +This split also keeps the two lifecycles independent. Editing a Harness or AgentTemplate does not affect AgentInstances already running against the ActorTemplate that they were created from. It only affects new AgentInstances, created after the edit is compiled. ## Next steps diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 10fd20f4..f48db4db 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -21,7 +21,7 @@ This guide walks you through creating an agent, from applying a Harness and an A ## Create a Harness and an AgentTemplate -1. Apply a `Harness` that uses kagent's native runtime. +1. Apply a `Harness` that uses kagent's native runtime. Its `substrate` section names the [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that this Harness's Actors run on, and the object storage location for their [snapshots]({{< link path="about/agent-substrate#suspend-snapshot-and-resume" >}}). ```yaml apiVersion: kagent.dev/v1alpha3 kind: Harness @@ -48,7 +48,7 @@ This guide walks you through creating an agent, from applying a Harness and an A > [!NOTE] > An `AgentTemplate` has no field naming this Harness. The `kagent.dev/harness: my-first-harness` selector is a convention that this guide uses to match the `kagent.dev/harness` label in the next step. However, you can choose any label key and value, as long as the Harness selector and the AgentTemplate's labels match. -2. Apply an `AgentTemplate` that is labeled to match the Harness's `allowedAgentTemplates` selector. The `ModelConfig` field references the `default-model-config` that was automatically created for the model provider API key that you provided during kagent installation. +2. Apply an `AgentTemplate` that is labeled to match the Harness's `allowedAgentTemplates` selector. The `modelConfig` field references the `default-model-config` ModelConfig that was automatically created for the model provider API key that you provided during kagent installation. ```yaml apiVersion: kagent.dev/v1alpha3 kind: AgentTemplate @@ -91,6 +91,8 @@ This guide walks you through creating an agent, from applying a Harness and an A ] ``` + The `latestSuccessfulRevision` value is the compiled revision that kagent creates your AgentInstance from in the next section. + ## Create the AgentInstance 1. Create an AgentInstance from the Harness and AgentTemplate pair. From d745f9bf5f2d557b92fab632057a0b0e4c3a8de4 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 16:58:36 -0500 Subject: [PATCH 11/70] Phase 1, review 5: restore dropped relative pronoun Keep "that" in the restrictive relative clause on the Agent Substrate intro so all four items in the list read in parallel. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/about/agent-substrate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index d77054a2..b7f167cf 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -5,7 +5,7 @@ weight: 40 author: kagent.dev --- -[Architecture]({{< link path="about/architecture" >}}) established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate it is created from, the compute that hosts it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand. +[Architecture]({{< link path="about/architecture" >}}) established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand. ## ActorTemplate From 03ca8d2ad35f32112f4d8e628ce3848122807f18 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 17:41:55 -0500 Subject: [PATCH 12/70] Write Phase 2 Installation page for kagent 1.0 Adds the Setup section and its Installation page, covering the three install phases: Agent Substrate, the identity bootstrap, and kagent. The install path was verified end to end on a local kind cluster (Kubernetes 1.35, Substrate 0.0.20) by reproducing the kagent CI e2e job. All 7 e2e tests passed. Notably, the identity bootstrap is mandatory and no Helm chart performs it: without it every ate-system pod stays in ContainerCreating on FailedMount for the podidentity and servicedns volumes. The 0.x page sidestepped this with controller.substrate.ateApiInsecure, which no longer exists. Also notes that the kagent CLI cannot produce a working 1.0 install, since kagent install has no Agent Substrate awareness. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- .../assets/versions/agent-substrate-1x.md | 1 + docs-site/content/kagent/1.x/setup/_index.md | 6 + .../content/kagent/1.x/setup/installation.md | 249 ++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 docs-site/assets/versions/agent-substrate-1x.md create mode 100644 docs-site/content/kagent/1.x/setup/_index.md create mode 100644 docs-site/content/kagent/1.x/setup/installation.md diff --git a/docs-site/assets/versions/agent-substrate-1x.md b/docs-site/assets/versions/agent-substrate-1x.md new file mode 100644 index 00000000..eb1591a7 --- /dev/null +++ b/docs-site/assets/versions/agent-substrate-1x.md @@ -0,0 +1 @@ +0.0.20 \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/setup/_index.md b/docs-site/content/kagent/1.x/setup/_index.md new file mode 100644 index 00000000..3a0e64be --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/_index.md @@ -0,0 +1,6 @@ +--- +title: Setup +description: Install kagent and configure the model providers that your agents use. +weight: 30 +author: kagent.dev +--- \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md new file mode 100644 index 00000000..f7f24ccf --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -0,0 +1,249 @@ +--- +title: Install kagent +description: Install kagent 1.0 and Agent Substrate on a Kubernetes cluster. +weight: 10 +author: kagent.dev +--- + +kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-substrate" >}}), so an installation sets up two systems in the same cluster. Agent Substrate provides the sandboxed compute that agents run on, and kagent provides the Harness, AgentTemplate, and AgentInstance API that you author against. + +## About installing kagent + +Installation has three phases, and the order matters. + +- **Install Agent Substrate**: Deploys the Agent Substrate control plane and data plane into the `ate-system` namespace. +- **Bootstrap Agent Substrate identity**: Creates the certificate authority (CA) pools, the JSON Web Token (JWT) authority pool, and the authentication configuration that Agent Substrate components use to prove identity to each other and to kagent. +- **Install kagent**: Deploys the kagent controller with the Agent Substrate integration enabled, and provisions the WorkerPool that agents run on. + +> [!IMPORTANT] +> The bootstrap phase is required, and no Helm chart performs it for you. Until you complete it, every pod in the `ate-system` namespace stays in `ContainerCreating` and reports `FailedMount` events for the `podidentity` and `servicedns` volumes. Agent Substrate authenticates its components with mutual Transport Layer Security (mTLS), and the identity material that mTLS depends on is created by the `kubectl-ate` plugin, not by Helm. + +> [!NOTE] +> Install kagent 1.0 with Helm. The `kagent install` command does not provision Agent Substrate and cannot produce a working 1.0 installation. + +## Before you begin + +You need the following tools and cluster capabilities. + +- **Kubernetes 1.35 or later**: Agent Substrate requires the `ClusterTrustBundle`, `ClusterTrustBundleProjection`, and `PodCertificateRequest` feature gates, along with the `certificates.k8s.io/v1beta1` API. Kubernetes 1.35 enables all of them by default. On an earlier version, enable them explicitly on the API server. +- **Helm 3 and `kubectl`**: Both must be on your `PATH`. +- **`jq` and `openssl`**: The bootstrap phase uses both to extract a root certificate from a generated CA pool. +- **A model provider API key**: The examples on this page use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/configure-model-providers" >}}). + +### Prepare a cluster + +Confirm that your cluster exposes the certificate APIs that Agent Substrate depends on. + +{{< tabs >}} +{{% tab name="Existing cluster" %}} +Check that both resources are present. +```bash +kubectl api-resources --api-group=certificates.k8s.io +``` + +Example output, truncated to the two resources that matter. +```console +NAME APIVERSION NAMESPACED KIND +clustertrustbundles certificates.k8s.io/v1beta1 false ClusterTrustBundle +podcertificaterequests certificates.k8s.io/v1beta1 true PodCertificateRequest +``` + +If either resource is missing, enable the feature gates on your API server before you continue. +{{% /tab %}} +{{% tab name="Local kind cluster" %}} +Create a kind cluster on a node image that includes the certificate APIs. +```bash +kind create cluster --name kagent --image kindest/node:v1.35.0 +``` + +An earlier node image does not expose `certificates.k8s.io/v1beta1`, and Agent Substrate cannot start on it. +{{% /tab %}} +{{< /tabs >}} + +### Install the kubectl-ate plugin + +Agent Substrate ships `kubectl-ate` as a standalone binary that is published with each Agent Substrate release. Download the build that matches your operating system and architecture, then put it on your `PATH` so that `kubectl` finds it as a plugin. +```bash +curl -fsSL -o kubectl-ate \ + "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "versions/agent-substrate-1x.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" +chmod +x kubectl-ate +sudo mv kubectl-ate /usr/local/bin/ +``` + +Confirm that `kubectl` picks the plugin up. +```bash +kubectl ate --help +``` + +## Install Agent Substrate + +1. Install the Agent Substrate custom resource definitions (CRDs). + ```bash + helm upgrade --install substrate-crds \ + oci://ghcr.io/kagent-dev/substrate/helm/substrate-crds \ + --version {{< reuse "versions/agent-substrate-1x.md" >}} \ + --namespace ate-system --create-namespace + ``` +2. Install the Agent Substrate control plane and data plane. Do not add `--wait` to this command, because the pods cannot become ready until you bootstrap identity in the next section. + ```bash + helm upgrade --install substrate \ + oci://ghcr.io/kagent-dev/substrate/helm/substrate \ + --version {{< reuse "versions/agent-substrate-1x.md" >}} \ + --namespace ate-system + ``` + +## Bootstrap Agent Substrate identity + +Agent Substrate signs pod identities and service certificates from CA pools that you generate, and it authenticates callers against a JWT authority pool. The `kubectl-ate admin` commands create that material as Kubernetes secrets, and a ConfigMap tells the Agent Substrate API server which token issuer to trust. + +1. Create the CA pools that sign service DNS and pod identity certificates. + ```bash + kubectl ate admin make-ca-pool --ca-id=1 \ + --name=service-dns-ca-pool \ + --secret-namespace=podcertificate-controller-system + kubectl ate admin make-ca-pool --ca-id=1 \ + --name=pod-identity-ca-pool \ + --secret-namespace=podcertificate-controller-system + ``` +2. Create the actor identity pools that Agent Substrate uses to issue and verify actor credentials. + ```bash + kubectl ate admin make-jwt-pool --key-id=1 \ + --name=actor-id-jwt-pool \ + --secret-namespace=ate-system + kubectl ate admin make-ca-pool --ca-id=1 \ + --name=actor-id-ca-pool \ + --secret-namespace=ate-system + ``` +3. Extract the actor identity root certificate and store it in the secret that the Agent Substrate API server reads. + ```bash + actor_id_ca_root="$(kubectl get secret actor-id-ca-pool -n ate-system \ + -o jsonpath='{.data.pool}' | base64 --decode \ + | jq -r '.CAs[0].RootCertificateDER' | base64 --decode \ + | openssl x509 -inform der -outform pem)" + + kubectl create secret generic actor-id-ca-certs -n ate-system \ + --from-literal=ca.crt="${actor_id_ca_root}" + ``` +4. Create the authentication configuration. The `kubernetes` provider accepts Kubernetes ServiceAccount tokens that are issued for the Agent Substrate API server audience. + ```bash + kubectl create configmap ate-api-authentication -n ate-system \ + --from-literal=authentication.yaml='actorIdentityJWTProvider: kubernetes + jwtProviders: + - name: kubernetes + issuer: https://kubernetes.default.svc + audiences: [api.ate-system.svc] + certificateAuthorityFile: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + discoveryTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + ' + ``` +5. Roll Agent Substrate out again so that its pods mount the identity material, and wait for them to become ready. + ```bash + helm upgrade substrate \ + oci://ghcr.io/kagent-dev/substrate/helm/substrate \ + --version {{< reuse "versions/agent-substrate-1x.md" >}} \ + --namespace ate-system --reuse-values --wait --timeout 10m + ``` +6. Verify that Agent Substrate is running. + ```bash + kubectl get pods -n ate-system + ``` + Example output. + ```console + NAME READY STATUS RESTARTS AGE + ate-api-server-59fccdf6dc-f77h6 1/1 Running 3 9m + ate-api-server-59fccdf6dc-q49hv 1/1 Running 3 9m + ate-controller-6c788456f8-zh2rm 1/1 Running 0 9m + atelet-wxm5s 1/1 Running 0 9m + atenet-egress-66f5699886-6rgg9 2/2 Running 0 9m + atenet-router-645bd98bdd-dlrv2 2/2 Running 0 9m + dns-6bf4fff5bb-zqsnm 2/2 Running 0 9m + postgres-0 1/1 Running 0 9m + rustfs-56cdbc9dcb-2ntck 1/1 Running 0 9m + rustfs-bucket-init-4pxgt 0/1 Completed 0 9m + ``` + +## Install kagent + +The kagent chart connects the controller to Agent Substrate and creates a WorkerPool for agents to run on. A WorkerPool is platform capacity that you provision once, and every Harness references it. No Harness can run until a WorkerPool exists. + +1. Install the kagent CRDs. + ```bash + helm upgrade --install kagent-crds \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds \ + --version \ + --namespace kagent --create-namespace --wait + ``` +2. Set your model provider API key. + ```bash + export OPENAI_API_KEY="your-api-key-here" + ``` +3. Install kagent with the Agent Substrate integration enabled. Set `substrateWorkerPool.ateomImage` explicitly, because the chart has no default for it and the install fails without it whenever `substrateWorkerPool.create` is `true`. + ```bash + helm upgrade --install kagent \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --version \ + --namespace kagent --create-namespace --timeout 10m \ + --set providers.default=openAI \ + --set providers.openAI.apiKey="${OPENAI_API_KEY}" \ + --set controller.substrate.enabled=true \ + --set controller.substrate.ateApiEndpoint=dns:///api.ate-system.svc:443 \ + --set controller.substrate.atenetRouterURL=http://atenet-router.ate-system.svc:80 \ + --set controller.substrate.defaultWorkerPool.name=kagent-default \ + --set substrateWorkerPool.create=true \ + --set substrateWorkerPool.replicas=1 \ + --set-string substrateWorkerPool.ateomImage=ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "versions/agent-substrate-1x.md" >}} + ``` +4. Wait for the controller to roll out. + ```bash + kubectl rollout status deployment/kagent-controller -n kagent --timeout=300s + ``` + +> [!NOTE] +> The kagent controller can restart a few times during a first install while it waits for its bundled PostgreSQL database to accept connections. The controller logs `dial tcp ...:5432: connect: connection refused` and then recovers on its own. A restart loop that reports an `ate-api` dial failure instead points at an incomplete identity bootstrap. + +## Verify the installation + +1. Confirm that the kagent pods are running. + ```bash + kubectl get pods -n kagent + ``` + Example output. + ```console + NAME READY STATUS RESTARTS AGE + kagent-controller-659b58768b-2k6h4 1/1 Running 3 2m + kagent-default-864fdc4c94-xbsl9 1/1 Running 0 2m + kagent-postgresql-65cc684b78-9qbh2 1/1 Running 0 2m + ``` +2. Confirm that the WorkerPool reports a ready replica. Agents cannot start until the pool is ready. + ```bash + kubectl get workerpools -n kagent + ``` + Example output. + ```console + NAMESPACE NAME DESIRED REPLICAS READY AGE + kagent kagent-default 1 1 1 2m + ``` +3. Note how you reach the kagent gRPC API, which serves the AgentInstance lifecycle and conversation calls. [Your first agent]({{< link path="get-started/your-first-agent" >}}) assumes the port-forward. + {{< tabs >}} + {{% tab name="Cloud Provider LoadBalancer" %}} + Read the external address of the controller service. The gRPC API listens on port `8084`. + ```bash + kubectl get svc -n kagent kagent-controller \ + -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}" + ``` + {{% /tab %}} + {{% tab name="Port-forward for local testing" %}} + Forward the gRPC port and leave the command running. The API is then available at `localhost:8084`. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + On a local kind cluster, use the port-forward. kind assigns a LoadBalancer address that is routable from inside the cluster, but not from your workstation. + {{% /tab %}} + {{< /tabs >}} + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} + {{< card link=`{{< link path="setup/configure-model-providers" >}}` title="Configure model providers" subtitle="Point kagent at OpenAI, Anthropic, Gemini, or a provider of your own." >}} +{{< /cards >}} From d74f87f820c0cfdcee9802462d699d212bb37a3d Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 17:48:53 -0500 Subject: [PATCH 13/70] rm newlines Signed-off-by: Rachael Graham --- docs-site/assets/versions/agent-substrate.md | 2 +- docs-site/assets/versions/jaeger.md | 2 +- docs-site/assets/versions/kagent.md | 2 +- docs-site/assets/versions/kmcp.md | 2 +- docs-site/assets/versions/loki.md | 2 +- docs-site/assets/versions/max-kube.md | 2 +- docs-site/assets/versions/tempo.md | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs-site/assets/versions/agent-substrate.md b/docs-site/assets/versions/agent-substrate.md index 1750564f..99d85ecd 100644 --- a/docs-site/assets/versions/agent-substrate.md +++ b/docs-site/assets/versions/agent-substrate.md @@ -1 +1 @@ -0.0.6 +0.0.6 \ No newline at end of file diff --git a/docs-site/assets/versions/jaeger.md b/docs-site/assets/versions/jaeger.md index c966188e..34014745 100644 --- a/docs-site/assets/versions/jaeger.md +++ b/docs-site/assets/versions/jaeger.md @@ -1 +1 @@ -4.4.7 +4.4.7 \ No newline at end of file diff --git a/docs-site/assets/versions/kagent.md b/docs-site/assets/versions/kagent.md index 7e310bae..6f060dcb 100644 --- a/docs-site/assets/versions/kagent.md +++ b/docs-site/assets/versions/kagent.md @@ -1 +1 @@ -0.9.9 +0.9.9 \ No newline at end of file diff --git a/docs-site/assets/versions/kmcp.md b/docs-site/assets/versions/kmcp.md index 0d91a54c..9325c3cc 100644 --- a/docs-site/assets/versions/kmcp.md +++ b/docs-site/assets/versions/kmcp.md @@ -1 +1 @@ -0.3.0 +0.3.0 \ No newline at end of file diff --git a/docs-site/assets/versions/loki.md b/docs-site/assets/versions/loki.md index 2496b04b..57f7599b 100644 --- a/docs-site/assets/versions/loki.md +++ b/docs-site/assets/versions/loki.md @@ -1 +1 @@ -6.24.0 +6.24.0 \ No newline at end of file diff --git a/docs-site/assets/versions/max-kube.md b/docs-site/assets/versions/max-kube.md index f7613c2d..f71ef947 100644 --- a/docs-site/assets/versions/max-kube.md +++ b/docs-site/assets/versions/max-kube.md @@ -1 +1 @@ -1.35 +1.35 \ No newline at end of file diff --git a/docs-site/assets/versions/tempo.md b/docs-site/assets/versions/tempo.md index 15b989e3..71bd5d9e 100644 --- a/docs-site/assets/versions/tempo.md +++ b/docs-site/assets/versions/tempo.md @@ -1 +1 @@ -1.16.0 +1.16.0 \ No newline at end of file From c6eb2a49c9196eff3d50520aa1945887a38a24ae Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 17:51:22 -0500 Subject: [PATCH 14/70] Write Phase 2 Suspend and resume page, and fix two Phase 1 errors Adds the Substrate runtime section and its suspend-and-resume page, covering the Actor lifecycle operations, snapshot scopes, golden and per-Actor snapshots, kagent's per-turn suspension, on-demand resume, and checkpoint retention. Titled "Suspend and resume" rather than the scope doc's "Sessions and passivation". Neither "passivation" nor a conversation-level "session" appears anywhere in Substrate or kagent: Substrate's lifecycle vocabulary is Suspend, Pause, and Resume. Fixes two errors in about/agent-substrate.md: - An ActorSnapshotTag cannot be repointed at a newer snapshot. Both snapshot.atespace and snapshot.name are enforced immutable on update, and only the visibility scope can change. - Spells out the ordinal in "95th percentile" per Solo.Ordinal. That error had gone undetected because Vale's BlockIgnores skips page content following a code fence, which on that page is the mermaid diagram. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 4 +- .../kagent/1.x/substrate-runtime/_index.md | 6 ++ .../substrate-runtime/suspend-and-resume.md | 75 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 docs-site/content/kagent/1.x/substrate-runtime/_index.md create mode 100644 docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index b7f167cf..44ead771 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -48,9 +48,9 @@ flowchart LR Suspending an Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker that it was running on. Resuming reads that snapshot back and restores the Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that it originally ran on. Because the snapshot captures the Actor's full state, the conversation continues from where it left off. -An **ActorSnapshotTag** gives a snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag can be repointed at a newer snapshot without its own name changing, and Substrate does not delete a snapshot while any tag still points to it. +An **ActorSnapshotTag** gives a snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag names one snapshot permanently, and only its visibility scope can change afterward. A tag also acts as a retention pin, so Substrate does not delete a snapshot while a tag still names it. -Substrate's own target for this cycle is 100ms at the 95th percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. +Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. ## Next steps diff --git a/docs-site/content/kagent/1.x/substrate-runtime/_index.md b/docs-site/content/kagent/1.x/substrate-runtime/_index.md new file mode 100644 index 00000000..7fc8789f --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/_index.md @@ -0,0 +1,6 @@ +--- +title: Substrate runtime +description: Learn how Agent Substrate isolates, suspends, and resumes the Actors that run your agents. +weight: 60 +author: kagent.dev +--- \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md new file mode 100644 index 00000000..fe4f3d62 --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -0,0 +1,75 @@ +--- +title: Suspend and resume +description: Learn how Agent Substrate suspends idle Actors to snapshots and resumes them on demand. +weight: 20 +author: kagent.dev +--- + +An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) treats that idle time as reclaimable: it suspends an idle Actor into a snapshot, frees the Worker that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. + +## Actor lifecycle operations + +Agent Substrate provides three lifecycle operations, and each one moves an Actor between states that you can observe on the Actor record. + +- **Suspend**: Writes the Actor's state to a durable snapshot in snapshot storage, then frees its Worker. A running Actor is checkpointed on its Worker. A paused Actor's node-local snapshot is uploaded instead. +- **Pause**: Takes a short-term checkpoint whose files stay on the node. Pausing pins the Actor to that node, because the following resume is prioritized onto the node that holds the snapshot files. +- **Resume**: Restores a suspended or paused Actor onto a Worker, from its latest snapshot. The common path restores from a snapshot rather than cold-booting the workload. + +An Actor reports its position in that cycle through its state, which is one of `RESUMING`, `RUNNING`, `SUSPENDING`, `SUSPENDED`, `PAUSING`, `PAUSED`, `CRASHED`, or `DELETING`. Only a suspended Actor can be deleted. + +> [!NOTE] +> Resume restores an Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that the Actor ran on before. Suspend and resume are what let a WorkerPool carry far more Actors than it has Workers at any one moment. + +## What a snapshot captures + +An ActorTemplate's snapshot configuration decides how much of an Actor a given snapshot holds. Two scopes exist. + +- **`Full`**: Captures process memory, the root filesystem changes layered on top of the container image, and any attached durable volumes. A `Full` snapshot holds everything that is needed to resume the Actor hot, with its in-memory state intact. +- **`Data`**: Captures only the contents of attached durable volumes. Process memory and the rest of the root filesystem are discarded, which makes the snapshot much cheaper to write and store. + +Scopes describe only what a snapshot captures, and they are configured per trigger. The `onPause` setting selects what a pause captures on the node, and `onCommit` selects what a suspend uploads to snapshot storage. What `onCommit` captures must be a subset of what `onPause` captures. + +A **DurableDir volume** is the per-Actor application data surface. Its contents are preserved by the `Data` scope, so they survive a suspend and resume cycle independently of process memory. How many such volumes an ActorTemplate can declare depends on its sandbox class. A `microvm` template can declare several, because they are subdirectories of a single shared filesystem. A `gvisor` template is limited to one, until gVisor accepts more than a single durable mount. + +When an Actor resumes from a `Data`-scope snapshot, the ActorTemplate's `onResume.fromData` setting decides where the rest of the guest state comes from. The default is `ColdBoot`, which starts the containers fresh from the container image with the durable volume contents restored over them. + +## Golden and per-Actor snapshots + +Two kinds of snapshot serve different purposes, and both appear in a normal installation. + +- **Golden snapshot**: Captured once, when an ActorTemplate is created, from a temporary golden boot of the workload. Every Actor of that template is first restored from this one shared snapshot, so a new Actor starts from an already-booted image rather than a cold start. An AgentTemplate is not ready until its golden snapshot exists, which is why the kagent controller reports `waiting for the ActorTemplate golden snapshot` while Agent Substrate captures it. +- **Last snapshot**: The most recent per-Actor snapshot, written on every suspend and used to restore that specific Actor on its next resume. Because it carries the Actor's own accumulated state, the conversation continues from where it stopped. + +Snapshots are persisted to object storage, either Google Cloud Storage or Amazon Simple Storage Service (S3), so that Actor state is durable and portable across the cluster. A Harness names the location for its Actors' snapshots in its `substrate.snapshotPolicy` section. + +## Suspension between turns + +kagent does not wait for an Actor to go idle for a long stretch before suspending it. It suspends the Actor at every turn boundary, as soon as the conversation reaches a point where nothing is running. + +A turn reaches such a boundary when its task enters a terminal state, or when the task stops to wait on a person, which is the `INPUT_REQUIRED` and `AUTH_REQUIRED` case. At that point kagent suspends the Actor durably and records the exact snapshot that the suspend produced. + +The AgentInstance's own state does not change while this happens. It stays `READY` throughout, because suspension is a property of the runtime underneath it rather than of the conversation. A caller that lists AgentInstances sees a ready agent whether or not an Actor is currently running for it. + +> [!NOTE] +> Creating an AgentInstance does not start an Actor running. The Actor is created suspended, and the first message addressed to the AgentInstance is what resumes it. + +## Resuming on demand + +Every Actor is reachable at a uniform address, `..actors.resources.substrate.ate.dev`, resolved by Agent Substrate's own Domain Name System (DNS) server. Traffic sent to that name is routed to the right Worker, and an Actor that is currently suspended is resumed automatically to receive it. Nothing in the calling path needs to know whether the Actor was running beforehand. + +Resume speed is what makes suspending at every turn boundary practical rather than costly. Agent Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. + +## Checkpoints + +A snapshot that Agent Substrate writes on suspend is transient. Agent Substrate is free to collect it once a newer snapshot supersedes it. A **checkpoint** makes one of those snapshots durable by pinning it. + +Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the AgentInstance most recently suspended to. The tag names that one snapshot permanently, and it acts as a retention pin, so Agent Substrate does not collect a snapshot while a tag still names it. Deleting the checkpoint removes the tag and releases the pin. + +Because a checkpoint captures a turn boundary, an AgentInstance must be at one to be checkpointed. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="substrate-runtime/sandboxing" >}}` title="Sandboxing" subtitle="See how a sandbox isolates each Actor's process, filesystem, and network." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} +{{< /cards >}} From 3591d73fde6e1d0048d990ba080082e202d24217 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 17:53:31 -0500 Subject: [PATCH 15/70] Write Phase 2 Sandboxing page Covers sandbox classes (gvisor and microvm), the SandboxConfig resource, what the sandbox separates across process, filesystem, and network, and the routing path that reaches a sandboxed Actor. Describes the default network posture from what Substrate actually creates, verified on a live cluster: the per-WorkerPool NetworkPolicy restricts ingress to the Substrate router and sets no egress rule at all. The page says so plainly rather than implying the sandbox blocks outbound traffic by default, since Substrate's own threat model states it has little to no security hardening yet and its granular authorization policies are still planned. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- .../1.x/substrate-runtime/sandboxing.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md new file mode 100644 index 00000000..7ff9fbfb --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -0,0 +1,59 @@ +--- +title: Sandboxing +description: Learn how Agent Substrate isolates each Actor in its own sandbox, and what that sandbox separates. +weight: 10 +author: kagent.dev +--- + +An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools that it was given. [Agent Substrate]({{< link path="about/agent-substrate" >}}) therefore does not run an Actor as an ordinary container process. It runs each Actor inside its own sandbox, on a Worker that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it. + +## Sandbox classes + +A **sandbox class** is the sandbox runtime family that a Worker uses. Agent Substrate supports two. + +- **`gvisor`**: The default. [gVisor](https://gvisor.dev) runs a user-space kernel that intercepts the sandboxed program's system calls, so the workload does not call the host kernel directly. +- **`microvm`**: Runs the workload inside a lightweight virtual machine, which places a hypervisor boundary between the workload and the host. + +A WorkerPool selects its class through the `sandboxClass` field, which defaults to `gvisor`. The choice is not only a runtime preference. It also determines the shape of the Worker pods that Agent Substrate creates for that pool, including the virtualization device mounts and node placement that a micro-VM needs, and it determines which sandbox configurations the pool can draw on. + +> [!NOTE] +> kagent generates ActorTemplates that use the `gvisor` class. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. + +## Sandbox configuration + +A **SandboxConfig** is a cluster-scoped resource that holds the material needed to start one sandbox runtime family. It carries the runtime assets that the node agent fetches, keyed by processor architecture, along with the pause image that holds the sandbox's namespaces as its root container. One SandboxConfig can be marked as the cluster default for its class, and a WorkerPool that names no configuration explicitly resolves to that default. + +Holding these assets in a cluster resource is what lets one configuration pin a runtime version for many ActorTemplates at once, rather than each template carrying its own copy. A default installation creates a single `gvisor-default` configuration. + +## What the sandbox separates + +The sandbox draws a boundary in three places. + +- **Process and kernel**: The Actor's processes run against the sandbox runtime rather than the Worker node's kernel. A system call that the workload makes is handled by gVisor's user-space kernel, or by the guest kernel inside a micro-VM, instead of reaching the host directly. +- **Filesystem**: The Actor sees the filesystem assembled from its container image, plus whatever durable volume its ActorTemplate declares. Writes to the root filesystem are a layer on top of the image, captured in a `Full` snapshot and discarded by a `Data` one. See [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) for what each scope keeps. +- **Network**: The Actor does not share the Worker pod's network position. The node agent gives the active Actor a private, point-to-point virtual network inside the Worker pod, so reaching the Actor means going through Agent Substrate's own network path rather than connecting to the Worker directly. + +## How traffic reaches a sandboxed Actor + +Every Actor is addressed by name, at `..actors.resources.substrate.ate.dev`. Reaching it involves several hops, and each one is what keeps a sandboxed Actor addressable without exposing the Worker that it happens to be running on. + +1. Agent Substrate runs its own Domain Name System (DNS) service that answers queries for that address pattern with the address of the router, rather than any individual Worker. +2. The router reads the Actor name and atespace from the request, asks the Agent Substrate API to resume that Actor and report which Worker it is now assigned to, then selects that Worker as the destination. +3. The router connects to a listener on the Worker over mutual Transport Layer Security (mTLS). The listener validates that the caller is the router, and forwards traffic only to the Actor currently assigned to that Worker. + +Because the router resolves the Worker assignment on every request, an Actor keeps a stable address across suspends, resumes, and moves between Workers. + +Traffic in the other direction leaves through a separate egress gateway rather than going straight out from the Worker. Routing Actor egress through one gateway is what gives Agent Substrate a single place to apply outbound controls. + +## Default network posture + +Agent Substrate creates a Kubernetes NetworkPolicy for each WorkerPool, selecting that pool's Worker pods. The policy restricts **ingress** to the Agent Substrate router alone. No other pod in the cluster can open a connection to a Worker, so an Actor is not reachable by anything that bypasses the routing path. + +That policy governs inbound traffic only. It does not constrain what an Actor may reach outbound, so outbound access is whatever the surrounding cluster and its infrastructure already allow. Treat network egress as something to configure deliberately for your environment rather than as something the WorkerPool policy settles. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="substrate-runtime/suspend-and-resume" >}}` title="Suspend and resume" subtitle="See what a snapshot captures and how an idle Actor comes back." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} +{{< /cards >}} From 7835dd8e81405c388d82bbab9c125975d6945b2a Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 17:55:24 -0500 Subject: [PATCH 16/70] Write Phase 2 Skills page Adds the Skills and MCP section and its Skills page: what a skill is, how SKILL.md front matter becomes a tool the model can call, and the two ways an AgentTemplate attaches skills. Documents the allowlist behavior the scope doc called for, verified against the API and the materializer: a plugin package enables only the skills named in plugins[].skills, and an empty list enables nothing. Also covers the pinning rules that every artifact source enforces, and the name uniqueness checks that run across standalone and plugin skills together. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- .../kagent/1.x/skills-and-mcp/_index.md | 8 ++ .../kagent/1.x/skills-and-mcp/skills.md | 86 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 docs-site/content/kagent/1.x/skills-and-mcp/_index.md create mode 100644 docs-site/content/kagent/1.x/skills-and-mcp/skills.md diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/_index.md b/docs-site/content/kagent/1.x/skills-and-mcp/_index.md new file mode 100644 index 00000000..04ac9723 --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/_index.md @@ -0,0 +1,8 @@ +--- +title: Skills and MCP +description: Give an agent capabilities through skills and Model Context Protocol tools. +weight: 50 +author: kagent.dev +--- + +Extend what an agent can do, with skills that package instructions and supporting files, and with tools served over the Model Context Protocol. 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 new file mode 100644 index 00000000..0e72792e --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/skills.md @@ -0,0 +1,86 @@ +--- +title: Skills +description: Package instructions and supporting files as skills, and attach them to an AgentTemplate. +weight: 20 +author: kagent.dev +--- + +A **skill** 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 AgentTemplate attaches skills by naming where each one comes from, and kagent fetches them and places them where the agent runtime can find them. + +## What a skill is + +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 is what 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, so a description that states plainly when to use the skill matters more than the length of the instructions behind it. + +## Attach skills to an AgentTemplate + +An AgentTemplate attaches skills two ways, and it can use both at once. Use `spec.skills` for a skill that is published on its own, and `spec.plugins` for a bundle that carries several skills together. + +```yaml +apiVersion: 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. + skills: + - 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` | Where to fetch this one skill from. The source root must hold a `SKILL.md` file. | +| `plugins[].source` | Where 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. | +| `source.path` | Selects a directory 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. | + +A plugin package follows the Agent Plugins 1.0.0 format. Its `plugin.json` names the package, and its skills live in a `skills` directory, one subdirectory per skill. A package may also declare Model Context Protocol (MCP) servers, which kagent adds to the agent's tools alongside the skills that you enabled. + +## Every source is immutable + +A skill 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 each one has to be pinned. + +- **`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 of a skill 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 skill content that they started with. + +## The plugin allowlist + +A plugin package can carry many skills, and attaching the package does not enable any of them. 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. + +## Naming rules + +Skill names are checked before anything is fetched, and two rules apply across every skill on an AgentTemplate. + +- 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. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="See how MCP tools and agent tools attach to an AgentTemplate." >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} +{{< /cards >}} From b09915905277d568bab6fa4b707ae10d008e74ea Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 18:07:12 -0500 Subject: [PATCH 17/70] Redraw the suspend-and-resume diagram to show both snapshot paths The old diagram routed resume through the tag, which conflated two different mechanisms. ResumeActor restores an existing Actor from its latest snapshot with no tag involved, while a tag is used at CreateActor via source_snapshot_tag to seed a new Actor. The diagram now forks at ActorSnapshot: resume restores the same Actor onto any free Worker, and a tag pins the snapshot and can seed a new Actor. The walkthrough states outright that resuming an existing Actor never goes through a tag. Also drops the pool-to-second-Worker edge, which rendered as a long line sweeping across the whole diagram to a node labeled identically to the first Worker, and moves the walkthrough after the diagram to match core-concepts.md and architecture.md. Verified by rendering the mermaid block extracted from this file: 784x132px, clean left-to-right spine, no crossing edges. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 44ead771..1852c4ce 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -29,26 +29,26 @@ Because an Actor often runs a model-directed agent that calls tools and executes Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming allows a WorkerPool to run far more Actors than it has Workers for at any given moment. -The following diagram traces an Actor through one suspend-and-resume cycle. -1. A WorkerPool hosts Workers. -2. A Worker hosts a running Actor. -3. Suspending that Actor produces a snapshot. -4. That snapshot is tagged. -5. A later Actor uses the tag to resume from the snapshot on whichever Worker is free. +The following diagram traces an Actor through one suspend-and-resume cycle, and shows the second path that opens up once the resulting snapshot is tagged. ```mermaid flowchart LR pool["WorkerPool"] --> worker1["Worker"] - pool --> worker2["Worker"] worker1 -->|hosts| actor["Actor
      (running)"] actor -->|suspend| snapshot["ActorSnapshot
      (immutable)"] - snapshot -->|tag| tag["ActorSnapshotTag
      (stable handle)"] - tag -->|resume| worker2 + snapshot -->|resume| worker2["Any free Worker
      in the pool"] + snapshot -->|pinned by| tag["ActorSnapshotTag
      (retention pin)"] + tag -->|seeds| newactor["New Actor"] ``` -Suspending an Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker that it was running on. Resuming reads that snapshot back and restores the Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that it originally ran on. Because the snapshot captures the Actor's full state, the conversation continues from where it left off. +A **WorkerPool** keeps **Workers** running and ready, and one Worker hosts the **Actor** while its conversation is active. Suspending that Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker that it was running on. -An **ActorSnapshotTag** gives a snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag names one snapshot permanently, and only its visibility scope can change afterward. A tag also acts as a retention pin, so Substrate does not delete a snapshot while a tag still names it. +The diagram forks at that snapshot, because a snapshot serves two purposes. + +- **Resume** restores the same Actor onto **any free Worker in the pool**, which is not necessarily the Worker that it ran on before. Because the snapshot captures the Actor's full state, the conversation continues from where it left off. Every idle agent takes this path. +- An **ActorSnapshotTag** pins that snapshot, and a **New Actor** can be seeded from the tag at the moment that it is created. Resuming an existing Actor never goes through a tag. + +A tag gives a snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag names one snapshot permanently, and only its visibility scope can change afterward. A tag also acts as a retention pin, so Substrate does not delete a snapshot while a tag still names it. Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. From a52e5b841d147ed85fe042b205a0ad6c8f079035 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 18:07:45 -0500 Subject: [PATCH 18/70] Update _index.md Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/skills-and-mcp/_index.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs-site/content/kagent/1.x/skills-and-mcp/_index.md b/docs-site/content/kagent/1.x/skills-and-mcp/_index.md index 04ac9723..da14a380 100644 --- a/docs-site/content/kagent/1.x/skills-and-mcp/_index.md +++ b/docs-site/content/kagent/1.x/skills-and-mcp/_index.md @@ -3,6 +3,4 @@ title: Skills and MCP description: Give an agent capabilities through skills and Model Context Protocol tools. weight: 50 author: kagent.dev ---- - -Extend what an agent can do, with skills that package instructions and supporting files, and with tools served over the Model Context Protocol. +--- \ No newline at end of file From a3d95d493ea81e832bce3037ccf55d51f4fabc78 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 18:26:30 -0500 Subject: [PATCH 19/70] Rename the two About architecture pages as a parallel pair "Architecture" and "Architecture: Agent Substrate" become "kagent architecture" and "Agent Substrate architecture". The colon prefix implied that the Agent Substrate page was a deeper cut of the Architecture page. It is not: it describes a different system that kagent runs on top of, so the two are sibling subjects rather than parent and child. Naming each page after its own subject makes the symmetry honest, and separates the conceptual page from the Substrate runtime section that now covers sandboxing and suspend and resume in depth. Updates all 11 occurrences, including the six places where the old title was quoted as card link text. Two prose links were rephrased so the lowercase project name is not sentence-initial. Lowercase "kagent" at the start of a title follows the section landing page, which is titled "kagent 1.0 (preview)". Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/about/agent-substrate.md | 4 ++-- docs-site/content/kagent/1.x/about/architecture.md | 4 ++-- docs-site/content/kagent/1.x/about/core-concepts.md | 6 +++--- docs-site/content/kagent/1.x/about/what-is-kagent.md | 2 +- .../content/kagent/1.x/get-started/your-first-agent.md | 2 +- .../content/kagent/1.x/substrate-runtime/sandboxing.md | 2 +- .../kagent/1.x/substrate-runtime/suspend-and-resume.md | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 1852c4ce..8a374708 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -1,11 +1,11 @@ --- -title: "Architecture: Agent Substrate" +title: Agent Substrate architecture description: See how Agent Substrate runs, suspends, and resumes the Actors behind every AgentInstance. weight: 40 author: kagent.dev --- -[Architecture]({{< link path="about/architecture" >}}) established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand. +The [kagent architecture]({{< link path="about/architecture" >}}) page established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand. ## ActorTemplate diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 68e6e15f..cd34d668 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -1,5 +1,5 @@ --- -title: Architecture +title: kagent architecture description: See how a Harness and AgentTemplate become a running conversation, across kagent's two authorization planes. weight: 30 author: kagent.dev @@ -71,6 +71,6 @@ This split also keeps the two lifecycles independent. Editing a Harness or Agent ## Next steps {{< cards >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="See what an Actor actually runs on, and how it suspends and resumes." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="See what an Actor actually runs on, and how it suspends and resumes." >}} {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} {{< /cards >}} 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 6f314293..663c726b 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -91,7 +91,7 @@ For the AgentInstance gRPC service definition, see the [API reference]({{< link An **Actor** is the sandboxed unit of compute, provided by [Agent Substrate]({{< link path="about/agent-substrate" >}}), that _runs an AgentInstance's conversation loop_. Every AgentInstance is backed by an Actor. -Actors are the reason why AgentInstances can suspend and resume cheaply instead of staying resident. An idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. To understand the full mechanics (Workers, WorkerPools, ActorTemplates, and snapshotting), see [Architecture: Agent Substrate]({{< link path="about/agent-substrate" >}}). +Actors are the reason why AgentInstances can suspend and resume cheaply instead of staying resident. An idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. To understand the full mechanics (Workers, WorkerPools, ActorTemplates, and snapshotting), see [Agent Substrate architecture]({{< link path="about/agent-substrate" >}}). ## Agent tools: Shared vs. Dedicated @@ -107,7 +107,7 @@ This limit keeps the model predictable. A Dedicated binding gives the child its ## Next steps {{< cards >}} - {{< card link=`{{< link path="about/architecture" >}}` title="Architecture" subtitle="See how these pieces fit together end to end, from `kubectl apply` to a live conversation." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Learn about Workers, WorkerPools, and ActorTemplates, and how Actors suspend and resume." >}} + {{< card link=`{{< link path="about/architecture" >}}` title="kagent architecture" subtitle="See how these pieces fit together end to end, from `kubectl apply` to a live conversation." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Learn about Workers, WorkerPools, and ActorTemplates, and how Actors suspend and resume." >}} {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md index 42362f61..0c6ef586 100644 --- a/docs-site/content/kagent/1.x/about/what-is-kagent.md +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -62,7 +62,7 @@ Check out [Solo Enterprise for kagent](https://www.solo.io/products/kagent-enter ## Getting started -To start using kagent, see [Your first agent]({{< link path="get-started/your-first-agent" >}}). For a deeper understanding of how kagent works, see [Architecture]({{< link path="about/architecture" >}}). +To start using kagent, see [Your first agent]({{< link path="get-started/your-first-agent" >}}). For a deeper understanding of how the pieces fit together, see [kagent architecture]({{< link path="about/architecture" >}}). Ready to contribute? Visit the [GitHub repository](https://github.com/kagent-dev) to learn how you can help expand the ecosystem of cloud-native AI agents. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index f48db4db..ff1731ad 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -172,7 +172,7 @@ The response carries the agent's reply in the same `parts` shape as the request. ## Next steps {{< cards >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Understand what happens to your AgentInstance's Actor when it sits idle." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Understand what happens to your AgentInstance's Actor when it sits idle." >}} {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Choose from the full set of Harness runtime options, including Claude Code and Codex." >}} {{< card link=`{{< link path="skills-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities beyond its system prompt." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index 7ff9fbfb..fce33678 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -55,5 +55,5 @@ That policy governs inbound traffic only. It does not constrain what an Actor ma {{< cards >}} {{< card link=`{{< link path="substrate-runtime/suspend-and-resume" >}}` title="Suspend and resume" subtitle="See what a snapshot captures and how an idle Actor comes back." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index fe4f3d62..4cf12290 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -71,5 +71,5 @@ Because a checkpoint captures a turn boundary, an AgentInstance must be at one t {{< cards >}} {{< card link=`{{< link path="substrate-runtime/sandboxing" >}}` title="Sandboxing" subtitle="See how a sandbox isolates each Actor's process, filesystem, and network." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Architecture: Agent Substrate" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} + {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} {{< /cards >}} From c487eda4c98026e44bac1d5958d0a8b2d2a49dc6 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 25 Aug 2026 18:28:10 -0500 Subject: [PATCH 20/70] Illustrate ActorSnapshotTag with a concrete example The tag paragraph explained the mechanism but gave the reader nothing to picture. Adds a short worked example: checkpointing an agent partway through an incident investigation tags the snapshot it most recently suspended to, which holds that snapshot in place while newer ones accumulate, and links forward to the checkpoint section on the Suspend and resume page. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/about/agent-substrate.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 8a374708..798aa2ed 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -50,6 +50,8 @@ The diagram forks at that snapshot, because a snapshot serves two purposes. A tag gives a snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. A tag names one snapshot permanently, and only its visibility scope can change afterward. A tag also acts as a retention pin, so Substrate does not delete a snapshot while a tag still names it. +For example, an agent partway through a long incident investigation reaches a state worth keeping. Creating a [checkpoint]({{< link path="substrate-runtime/suspend-and-resume#checkpoints" >}}) tags the snapshot that the agent most recently suspended to, which holds that one snapshot in place while the agent carries on and writes newer ones. Without the tag, Substrate collects that snapshot once a newer one supersedes it. + Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. ## Next steps From 7762b08d56815a23d402586ca597afafc5cfee9e Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 26 Aug 2026 11:00:15 -0500 Subject: [PATCH 21/70] Phase 2, review 1 Signed-off-by: Rachael Graham --- .../content/kagent/1.x/setup/installation.md | 137 ++++++++++-------- 1 file changed, 77 insertions(+), 60 deletions(-) diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index f7f24ccf..f487d548 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -9,74 +9,77 @@ kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-subs ## About installing kagent -Installation has three phases, and the order matters. +Installation has three phases that you must complete in this order. -- **Install Agent Substrate**: Deploys the Agent Substrate control plane and data plane into the `ate-system` namespace. -- **Bootstrap Agent Substrate identity**: Creates the certificate authority (CA) pools, the JSON Web Token (JWT) authority pool, and the authentication configuration that Agent Substrate components use to prove identity to each other and to kagent. -- **Install kagent**: Deploys the kagent controller with the Agent Substrate integration enabled, and provisions the WorkerPool that agents run on. +1. **Install Agent Substrate**: Deploys the Agent Substrate control plane and data plane into the `ate-system` namespace. +2. **Bootstrap Agent Substrate identity**: Creates the certificate authority (CA) pools, the JSON Web Token (JWT) authority pool, and the authentication configuration that Agent Substrate components use to prove identity to each other and to kagent. +3. **Install kagent**: Deploys the kagent controller with the Agent Substrate integration enabled, and provisions the WorkerPool that agents run on. > [!IMPORTANT] -> The bootstrap phase is required, and no Helm chart performs it for you. Until you complete it, every pod in the `ate-system` namespace stays in `ContainerCreating` and reports `FailedMount` events for the `podidentity` and `servicedns` volumes. Agent Substrate authenticates its components with mutual Transport Layer Security (mTLS), and the identity material that mTLS depends on is created by the `kubectl-ate` plugin, not by Helm. - -> [!NOTE] -> Install kagent 1.0 with Helm. The `kagent install` command does not provision Agent Substrate and cannot produce a working 1.0 installation. +> The bootstrap phase is required, and no Helm chart performs it for you. Agent Substrate authenticates its components with mutual Transport Layer Security (mTLS), and the identity material that mTLS depends on is created by the `kubectl-ate` plugin, not by Helm. ## Before you begin -You need the following tools and cluster capabilities. - -- **Kubernetes 1.35 or later**: Agent Substrate requires the `ClusterTrustBundle`, `ClusterTrustBundleProjection`, and `PodCertificateRequest` feature gates, along with the `certificates.k8s.io/v1beta1` API. Kubernetes 1.35 enables all of them by default. On an earlier version, enable them explicitly on the API server. -- **Helm 3 and `kubectl`**: Both must be on your `PATH`. -- **`jq` and `openssl`**: The bootstrap phase uses both to extract a root certificate from a generated CA pool. -- **A model provider API key**: The examples on this page use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/configure-model-providers" >}}). - -### Prepare a cluster - -Confirm that your cluster exposes the certificate APIs that Agent Substrate depends on. - -{{< tabs >}} -{{% tab name="Existing cluster" %}} -Check that both resources are present. -```bash -kubectl api-resources --api-group=certificates.k8s.io -``` - -Example output, truncated to the two resources that matter. -```console -NAME APIVERSION NAMESPACED KIND -clustertrustbundles certificates.k8s.io/v1beta1 false ClusterTrustBundle -podcertificaterequests certificates.k8s.io/v1beta1 true PodCertificateRequest -``` - -If either resource is missing, enable the feature gates on your API server before you continue. -{{% /tab %}} -{{% tab name="Local kind cluster" %}} -Create a kind cluster on a node image that includes the certificate APIs. -```bash -kind create cluster --name kagent --image kindest/node:v1.35.0 -``` - -An earlier node image does not expose `certificates.k8s.io/v1beta1`, and Agent Substrate cannot start on it. -{{% /tab %}} -{{< /tabs >}} - -### Install the kubectl-ate plugin - -Agent Substrate ships `kubectl-ate` as a standalone binary that is published with each Agent Substrate release. Download the build that matches your operating system and architecture, then put it on your `PATH` so that `kubectl` finds it as a plugin. -```bash -curl -fsSL -o kubectl-ate \ - "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "versions/agent-substrate-1x.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" -chmod +x kubectl-ate -sudo mv kubectl-ate /usr/local/bin/ -``` - -Confirm that `kubectl` picks the plugin up. -```bash -kubectl ate --help -``` +1. Install the following CLI tools. + * [`helm`](https://helm.sh/docs/intro/install/), the Kubernetes package manager. Use Helm 3. + * [`kubectl`](https://kubernetes.io/docs/tasks/tools/#kubectl), the Kubernetes command line tool. + * [`jq`](https://jqlang.org/download/), to read the root certificate out of the generated CA pool. + * [`openssl`](https://www.openssl.org), to convert that certificate to PEM format. + * [`kubectl-ate`](https://github.com/kagent-dev/substrate/releases), the Agent Substrate command line tool, published as a `kubectl` plugin with each Agent Substrate release. No Helm chart creates the identity material that Agent Substrate needs, so the bootstrap phase depends on this plugin. + ```bash + curl -fsSL -o kubectl-ate \ + "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "versions/agent-substrate-1x.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" + chmod +x kubectl-ate + sudo mv kubectl-ate /usr/local/bin/ + kubectl ate --help + ``` + +2. Prepare a Kubernetes cluster at **version 1.37 or later**. Agent Substrate depends on the `ClusterTrustBundle`, `ClusterTrustBundleProjection`, and `PodCertificateRequest` feature gates, along with the `certificates.k8s.io/v1beta1` API. Kubernetes promotes all three feature gates to generally available, and enables them by default, in version 1.37. In 1.36 and earlier, none are enabled by default, and must be manually enabled. + + {{< tabs >}} + {{% tab name="Local kind cluster" %}} + For local testing and development, create a kind cluster at version 1.37. + + {{% /tab %}} + {{% tab name="Existing upgraded 1.37 cluster" %}} + + {{% /tab %}} + {{% tab name="Use an existing 1.36 or earlier cluster" %}} + To use an existing cluster that continues to run on 1.36, first confirm that your cluster exposes both certificate resources. + ```bash + kubectl api-resources --api-group=certificates.k8s.io + ``` + + Example output: + ```console + NAME APIVERSION NAMESPACED KIND + ... + clustertrustbundles certificates.k8s.io/v1beta1 false ClusterTrustBundle + podcertificaterequests certificates.k8s.io/v1beta1 true PodCertificateRequest + ``` + + If either resource is missing, enable the gates on each control plane component, then restart that component. + + > [!WARNING] + > Changing these settings requires control over your control plane configuration. Before you plan an installation on a managed Kubernetes service, confirm that the provider lets you set API server flags and kubelet configuration. + > If you cannot change the component configuration, use the **Local kind cluster** tab instead. + + * **kube-apiserver**: Add `--feature-gates=ClusterTrustBundle=true` and `--runtime-config=certificates.k8s.io/v1beta1=true`. + * **kube-controller-manager**: Add `--feature-gates=ClusterTrustBundle=true`. + * **kubelet, on every node**: Add all three gates to the kubelet configuration file. + ```yaml + featureGates: + ClusterTrustBundle: true + ClusterTrustBundleProjection: true + PodCertificateRequest: true + ``` + {{% /tab %}} + {{< /tabs >}} ## Install Agent Substrate +Deploy the Agent Substrate control plane and data plane into the `ate-system` namespace. + 1. Install the Agent Substrate custom resource definitions (CRDs). ```bash helm upgrade --install substrate-crds \ @@ -84,6 +87,7 @@ kubectl ate --help --version {{< reuse "versions/agent-substrate-1x.md" >}} \ --namespace ate-system --create-namespace ``` + 2. Install the Agent Substrate control plane and data plane. Do not add `--wait` to this command, because the pods cannot become ready until you bootstrap identity in the next section. ```bash helm upgrade --install substrate \ @@ -105,6 +109,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that --name=pod-identity-ca-pool \ --secret-namespace=podcertificate-controller-system ``` + 2. Create the actor identity pools that Agent Substrate uses to issue and verify actor credentials. ```bash kubectl ate admin make-jwt-pool --key-id=1 \ @@ -114,6 +119,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that --name=actor-id-ca-pool \ --secret-namespace=ate-system ``` + 3. Extract the actor identity root certificate and store it in the secret that the Agent Substrate API server reads. ```bash actor_id_ca_root="$(kubectl get secret actor-id-ca-pool -n ate-system \ @@ -124,6 +130,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that kubectl create secret generic actor-id-ca-certs -n ate-system \ --from-literal=ca.crt="${actor_id_ca_root}" ``` + 4. Create the authentication configuration. The `kubernetes` provider accepts Kubernetes ServiceAccount tokens that are issued for the Agent Substrate API server audience. ```bash kubectl create configmap ate-api-authentication -n ate-system \ @@ -136,6 +143,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that discoveryTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token ' ``` + 5. Roll Agent Substrate out again so that its pods mount the identity material, and wait for them to become ready. ```bash helm upgrade substrate \ @@ -143,6 +151,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that --version {{< reuse "versions/agent-substrate-1x.md" >}} \ --namespace ate-system --reuse-values --wait --timeout 10m ``` + 6. Verify that Agent Substrate is running. ```bash kubectl get pods -n ate-system @@ -166,6 +175,9 @@ Agent Substrate signs pod identities and service certificates from CA pools that The kagent chart connects the controller to Agent Substrate and creates a WorkerPool for agents to run on. A WorkerPool is platform capacity that you provision once, and every Harness references it. No Harness can run until a WorkerPool exists. +> [!IMPORTANT] +> Install kagent 1.0 with Helm. The `kagent install` command does not yet provision Agent Substrate and cannot produce a working 1.0 installation. + 1. Install the kagent CRDs. ```bash helm upgrade --install kagent-crds \ @@ -173,10 +185,12 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker --version \ --namespace kagent --create-namespace --wait ``` -2. Set your model provider API key. + +2. Set your model provider API key. The examples in this guide use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/configure-model-providers" >}}). ```bash export OPENAI_API_KEY="your-api-key-here" ``` + 3. Install kagent with the Agent Substrate integration enabled. Set `substrateWorkerPool.ateomImage` explicitly, because the chart has no default for it and the install fails without it whenever `substrateWorkerPool.create` is `true`. ```bash helm upgrade --install kagent \ @@ -193,6 +207,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker --set substrateWorkerPool.replicas=1 \ --set-string substrateWorkerPool.ateomImage=ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "versions/agent-substrate-1x.md" >}} ``` + 4. Wait for the controller to roll out. ```bash kubectl rollout status deployment/kagent-controller -n kagent --timeout=300s @@ -214,6 +229,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker kagent-default-864fdc4c94-xbsl9 1/1 Running 0 2m kagent-postgresql-65cc684b78-9qbh2 1/1 Running 0 2m ``` + 2. Confirm that the WorkerPool reports a ready replica. Agents cannot start until the pool is ready. ```bash kubectl get workerpools -n kagent @@ -223,6 +239,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker NAMESPACE NAME DESIRED REPLICAS READY AGE kagent kagent-default 1 1 1 2m ``` + 3. Note how you reach the kagent gRPC API, which serves the AgentInstance lifecycle and conversation calls. [Your first agent]({{< link path="get-started/your-first-agent" >}}) assumes the port-forward. {{< tabs >}} {{% tab name="Cloud Provider LoadBalancer" %}} From 03e2a25d4bb0c43bc3a86fffc101c0a79e868a0b Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 26 Aug 2026 12:22:51 -0500 Subject: [PATCH 22/70] Phase 2, review 2 Signed-off-by: Rachael Graham --- .../content/kagent/1.x/setup/installation.md | 149 ++++++++++-------- 1 file changed, 82 insertions(+), 67 deletions(-) diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index f487d548..13428da3 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -5,18 +5,7 @@ weight: 10 author: kagent.dev --- -kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-substrate" >}}), so an installation sets up two systems in the same cluster. Agent Substrate provides the sandboxed compute that agents run on, and kagent provides the Harness, AgentTemplate, and AgentInstance API that you author against. - -## About installing kagent - -Installation has three phases that you must complete in this order. - -1. **Install Agent Substrate**: Deploys the Agent Substrate control plane and data plane into the `ate-system` namespace. -2. **Bootstrap Agent Substrate identity**: Creates the certificate authority (CA) pools, the JSON Web Token (JWT) authority pool, and the authentication configuration that Agent Substrate components use to prove identity to each other and to kagent. -3. **Install kagent**: Deploys the kagent controller with the Agent Substrate integration enabled, and provisions the WorkerPool that agents run on. - -> [!IMPORTANT] -> The bootstrap phase is required, and no Helm chart performs it for you. Agent Substrate authenticates its components with mutual Transport Layer Security (mTLS), and the identity material that mTLS depends on is created by the `kubectl-ate` plugin, not by Helm. +kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-substrate" >}}), so an installation sets up two systems in the same cluster. Agent Substrate provides the sandboxed compute that agents run on, and kagent provides the Harness, AgentTemplate, and AgentInstance API that you author against. Install Agent Substrate first, because the kagent controller connects to it at startup. ## Before you begin @@ -25,43 +14,67 @@ Installation has three phases that you must complete in this order. * [`kubectl`](https://kubernetes.io/docs/tasks/tools/#kubectl), the Kubernetes command line tool. * [`jq`](https://jqlang.org/download/), to read the root certificate out of the generated CA pool. * [`openssl`](https://www.openssl.org), to convert that certificate to PEM format. - * [`kubectl-ate`](https://github.com/kagent-dev/substrate/releases), the Agent Substrate command line tool, published as a `kubectl` plugin with each Agent Substrate release. No Helm chart creates the identity material that Agent Substrate needs, so the bootstrap phase depends on this plugin. + * [`kubectl-ate`](https://github.com/kagent-dev/substrate/releases), the Agent Substrate command line tool, published as a `kubectl` plugin with each Agent Substrate release. ```bash curl -fsSL -o kubectl-ate \ - "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "versions/agent-substrate-1x.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" + "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" chmod +x kubectl-ate sudo mv kubectl-ate /usr/local/bin/ kubectl ate --help ``` -2. Prepare a Kubernetes cluster at **version 1.37 or later**. Agent Substrate depends on the `ClusterTrustBundle`, `ClusterTrustBundleProjection`, and `PodCertificateRequest` feature gates, along with the `certificates.k8s.io/v1beta1` API. Kubernetes promotes all three feature gates to generally available, and enables them by default, in version 1.37. In 1.36 and earlier, none are enabled by default, and must be manually enabled. +2. Set your model provider API key. The examples in this guide use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/configure-model-providers" >}}). + ```bash + export OPENAI_API_KEY="your-api-key-here" + ``` + +3. Prepare a Kubernetes cluster at **1.37 or later** and enable it with the following requirements for Agent Substrate. {{< tabs >}} {{% tab name="Local kind cluster" %}} - For local testing and development, create a kind cluster at version 1.37. - - {{% /tab %}} - {{% tab name="Existing upgraded 1.37 cluster" %}} - - {{% /tab %}} - {{% tab name="Use an existing 1.36 or earlier cluster" %}} - To use an existing cluster that continues to run on 1.36, first confirm that your cluster exposes both certificate resources. + For local testing and development, create a [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) cluster at Kubernetes 1.37 or later. Enable the `certificates.k8s.io/v1beta1` API, which Agent Substrate depends on. ```bash - kubectl api-resources --api-group=certificates.k8s.io + kind create cluster --image kindest/node:v1.37.0 --config=- < [!NOTE] + > If the command list already has a `--runtime-config` flag, edit that line instead of adding a second one. A duplicate flag is silently ignored, and the API is not served. + + 2. Confirm that the beta group is served. Be sure to check the served API versions, not the resource list. + ```bash + kubectl api-versions | grep certificates.k8s.io + ``` + + Example output: + ```console + certificates.k8s.io/v1 + certificates.k8s.io/v1beta1 + ``` + {{% /tab %}} - If either resource is missing, enable the gates on each control plane component, then restart that component. + {{% tab name="1.36 or earlier cluster" %}} + Agent Substrate depends on the `ClusterTrustBundle`, `ClusterTrustBundleProjection`, and `PodCertificateRequest` feature gates, along with the `certificates.k8s.io/v1beta1` API. In 1.36 and earlier, none of these are enabled by default, and must be manually enabled. > [!WARNING] - > Changing these settings requires control over your control plane configuration. Before you plan an installation on a managed Kubernetes service, confirm that the provider lets you set API server flags and kubelet configuration. + > Changing these settings requires control over your control plane configuration. When planning a kagent installation on a managed Kubernetes service, confirm that the provider lets you set API server flags and kubelet configuration. > If you cannot change the component configuration, use the **Local kind cluster** tab instead. * **kube-apiserver**: Add `--feature-gates=ClusterTrustBundle=true` and `--runtime-config=certificates.k8s.io/v1beta1=true`. @@ -78,29 +91,28 @@ Installation has three phases that you must complete in this order. ## Install Agent Substrate -Deploy the Agent Substrate control plane and data plane into the `ate-system` namespace. +Deploy the Agent Substrate control plane and data plane into the `ate-system` namespace, then create the identity material that its components authenticate with. Agent Substrate signs pod identities and service certificates from certificate authority (CA) pools that you generate, and it authenticates callers against a JSON Web Token (JWT) authority pool. + +> [!IMPORTANT] +> Creating the identity material is required, and no Helm chart performs it for you. Agent Substrate authenticates its components with mutual Transport Layer Security (mTLS), and the identity material that mTLS depends on is created by the `kubectl-ate` plugin, not by Helm. 1. Install the Agent Substrate custom resource definitions (CRDs). ```bash helm upgrade --install substrate-crds \ oci://ghcr.io/kagent-dev/substrate/helm/substrate-crds \ - --version {{< reuse "versions/agent-substrate-1x.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}} \ --namespace ate-system --create-namespace ``` -2. Install the Agent Substrate control plane and data plane. Do not add `--wait` to this command, because the pods cannot become ready until you bootstrap identity in the next section. +2. Install the Agent Substrate control plane and data plane. Do not add `--wait` to this command, because the pods cannot become ready until you create the identity material in the following steps. ```bash helm upgrade --install substrate \ oci://ghcr.io/kagent-dev/substrate/helm/substrate \ - --version {{< reuse "versions/agent-substrate-1x.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}} \ --namespace ate-system ``` -## Bootstrap Agent Substrate identity - -Agent Substrate signs pod identities and service certificates from CA pools that you generate, and it authenticates callers against a JWT authority pool. The `kubectl-ate admin` commands create that material as Kubernetes secrets, and a ConfigMap tells the Agent Substrate API server which token issuer to trust. - -1. Create the CA pools that sign service DNS and pod identity certificates. +3. Create the CA pools that sign service DNS and pod identity certificates. ```bash kubectl ate admin make-ca-pool --ca-id=1 \ --name=service-dns-ca-pool \ @@ -110,7 +122,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that --secret-namespace=podcertificate-controller-system ``` -2. Create the actor identity pools that Agent Substrate uses to issue and verify actor credentials. +4. Create the actor identity pools that Agent Substrate uses to issue and verify actor credentials. ```bash kubectl ate admin make-jwt-pool --key-id=1 \ --name=actor-id-jwt-pool \ @@ -120,7 +132,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that --secret-namespace=ate-system ``` -3. Extract the actor identity root certificate and store it in the secret that the Agent Substrate API server reads. +5. Extract the actor identity root certificate and store it in the secret that the Agent Substrate API server reads. ```bash actor_id_ca_root="$(kubectl get secret actor-id-ca-pool -n ate-system \ -o jsonpath='{.data.pool}' | base64 --decode \ @@ -131,7 +143,7 @@ Agent Substrate signs pod identities and service certificates from CA pools that --from-literal=ca.crt="${actor_id_ca_root}" ``` -4. Create the authentication configuration. The `kubernetes` provider accepts Kubernetes ServiceAccount tokens that are issued for the Agent Substrate API server audience. +6. Create the authentication configuration. The `kubernetes` provider accepts Kubernetes ServiceAccount tokens that are issued for the Agent Substrate API server audience. ```bash kubectl create configmap ate-api-authentication -n ate-system \ --from-literal=authentication.yaml='actorIdentityJWTProvider: kubernetes @@ -144,19 +156,19 @@ Agent Substrate signs pod identities and service certificates from CA pools that ' ``` -5. Roll Agent Substrate out again so that its pods mount the identity material, and wait for them to become ready. +7. Roll Agent Substrate out again so that its pods mount the identity material, and wait for them to become ready. ```bash helm upgrade substrate \ oci://ghcr.io/kagent-dev/substrate/helm/substrate \ - --version {{< reuse "versions/agent-substrate-1x.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}} \ --namespace ate-system --reuse-values --wait --timeout 10m ``` -6. Verify that Agent Substrate is running. +8. Verify that Agent Substrate is running. ```bash kubectl get pods -n ate-system ``` - Example output. + Example output: ```console NAME READY STATUS RESTARTS AGE ate-api-server-59fccdf6dc-f77h6 1/1 Running 3 9m @@ -186,29 +198,32 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker --namespace kagent --create-namespace --wait ``` -2. Set your model provider API key. The examples in this guide use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/configure-model-providers" >}}). - ```bash - export OPENAI_API_KEY="your-api-key-here" - ``` - -3. Install kagent with the Agent Substrate integration enabled. Set `substrateWorkerPool.ateomImage` explicitly, because the chart has no default for it and the install fails without it whenever `substrateWorkerPool.create` is `true`. +2. Install kagent with the Agent Substrate integration enabled. Set `substrateWorkerPool.ateomImage` explicitly, because the chart has no default for it and the install fails without it whenever `substrateWorkerPool.create` is `true`. ```bash helm upgrade --install kagent \ oci://ghcr.io/kagent-dev/kagent/helm/kagent \ --version \ --namespace kagent --create-namespace --timeout 10m \ - --set providers.default=openAI \ - --set providers.openAI.apiKey="${OPENAI_API_KEY}" \ - --set controller.substrate.enabled=true \ - --set controller.substrate.ateApiEndpoint=dns:///api.ate-system.svc:443 \ - --set controller.substrate.atenetRouterURL=http://atenet-router.ate-system.svc:80 \ - --set controller.substrate.defaultWorkerPool.name=kagent-default \ - --set substrateWorkerPool.create=true \ - --set substrateWorkerPool.replicas=1 \ - --set-string substrateWorkerPool.ateomImage=ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "versions/agent-substrate-1x.md" >}} + -f - <}}" + EOF ``` -4. Wait for the controller to roll out. +3. Wait for the controller to roll out. ```bash kubectl rollout status deployment/kagent-controller -n kagent --timeout=300s ``` @@ -222,7 +237,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ```bash kubectl get pods -n kagent ``` - Example output. + Example output: ```console NAME READY STATUS RESTARTS AGE kagent-controller-659b58768b-2k6h4 1/1 Running 3 2m @@ -234,7 +249,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ```bash kubectl get workerpools -n kagent ``` - Example output. + Example output: ```console NAMESPACE NAME DESIRED REPLICAS READY AGE kagent kagent-default 1 1 1 2m From 92dc29e937edaf33d1d0cdec2e65abbc63f01ce3 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 26 Aug 2026 12:41:49 -0500 Subject: [PATCH 23/70] Move version conrefs Signed-off-by: Rachael Graham --- .../snippets}/review-table.md | 0 .../kagent-docs/versions/agent-substrate.md | 1 + .../{ => kagent-docs}/versions/jaeger.md | 0 .../assets/kagent-docs/versions/kagent.md | 1 + .../assets/{ => kagent-docs}/versions/loki.md | 0 .../{ => kagent-docs}/versions/max-kube.md | 0 .../{ => kagent-docs}/versions/tempo.md | 0 .../assets/versions/agent-substrate-1x.md | 1 - docs-site/assets/versions/agent-substrate.md | 1 - docs-site/assets/versions/kagent.md | 1 - .../kagent/0.x/examples/agent-substrate.md | 16 ++++----- .../kagent/0.x/getting-started/quickstart.md | 2 +- .../kagent/0.x/introduction/installation.md | 2 +- .../kagent/0.x/observability/audit-prompts.md | 4 +-- .../kagent/0.x/observability/tracing.md | 2 +- .../content/kagent/0.x/resources/versions.md | 4 +-- .../supported-providers/byo-agentgateway.md | 4 +-- .../content/kagent/1.x/setup/installation.md | 35 +++++++++---------- 18 files changed, 36 insertions(+), 38 deletions(-) rename docs-site/assets/{conrefs/snippets/field-desc => kagent-docs/snippets}/review-table.md (100%) create mode 100644 docs-site/assets/kagent-docs/versions/agent-substrate.md rename docs-site/assets/{ => kagent-docs}/versions/jaeger.md (100%) create mode 100644 docs-site/assets/kagent-docs/versions/kagent.md rename docs-site/assets/{ => kagent-docs}/versions/loki.md (100%) rename docs-site/assets/{ => kagent-docs}/versions/max-kube.md (100%) rename docs-site/assets/{ => kagent-docs}/versions/tempo.md (100%) delete mode 100644 docs-site/assets/versions/agent-substrate-1x.md delete mode 100644 docs-site/assets/versions/agent-substrate.md delete mode 100644 docs-site/assets/versions/kagent.md diff --git a/docs-site/assets/conrefs/snippets/field-desc/review-table.md b/docs-site/assets/kagent-docs/snippets/review-table.md similarity index 100% rename from docs-site/assets/conrefs/snippets/field-desc/review-table.md rename to docs-site/assets/kagent-docs/snippets/review-table.md diff --git a/docs-site/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md new file mode 100644 index 00000000..8ade5faa --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -0,0 +1 @@ +{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.20{{< /version >}} \ No newline at end of file diff --git a/docs-site/assets/versions/jaeger.md b/docs-site/assets/kagent-docs/versions/jaeger.md similarity index 100% rename from docs-site/assets/versions/jaeger.md rename to docs-site/assets/kagent-docs/versions/jaeger.md diff --git a/docs-site/assets/kagent-docs/versions/kagent.md b/docs-site/assets/kagent-docs/versions/kagent.md new file mode 100644 index 00000000..68d3c797 --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/kagent.md @@ -0,0 +1 @@ +{{< version include-if="0.x" >}}0.9.9{{< /version >}}{{< version include-if="1.x" >}}1.0.0-beta0{{< /version >}} \ No newline at end of file diff --git a/docs-site/assets/versions/loki.md b/docs-site/assets/kagent-docs/versions/loki.md similarity index 100% rename from docs-site/assets/versions/loki.md rename to docs-site/assets/kagent-docs/versions/loki.md diff --git a/docs-site/assets/versions/max-kube.md b/docs-site/assets/kagent-docs/versions/max-kube.md similarity index 100% rename from docs-site/assets/versions/max-kube.md rename to docs-site/assets/kagent-docs/versions/max-kube.md diff --git a/docs-site/assets/versions/tempo.md b/docs-site/assets/kagent-docs/versions/tempo.md similarity index 100% rename from docs-site/assets/versions/tempo.md rename to docs-site/assets/kagent-docs/versions/tempo.md diff --git a/docs-site/assets/versions/agent-substrate-1x.md b/docs-site/assets/versions/agent-substrate-1x.md deleted file mode 100644 index eb1591a7..00000000 --- a/docs-site/assets/versions/agent-substrate-1x.md +++ /dev/null @@ -1 +0,0 @@ -0.0.20 \ No newline at end of file diff --git a/docs-site/assets/versions/agent-substrate.md b/docs-site/assets/versions/agent-substrate.md deleted file mode 100644 index 99d85ecd..00000000 --- a/docs-site/assets/versions/agent-substrate.md +++ /dev/null @@ -1 +0,0 @@ -0.0.6 \ No newline at end of file diff --git a/docs-site/assets/versions/kagent.md b/docs-site/assets/versions/kagent.md deleted file mode 100644 index 6f060dcb..00000000 --- a/docs-site/assets/versions/kagent.md +++ /dev/null @@ -1 +0,0 @@ -0.9.9 \ No newline at end of file diff --git a/docs-site/content/kagent/0.x/examples/agent-substrate.md b/docs-site/content/kagent/0.x/examples/agent-substrate.md index ffd6acc4..5cba795a 100644 --- a/docs-site/content/kagent/0.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/0.x/examples/agent-substrate.md @@ -9,7 +9,7 @@ In this guide, you install Agent Substrate and kagent on a local kind cluster, t By the end, you will have: -- Agent Substrate v{{< reuse "versions/agent-substrate.md" >}} running in the `ate-system` namespace. +- Agent Substrate v{{< reuse "kagent-docs/versions/agent-substrate.md" >}} running in the `ate-system` namespace. - kagent v0.9.7 or later installed with the substrate integration enabled. Earlier kagent releases do not include the controller wiring that lets a `SandboxAgent` target substrate. - A `SandboxAgent` running on substrate, reachable from the kagent UI. @@ -33,7 +33,7 @@ export OPENAI_API_KEY="sk-..." kind create cluster --name kagent-substrate ``` -The substrate v{{< reuse "versions/agent-substrate.md" >}} chart defaults to JWT auth backed by Kubernetes ServiceAccount tokens, so a vanilla kind cluster works — no feature gates or custom kind config are required. +The substrate v{{< reuse "kagent-docs/versions/agent-substrate.md" >}} chart defaults to JWT auth backed by Kubernetes ServiceAccount tokens, so a vanilla kind cluster works — no feature gates or custom kind config are required. ## Step 2: Install Agent Substrate @@ -42,12 +42,12 @@ Install the CRDs first, then the substrate control plane and data plane. ```bash helm upgrade --install substrate-crds \ oci://ghcr.io/kagent-dev/substrate/helm/substrate-crds \ - --version {{< reuse "versions/agent-substrate.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate.md" >}} \ --namespace ate-system --create-namespace --wait helm upgrade --install substrate \ oci://ghcr.io/kagent-dev/substrate/helm/substrate \ - --version {{< reuse "versions/agent-substrate.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate.md" >}} \ --namespace ate-system --wait --timeout 10m ``` @@ -78,12 +78,12 @@ Install the CRDs, then kagent with the substrate flags. ```bash helm upgrade --install kagent-crds \ oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds \ - --version {{< reuse "versions/kagent.md" >}} \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ --namespace kagent --create-namespace --wait helm upgrade --install kagent \ oci://ghcr.io/kagent-dev/kagent/helm/kagent \ - --version {{< reuse "versions/kagent.md" >}} \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ --namespace kagent --timeout 10m --wait \ --set providers.openAI.apiKey="${OPENAI_API_KEY}" \ --set providers.default=openAI \ @@ -92,7 +92,7 @@ helm upgrade --install kagent \ --set controller.substrate.ateApiInsecure=true \ --set substrateWorkerPool.create=true \ --set substrateWorkerPool.replicas=1 \ - --set substrateWorkerPool.ateomImage=ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "versions/agent-substrate.md" >}} + --set substrateWorkerPool.ateomImage=ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}} ``` The `controller.substrate.*` and `substrateWorkerPool.*` flags turn on the substrate integration. The rest is a standard kagent install. @@ -127,7 +127,7 @@ kubectl scale workerpool kagent-default -n kagent --replicas=3 # 2) Stick it into the helm release — survives upgrades. helm upgrade kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \ - --version {{< reuse "versions/kagent.md" >}} --namespace kagent --reuse-values \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} --namespace kagent --reuse-values \ --set substrateWorkerPool.replicas=3 # 3) Fresh install — change the value on the Step 3 install command above. diff --git a/docs-site/content/kagent/0.x/getting-started/quickstart.md b/docs-site/content/kagent/0.x/getting-started/quickstart.md index 6f0c76ae..9e548226 100644 --- a/docs-site/content/kagent/0.x/getting-started/quickstart.md +++ b/docs-site/content/kagent/0.x/getting-started/quickstart.md @@ -25,7 +25,7 @@ To run the AI agents you'll also need an [OpenAI](https://openai.com) API key. Y export OPENAI_API_KEY="your-api-key-here" ``` -2. Download the kagent CLI. By default, the latest version {{< reuse "versions/kagent.md" >}} of kagent is installed. +2. Download the kagent CLI. By default, the latest version {{< reuse "kagent-docs/versions/kagent.md" >}} of kagent is installed. ```bash brew install kagent diff --git a/docs-site/content/kagent/0.x/introduction/installation.md b/docs-site/content/kagent/0.x/introduction/installation.md index 8eba5679..ca6e3350 100644 --- a/docs-site/content/kagent/0.x/introduction/installation.md +++ b/docs-site/content/kagent/0.x/introduction/installation.md @@ -21,7 +21,7 @@ Install kagent by using the kagent CLI or Helm. export OPENAI_API_KEY="your-api-key-here" ``` -2. Download the kagent CLI. By default, the latest version {{< reuse "versions/kagent.md" >}} of kagent is installed. +2. Download the kagent CLI. By default, the latest version {{< reuse "kagent-docs/versions/kagent.md" >}} of kagent is installed. ```bash brew install kagent diff --git a/docs-site/content/kagent/0.x/observability/audit-prompts.md b/docs-site/content/kagent/0.x/observability/audit-prompts.md index d04b306d..9f48205b 100644 --- a/docs-site/content/kagent/0.x/observability/audit-prompts.md +++ b/docs-site/content/kagent/0.x/observability/audit-prompts.md @@ -34,7 +34,7 @@ kagent supports logging input/output messages for the following LLM providers: ```yaml helm upgrade --install loki loki \ --repo https://grafana.github.io/helm-charts \ - --version {{< reuse "versions/loki.md" >}} \ + --version {{< reuse "kagent-docs/versions/loki.md" >}} \ --namespace telemetry \ --create-namespace \ --values - <}} \ + --version {{< reuse "kagent-docs/versions/tempo.md" >}} \ --namespace telemetry \ --create-namespace \ --values - <}} + --version {{< reuse "kagent-docs/versions/jaeger.md" >}} ``` ## Upgrade kagent diff --git a/docs-site/content/kagent/0.x/resources/versions.md b/docs-site/content/kagent/0.x/resources/versions.md index f40549bc..9624c729 100644 --- a/docs-site/content/kagent/0.x/resources/versions.md +++ b/docs-site/content/kagent/0.x/resources/versions.md @@ -6,7 +6,7 @@ weight: 4 author: kagent.dev --- -kagent's CI tests against Kubernetes {{< reuse "versions/max-kube.md" >}} today. +kagent's CI tests against Kubernetes {{< reuse "kagent-docs/versions/max-kube.md" >}} today. Only the latest kagent release is supported. The tested Kubernetes version above applies to that release. Older kagent releases are not maintained or supported, regardless of which Kubernetes version they were originally tested against. @@ -15,5 +15,5 @@ The tested version is sourced from `KIND_IMAGE_VERSION` in the [kagent Makefile] Kubernetes versions other than the one listed above are not tested in CI and are not guaranteed to work, though kagent's Kubernetes client libraries generally follow the [client-go version skew policy](https://github.com/kubernetes/client-go#compatibility-matrix). diff --git a/docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md b/docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md index 4c0095cc..86c331b2 100644 --- a/docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md +++ b/docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md @@ -84,7 +84,7 @@ You can route model requests through an [agentgateway](https://agentgateway.dev/ EOF ``` - {{< reuse "conrefs/snippets/field-desc/review-table.md" >}} For more information, see the [API docs](https://kagent.dev/docs/kagent/resources/api-ref#modelconfigspec). + {{< reuse "kagent-docs/snippets/review-table.md" >}} For more information, see the [API docs](https://kagent.dev/docs/kagent/resources/api-ref#modelconfigspec). | Setting | Description | | --- | --- | @@ -120,7 +120,7 @@ You can route model requests through an [agentgateway](https://agentgateway.dev/ EOF ``` - {{< reuse "conrefs/snippets/field-desc/review-table.md" >}} For more information, see the [API docs](https://kagent.dev/docs/kagent/resources/api-ref#modelconfigspec). + {{< reuse "kagent-docs/snippets/review-table.md" >}} For more information, see the [API docs](https://kagent.dev/docs/kagent/resources/api-ref#modelconfigspec). | Setting | Description | | --- | --- | diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index 13428da3..45ffd699 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -17,7 +17,7 @@ kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-subs * [`kubectl-ate`](https://github.com/kagent-dev/substrate/releases), the Agent Substrate command line tool, published as a `kubectl` plugin with each Agent Substrate release. ```bash curl -fsSL -o kubectl-ate \ - "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" + "https://github.com/kagent-dev/substrate/releases/download/v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}/kubectl-ate-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')" chmod +x kubectl-ate sudo mv kubectl-ate /usr/local/bin/ kubectl ate --help @@ -100,7 +100,7 @@ Deploy the Agent Substrate control plane and data plane into the `ate-system` na ```bash helm upgrade --install substrate-crds \ oci://ghcr.io/kagent-dev/substrate/helm/substrate-crds \ - --version {{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate.md" >}} \ --namespace ate-system --create-namespace ``` @@ -108,7 +108,7 @@ Deploy the Agent Substrate control plane and data plane into the `ate-system` na ```bash helm upgrade --install substrate \ oci://ghcr.io/kagent-dev/substrate/helm/substrate \ - --version {{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate.md" >}} \ --namespace ate-system ``` @@ -160,7 +160,7 @@ Deploy the Agent Substrate control plane and data plane into the `ate-system` na ```bash helm upgrade substrate \ oci://ghcr.io/kagent-dev/substrate/helm/substrate \ - --version {{< reuse "kagent-docs/versions/agent-substrate-1x.md" >}} \ + --version {{< reuse "kagent-docs/versions/agent-substrate.md" >}} \ --namespace ate-system --reuse-values --wait --timeout 10m ``` @@ -194,15 +194,15 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ```bash helm upgrade --install kagent-crds \ oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds \ - --version \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ --namespace kagent --create-namespace --wait ``` -2. Install kagent with the Agent Substrate integration enabled. Set `substrateWorkerPool.ateomImage` explicitly, because the chart has no default for it and the install fails without it whenever `substrateWorkerPool.create` is `true`. +2. Install kagent with the Agent Substrate integration enabled. ```bash helm upgrade --install kagent \ oci://ghcr.io/kagent-dev/kagent/helm/kagent \ - --version \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ --namespace kagent --create-namespace --timeout 10m \ -f - <}}" + ateomImage: "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" EOF ``` @@ -229,7 +229,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ``` > [!NOTE] -> The kagent controller can restart a few times during a first install while it waits for its bundled PostgreSQL database to accept connections. The controller logs `dial tcp ...:5432: connect: connection refused` and then recovers on its own. A restart loop that reports an `ate-api` dial failure instead points at an incomplete identity bootstrap. +> The kagent controller can restart a few times during a first install while it waits for its bundled PostgreSQL database to accept connections. The controller logs `dial tcp ...:5432: connect: connection refused` and then recovers on its own. A restart loop that reports an `ate-api` dial failure instead indicates an incomplete identity bootstrap. ## Verify the installation @@ -245,7 +245,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker kagent-postgresql-65cc684b78-9qbh2 1/1 Running 0 2m ``` -2. Confirm that the WorkerPool reports a ready replica. Agents cannot start until the pool is ready. +2. Confirm that the WorkerPool reports a ready replica. ```bash kubectl get workerpools -n kagent ``` @@ -255,8 +255,14 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker kagent kagent-default 1 1 1 2m ``` -3. Note how you reach the kagent gRPC API, which serves the AgentInstance lifecycle and conversation calls. [Your first agent]({{< link path="get-started/your-first-agent" >}}) assumes the port-forward. +3. Get the address to reach the kagent gRPC API, which serves the AgentInstance lifecycle and conversation calls. The guide to [create your first agent]({{< link path="get-started/your-first-agent" >}}) assumes port-forwarding. {{< tabs >}} + {{% tab name="Port-forward for local testing" %}} + Forward the gRPC port and leave the command running. The API is then available at `localhost:8084`. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + {{% /tab %}} {{% tab name="Cloud Provider LoadBalancer" %}} Read the external address of the controller service. The gRPC API listens on port `8084`. ```bash @@ -264,13 +270,6 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}" ``` {{% /tab %}} - {{% tab name="Port-forward for local testing" %}} - Forward the gRPC port and leave the command running. The API is then available at `localhost:8084`. - ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 - ``` - On a local kind cluster, use the port-forward. kind assigns a LoadBalancer address that is routable from inside the cluster, but not from your workstation. - {{% /tab %}} {{< /tabs >}} ## Next steps From a030a3ceb9694beecb723edabf6ce3ced5486f39 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 26 Aug 2026 21:47:25 -0500 Subject: [PATCH 24/70] Phase 2, review 3 Signed-off-by: Rachael Graham --- .../1.x/get-started/your-first-agent.md | 4 +-- .../content/kagent/1.x/setup/installation.md | 4 +++ .../kagent/1.x/skills-and-mcp/skills.md | 25 ++++++++++--------- .../1.x/substrate-runtime/sandboxing.md | 6 ++--- .../substrate-runtime/suspend-and-resume.md | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index ff1731ad..bbb36135 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -9,7 +9,7 @@ This guide walks you through creating an agent, from applying a Harness and an A ## Before you begin -1. [Install kagent with a WorkerPool provisioned]({{< link path="setup/installation" >}}). Be sure to add `--set controller.grpc.reflection=true` to the Helm install command so that grpcurl can discover the controller's gRPC methods without a local copy of kagent's proto files. +1. [Install kagent with a WorkerPool provisioned]({{< link path="setup/installation" >}}). 2. Install [grpcurl](https://github.com/fullstorydev/grpcurl). 3. Port-forward the controller's gRPC port to your local machine. ```shell @@ -174,5 +174,5 @@ The response carries the agent's reply in the same `parts` shape as the request. {{< cards >}} {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Understand what happens to your AgentInstance's Actor when it sits idle." >}} {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Choose from the full set of Harness runtime options, including Claude Code and Codex." >}} - {{< card link=`{{< link path="skills-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities beyond its system prompt." >}} + {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities beyond its system prompt." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index 45ffd699..cb46d323 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -210,6 +210,8 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker openAI: apiKey: ${OPENAI_API_KEY} controller: + grpc: + reflection: true substrate: enabled: true ateApiEndpoint: dns:///api.ate-system.svc:443 @@ -222,6 +224,8 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ateomImage: "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" EOF ``` + > [!NOTE] + > `controller.grpc.reflection` lets a gRPC client discover the controller's methods without a local copy of kagent's proto files, which is how [Your first agent]({{< link path="get-started/your-first-agent" >}}) calls the API. Leave it on while you explore the API, and turn it off for a production installation. 3. Wait for the controller to roll out. ```bash 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 0e72792e..60adc8d1 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 @@ -11,11 +11,13 @@ A **skill** packages a piece of know-how that an agent can pick up: a set of ins 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 is what 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, so a description that states plainly when to use the skill matters more than the length of the instructions behind it. +The description is what 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. + +A skill can be published on its own, or bundled with other skills in a **plugin package**. A plugin package follows the Agent Plugins 1.0.0 format. Its `plugin.json` manifest names the package, and its skills live in a `skills` directory, one subdirectory per skill. A package may also declare Model Context Protocol (MCP) servers, which kagent adds to the agent's tools alongside the skills that you enable from that package. ## Attach skills to an AgentTemplate -An AgentTemplate attaches skills two ways, and it can use both at once. Use `spec.skills` for a skill that is published on its own, and `spec.plugins` for a bundle that carries several skills together. +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 plugin package. ```yaml apiVersion: kagent.dev/v1alpha3 @@ -50,7 +52,12 @@ spec: | `plugins[].skills` | The names of the skills inside that package to enable. Omit or leave empty to enable none. | | `source.path` | Selects a directory 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. | -A plugin package follows the Agent Plugins 1.0.0 format. Its `plugin.json` names the package, and its skills live in a `skills` directory, one subdirectory per skill. A package may also declare Model Context Protocol (MCP) servers, which kagent adds to the agent's tools alongside the skills that you enabled. +### The 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. ## Every source is immutable @@ -60,14 +67,7 @@ A skill changes what an agent does, so kagent only accepts artifact references t - **`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 of a skill 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 skill content that they started with. - -## The plugin allowlist - -A plugin package can carry many skills, and attaching the package does not enable any of them. 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. +Pinning has a practical consequence worth planning for. Publishing a new version of a skill means updating the AgentTemplate to name the new digest, commit, or object version, which compiles a new revision. Agents that are already running keep using the skill content that they started with. ## Naming rules @@ -76,11 +76,12 @@ Skill names are checked before anything is fetched, and two rules apply across e - 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. +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. ## Next steps {{< cards >}} + {{< card link=`{{< link path="examples/skills" >}}` title="Add skills to agents" subtitle="Walk through attaching a skill from an OCI artifact, end to end." >}} {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="See how MCP tools and agent tools attach to an AgentTemplate." >}} {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index fce33678..c75a7b02 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -5,16 +5,16 @@ weight: 10 author: kagent.dev --- -An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools that it was given. [Agent Substrate]({{< link path="about/agent-substrate" >}}) therefore does not run an Actor as an ordinary container process. It runs each Actor inside its own sandbox, on a Worker that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it. +An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools that it was given. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, its own unit of compute, and it does not run that Actor as an ordinary container process. Each Actor runs inside its own sandbox, on a Worker that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it. ## Sandbox classes A **sandbox class** is the sandbox runtime family that a Worker uses. Agent Substrate supports two. -- **`gvisor`**: The default. [gVisor](https://gvisor.dev) runs a user-space kernel that intercepts the sandboxed program's system calls, so the workload does not call the host kernel directly. +- **`gvisor`** (default): Runs the workload against a [gVisor](https://gvisor.dev) user-space kernel, which keeps the workload's system calls from reaching the host kernel. - **`microvm`**: Runs the workload inside a lightweight virtual machine, which places a hypervisor boundary between the workload and the host. -A WorkerPool selects its class through the `sandboxClass` field, which defaults to `gvisor`. The choice is not only a runtime preference. It also determines the shape of the Worker pods that Agent Substrate creates for that pool, including the virtualization device mounts and node placement that a micro-VM needs, and it determines which sandbox configurations the pool can draw on. +A WorkerPool selects its class through the `sandboxClass` field, which defaults to `gvisor`. The choice is not only a runtime preference. It also shapes the Worker pods that Agent Substrate creates for that pool, including the virtualization device mounts and node placement that a micro-VM needs. > [!NOTE] > kagent generates ActorTemplates that use the `gvisor` class. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 4cf12290..2252bb5b 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -5,7 +5,7 @@ weight: 20 author: kagent.dev --- -An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) treats that idle time as reclaimable: it suspends an idle Actor into a snapshot, frees the Worker that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. +An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, the unit that it suspends and resumes, and it treats that idle time as reclaimable: it suspends an idle Actor into a snapshot, frees the Worker that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. ## Actor lifecycle operations From 650fd0b5d4189d074ab0205caa3afc962401d04f Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 27 Aug 2026 15:24:00 -0500 Subject: [PATCH 25/70] update mermaid styling Signed-off-by: Rachael Graham --- docs-site/assets/css/custom.css | 17 ++++++ .../kagent/1.x/about/agent-substrate.md | 8 ++- .../content/kagent/1.x/about/architecture.md | 2 +- .../content/kagent/1.x/about/core-concepts.md | 2 +- .../kagent/1.x/skills-and-mcp/skills.md | 2 +- .../1.x/substrate-runtime/sandboxing.md | 51 ++++++++++++++++-- .../layouts/partials/custom/head-end.html | 54 +++++++++++++++++++ 7 files changed, 129 insertions(+), 7 deletions(-) diff --git a/docs-site/assets/css/custom.css b/docs-site/assets/css/custom.css index 2680967b..2f66da83 100644 --- a/docs-site/assets/css/custom.css +++ b/docs-site/assets/css/custom.css @@ -434,3 +434,20 @@ h6 { :where(.dark, .dark *) .hextra-nav-container img[src*="kagent-logo-light"] { display: none; } :where(.dark, .dark *) .hextra-nav-container img[src*="kagent-logo-dark"] { display: block; } } + +/* ── Mermaid diagram alignment ──────────────────────────────────────────── + Hextra renders every diagram into a full-width
       that
      +   carries the code-block background, while Mermaid sizes its own SVG to the
      +   diagram's natural width. A narrow diagram therefore sits against the left
      +   edge of a wide, mostly empty panel. Center it instead.
      +
      +   Note: the panel itself cannot be shrunk to fit from CSS. Mermaid sets
      +   width="100%" on the SVG and records the real size only in an inline
      +   max-width, so width:fit-content has no definite width to measure and
      +   collapses every diagram to the 300px SVG default. Shrinking the panel would
      +   require Mermaid's useMaxWidth:false, which means overriding the theme's
      +   scripts/mermaid.html partial. */
      +pre.mermaid {
      +  display: flex;
      +  justify-content: center;
      +}
      diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md
      index 798aa2ed..e21f94af 100644
      --- a/docs-site/content/kagent/1.x/about/agent-substrate.md
      +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md
      @@ -5,7 +5,7 @@ weight: 40
       author: kagent.dev
       ---
       
      -The [kagent architecture]({{< link path="about/architecture" >}}) page established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand.
      +The [kagent architecture]({{< link path="about/architecture" >}}) page established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the atespace that identifies it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand.
       
       ## ActorTemplate
       
      @@ -21,6 +21,12 @@ Workers come from a **WorkerPool**, a Kubernetes custom resource that an operato
       
       An operator never creates a Worker directly. Substrate manages them, keeping enough ready in each WorkerPool so that an Actor can start or resume on one immediately, without waiting on the Kubernetes scheduler to place a new Pod.
       
      +## Atespaces
      +
      +An **atespace** is the isolation boundary that an Actor belongs to, and the first half of its identity. Agent Substrate addresses an Actor by its atespace and its name together, so the same Actor name can exist in two atespaces without colliding. Despite the resemblance, an atespace is a global-scoped Agent Substrate resource rather than a Kubernetes namespace.
      +
      +kagent names each atespace after the Kubernetes namespace of the AgentInstance whose Actor it holds, and creates that atespace on demand the first time an AgentInstance in the namespace needs an Actor. The Actor's own name comes from the AgentInstance's identifier. An AgentInstance in the `kagent` namespace therefore runs on an Actor that Agent Substrate addresses within the `kagent` atespace. Both halves of that identity appear in the address that traffic uses to reach the Actor, which [Sandboxing]({{< link path="substrate-runtime/sandboxing#how-traffic-reaches-a-sandboxed-actor" >}}) covers.
      +
       ## Sandboxing
       
       Because an Actor often runs a model-directed agent that calls tools and executes commands, Substrate runs each Actor in an isolated sandbox rather than a plain container. A WorkerPool's `sandboxClass` field selects the sandbox technology for its Workers: [gVisor](https://gvisor.dev) or a micro-VM technology such as [Kata Containers](https://katacontainers.io). Both technologies isolate an Actor from its Worker's host kernel, and both support suspend and resume operations.
      diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md
      index cd34d668..c2f5021e 100644
      --- a/docs-site/content/kagent/1.x/about/architecture.md
      +++ b/docs-site/content/kagent/1.x/about/architecture.md
      @@ -52,7 +52,7 @@ flowchart TB
           %% plane. Without it, the layout engine staggers the two planes diagonally.
           %% actortemplate ~~~ caller
       
      -    classDef crd stroke:#a78bfa,fill:transparent
      +    classDef crd stroke:#a78bfa,stroke-width:2px
           class harness,template crd
       ```
       
      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 663c726b..cadad85d 100644
      --- a/docs-site/content/kagent/1.x/about/core-concepts.md
      +++ b/docs-site/content/kagent/1.x/about/core-concepts.md
      @@ -31,7 +31,7 @@ flowchart LR
           actortemplate -->|instantiated as| instance
           instance -->|runs on| actor
       
      -    classDef crd stroke:#a78bfa,fill:transparent
      +    classDef crd stroke:#a78bfa,stroke-width:2px
           class harness,template crd
       ```
       
      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 60adc8d1..f5b0f9b9 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
      @@ -52,7 +52,7 @@ spec:
       | `plugins[].skills` | The names of the skills inside that package to enable. Omit or leave empty to enable none. |
       | `source.path` | Selects a directory 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. |
       
      -### The plugin allowlist
      +### 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.
       
      diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md
      index c75a7b02..6d4da3c8 100644
      --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md
      +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md
      @@ -5,7 +5,22 @@ weight: 10
       author: kagent.dev
       ---
       
      -An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools that it was given. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, its own unit of compute, and it does not run that Actor as an ordinary container process. Each Actor runs inside its own sandbox, on a Worker that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it.
      +An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools it can access. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, its own unit of compute, and it does not run that Actor as an ordinary container process. Each Actor runs inside its own **sandbox**, on a Worker that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it.
      +
      +```mermaid
      +flowchart LR
      +    subgraph worker["Worker pod"]
      +        subgraph sandbox["Sandbox: gvisor or microvm"]
      +            subgraph actor["Actor"]
      +                agent["Agent"]
      +            end
      +        end
      +    end
      +    classDef boundary fill:#a78bfa26,stroke:#a78bfa,stroke-width:2px
      +    classDef inner fill:#80808033,stroke:#9ca3af,stroke-width:1px
      +    class sandbox boundary
      +    class agent inner
      +```
       
       ## Sandbox classes
       
      @@ -23,14 +38,44 @@ A WorkerPool selects its class through the `sandboxClass` field, which defaults
       
       A **SandboxConfig** is a cluster-scoped resource that holds the material needed to start one sandbox runtime family. It carries the runtime assets that the node agent fetches, keyed by processor architecture, along with the pause image that holds the sandbox's namespaces as its root container. One SandboxConfig can be marked as the cluster default for its class, and a WorkerPool that names no configuration explicitly resolves to that default.
       
      -Holding these assets in a cluster resource is what lets one configuration pin a runtime version for many ActorTemplates at once, rather than each template carrying its own copy. A default installation creates a single `gvisor-default` configuration.
      +Defining these assets in a cluster resource is what lets one configuration pin a runtime version for many ActorTemplates at once, rather than each template carrying its own copy.
      +
      +A default installation creates a single `gvisor-default` configuration, which looks like the following:
      +
      +```yaml
      +apiVersion: ate.dev/v1alpha1
      +kind: SandboxConfig
      +metadata:
      +  name: gvisor-default
      +spec:
      +  sandboxClass: gvisor
      +  default: true
      +  pauseImage: registry.k8s.io/pause:3.10.2@sha256:
      +  assets:
      +    amd64:
      +      gvisor:
      +        url: gs://gvisor/releases/release/20260803/x86_64/gvisor.tar.bz2
      +        sha256: 
      +    arm64:
      +      gvisor:
      +        url: gs://gvisor/releases/release/20260803/aarch64/gvisor.tar.bz2
      +        sha256: 
      +```
      +
      +| Field | Description |
      +| ----- | ----------- |
      +| `sandboxClass` | The sandbox runtime family that this configuration applies to, `gvisor` or `microvm`. A WorkerPool only draws on configurations whose class matches its own. |
      +| `default` | Marks this configuration as the cluster default for its class. Expect at most one default per class. |
      +| `pauseImage` | The image for the root sandbox container, which holds the sandbox's namespaces and runs no workload code. It must be pinned to a digest, because the snapshot manifest records it, and changing the image invalidates the snapshots that were taken with it. |
      +| `assets` | The files that the node agent fetches, keyed first by processor architecture and then by asset name. A `gvisor` class expects one `gvisor` asset, the release archive that the node agent extracts. A `microvm` class expects several, such as `cloud-hypervisor`, `kata-kernel`, and `kata-image`. |
      +| `assets...sha256` | The lowercase hex digest of the file. The node agent verifies each download against it, and caches the result under a path that includes the digest, so changing the digest fetches the new asset instead of reusing the cached one. To read the configuration that your own cluster installed, including the pinned digests, run `kubectl get sandboxconfig gvisor-default -o yaml`.|
       
       ## What the sandbox separates
       
       The sandbox draws a boundary in three places.
       
       - **Process and kernel**: The Actor's processes run against the sandbox runtime rather than the Worker node's kernel. A system call that the workload makes is handled by gVisor's user-space kernel, or by the guest kernel inside a micro-VM, instead of reaching the host directly.
      -- **Filesystem**: The Actor sees the filesystem assembled from its container image, plus whatever durable volume its ActorTemplate declares. Writes to the root filesystem are a layer on top of the image, captured in a `Full` snapshot and discarded by a `Data` one. See [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) for what each scope keeps.
      +- **Filesystem**: The Actor sees the filesystem assembled from its container image, plus whatever durable volume its ActorTemplate declares. Writes to the root filesystem are a layer on top of the image, captured in a `Full` snapshot and discarded by a `Data` one. For what each scope keeps, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}).
       - **Network**: The Actor does not share the Worker pod's network position. The node agent gives the active Actor a private, point-to-point virtual network inside the Worker pod, so reaching the Actor means going through Agent Substrate's own network path rather than connecting to the Worker directly.
       
       ## How traffic reaches a sandboxed Actor
      diff --git a/docs-site/layouts/partials/custom/head-end.html b/docs-site/layouts/partials/custom/head-end.html
      index 603d7cc0..23e750a2 100644
      --- a/docs-site/layouts/partials/custom/head-end.html
      +++ b/docs-site/layouts/partials/custom/head-end.html
      @@ -23,3 +23,57 @@
       
       
       
      +
      +{{- /* Mermaid light-theme colors.
      +
      +  Mermaid's stock "default" (light) theme fills clusters pale yellow (#ffffde)
      +  and nodes lavender (#ECECFF), which is not the house palette. Its "dark" theme
      +  is already correct: a gray cluster with the node reading as the page behind it.
      +
      +  This cannot be fixed from CSS or from a classDef:
      +    - Mermaid emits classDef rules as `#mermaid- .cls>*{...!important}`.
      +      That is ID-scoped, so no class-based rule in custom.css can outrank it.
      +    - `fill:var(--x)` inside a classDef is a parse error — the parentheses break
      +      Mermaid's classDef grammar — so the color cannot be a CSS variable.
      +    - `fill:transparent` is not "the page" inside nested subgraphs: SVG
      +      composites, so a transparent node shows the stacked cluster tints behind
      +      it rather than the panel color.
      +
      +  So the light values are supplied as themeVariables, the same mechanism
      +  Mermaid's dark theme uses. docs-theme-extras owns the Mermaid partial and
      +  re-runs mermaid.initialize() on every theme switch, so this wraps initialize
      +  rather than calling it, and stays correct across toggles without forking that
      +  partial. Kept in this file (not a new _partials/custom/head-end.html) because
      +  Hugo prefers _partials/ over partials/, so a second file would shadow this one
      +  and drop the themeExtras bootstrap above. */ -}}
      +
      
      From e3f8c4d8ccdec9f98c8326106640ef8c0e456da5 Mon Sep 17 00:00:00 2001
      From: Rachael Graham 
      Date: Thu, 27 Aug 2026 16:09:03 -0500
      Subject: [PATCH 26/70] glossary
      
      Signed-off-by: Rachael Graham 
      ---
       docs-site/assets/css/custom.css               | 30 ++++++++++++
       .../kagent/1.x/about/agent-substrate.md       |  5 +-
       .../content/kagent/1.x/about/architecture.md  | 10 ++--
       .../content/kagent/1.x/about/core-concepts.md |  5 +-
       .../kagent/1.x/skills-and-mcp/skills.md       |  4 +-
       .../1.x/substrate-runtime/sandboxing.md       | 13 ++---
       .../substrate-runtime/suspend-and-resume.md   | 16 +++----
       docs-site/data/glossary.yaml                  | 47 +++++++++++++++++++
       8 files changed, 105 insertions(+), 25 deletions(-)
       create mode 100644 docs-site/data/glossary.yaml
      
      diff --git a/docs-site/assets/css/custom.css b/docs-site/assets/css/custom.css
      index 2f66da83..a1826742 100644
      --- a/docs-site/assets/css/custom.css
      +++ b/docs-site/assets/css/custom.css
      @@ -451,3 +451,33 @@ pre.mermaid {
         display: flex;
         justify-content: center;
       }
      +
      +/* ── Glossary term indicator ──────────────────────────────────────────────
      +   docs-theme-extras marks a {{< gloss >}} term with `border-bottom: 1px
      +   dotted #666` and defines no dark-mode variant. Two problems: that color
      +   lands near 3:1 on this site's dark page, and a 1px dotted rule is only
      +   about half coverage, so it reads as a hairline whatever its contrast.
      +
      +   Swap the border for a text-decoration underline, which allows a real
      +   thickness and an offset that lifts the dots off the baseline, and raise
      +   the color per theme. Hover and focus use the OSS brand color in place of
      +   the theme's hardcoded #007acc.
      +
      +   The `html` prefix is load-bearing: glossary.css is a separate  that
      +   loads AFTER custom.css in both the production and dev pipelines, so a bare
      +   `.glossary-term` would lose the cascade at equal specificity. */
      +html .glossary-term {
      +  border-bottom: none;
      +  text-decoration: underline;
      +  text-decoration-style: dotted;
      +  text-decoration-thickness: 2px;
      +  text-underline-offset: 4px;
      +  text-decoration-color: #4b5563;
      +}
      +html.dark .glossary-term {
      +  text-decoration-color: #9ca3af;
      +}
      +html .glossary-term:hover,
      +html .glossary-term:focus {
      +  text-decoration-color: var(--theme-primary, #0060cf);
      +}
      diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md
      index e21f94af..74a9bbe3 100644
      --- a/docs-site/content/kagent/1.x/about/agent-substrate.md
      +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md
      @@ -5,11 +5,11 @@ weight: 40
       author: kagent.dev
       ---
       
      -The [kagent architecture]({{< link path="about/architecture" >}}) page established that every AgentInstance runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the atespace that identifies it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand.
      +The [kagent architecture]({{< link path="about/architecture" >}}) page established that every {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the atespace that identifies it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand.
       
       ## ActorTemplate
       
      -Every Actor is created from an **ActorTemplate**, the compiled definition that the kagent controller produces from a Harness and AgentTemplate pair.
      +Every Actor is created from an **ActorTemplate**, the compiled definition that the kagent controller produces from a {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} pair.
       
       What Substrate adds is enforcement. Substrate rejects any change to an ActorTemplate's spec after it is created, so immutability is a property of the resource itself rather than a convention that the controller follows. That immutability requires the controller to create a new ActorTemplate for every compiled revision instead of editing an existing one, and allows the controller to safely reclaim an old ActorTemplate once no AgentInstance references it.
       
      @@ -36,6 +36,7 @@ Because an Actor often runs a model-directed agent that calls tools and executes
       Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming allows a WorkerPool to run far more Actors than it has Workers for at any given moment.
       
       The following diagram traces an Actor through one suspend-and-resume cycle, and shows the second path that opens up once the resulting snapshot is tagged.
      +

      ```mermaid flowchart LR diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index c2f5021e..508614ba 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -11,8 +11,8 @@ The previous page defined the [core concepts]({{< link path="about/core-concepts kagent 1.0 splits authorization across two planes: -- The **Kubernetes plane** governs the Harness and AgentTemplate custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit the resources, exactly as it would for any other Custom Resource Definition (CRD). -- The **kagent plane** governs any interactions involving AgentInstances, such as creating, suspending, resuming, sharing, deleting, and holding a conversation with an AgentInstance. kagent's own gRPC authentication and authorization decide who can complete these interactions, independent of Kubernetes RBAC. +- The **Kubernetes plane** governs the {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit the resources, exactly as it would for any other Custom Resource Definition (CRD). +- The **kagent plane** governs any interactions involving {{< gloss "AgentInstance" >}}AgentInstances{{< /gloss >}}, such as creating, suspending, resuming, sharing, deleting, and holding a conversation with an AgentInstance. kagent's own gRPC authentication and authorization decide who can complete these interactions, independent of Kubernetes RBAC. Someone with Kubernetes RBAC access to apply a Harness and AgentTemplate does not automatically have access to create or talk to AgentInstances that use them, and the reverse is also true. The following diagram shows where the boundary between the two planes falls.

      @@ -56,11 +56,11 @@ flowchart TB class harness,template crd ``` -Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an ActorTemplate on Substrate. +Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. -The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an Actor. +The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an {{< gloss "Actor" >}}Actor{{< /gloss >}}. -From there, the caller holds a conversation with the AgentInstance over the A2A (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance. This means that the caller only ever needs to know an AgentInstance's identity, never which Actor or Worker is behind it. +From there, the caller holds a conversation with the AgentInstance over the A2A (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance. This means that the caller only ever needs to know an AgentInstance's identity, never which Actor or {{< gloss "Worker" >}}Worker{{< /gloss >}} is behind it. ## Why two planes 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 cadad85d..d0e064cf 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -14,7 +14,8 @@ The new model separates what an agent can do from how it is allowed to run: - An [**AgentInstance**](#agentinstance) is a running conversation, created by pairing the two. - An [**Actor**](#actor) is the sandboxed process, provided by Substrate, that an AgentInstance runs on. -The following diagram shows how a Harness and an AgentTemplate become a running conversation. The kagent controller compiles the Harness and AgentTemplate pair into an ActorTemplate, and each AgentInstance is created from that ActorTemplate and runs on an Actor. +The following diagram shows how a Harness and an AgentTemplate become a running conversation. The kagent controller compiles the Harness and AgentTemplate pair into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}}, and each AgentInstance is created from that ActorTemplate and runs on an Actor. +

      ```mermaid flowchart LR @@ -91,7 +92,7 @@ For the AgentInstance gRPC service definition, see the [API reference]({{< link An **Actor** is the sandboxed unit of compute, provided by [Agent Substrate]({{< link path="about/agent-substrate" >}}), that _runs an AgentInstance's conversation loop_. Every AgentInstance is backed by an Actor. -Actors are the reason why AgentInstances can suspend and resume cheaply instead of staying resident. An idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. To understand the full mechanics (Workers, WorkerPools, ActorTemplates, and snapshotting), see [Agent Substrate architecture]({{< link path="about/agent-substrate" >}}). +Actors are the reason why AgentInstances can suspend and resume cheaply instead of staying resident. An idle Actor can be snapshotted and torn down, then resumed from that snapshot on demand. To understand the full mechanics ({{< gloss "Worker" >}}Workers{{< /gloss >}}, {{< gloss "WorkerPool" >}}WorkerPools{{< /gloss >}}, ActorTemplates, and snapshotting), see [Agent Substrate architecture]({{< link path="about/agent-substrate" >}}). ## Agent tools: Shared vs. Dedicated 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 f5b0f9b9..1131e0f4 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,9 +5,9 @@ weight: 20 author: kagent.dev --- -A **skill** 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 AgentTemplate attaches skills by naming where each one comes from, and kagent fetches them and places them where the agent runtime can find them. +A **skill** 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. -## What a skill is +## 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. diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index 6d4da3c8..307ea864 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -5,7 +5,8 @@ weight: 10 author: kagent.dev --- -An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools it can access. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, its own unit of compute, and it does not run that Actor as an ordinary container process. Each Actor runs inside its own **sandbox**, on a Worker that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it. +An agent is a program that decides at run time what to do next. It runs the commands that a model asks for, and it calls the tools it can access. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, its own unit of compute, and it does not run that Actor as an ordinary container process. Each Actor runs inside its own **sandbox**, on a {{< gloss "Worker" >}}Worker{{< /gloss >}} that hosts one Actor at a time. This page explains what selects a sandbox, what the sandbox separates, and how traffic reaches an Actor through it. +

      ```mermaid flowchart LR @@ -24,15 +25,15 @@ flowchart LR ## Sandbox classes -A **sandbox class** is the sandbox runtime family that a Worker uses. Agent Substrate supports two. +A **sandbox class** is the sandbox runtime family that a Worker uses. {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} supports two. - **`gvisor`** (default): Runs the workload against a [gVisor](https://gvisor.dev) user-space kernel, which keeps the workload's system calls from reaching the host kernel. - **`microvm`**: Runs the workload inside a lightweight virtual machine, which places a hypervisor boundary between the workload and the host. -A WorkerPool selects its class through the `sandboxClass` field, which defaults to `gvisor`. The choice is not only a runtime preference. It also shapes the Worker pods that Agent Substrate creates for that pool, including the virtualization device mounts and node placement that a micro-VM needs. +A {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} selects its class through the `sandboxClass` field, which defaults to `gvisor`. The choice is not only a runtime preference. It also shapes the Worker pods that Agent Substrate creates for that pool, including the virtualization device mounts and node placement that a micro-VM needs. > [!NOTE] -> kagent generates ActorTemplates that use the `gvisor` class. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. +> kagent generates {{< gloss "ActorTemplate" >}}ActorTemplates{{< /gloss >}} that use the `gvisor` class. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. ## Sandbox configuration @@ -80,7 +81,7 @@ The sandbox draws a boundary in three places. ## How traffic reaches a sandboxed Actor -Every Actor is addressed by name, at `..actors.resources.substrate.ate.dev`. Reaching it involves several hops, and each one is what keeps a sandboxed Actor addressable without exposing the Worker that it happens to be running on. +Every Actor is addressed by its {{< gloss "Atespace" >}}atespace{{< /gloss >}} and name, at `..actors.resources.substrate.ate.dev`. Reaching it involves several hops, and each one is what keeps a sandboxed Actor addressable without exposing the Worker that it happens to be running on. 1. Agent Substrate runs its own Domain Name System (DNS) service that answers queries for that address pattern with the address of the router, rather than any individual Worker. 2. The router reads the Actor name and atespace from the request, asks the Agent Substrate API to resume that Actor and report which Worker it is now assigned to, then selects that Worker as the destination. @@ -88,7 +89,7 @@ Every Actor is addressed by name, at `..actors.resources.s Because the router resolves the Worker assignment on every request, an Actor keeps a stable address across suspends, resumes, and moves between Workers. -Traffic in the other direction leaves through a separate egress gateway rather than going straight out from the Worker. Routing Actor egress through one gateway is what gives Agent Substrate a single place to apply outbound controls. +Traffic in the other direction leaves through a separate egress gateway rather than going straight out from the Worker. Routing Actor egress through one gateway provides a single place to apply outbound controls. ## Default network posture diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 2252bb5b..7b59dc34 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -5,11 +5,11 @@ weight: 20 author: kagent.dev --- -An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, the unit that it suspends and resumes, and it treats that idle time as reclaimable: it suspends an idle Actor into a snapshot, frees the Worker that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. +An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, the unit that it suspends and resumes, and it treats that idle time as reclaimable: it suspends an idle Actor into a snapshot, frees the {{< gloss "Worker" >}}Worker{{< /gloss >}} that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. ## Actor lifecycle operations -Agent Substrate provides three lifecycle operations, and each one moves an Actor between states that you can observe on the Actor record. +{{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} provides three lifecycle operations, and each one moves an Actor between states that you can observe on the Actor record. - **Suspend**: Writes the Actor's state to a durable snapshot in snapshot storage, then frees its Worker. A running Actor is checkpointed on its Worker. A paused Actor's node-local snapshot is uploaded instead. - **Pause**: Takes a short-term checkpoint whose files stay on the node. Pausing pins the Actor to that node, because the following resume is prioritized onto the node that holds the snapshot files. @@ -18,11 +18,11 @@ Agent Substrate provides three lifecycle operations, and each one moves an Actor An Actor reports its position in that cycle through its state, which is one of `RESUMING`, `RUNNING`, `SUSPENDING`, `SUSPENDED`, `PAUSING`, `PAUSED`, `CRASHED`, or `DELETING`. Only a suspended Actor can be deleted. > [!NOTE] -> Resume restores an Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that the Actor ran on before. Suspend and resume are what let a WorkerPool carry far more Actors than it has Workers at any one moment. +> Resume restores an Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that the Actor ran on before. Suspend and resume are what let a {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} carry far more Actors than it has Workers at any one moment. ## What a snapshot captures -An ActorTemplate's snapshot configuration decides how much of an Actor a given snapshot holds. Two scopes exist. +An {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}}'s snapshot configuration decides how much of an Actor a given snapshot holds. Two scopes exist. - **`Full`**: Captures process memory, the root filesystem changes layered on top of the container image, and any attached durable volumes. A `Full` snapshot holds everything that is needed to resume the Actor hot, with its in-memory state intact. - **`Data`**: Captures only the contents of attached durable volumes. Process memory and the rest of the root filesystem are discarded, which makes the snapshot much cheaper to write and store. @@ -37,10 +37,10 @@ When an Actor resumes from a `Data`-scope snapshot, the ActorTemplate's `onResum Two kinds of snapshot serve different purposes, and both appear in a normal installation. -- **Golden snapshot**: Captured once, when an ActorTemplate is created, from a temporary golden boot of the workload. Every Actor of that template is first restored from this one shared snapshot, so a new Actor starts from an already-booted image rather than a cold start. An AgentTemplate is not ready until its golden snapshot exists, which is why the kagent controller reports `waiting for the ActorTemplate golden snapshot` while Agent Substrate captures it. +- **Golden snapshot**: Captured once, when an ActorTemplate is created, from a temporary golden boot of the workload. Every Actor of that template is first restored from this one shared snapshot, so a new Actor starts from an already-booted image rather than a cold start. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} is not ready until its golden snapshot exists, which is why the kagent controller reports `waiting for the ActorTemplate golden snapshot` while Agent Substrate captures it. - **Last snapshot**: The most recent per-Actor snapshot, written on every suspend and used to restore that specific Actor on its next resume. Because it carries the Actor's own accumulated state, the conversation continues from where it stopped. -Snapshots are persisted to object storage, either Google Cloud Storage or Amazon Simple Storage Service (S3), so that Actor state is durable and portable across the cluster. A Harness names the location for its Actors' snapshots in its `substrate.snapshotPolicy` section. +Snapshots are persisted to object storage, either Google Cloud Storage or Amazon Simple Storage Service (S3), so that Actor state is durable and portable across the cluster. A {{< gloss "Harness" >}}Harness{{< /gloss >}} names the location for its Actors' snapshots in its `substrate.snapshotPolicy` section. ## Suspension between turns @@ -48,14 +48,14 @@ kagent does not wait for an Actor to go idle for a long stretch before suspendin A turn reaches such a boundary when its task enters a terminal state, or when the task stops to wait on a person, which is the `INPUT_REQUIRED` and `AUTH_REQUIRED` case. At that point kagent suspends the Actor durably and records the exact snapshot that the suspend produced. -The AgentInstance's own state does not change while this happens. It stays `READY` throughout, because suspension is a property of the runtime underneath it rather than of the conversation. A caller that lists AgentInstances sees a ready agent whether or not an Actor is currently running for it. +The {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}}'s own state does not change while this happens. It stays `READY` throughout, because suspension is a property of the runtime underneath it rather than of the conversation. A caller that lists AgentInstances sees a ready agent whether or not an Actor is currently running for it. > [!NOTE] > Creating an AgentInstance does not start an Actor running. The Actor is created suspended, and the first message addressed to the AgentInstance is what resumes it. ## Resuming on demand -Every Actor is reachable at a uniform address, `..actors.resources.substrate.ate.dev`, resolved by Agent Substrate's own Domain Name System (DNS) server. Traffic sent to that name is routed to the right Worker, and an Actor that is currently suspended is resumed automatically to receive it. Nothing in the calling path needs to know whether the Actor was running beforehand. +Every Actor is reachable at a uniform address built from its {{< gloss "Atespace" >}}atespace{{< /gloss >}} and name, `..actors.resources.substrate.ate.dev`, resolved by Agent Substrate's own Domain Name System (DNS) server. Traffic sent to that name is routed to the right Worker, and an Actor that is currently suspended is resumed automatically to receive it. Nothing in the calling path needs to know whether the Actor was running beforehand. Resume speed is what makes suspending at every turn boundary practical rather than costly. Agent Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml new file mode 100644 index 00000000..a506afb1 --- /dev/null +++ b/docs-site/data/glossary.yaml @@ -0,0 +1,47 @@ +# Glossary terms for the {{< gloss >}} shortcode, which docs-theme-extras +# provides along with the tooltip behavior (glossary.js) and styling +# (glossary.css). Both load automatically through themeExtras/head-end.html. +# +# Usage is a PAIRED shortcode; the unclosed form is a build error: +# {{< gloss "Atespace" >}}atespace{{< /gloss >}} +# The key is the tooltip heading, so it is capitalized. The inner text is what +# appears in the sentence, so it carries the prose's own casing and plurality. +# +# Gloss the FIRST instance of a term on a page only. Repeating it on every +# occurrence adds underlines without adding information. +# +# A key that is missing here renders as plain text with no tooltip and no +# warning, so check spelling against this file when a tooltip does not appear. +# +# Entries carry `short` only, matching agentgateway's glossary. The shortcode +# also supports an optional `link` ("Learn more"), but it hardcodes +# target="_blank", which suits an external reference rather than a link to +# another page in this docset. + +Actor: + short: "The sandboxed unit of compute, provided by Agent Substrate, that runs an AgentInstance's conversation loop. Every AgentInstance is backed by one." + +Atespace: + short: "The isolation boundary that an Actor belongs to, and the first half of its identity. Global-scoped in Agent Substrate, not a Kubernetes namespace." + +Agent Substrate: + short: "The runtime that kagent runs agents on. It multiplexes many sandboxed Actors onto a smaller pool of pre-started Workers, suspending idle ones to snapshots." + +ActorTemplate: + short: "The compiled, immutable definition that the kagent controller produces from a Harness and AgentTemplate pair. Every Actor is created from one." + +AgentInstance: + short: "A running, conversational pairing of a Harness and an AgentTemplate. Unlike the two, it is not a Kubernetes resource: kagent's gRPC API creates it and its database tracks it." + +AgentTemplate: + short: "A Kubernetes custom resource defining what an agent does: its model, system prompt, tools, skills, and plugins. It runs only once a Harness accepts it." + +Harness: + short: "A Kubernetes custom resource defining how an agent is allowed to run: its runtime, workload image, WorkerPool and snapshot storage, and which AgentTemplates it accepts." + +Worker: + short: "A pre-started, sandboxed pod that hosts at most one Actor at a time. Actors are multiplexed across a pool of Workers over time." + +WorkerPool: + short: "A Kubernetes custom resource declaring how many Workers to keep running and which sandbox class they use. An operator must provision one before any Harness can create AgentInstances." + From b7619a41d017ac517330ac7d099349585676a29d Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 27 Aug 2026 16:42:47 -0500 Subject: [PATCH 27/70] Phase 2, review 4 Signed-off-by: Rachael Graham --- .../snippets/snapshot-cycle-diagram.md | 9 +++++++ .../kagent/1.x/about/agent-substrate.md | 10 +------ .../substrate-runtime/suspend-and-resume.md | 26 ++++++++++++++++--- 3 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 docs-site/assets/kagent-docs/snippets/snapshot-cycle-diagram.md diff --git a/docs-site/assets/kagent-docs/snippets/snapshot-cycle-diagram.md b/docs-site/assets/kagent-docs/snippets/snapshot-cycle-diagram.md new file mode 100644 index 00000000..b52db498 --- /dev/null +++ b/docs-site/assets/kagent-docs/snippets/snapshot-cycle-diagram.md @@ -0,0 +1,9 @@ +```mermaid +flowchart LR + pool["WorkerPool"] --> worker1["Worker"] + worker1 -->|hosts| actor["Actor
      (running)"] + actor -->|suspend| snapshot["ActorSnapshot
      (immutable)"] + snapshot -->|resume| worker2["Any free Worker
      in the pool"] + snapshot -->|pinned by| tag["ActorSnapshotTag
      (retention pin)"] + tag -->|seeds| newactor["New Actor"] +``` diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 74a9bbe3..d9c0f31c 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -38,15 +38,7 @@ Substrate's density model rests on one fact about agent workloads: an Actor spen The following diagram traces an Actor through one suspend-and-resume cycle, and shows the second path that opens up once the resulting snapshot is tagged.

      -```mermaid -flowchart LR - pool["WorkerPool"] --> worker1["Worker"] - worker1 -->|hosts| actor["Actor
      (running)"] - actor -->|suspend| snapshot["ActorSnapshot
      (immutable)"] - snapshot -->|resume| worker2["Any free Worker
      in the pool"] - snapshot -->|pinned by| tag["ActorSnapshotTag
      (retention pin)"] - tag -->|seeds| newactor["New Actor"] -``` +{{< reuse "kagent-docs/snippets/snapshot-cycle-diagram.md" >}} A **WorkerPool** keeps **Workers** running and ready, and one Worker hosts the **Actor** while its conversation is active. Suspending that Actor writes its full state to an immutable **ActorSnapshot** and frees the Worker that it was running on. diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 7b59dc34..ed0c3455 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -15,6 +15,11 @@ An agent spends most of its life waiting. It waits on a person to reply, and it - **Pause**: Takes a short-term checkpoint whose files stay on the node. Pausing pins the Actor to that node, because the following resume is prioritized onto the node that holds the snapshot files. - **Resume**: Restores a suspended or paused Actor onto a Worker, from its latest snapshot. The common path restores from a snapshot rather than cold-booting the workload. +The following diagram traces an Actor through those operations, and shows the further path that opens once a snapshot is [pinned by a tag](#checkpoints). +

      + +{{< reuse "kagent-docs/snippets/snapshot-cycle-diagram.md" >}} + An Actor reports its position in that cycle through its state, which is one of `RESUMING`, `RUNNING`, `SUSPENDING`, `SUSPENDED`, `PAUSING`, `PAUSED`, `CRASHED`, or `DELETING`. Only a suspended Actor can be deleted. > [!NOTE] @@ -29,10 +34,13 @@ An {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}}'s snapshot configura Scopes describe only what a snapshot captures, and they are configured per trigger. The `onPause` setting selects what a pause captures on the node, and `onCommit` selects what a suspend uploads to snapshot storage. What `onCommit` captures must be a subset of what `onPause` captures. -A **DurableDir volume** is the per-Actor application data surface. Its contents are preserved by the `Data` scope, so they survive a suspend and resume cycle independently of process memory. How many such volumes an ActorTemplate can declare depends on its sandbox class. A `microvm` template can declare several, because they are subdirectories of a single shared filesystem. A `gvisor` template is limited to one, until gVisor accepts more than a single durable mount. +A **DurableDir volume** is the per-Actor application data surface. Its contents are preserved by the `Data` scope, so they survive a suspend and resume cycle independently of process memory. How many volumes an ActorTemplate can declare depends on its sandbox class. A `microvm` template can declare several, because they are subdirectories of a single shared filesystem. A `gvisor` template is limited to one, until gVisor accepts more than a single durable mount. When an Actor resumes from a `Data`-scope snapshot, the ActorTemplate's `onResume.fromData` setting decides where the rest of the guest state comes from. The default is `ColdBoot`, which starts the containers fresh from the container image with the durable volume contents restored over them. +> [!NOTE] +> These scopes describe what Agent Substrate supports, not choices that you make. kagent compiles every ActorTemplate with the same snapshot configuration: `Full` on pause, `Data` on commit, `ColdBoot` on resume, and a single DurableDir volume named `data`. The only snapshot setting that you author is the storage location, on the Harness. + ## Golden and per-Actor snapshots Two kinds of snapshot serve different purposes, and both appear in a normal installation. @@ -42,6 +50,16 @@ Two kinds of snapshot serve different purposes, and both appear in a normal inst Snapshots are persisted to object storage, either Google Cloud Storage or Amazon Simple Storage Service (S3), so that Actor state is durable and portable across the cluster. A {{< gloss "Harness" >}}Harness{{< /gloss >}} names the location for its Actors' snapshots in its `substrate.snapshotPolicy` section. +```yaml +spec: + substrate: + workerPoolRef: + name: kagent-default + snapshotPolicy: + # The object storage location your cluster's Substrate installation uses + location: gs:///kagent/ +``` + ## Suspension between turns kagent does not wait for an Actor to go idle for a long stretch before suspending it. It suspends the Actor at every turn boundary, as soon as the conversation reaches a point where nothing is running. @@ -51,7 +69,7 @@ A turn reaches such a boundary when its task enters a terminal state, or when th The {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}}'s own state does not change while this happens. It stays `READY` throughout, because suspension is a property of the runtime underneath it rather than of the conversation. A caller that lists AgentInstances sees a ready agent whether or not an Actor is currently running for it. > [!NOTE] -> Creating an AgentInstance does not start an Actor running. The Actor is created suspended, and the first message addressed to the AgentInstance is what resumes it. +> Creating an AgentInstance does not start an Actor running. The Actor is created as suspended, and the first message addressed to the AgentInstance resumes it. ## Resuming on demand @@ -63,9 +81,9 @@ Resume speed is what makes suspending at every turn boundary practical rather th A snapshot that Agent Substrate writes on suspend is transient. Agent Substrate is free to collect it once a newer snapshot supersedes it. A **checkpoint** makes one of those snapshots durable by pinning it. -Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the AgentInstance most recently suspended to. The tag names that one snapshot permanently, and it acts as a retention pin, so Agent Substrate does not collect a snapshot while a tag still names it. Deleting the checkpoint removes the tag and releases the pin. +Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the AgentInstance most recently suspended to. The tag names that one snapshot permanently and acts as a retention pin, such that Agent Substrate does not collect a snapshot while a tag still names it. Deleting the checkpoint removes the tag and releases the pin. -Because a checkpoint captures a turn boundary, an AgentInstance must be at one to be checkpointed. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. +An AgentInstance must be a turn boundary to be checkpointed, because the turn boundary is captured. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. ## Next steps From 6e7d3b702798862babb0126ed33b7294e2848ec0 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 28 Aug 2026 11:57:22 -0500 Subject: [PATCH 28/70] Phase 2, review 5 Signed-off-by: Rachael Graham --- .../kagent-docs/snippets/artifact-sources.md | 9 +++ .../kagent/1.x/about/agent-substrate.md | 7 --- .../content/kagent/1.x/about/architecture.md | 7 --- .../content/kagent/1.x/about/core-concepts.md | 8 --- .../content/kagent/1.x/setup/installation.md | 13 +++-- .../kagent/1.x/skills-and-mcp/plugins.md | 57 +++++++++++++++++++ .../kagent/1.x/skills-and-mcp/skills.md | 20 +------ .../1.x/substrate-runtime/sandboxing.md | 7 --- .../substrate-runtime/suspend-and-resume.md | 7 --- 9 files changed, 75 insertions(+), 60 deletions(-) create mode 100644 docs-site/assets/kagent-docs/snippets/artifact-sources.md create mode 100644 docs-site/content/kagent/1.x/skills-and-mcp/plugins.md diff --git a/docs-site/assets/kagent-docs/snippets/artifact-sources.md b/docs-site/assets/kagent-docs/snippets/artifact-sources.md new file mode 100644 index 00000000..4f4643ab --- /dev/null +++ b/docs-site/assets/kagent-docs/snippets/artifact-sources.md @@ -0,0 +1,9 @@ +## 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. + +- **`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. diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index d9c0f31c..4844c0a2 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -52,10 +52,3 @@ A tag gives a snapshot a stable, human-meaningful name, so callers do not need t For example, an agent partway through a long incident investigation reaches a state worth keeping. Creating a [checkpoint]({{< link path="substrate-runtime/suspend-and-resume#checkpoints" >}}) tags the snapshot that the agent most recently suspended to, which holds that one snapshot in place while the agent carries on and writes newer ones. Without the tag, Substrate collects that snapshot once a newer one supersedes it. Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. - -## Next steps - -{{< cards >}} - {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} - {{< card link=`{{< link path="operations/substrate-operations" >}}` title="Substrate operations" subtitle="Size a WorkerPool and choose a sandbox class for your cluster." >}} -{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 508614ba..59230b3a 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -67,10 +67,3 @@ From there, the caller holds a conversation with the AgentInstance over the A2A Kubernetes RBAC is designed to authorize configuration changes: who can create a Deployment, edit a ConfigMap, or in this case, apply a Harness or AgentTemplate. It is not designed to authorize a running conversation, share access to it with another user, or scope who can suspend it. kagent's gRPC plane exists to authorize exactly those actions, at the granularity of a single AgentInstance rather than a namespace or a resource kind. This split also keeps the two lifecycles independent. Editing a Harness or AgentTemplate does not affect AgentInstances already running against the ActorTemplate that they were created from. It only affects new AgentInstances, created after the edit is compiled. - -## Next steps - -{{< cards >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="See what an Actor actually runs on, and how it suspends and resumes." >}} - {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} -{{< /cards >}} 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 d0e064cf..f3d5770c 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -104,11 +104,3 @@ An AgentTemplate's tools are not limited to MCP servers. A tool binding can also Shared nesting never goes more than one level deep. A Shared agent tool can have Dedicated agent tools beneath it, but it cannot contain another Shared one. This limit keeps the model predictable. A Dedicated binding gives the child its own Actor. A Shared binding puts the child in its parent's Actor, and because Shared bindings cannot chain, that parent always has an Actor of its own. Working out where any agent runs is therefore never more than a single step. - -## Next steps - -{{< cards >}} - {{< card link=`{{< link path="about/architecture" >}}` title="kagent architecture" subtitle="See how these pieces fit together end to end, from `kubectl apply` to a live conversation." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Learn about Workers, WorkerPools, and ActorTemplates, and how Actors suspend and resume." >}} - {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} -{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index cb46d323..54fe2ee5 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -243,10 +243,11 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ``` Example output: ```console - NAME READY STATUS RESTARTS AGE - kagent-controller-659b58768b-2k6h4 1/1 Running 3 2m - kagent-default-864fdc4c94-xbsl9 1/1 Running 0 2m - kagent-postgresql-65cc684b78-9qbh2 1/1 Running 0 2m + NAME READY STATUS RESTARTS AGE + kagent-controller-659b58768b-2k6h4 1/1 Running 3 2m + kagent-default-864fdc4c94-xbsl9 1/1 Running 0 2m + kagent-kmcp-controller-manager-6676b45958-knkzd 1/1 Running 0 2m + kagent-postgresql-65cc684b78-9qbh2 1/1 Running 0 2m ``` 2. Confirm that the WorkerPool reports a ready replica. @@ -255,8 +256,8 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker ``` Example output: ```console - NAMESPACE NAME DESIRED REPLICAS READY AGE - kagent kagent-default 1 1 1 2m + NAME DESIRED REPLICAS READY AGE + kagent-default 1 1 1 2m ``` 3. Get the address to reach the kagent gRPC API, which serves the AgentInstance lifecycle and conversation calls. The guide to [create your first agent]({{< link path="get-started/your-first-agent" >}}) assumes port-forwarding. 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 new file mode 100644 index 00000000..523ac2aa --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/plugins.md @@ -0,0 +1,57 @@ +--- +title: Plugins +description: Understand what a plugin package holds, and what kagent does with one when an agent starts. +weight: 30 +author: kagent.dev +--- + +A **plugin package** is a bundle that an AgentTemplate attaches with `spec.plugins`. The package carries skills and can also declare Model Context Protocol (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" >}}). + +## What a package holds + +A package root can hold up to three things. + +* `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. + +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`. + +> [!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. + +## MCP servers + +A package that includes `mcp.json` contributes MCP servers to every agent that enables it. 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`. + +Each server names 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. | +| `streamable-http` | `url`, `headers` | Calls a remote server. Specifying `command`, `args`, `env`, or `cwd` is rejected. | +| `sse` | `url`, `headers` | As `streamable-http`, over Server-Sent Events. | + +kagent enforces several rules on these servers, and each one exists to keep a package from reaching outside itself. + +- 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. +- 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. + +### Referring to package 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`. + +* `${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. + +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. + +## Package 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. + +{{< 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 1131e0f4..7bee3a54 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 @@ -13,7 +13,7 @@ A skill is a directory whose root holds a `SKILL.md` file. That file carries fro The description is what 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. -A skill can be published on its own, or bundled with other skills in a **plugin package**. A plugin package follows the Agent Plugins 1.0.0 format. Its `plugin.json` manifest names the package, and its skills live in a `skills` directory, one subdirectory per skill. A package may also declare Model Context Protocol (MCP) servers, which kagent adds to the agent's tools alongside the skills that you enable from that package. +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 Model Context Protocol (MCP) servers that kagent adds to the agent's tools. ## Attach skills to an AgentTemplate @@ -59,15 +59,7 @@ Attaching a plugin package does not enable any of the skills that it carries. On > [!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. -## Every source is immutable - -A skill 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 each one has to be pinned. - -- **`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 of a skill means updating the AgentTemplate to name the new digest, commit, or object version, which compiles a new revision. Agents that are already running keep using the skill content that they started with. +{{< reuse "kagent-docs/snippets/artifact-sources.md" >}} ## Naming rules @@ -77,11 +69,3 @@ Skill names are checked before anything is fetched, and two rules apply across e - 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. - -## Next steps - -{{< cards >}} - {{< card link=`{{< link path="examples/skills" >}}` title="Add skills to agents" subtitle="Walk through attaching a skill from an OCI artifact, end to end." >}} - {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="See how MCP tools and agent tools attach to an AgentTemplate." >}} - {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} -{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index 307ea864..7a607d50 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -96,10 +96,3 @@ Traffic in the other direction leaves through a separate egress gateway rather t Agent Substrate creates a Kubernetes NetworkPolicy for each WorkerPool, selecting that pool's Worker pods. The policy restricts **ingress** to the Agent Substrate router alone. No other pod in the cluster can open a connection to a Worker, so an Actor is not reachable by anything that bypasses the routing path. That policy governs inbound traffic only. It does not constrain what an Actor may reach outbound, so outbound access is whatever the surrounding cluster and its infrastructure already allow. Treat network egress as something to configure deliberately for your environment rather than as something the WorkerPool policy settles. - -## Next steps - -{{< cards >}} - {{< card link=`{{< link path="substrate-runtime/suspend-and-resume" >}}` title="Suspend and resume" subtitle="See what a snapshot captures and how an idle Actor comes back." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} -{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index ed0c3455..2a7054b1 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -84,10 +84,3 @@ A snapshot that Agent Substrate writes on suspend is transient. Agent Substrate Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the AgentInstance most recently suspended to. The tag names that one snapshot permanently and acts as a retention pin, such that Agent Substrate does not collect a snapshot while a tag still names it. Deleting the checkpoint removes the tag and releases the pin. An AgentInstance must be a turn boundary to be checkpointed, because the turn boundary is captured. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. - -## Next steps - -{{< cards >}} - {{< card link=`{{< link path="substrate-runtime/sandboxing" >}}` title="Sandboxing" subtitle="See how a sandbox isolates each Actor's process, filesystem, and network." >}} - {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Review how Workers, Actors, and ActorTemplates fit together." >}} -{{< /cards >}} From 19a4fd244ae55eff1ab79e3435ad7db36ed9f8ea Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 28 Aug 2026 12:38:38 -0500 Subject: [PATCH 29/70] Phase 2, review 6 Signed-off-by: Rachael Graham --- .../1.x/get-started/your-first-agent.md | 41 ++++++++-- .../kagent/1.x/skills-and-mcp/about-tools.md | 75 +++++++++++++++++++ .../kagent/1.x/skills-and-mcp/plugins.md | 14 ++-- .../kagent/1.x/skills-and-mcp/skills.md | 8 +- .../1.x/substrate-runtime/sandboxing.md | 2 +- 5 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index bbb36135..5eb909b8 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -71,22 +71,47 @@ This guide walks you through creating an agent, from applying a Harness and an A kubectl get agenttemplate my-first-agent -n kagent -o jsonpath='{.status.harnesses}' | jq . ``` - A ready pair reports a `Ready` condition for `my-first-harness`. If the status is empty, wait a few seconds for the kagent controller to reconcile, then check again. + A ready pair reports four conditions for `my-first-harness`, ending in `Ready`. If the status is empty, wait a few seconds for the kagent controller to reconcile, then check again. ```json [ { - "harness": "my-first-harness", - "desiredRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b", - "latestSuccessfulRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b", "conditions": [ { - "type": "Ready", + "lastTransitionTime": "2026-08-24T15:02:10Z", + "message": "Harness admission selector matches the AgentTemplate", + "observedGeneration": 1, + "reason": "Accepted", + "status": "True", + "type": "Accepted" + }, + { + "lastTransitionTime": "2026-08-24T15:02:10Z", + "message": "All runtime references resolved", + "observedGeneration": 1, + "reason": "Resolved", + "status": "True", + "type": "ResolvedRefs" + }, + { + "lastTransitionTime": "2026-08-24T15:02:10Z", + "message": "Resolved configuration is compatible with the Harness", + "observedGeneration": 1, + "reason": "Compatible", "status": "True", + "type": "Compatible" + }, + { + "lastTransitionTime": "2026-08-24T15:02:10Z", + "message": "ActorTemplate golden snapshot is ready", + "observedGeneration": 1, "reason": "Ready", - "message": "ActorTemplate is ready", - "lastTransitionTime": "2026-08-24T15:02:10Z" + "status": "True", + "type": "Ready" } - ] + ], + "desiredRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b", + "harness": "my-first-harness", + "latestSuccessfulRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b" } ] ``` 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 new file mode 100644 index 00000000..9441fee6 --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md @@ -0,0 +1,75 @@ +--- +title: About tools +description: Give an agent tools by binding Model Context Protocol servers or other agents to an AgentTemplate. +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 **tool binding**, and every binding selects exactly one source: a Model Context Protocol (MCP) server, or another AgentTemplate used as a tool. A binding that names both, or neither, is rejected. + +- `mcp`: Binds tools from an MCP server. +- `agent`: Binds another AgentTemplate, so that the agent can hand work to it. + +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 the tools to take from it. Naming the tools is required. A binding takes between 1 and 50 named tools, never the server's whole catalog. + +```yaml +tools: + - mcp: + server: + kind: RemoteMCPServer + name: my-mcp-server + tools: + - search_docs + - fetch_page +``` + +| Field | Description | +| ----- | ----------- | +| `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` | The names of the tools to bind, between 1 and 50. Duplicates in the list are collapsed. | + +## Agents as tools + +An `agent` binding points at another AgentTemplate, which lets one agent route work to another. The model reads the `description` when it decides whether to route work here, so a description that states plainly what the bound agent is for matters more than the detail of its configuration. + +```yaml +tools: + - agent: + name: log-searcher + description: Search application logs for a time range and a query string. + templateRef: + name: log-search-agent + isolation: Shared +``` + +| Field | Description | +| ----- | ----------- | +| `agent.name` | The name that the model sees for this binding. | +| `agent.description` | The text that tells the parent agent when to route work here. | +| `agent.templateRef.name` | The AgentTemplate to bind, in the same namespace. | +| `agent.isolation` | The [isolation mode](#shared-and-dedicated-isolation) for the bound agent. Currently, `Shared` is the only supported value. | + +### Shared and Dedicated isolation + +The isolation setting determines whether a bound agent runs inside its parent's runtime boundary, or runs within a boundary of its own. + +- **`Shared`**: The bound agent runs inside the parent's {{< gloss "Actor" >}}Actor{{< /gloss >}}. Nesting costs no extra compute, and the two agents share one sandbox. +- **`Dedicated`**: The bound agent would run in its own Actor, with its own sandbox and its own suspend and resume cycle. + +> [!WARNING] +> `Dedicated` is not currently implemented. The AgentTemplate schema accepts the value, but compiling a binding that uses it fails with `Dedicated AgentTemplate tools are not supported yet`, and the pair does not become ready. Use `Shared`, which is the default. + +### What a Shared tree allows + +A `Shared` 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 revision rather than a failure at run time. + +- **One level of nesting.** A bound agent cannot itself bind another agent. A second consecutive binding is rejected as exceeding the kagent runtime boundary. +- **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`. +- **The bound template must be admitted too.** A nested AgentTemplate has to match the same {{< gloss "Harness" >}}Harness{{< /gloss >}}'s `allowedAgentTemplates` selector. Binding a template that the Harness does not admit is rejected. 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 523ac2aa..4f34fb79 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 @@ -11,9 +11,9 @@ A **plugin package** is a bundle that an AgentTemplate attaches with `spec.plugi A package root can hold up to three things. -* `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 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. 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`. @@ -22,7 +22,7 @@ kagent reads `name` from the manifest and ignores the rest, so a package that ca ## MCP servers -A package that includes `mcp.json` contributes MCP servers to every agent that enables it. 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 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`. Each server names a transport in its `type` field, and the transport determines which other fields are allowed. @@ -30,7 +30,7 @@ Each server names a transport in its `type` field, and the transport determines | --------- | ------ | ----------- | | `stdio` | `command`, `args`, `env`, `cwd` | Runs a process inside 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` | As `streamable-http`, over Server-Sent Events. | +| `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. @@ -45,8 +45,8 @@ An invalid server is skipped with a log entry, and the rest of the file still lo 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`. -* `${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 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. 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. 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 7bee3a54..6cfd1ba2 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 @@ -13,7 +13,7 @@ A skill is a directory whose root holds a `SKILL.md` file. That file carries fro The description is what 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. -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 Model Context Protocol (MCP) servers that kagent adds to the agent's tools. +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 Model Context Protocol (MCP) servers that kagent adds to the agent's [tools]({{< link path="skills-and-mcp/about-tools" >}}). ## Attach skills to an AgentTemplate @@ -47,10 +47,10 @@ spec: | Field | Description | | ----- | ----------- | | `skills[].name` | The name that the skill is mounted under, and the name that the model sees. | -| `skills[].source` | Where to fetch this one skill from. The source root must hold a `SKILL.md` file. | -| `plugins[].source` | Where to fetch the plugin package from. The source root must hold a `plugin.json` manifest. | +| `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. | -| `source.path` | Selects a directory 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. | +| `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 diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index 7a607d50..d919773b 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -66,7 +66,7 @@ spec: | Field | Description | | ----- | ----------- | | `sandboxClass` | The sandbox runtime family that this configuration applies to, `gvisor` or `microvm`. A WorkerPool only draws on configurations whose class matches its own. | -| `default` | Marks this configuration as the cluster default for its class. Expect at most one default per class. | +| `default` | Whether this configuration is the cluster default for its class. Expect at most one default per class. | | `pauseImage` | The image for the root sandbox container, which holds the sandbox's namespaces and runs no workload code. It must be pinned to a digest, because the snapshot manifest records it, and changing the image invalidates the snapshots that were taken with it. | | `assets` | The files that the node agent fetches, keyed first by processor architecture and then by asset name. A `gvisor` class expects one `gvisor` asset, the release archive that the node agent extracts. A `microvm` class expects several, such as `cloud-hypervisor`, `kata-kernel`, and `kata-image`. | | `assets...sha256` | The lowercase hex digest of the file. The node agent verifies each download against it, and caches the result under a path that includes the digest, so changing the digest fetches the new asset instead of reusing the cached one. To read the configuration that your own cluster installed, including the pinned digests, run `kubectl get sandboxconfig gvisor-default -o yaml`.| From 5a463c840d0c2c21510e88b20987b83ccc2508c8 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 28 Aug 2026 13:12:29 -0500 Subject: [PATCH 30/70] Create identity.md Signed-off-by: Rachael Graham --- .../kagent/1.x/substrate-runtime/identity.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs-site/content/kagent/1.x/substrate-runtime/identity.md diff --git a/docs-site/content/kagent/1.x/substrate-runtime/identity.md b/docs-site/content/kagent/1.x/substrate-runtime/identity.md new file mode 100644 index 00000000..23574cee --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/identity.md @@ -0,0 +1,53 @@ +--- +title: Identity +description: Understand how kagent authenticates callers, scopes an AgentInstance to its creator, and how Agent Substrate identifies its own components. +weight: 30 +author: kagent.dev +--- + +A kagent installation authenticates three different kinds of caller, and each one is handled by a different system. This page describes what each layer establishes, and what it does not. + +- An operator applying a {{< gloss "Harness" >}}Harness{{< /gloss >}} is authenticated by [Kubernetes](#the-kubernetes-plane). +- A caller creating or talking to an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} is authenticated by [kagent's own gRPC API](#the-kagent-plane). +- The components inside [Agent Substrate](#the-agent-substrate-plane) authenticate each other. + +## The Kubernetes plane + +Harness and AgentTemplate are Kubernetes custom resources, so Kubernetes role-based access control (RBAC) governs who can create, read, edit, or delete them. Nothing in kagent replaces or supplements that: a cluster's existing roles and bindings decide who authors an agent's runtime and behavior. + +A Harness's `allowedAgentTemplates` selector adds a second, narrower control on top of RBAC. Whoever holds edit access on a Harness decides which AgentTemplates that Harness admits. In this way, RBAC governs who can write the resources, and the selector governs which pairs can run. For more information on the one-way match, see the [Harness core concept]({{< link path="about/core-concepts/#harness" >}}). + +## The kagent plane + +An AgentInstance is not a Kubernetes resource. kagent's gRPC API creates the AgentInstance and kagent's database tracks it, so Kubernetes RBAC does not reach it. kagent authenticates these calls itself. + +Every call on the AgentInstance API requires an authenticated principal. A call that arrives without one is rejected as unauthenticated before any other check runs. + +### Creator ownership + +kagent records a **creator** on every AgentInstance, taken from the authenticated principal that created it. That creator is then part of the database query for every read, so a caller who asks for an AgentInstance that another principal created receives a not-found response rather than a permission error. + +Listing behaves the same way. A list returns the caller's own AgentInstances by default. A caller that sets the request's all-creators flag asks to widen that to every creator in the namespace, and kagent authorizes that request separately from an ordinary list. + +> [!IMPORTANT] +> Creator ownership is the boundary that the open source build enforces. kagent calls an authorizer before every AgentInstance operation. However, the authorizer that this build installs permits every check, so a widened list is available to any authenticated caller. Treat authentication and creator scoping as the guarantees that this build makes. + +### Shares + +A share lets an AgentInstance's owner give another account access to that one conversation. Creating a share produces a token, and a caller presenting that token reaches the shared AgentInstance without becoming its creator. + +A share carries one of two permissions. + +- **`READ_ONLY`**: The holder can read the conversation. kagent refuses any call that is not a read before the request reaches the service. +- **`READ_WRITE`**: The holder can also send messages to the AgentInstance. + +A share widens what the holder can reach to what the owner can see, and the underlying record is read as the owner rather than as the visitor. Revoking the share withdraws that access. + +## The Agent Substrate plane + +{{< 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. + +Each Actor also carries an identity of its own, addressed as its {{< gloss "Atespace" >}}atespace{{< /gloss >}} and name together. [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}) covers how the router uses that identity to reach the right Worker over mTLS. + +> [!IMPORTANT] +> Agent Substrate authenticates callers but does not authorize them. Any provider that you configure as an authenticated caller can reach every remote procedure call, including destructive ones, so configure only providers whose users require full access to Agent Substrate. From cba2dd27003e40b7075f9d2cdea11d095363af78 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 31 Aug 2026 11:40:01 -0500 Subject: [PATCH 31/70] weekend update Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 2 + .../kagent/1.x/about/what-is-kagent.md | 8 +- .../content/kagent/1.x/examples/_index.md | 6 + .../kagent/1.x/examples/agent-substrate.md | 171 ++++++++++++++++ .../1.x/get-started/your-first-agent.md | 190 ++++++++---------- .../content/kagent/1.x/setup/installation.md | 2 +- .../substrate-runtime/suspend-and-resume.md | 6 +- docs-site/data/glossary.yaml | 3 + 8 files changed, 270 insertions(+), 118 deletions(-) create mode 100644 docs-site/content/kagent/1.x/examples/_index.md create mode 100644 docs-site/content/kagent/1.x/examples/agent-substrate.md diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 4844c0a2..29ed404c 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -31,6 +31,8 @@ kagent names each atespace after the Kubernetes namespace of the AgentInstance w Because an Actor often runs a model-directed agent that calls tools and executes commands, Substrate runs each Actor in an isolated sandbox rather than a plain container. A WorkerPool's `sandboxClass` field selects the sandbox technology for its Workers: [gVisor](https://gvisor.dev) or a micro-VM technology such as [Kata Containers](https://katacontainers.io). Both technologies isolate an Actor from its Worker's host kernel, and both support suspend and resume operations. +kagent compiles every ActorTemplate to the `gvisor` class, so a kagent agent runs in a gVisor sandbox today and the micro-VM class is a Substrate capability that kagent does not yet select. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. For what each class isolates, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). + ## Suspend, snapshot, and resume Substrate's density model rests on one fact about agent workloads: an Actor spends most of its time idle, waiting on a person or a large language model (LLM) to respond, not actively computing. Substrate exploits that by suspending idle Actors and reclaiming their Worker, then resuming them on demand when traffic arrives. Suspending and resuming allows a WorkerPool to run far more Actors than it has Workers for at any given moment. diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md index 0c6ef586..e7f78815 100644 --- a/docs-site/content/kagent/1.x/about/what-is-kagent.md +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -43,16 +43,16 @@ Everything works with a single `helm install`. No add-ons, no extra databases, n {{< feature-cards >}} {{< feature-card title="Agent lifecycle via CRDs" desc="Define, version, and roll out Harnesses and AgentTemplates with kubectl and GitOps, the same workflow as every other workload." >}} -{{< feature-card title="Sandboxed by default" desc="Every AgentInstance runs on a Substrate Actor, sandboxed with gVisor or a micro-VM. Run untrusted, model-directed code safely." >}} +{{< feature-card title="Sandboxed by default" desc="Every AgentInstance runs on a Substrate Actor, isolated from the host kernel by a gVisor sandbox. Run untrusted, model-directed code safely." >}} {{< feature-card title="Suspend and resume" desc="Idle AgentInstances suspend and free their compute, then resume on demand. Run far more agents than you have capacity for at any one moment." >}} -{{< feature-card title="Bring your own runtime" desc="Run kagent's native Go or Python engine, or bring Claude Code or Codex as the runtime behind a Harness." >}} -{{< feature-card title="Agent tools" desc="Compose agents from other agents. Choose Shared isolation for cheap nesting, or Dedicated isolation to give a nested agent its own Actor." >}} +{{< feature-card title="Bring your own runtime" desc="Run kagent's native Go or Python engine behind a Harness. Codex is planned as an additional runtime." >}} +{{< feature-card title="Agent tools" desc="Compose agents from other agents. A Shared binding nests an agent inside its parent's Actor, one level deep." >}} {{< feature-card title="Long-term memory" desc="Persistent, vector-backed memory across sessions. Agents remember context, not just the last prompt." >}} {{< feature-card title="Human-in-the-loop" desc="Tool approval gates and agent-initiated questions keep a person in control of consequential actions." >}} {{< feature-card title="Agent-to-Agent (A2A)" desc="AgentInstances talk to callers, and to each other, over the A2A protocol." >}} {{< feature-card title="Skills and plugins" desc="Load skills and capability packages from an Open Container Initiative (OCI) registry, Git, or S3 at startup." >}} {{< feature-card title="Prompt templates" desc="Reusable prompt fragments stored as ConfigMaps. Keep system prompts consistent across agents." >}} -{{< feature-card title="Full observability" desc="OpenTelemetry tracing, Prometheus metrics, and structured logs. See every prompt, every tool call, every token." >}} +{{< feature-card title="Full observability" desc="OpenTelemetry tracing, Prometheus metrics, and structured logs, with control plane traces carrying the Actor that they belong to." >}} {{< feature-card title="Postgres storage" desc="AgentInstances are tracked in production-grade, Postgres-backed storage with reviewable migrations." >}} {{< /feature-cards >}} diff --git a/docs-site/content/kagent/1.x/examples/_index.md b/docs-site/content/kagent/1.x/examples/_index.md new file mode 100644 index 00000000..65bb6f3c --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/_index.md @@ -0,0 +1,6 @@ +--- +title: Examples +description: Work through end-to-end examples that put kagent's runtime, tools, and Agent Substrate features together. +weight: 80 +author: kagent.dev +--- diff --git a/docs-site/content/kagent/1.x/examples/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md new file mode 100644 index 00000000..a8b47ce3 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -0,0 +1,171 @@ +--- +title: Agent Substrate +description: Watch an agent's Actor suspend between turns, pin the conversation with a checkpoint, and fork it into two independent branches. +weight: 10 +author: kagent.dev +--- + +[Agent Substrate]({{< link path="about/agent-substrate" >}}) runs every agent as an Actor: a sandboxed unit of compute that holds a {{< gloss "Worker" >}}Worker{{< /gloss >}} only while a turn is in progress, and whose state you can pin and branch. This example follows one agent through all three behaviors. + +## Before you begin + +1. Complete [Your first agent]({{< link path="get-started/your-first-agent" >}}). The steps on this page continues from the Harness, AgentTemplate, and AgentInstance that the agent guide creates, and assumes that you have sent the agent at least one message. + +2. If you have not already, save the AgentInstance's ID to an environment variable. To find the ID, run `kagent get agent-instance` to list your AgentInstances and copy the value from the `ID` column. + ```bash + export INSTANCE_ID= + ``` + +3. Install [grpcurl](https://github.com/fullstorydev/grpcurl), and confirm that your kagent installation sets `controller.grpc.reflection`. Checkpoints and forks have no kagent CLI commands yet, so this example calls `CheckpointService` directly. + +4. Port-forward the controller's gRPC port to your local machine. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + +## Watch the Actor suspend between turns + +1. List the Actors in your namespace's {{< gloss "Atespace" >}}atespace{{< /gloss >}}. kagent names an AgentInstance's Actor `ai-`. + ```bash + kubectl ate get actors --atespace kagent + ``` + + Between turns, the Actor reports `ACTOR_STATE_SUSPENDED` and holds no Worker, so the `ATEOM POD` column reads ``. Example output: + ```console + ATESPACE NAME TEMPLATE STATE ATEOM POD ATEOM IP VERSION AGE + kagent ai-0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 kagent/my-first-agent-my-first-harness-5f2b3c1a9e8d ACTOR_STATE_SUSPENDED 4 6m + ``` + + That Actor is also the isolation boundary. Every Actor runs in its own gVisor sandbox rather than sharing one with its neighbors, which is what makes it safe to let a model run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). + +2. Send the agent another message. Nothing in the command acknowledges that the Actor was suspended, because resuming is automatic. + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "Summarize this conversation so far." + ``` + +3. List the Actors again while the turn is running, and the same Actor reports `ACTOR_STATE_RUNNING` against a real Worker pod. Once the turn finishes it returns to `ACTOR_STATE_SUSPENDED`. + ```bash + kubectl ate get actors --atespace kagent + ``` + +The AgentInstance stays `READY` throughout all of this. Suspension is a property of the Actor underneath the conversation, not of the conversation, which is why a suspended agent is still listed and still readable. For the full cycle, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + +## Pin the conversation with a checkpoint + +Each suspend writes a snapshot, and Agent Substrate is free to collect that snapshot once a newer one supersedes it. A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} pins one so that you can come back to it. + +1. Create a checkpoint. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. + ```bash + grpcurl -plaintext \ + -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'","requestId":"'"$(uuidgen)"'"}' \ + localhost:8084 kagent.api.v1alpha1.CheckpointService/CreateCheckpoint + ``` + + The checkpoint records the snapshot it pinned and how far the transcript had advanced. Example output: + ```json + { + "checkpoint": { + "id": "0198c3e2-8a41-7d05-b6c2-1f4e9a7b3c58", + "namespace": "kagent", + "agentInstanceId": "0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10", + "headTaskId": "0198c3d9-b7e3-7a24-8f10-6c2d5e8a1b47", + "historySequence": "4", + "state": "CHECKPOINT_STATE_READY", + "createdAt": "2026-08-31T15:12:44Z" + } + } + ``` + +2. Save the checkpoint's `id`, to fork from it in the next section. + ```bash + export CHECKPOINT_ID= + ``` + +3. List the checkpoints on the AgentInstance at any time. Omit `limit` for the default page of 50, up to a maximum of 100. + ```bash + grpcurl -plaintext \ + -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'","page":{"limit":50}}' \ + localhost:8084 kagent.api.v1alpha1.CheckpointService/ListCheckpoints + ``` + +Underneath, the checkpoint attaches an ActorSnapshotTag named `checkpoint-` to the snapshot, and Agent Substrate does not collect a snapshot while a tag names it. You can see the tag with `kubectl ate get actor-snapshot-tag`. + +> [!NOTE] +> A checkpoint captures a turn boundary, so two conditions have to hold and a request that fails either one reports `AgentInstance has no quiescent turn boundary`. The AgentInstance must be `READY` with no lifecycle operation in flight, and at least one turn must have reached a quiescent state. Send the request again once the turn finishes. + +## Fork the conversation into a second agent + +Forking creates a second AgentInstance that starts from the pinned snapshot, with the transcript up to the checkpoint's position already in place. The original is untouched, so the two conversations diverge from that point. + +1. Fork the checkpoint. + ```bash + grpcurl -plaintext \ + -d '{"namespace":"kagent","checkpointId":"'"$CHECKPOINT_ID"'","requestId":"'"$(uuidgen)"'"}' \ + localhost:8084 kagent.api.v1alpha1.CheckpointService/ForkAgentInstance + ``` + + The response carries a new AgentInstance with its own ID. Example output: + ```json + { + "agentInstance": { + "id": "0198c3e5-1d62-7f38-a904-8b3c7e2f5d16", + "namespace": "kagent", + "harness": { + "namespace": "kagent", + "name": "my-first-harness" + }, + "agentTemplate": { + "namespace": "kagent", + "name": "my-first-agent" + }, + "state": "AGENT_INSTANCE_STATE_READY" + } + } + ``` + +2. Save the fork's ID, then send it down a different path than the original. + ```bash + export FORK_ID= + kagent invoke --agent-instance $FORK_ID --task "What did I ask you first?" + ``` + + The fork answers from the transcript it inherited, which is what distinguishes a fork from a new AgentInstance that happens to use the same AgentTemplate. + +3. List your AgentInstances, and both branches appear, each with its own Actor. + ```bash + kagent get agent-instance + ``` + +A fork runs the compiled revision that its checkpoint was taken on, not whatever revision the AgentTemplate resolves to now. Editing the AgentTemplate after checkpointing does not change what a fork of that checkpoint runs, which is what makes a fork a faithful continuation rather than a fresh start with an old transcript. + +> [!NOTE] +> A checkpoint can only be forked when its snapshot captured durable data alone. kagent compiles every ActorTemplate to take a `Data`-scope snapshot on commit, so a checkpoint taken on a suspended AgentInstance is forkable. A checkpoint whose snapshot also captured process state is rejected with `Checkpoint includes process state and cannot be forked`, because process memory belongs to the one Actor that produced it. + +## Clean up + +1. Delete the checkpoint. Deleting removes the ActorSnapshotTag and releases the pin, and Agent Substrate can collect the snapshot once no tag names it. + ```bash + grpcurl -plaintext \ + -d '{"namespace":"kagent","checkpointId":"'"$CHECKPOINT_ID"'"}' \ + localhost:8084 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint + ``` + +2. Delete both AgentInstances. + ```bash + kagent delete agent-instance $FORK_ID + kagent delete agent-instance $INSTANCE_ID + ``` + +3. Delete the AgentTemplate and the Harness. + ```bash + kubectl delete agenttemplate my-first-agent -n kagent + kubectl delete harness my-first-harness -n kagent + ``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="substrate-runtime/suspend-and-resume" >}}` title="Suspend and resume" subtitle="Understand the snapshot cycle that checkpoints pin." >}} + {{< card link=`{{< link path="substrate-runtime/sandboxing" >}}` title="Sandboxing" subtitle="See what the sandbox around each Actor isolates." >}} + {{< card link=`{{< link path="substrate-runtime/identity" >}}` title="Identity" subtitle="See who owns an AgentInstance and the checkpoints taken on it." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 5eb909b8..7b21fc0f 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -5,19 +5,20 @@ weight: 10 author: kagent.dev --- -This guide walks you through creating an agent, from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance that they produce. For definitions of each of these components, review the [core concepts]({{< link path="about/core-concepts" >}}). For an overview of how each component fits together in kagent, review the [architecture]({{< link path="about/architecture" >}}). For the complete schema of every field that this guide sets, see the [API reference]({{< link path="reference/api-ref" >}}). +This guide walks you through creating an agent, from applying a Harness and an AgentTemplate to holding a conversation with the AgentInstance that they produce. You apply the Harness and the AgentTemplate as Kubernetes resources, and you create and talk to the AgentInstance with the kagent CLI. For definitions of each of these components, review the [core concepts]({{< link path="about/core-concepts" >}}). For an overview of how each component fits together in kagent, review the [architecture]({{< link path="about/architecture" >}}). For the complete schema of every field that this guide sets, see the [API reference]({{< link path="reference/api-ref" >}}). ## Before you begin 1. [Install kagent with a WorkerPool provisioned]({{< link path="setup/installation" >}}). -2. Install [grpcurl](https://github.com/fullstorydev/grpcurl). -3. Port-forward the controller's gRPC port to your local machine. - ```shell - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 +2. Download the kagent CLI. + ```bash + curl https://raw.githubusercontent.com/kagent-dev/kagent/refs/heads/main/scripts/get-kagent | bash ``` +3. Install [`jq`](https://jqlang.org/download/), to read the AgentInstance ID out of the CLI's JSON output. + > [!NOTE] -> This guide uses `kubectl` and `grpcurl` directly, as the kagent CLI does not yet have commands for Harness, AgentTemplate, or AgentInstance. +> The CLI reaches the kagent controller at `localhost:8083` and `localhost:8084`. When nothing serves those ports, the CLI runs `kubectl port-forward` against the `kagent-controller` service for you, and closes the forward when the command exits. Keep `kubectl` on your path, and keep your kubeconfig pointed at the cluster that runs kagent. ## Create a Harness and an AgentTemplate @@ -66,132 +67,99 @@ This guide walks you through creating an agent, from applying a Harness and an A systemPrompt: You are a concise, helpful assistant. ``` -3. Confirm that the pair is ready. - ```shell - kubectl get agenttemplate my-first-agent -n kagent -o jsonpath='{.status.harnesses}' | jq . +3. Confirm that the pair is ready. The `HARNESS` column lists each Harness that admitted this AgentTemplate, and `READY` reports whether kagent compiled a runtime revision for that pairing. + ```bash + kagent get agent-template my-first-agent + ``` + + Example output: + ```console + +----------------+------------------+-------+----------------------+ + | NAME | HARNESS | READY | CREATED | + +----------------+------------------+-------+----------------------+ + | my-first-agent | my-first-harness | TRUE | 2026-08-31T15:01:44Z | + +----------------+------------------+-------+----------------------+ ``` - A ready pair reports four conditions for `my-first-harness`, ending in `Ready`. If the status is empty, wait a few seconds for the kagent controller to reconcile, then check again. - ```json - [ - { - "conditions": [ - { - "lastTransitionTime": "2026-08-24T15:02:10Z", - "message": "Harness admission selector matches the AgentTemplate", - "observedGeneration": 1, - "reason": "Accepted", - "status": "True", - "type": "Accepted" - }, - { - "lastTransitionTime": "2026-08-24T15:02:10Z", - "message": "All runtime references resolved", - "observedGeneration": 1, - "reason": "Resolved", - "status": "True", - "type": "ResolvedRefs" - }, - { - "lastTransitionTime": "2026-08-24T15:02:10Z", - "message": "Resolved configuration is compatible with the Harness", - "observedGeneration": 1, - "reason": "Compatible", - "status": "True", - "type": "Compatible" - }, - { - "lastTransitionTime": "2026-08-24T15:02:10Z", - "message": "ActorTemplate golden snapshot is ready", - "observedGeneration": 1, - "reason": "Ready", - "status": "True", - "type": "Ready" - } - ], - "desiredRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b", - "harness": "my-first-harness", - "latestSuccessfulRevision": "5f2b3c1a9e8d4b7a6c3e2f1d0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b" - } - ] + An empty `HARNESS` column with a `READY` value of `UNKNOWN` means that the kagent controller has not yet reconciled the pair. Wait a few seconds, then check again. If `READY` stays `FALSE`, inspect the individual conditions to find which stage failed. + ```bash + kagent get agent-template my-first-agent -o json ``` - The `latestSuccessfulRevision` value is the compiled revision that kagent creates your AgentInstance from in the next section. + Each entry in `status.harnesses` reports four conditions, ending in `Ready`. The `Accepted` condition covers the label selector match, `ResolvedRefs` covers the ModelConfig and tool references, `Compatible` covers whether the resolved configuration suits the Harness runtime, and `Ready` covers the compiled revision itself. ## Create the AgentInstance +An AgentInstance is one running conversation. Creating it starts an Actor on the WorkerPool from the revision that kagent compiled for the Harness and AgentTemplate pair. + 1. Create an AgentInstance from the Harness and AgentTemplate pair. - ```shell - RESPONSE=$(grpcurl -plaintext \ - -d '{"namespace":"kagent","harness":"my-first-harness","agentTemplate":"my-first-agent","requestId":"'"$(uuidgen)"'"}' \ - localhost:8084 kagent.api.v1alpha1.AgentInstanceService/CreateAgentInstance) - echo "$RESPONSE" + ```bash + kagent create agent-instance --harness my-first-harness --agent-template my-first-agent ``` - A successful response includes the new AgentInstance and its `id`. - ```json - { - "agentInstance": { - "id": "8f14e45f-ceea-4a37-b0f1-2b5c4d3a9c6e", - "namespace": "kagent", - "harness": { - "namespace": "kagent", - "name": "my-first-harness" - }, - "agentTemplate": { - "namespace": "kagent", - "name": "my-first-agent" - }, - "state": "AGENT_INSTANCE_STATE_READY" - } - } + The command returns output only after the AgentInstance reaches the `READY` state. Example output: + ```console + +--------------------------------------+----------------+------------------+-------+----------------------+ + | ID | AGENT TEMPLATE | HARNESS | STATE | CREATED | + +--------------------------------------+----------------+------------------+-------+----------------------+ + | 0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 | my-first-agent | my-first-harness | READY | 2026-08-31T15:02:10Z | + +--------------------------------------+----------------+------------------+-------+----------------------+ ``` -2. Save the AgentInstance's `id` to an environment variable. The next step needs it to address the AgentInstance that you created. - ```shell - export INSTANCE_ID=$(echo "$RESPONSE" | jq -r '.agentInstance.id') + An error reporting that the AgentTemplate and Harness have no ready prepared revision means that the pair is not `READY` yet. Return to step 3 of the previous section to check the conditions. + +2. Save the AgentInstance's ID to an environment variable. + ```bash + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "my-first-agent")] | sort_by(.createdAt) | last | .id') + echo $INSTANCE_ID ``` ## Talk to your agent -Send a message to the AgentInstance over the A2A (Agent-to-Agent) protocol. - -```shell -grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ - -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ - -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"What is 2+2?"}]}}' \ - localhost:8084 lf.a2a.v1.A2AService/SendMessage -``` - -The response carries the agent's reply in the same `parts` shape as the request. -```json -{ - "message": { - "messageId": "b2b1e2b4-5c3a-4f8e-9d1a-7e6f5c4b3a2d", - "role": "ROLE_AGENT", - "parts": [ - { - "text": "4" - } - ] - } -} -``` +1. Send a message to the AgentInstance. The CLI holds the conversation over the A2A (Agent-to-Agent) protocol. + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "What is 2+2?" + ``` + + The agent's reply prints as text. + ```console + 4 + ``` + +2. Send a follow-up message to the same AgentInstance. An AgentInstance holds the transcript of its conversation, so the agent answers with the earlier turns in context. + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "What did I just ask you?" + ``` + + ```console + You asked what 2+2 is. + ``` + +> [!NOTE] +> An AgentInstance gives its Worker back at the end of every turn. The AgentInstance itself stays `READY`, because suspension applies to the Actor running underneath it rather than to the conversation, and the next `kagent invoke` resumes that Actor automatically. To understand what happens to the Actor in between, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + +The `invoke` command takes a few more options that are useful beyond a first conversation. + +| Option | Description | +| ------ | ----------- | +| `--file` | Read the task from a file, or from standard input with `-`, instead of passing it inline with `--task`. | +| `--stream` | Print the reply as the agent produces it, rather than waiting for the complete answer. | + +> [!TIP] +> Run `kagent` with no arguments to open an interactive workspace in your terminal, where you can browse your AgentInstances and chat with them without passing an ID to each command. ## Clean up -1. Delete the Harness and AgentTemplate. - ```shell - kubectl delete agenttemplate my-first-agent -n kagent - kubectl delete harness my-first-harness -n kagent +1. Delete the AgentInstance. Deleting the Harness and the AgentTemplate does not delete the AgentInstances that you created from them, so delete the AgentInstance first. + ```bash + kagent delete agent-instance $INSTANCE_ID ``` -2. Delete the AgentInstance directly through the same `AgentInstanceService` that you used to create it, as deleting the Harness and AgentTemplate does not delete the AgentInstance that you created from them. - ```shell - grpcurl -plaintext \ - -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'"}' \ - localhost:8084 kagent.api.v1alpha1.AgentInstanceService/DeleteAgentInstance +2. Delete the AgentTemplate and the Harness. + ```bash + kubectl delete agenttemplate my-first-agent -n kagent + kubectl delete harness my-first-harness -n kagent ``` ## Next steps diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index 54fe2ee5..b7a438ff 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -225,7 +225,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker EOF ``` > [!NOTE] - > `controller.grpc.reflection` lets a gRPC client discover the controller's methods without a local copy of kagent's proto files, which is how [Your first agent]({{< link path="get-started/your-first-agent" >}}) calls the API. Leave it on while you explore the API, and turn it off for a production installation. + > `controller.grpc.reflection` lets a gRPC client discover the controller's methods without a local copy of kagent's proto files. The kagent CLI does not need it, because the CLI ships with generated clients for every kagent API. Leave reflection on to explore the API with a general-purpose client such as [grpcurl](https://github.com/fullstorydev/grpcurl), and turn it off for a production installation. 3. Wait for the controller to roll out. ```bash diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 2a7054b1..da935da6 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -11,8 +11,8 @@ An agent spends most of its life waiting. It waits on a person to reply, and it {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} provides three lifecycle operations, and each one moves an Actor between states that you can observe on the Actor record. -- **Suspend**: Writes the Actor's state to a durable snapshot in snapshot storage, then frees its Worker. A running Actor is checkpointed on its Worker. A paused Actor's node-local snapshot is uploaded instead. -- **Pause**: Takes a short-term checkpoint whose files stay on the node. Pausing pins the Actor to that node, because the following resume is prioritized onto the node that holds the snapshot files. +- **Suspend**: Writes the Actor's state to a durable snapshot in snapshot storage, then frees its Worker. A running Actor is snapshotted on its Worker. A paused Actor's node-local snapshot is uploaded instead. +- **Pause**: Takes a short-term snapshot whose files stay on the node. Pausing pins the Actor to that node, because the following resume is prioritized onto the node that holds the snapshot files. - **Resume**: Restores a suspended or paused Actor onto a Worker, from its latest snapshot. The common path restores from a snapshot rather than cold-booting the workload. The following diagram traces an Actor through those operations, and shows the further path that opens once a snapshot is [pinned by a tag](#checkpoints). @@ -84,3 +84,5 @@ A snapshot that Agent Substrate writes on suspend is transient. Agent Substrate Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the AgentInstance most recently suspended to. The tag names that one snapshot permanently and acts as a retention pin, such that Agent Substrate does not collect a snapshot while a tag still names it. Deleting the checkpoint removes the tag and releases the pin. An AgentInstance must be a turn boundary to be checkpointed, because the turn boundary is captured. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. + +A checkpoint also records where the conversation had reached, which lets you start a second AgentInstance from that point. To create a checkpoint and fork an AgentInstance from it, work through the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index a506afb1..d95ee706 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -33,6 +33,9 @@ ActorTemplate: AgentInstance: short: "A running, conversational pairing of a Harness and an AgentTemplate. Unlike the two, it is not a Kubernetes resource: kagent's gRPC API creates it and its database tracks it." +Checkpoint: + short: "A durable pin on the snapshot that an AgentInstance most recently suspended to, and a record of how far its transcript had advanced. Not a copy of the state: it tags a snapshot so that Agent Substrate does not collect it, and a second AgentInstance can be forked from it." + AgentTemplate: short: "A Kubernetes custom resource defining what an agent does: its model, system prompt, tools, skills, and plugins. It runs only once a Harness accepts it." From 6f4e407680e913eeefc059931b1e620cf8935426 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 31 Aug 2026 12:33:28 -0500 Subject: [PATCH 32/70] clarify codex & claude code Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/about/core-concepts.md | 5 ++++- docs-site/content/kagent/1.x/about/what-is-kagent.md | 4 ++-- docs-site/content/kagent/1.x/get-started/your-first-agent.md | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) 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 f3d5770c..cbf990cb 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -42,13 +42,16 @@ The Harness and AgentTemplate are the only two resources that an operator applie A **Harness** is a Kubernetes custom resource that defines _how an agent is allowed to run_. It specifies: -- **Runtime**: The engine that executes the agent. This is either kagent's own Go or Python runtime, or a bring-your-own coding agent such as Claude Code or Codex. +- **Runtime**: The engine that executes the agent. A Harness selects exactly one of `kagent`, `codex`, or `claude`. kagent compiles only the `kagent` runtime, which runs kagent's own Go and Python engines. - **Workload**: The container image and environment the runtime runs in. - **Substrate policy**: The [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their snapshots are stored. - **Allowed AgentTemplates**: A selector that names which AgentTemplates are permitted to run on this Harness. That last point is a one-way match, not a mutual handshake. An AgentTemplate has no field naming a Harness. Instead, a Harness's `allowedAgentTemplates` selector matches on labels, and any AgentTemplate in the same namespace carrying a matching label becomes eligible to run on it. Whoever controls a Harness's selector decides which AgentTemplates it accepts. +> [!NOTE] +> The `codex` and `claude` runtimes are part of the Harness API, so the Kubernetes API server accepts a Harness that selects either one. However, kagent currently has no compiler for them, so the pair then reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and the message `Harness runtime is not supported by any compiler`. + A Harness owns no running compute by itself. Applying one registers a runtime and policy that an AgentTemplate can pair with. For the complete Harness schema, see the [API reference]({{< link path="reference/api-ref#harness" >}}). diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md index e7f78815..302f5259 100644 --- a/docs-site/content/kagent/1.x/about/what-is-kagent.md +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -5,7 +5,7 @@ weight: 10 author: kagent.dev --- -kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability that you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with coding-agent runtimes such as Claude Code and Codex, agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and every major large language model (LLM) provider. +kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability that you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and with every major large language model (LLM) provider. Agents run on kagent's own Go and Python engines. kagent was created at [Solo.io](https://www.solo.io) in 2025 and is a [Cloud Native Computing Foundation](https://www.cncf.io) sandbox project. @@ -45,7 +45,7 @@ Everything works with a single `helm install`. No add-ons, no extra databases, n {{< feature-card title="Agent lifecycle via CRDs" desc="Define, version, and roll out Harnesses and AgentTemplates with kubectl and GitOps, the same workflow as every other workload." >}} {{< feature-card title="Sandboxed by default" desc="Every AgentInstance runs on a Substrate Actor, isolated from the host kernel by a gVisor sandbox. Run untrusted, model-directed code safely." >}} {{< feature-card title="Suspend and resume" desc="Idle AgentInstances suspend and free their compute, then resume on demand. Run far more agents than you have capacity for at any one moment." >}} -{{< feature-card title="Bring your own runtime" desc="Run kagent's native Go or Python engine behind a Harness. Codex is planned as an additional runtime." >}} +{{< feature-card title="Pluggable agent runtimes" desc="A Harness selects the engine behind an agent. kagent runs its own Go and Python engines, and the Harness API defines Codex and Claude runtime selectors." >}} {{< feature-card title="Agent tools" desc="Compose agents from other agents. A Shared binding nests an agent inside its parent's Actor, one level deep." >}} {{< feature-card title="Long-term memory" desc="Persistent, vector-backed memory across sessions. Agents remember context, not just the last prompt." >}} {{< feature-card title="Human-in-the-loop" desc="Tool approval gates and agent-initiated questions keep a person in control of consequential actions." >}} diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 7b21fc0f..9eb4e4eb 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -165,7 +165,8 @@ The `invoke` command takes a few more options that are useful beyond a first con ## Next steps {{< cards >}} + {{< card link=`{{< link path="get-started/your-first-mcp-tool" >}}` title="Your first MCP tool" subtitle="Bind a Model Context Protocol tool so that your agent can act on live cluster data." >}} {{< card link=`{{< link path="about/agent-substrate" >}}` title="Agent Substrate architecture" subtitle="Understand what happens to your AgentInstance's Actor when it sits idle." >}} - {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Choose from the full set of Harness runtime options, including Claude Code and Codex." >}} + {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Choose from the full set of Harness runtime options." >}} {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities beyond its system prompt." >}} {{< /cards >}} From e9519d417631806d308cc4945217f03db6b320bb Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 31 Aug 2026 13:33:38 -0500 Subject: [PATCH 33/70] Phase 3 - agent substrate example Signed-off-by: Rachael Graham --- .../kagent/1.x/examples/agent-substrate.md | 93 +++++++++++++------ 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/docs-site/content/kagent/1.x/examples/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md index a8b47ce3..a9360582 100644 --- a/docs-site/content/kagent/1.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -7,9 +7,11 @@ author: kagent.dev [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs every agent as an Actor: a sandboxed unit of compute that holds a {{< gloss "Worker" >}}Worker{{< /gloss >}} only while a turn is in progress, and whose state you can pin and branch. This example follows one agent through all three behaviors. +The Actor that these steps follow is also the isolation boundary. Every Actor runs in its own gVisor sandbox rather than sharing one with its neighbors, which is why a model can safely run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). + ## Before you begin -1. Complete [Your first agent]({{< link path="get-started/your-first-agent" >}}). The steps on this page continues from the Harness, AgentTemplate, and AgentInstance that the agent guide creates, and assumes that you have sent the agent at least one message. +1. Complete [Your first agent]({{< link path="get-started/your-first-agent" >}}). The steps on this page continue from the Harness, AgentTemplate, and AgentInstance that the agent guide creates, and assumes that you have sent the agent at least one message. 2. If you have not already, save the AgentInstance's ID to an environment variable. To find the ID, run `kagent get agent-instance` to list your AgentInstances and copy the value from the `ID` column. ```bash @@ -25,43 +27,77 @@ author: kagent.dev ## Watch the Actor suspend between turns -1. List the Actors in your namespace's {{< gloss "Atespace" >}}atespace{{< /gloss >}}. kagent names an AgentInstance's Actor `ai-`. +1. List the Actors in your namespace's {{< gloss "Atespace" >}}atespace{{< /gloss >}}. An AgentInstance's Actor name is formatted `ai-`. ```bash kubectl ate get actors --atespace kagent ``` - Between turns, the Actor reports `ACTOR_STATE_SUSPENDED` and holds no Worker, so the `ATEOM POD` column reads ``. Example output: + Between turns, the Actor reports `ACTOR_STATE_SUSPENDED` and holds no Worker, so the `ATEOM POD` column reads `` and the `ATEOM IP` column is blank. The `VERSION` column is the Actor record's revision counter, which increases each time the record is updated. Example output: ```console - ATESPACE NAME TEMPLATE STATE ATEOM POD ATEOM IP VERSION AGE - kagent ai-0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 kagent/my-first-agent-my-first-harness-5f2b3c1a9e8d ACTOR_STATE_SUSPENDED 4 6m + ATESPACE NAME TEMPLATE STATE ATEOM POD ATEOM IP VERSION AGE + kagent ai-0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 kagent/my-first-agent-my-first-harness-5f2b3c1a9e8d ACTOR_STATE_SUSPENDED 4 11m ``` - That Actor is also the isolation boundary. Every Actor runs in its own gVisor sandbox rather than sharing one with its neighbors, which is what makes it safe to let a model run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). - 2. Send the agent another message. Nothing in the command acknowledges that the Actor was suspended, because resuming is automatic. ```bash kagent invoke --agent-instance $INSTANCE_ID --task "Summarize this conversation so far." ``` -3. List the Actors again while the turn is running, and the same Actor reports `ACTOR_STATE_RUNNING` against a real Worker pod. Once the turn finishes it returns to `ACTOR_STATE_SUSPENDED`. +3. From a second terminal, list the Actors again while the turn is still running. + ```bash + kubectl ate get actors --atespace kagent + ``` + + The same Actor now reports `ACTOR_STATE_RUNNING`, names the Worker pod that it resumed onto, and carries a higher `VERSION`. Example output: + ```console + ATESPACE NAME TEMPLATE STATE ATEOM POD ATEOM IP VERSION AGE + kagent ai-0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 kagent/my-first-agent-my-first-harness-5f2b3c1a9e8d ACTOR_STATE_RUNNING kagent/kagent-default-7c9f8b6d54-x2n4p 10.244.1.37 6 12m + ``` + + If the listing already reads `ACTOR_STATE_SUSPENDED`, the turn finished before the command ran. Repeat steps 2 and 3 to catch the Actor mid-turn. A turn is short, and the two transitions on either side of one, `ACTOR_STATE_RESUMING` and `ACTOR_STATE_SUSPENDING`, pass quickly enough that a single listing rarely catches them. + +4. After the turn finishes, list the Actors again. ```bash kubectl ate get actors --atespace kagent ``` -The AgentInstance stays `READY` throughout all of this. Suspension is a property of the Actor underneath the conversation, not of the conversation, which is why a suspended agent is still listed and still readable. For the full cycle, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + The Actor is back to `ACTOR_STATE_SUSPENDED` and holds no Worker again, at a higher `VERSION` than the listing in step 1. The `NAME` and `AGE` columns confirm that this is the same Actor throughout, rather than a new one per turn. Example output: + ```console + ATESPACE NAME TEMPLATE STATE ATEOM POD ATEOM IP VERSION AGE + kagent ai-0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 kagent/my-first-agent-my-first-harness-5f2b3c1a9e8d ACTOR_STATE_SUSPENDED 8 13m + ``` + +5. Check the AgentInstance while its Actor is suspended. + ```bash + kagent get agent-instance + ``` + + The AgentInstance reports `READY`, even though the Actor that runs it holds no Worker. Example output: + ```console + +--------------------------------------+----------------+------------------+-------+----------------------+ + | ID | AGENT TEMPLATE | HARNESS | STATE | CREATED | + +--------------------------------------+----------------+------------------+-------+----------------------+ + | 0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 | my-first-agent | my-first-harness | READY | 2026-08-31T15:02:10Z | + +--------------------------------------+----------------+------------------+-------+----------------------+ + ``` + +The AgentInstance stays `READY` throughout all steps. A suspended agent remains listed and readable because suspension is a property of the Actor underneath the conversation, not of the conversation itself. For the full cycle, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + +> [!NOTE] +> Two objects report state on this page, and each interface names its states differently. `kubectl ate get actors` reports the Actor's state in full, such as `ACTOR_STATE_SUSPENDED`, because the command prints the Agent Substrate enum name. The kagent CLI trims the prefix from the AgentInstance's state and prints `READY`, and the same value reaches you as `AGENT_INSTANCE_STATE_READY` in a `grpcurl` response. Checkpoints have no CLI command yet, so the next section calls the API directly and reads the checkpoint's state in full, as `CHECKPOINT_STATE_READY`. ## Pin the conversation with a checkpoint -Each suspend writes a snapshot, and Agent Substrate is free to collect that snapshot once a newer one supersedes it. A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} pins one so that you can come back to it. +Each suspend writes a snapshot, and Agent Substrate is free to collect that snapshot once a newer one supersedes it. A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} pins a snapshot so that you can come back to it. -1. Create a checkpoint. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. +1. Create a checkpoint. The checkpoint records the snapshot it pinned and how far the transcript had advanced. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. ```bash grpcurl -plaintext \ -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'","requestId":"'"$(uuidgen)"'"}' \ localhost:8084 kagent.api.v1alpha1.CheckpointService/CreateCheckpoint ``` - The checkpoint records the snapshot it pinned and how far the transcript had advanced. Example output: + Example output: ```json { "checkpoint": { @@ -76,7 +112,10 @@ Each suspend writes a snapshot, and Agent Substrate is free to collect that snap } ``` -2. Save the checkpoint's `id`, to fork from it in the next section. + > [!NOTE] + > A checkpoint captures a turn boundary, so two conditions must hold: the AgentInstance must be `READY` with no lifecycle operation in flight, and at least one turn must have reached a quiescent state. A request that fails either one reports `AgentInstance has no quiescent turn boundary`. Send the request again once the turn finishes. + +2. Save the checkpoint's `id` to fork from it in the next section. ```bash export CHECKPOINT_ID= ``` @@ -88,10 +127,7 @@ Each suspend writes a snapshot, and Agent Substrate is free to collect that snap localhost:8084 kagent.api.v1alpha1.CheckpointService/ListCheckpoints ``` -Underneath, the checkpoint attaches an ActorSnapshotTag named `checkpoint-` to the snapshot, and Agent Substrate does not collect a snapshot while a tag names it. You can see the tag with `kubectl ate get actor-snapshot-tag`. - -> [!NOTE] -> A checkpoint captures a turn boundary, so two conditions have to hold and a request that fails either one reports `AgentInstance has no quiescent turn boundary`. The AgentInstance must be `READY` with no lifecycle operation in flight, and at least one turn must have reached a quiescent state. Send the request again once the turn finishes. +Underneath, the checkpoint attaches an ActorSnapshotTag named `checkpoint-` to the snapshot, and Agent Substrate does not collect a snapshot while a tag names it. You can see the tag by running `kubectl ate get actor-snapshot-tag`. ## Fork the conversation into a second agent @@ -131,11 +167,21 @@ Forking creates a second AgentInstance that starts from the pinned snapshot, wit The fork answers from the transcript it inherited, which is what distinguishes a fork from a new AgentInstance that happens to use the same AgentTemplate. -3. List your AgentInstances, and both branches appear, each with its own Actor. +3. List your AgentInstances to verify that both branches appear as separate conversations. ```bash kagent get agent-instance ``` + The two rows share an AgentTemplate and a Harness, and differ in their IDs and creation times. Each one has its own Actor, named `ai-`. Example output: + ```console + +--------------------------------------+----------------+------------------+-------+----------------------+ + | ID | AGENT TEMPLATE | HARNESS | STATE | CREATED | + +--------------------------------------+----------------+------------------+-------+----------------------+ + | 0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 | my-first-agent | my-first-harness | READY | 2026-08-31T15:02:10Z | + | 0198c3e5-1d62-7f38-a904-8b3c7e2f5d16 | my-first-agent | my-first-harness | READY | 2026-08-31T15:14:02Z | + +--------------------------------------+----------------+------------------+-------+----------------------+ + ``` + A fork runs the compiled revision that its checkpoint was taken on, not whatever revision the AgentTemplate resolves to now. Editing the AgentTemplate after checkpointing does not change what a fork of that checkpoint runs, which is what makes a fork a faithful continuation rather than a fresh start with an old transcript. > [!NOTE] @@ -143,23 +189,16 @@ A fork runs the compiled revision that its checkpoint was taken on, not whatever ## Clean up -1. Delete the checkpoint. Deleting removes the ActorSnapshotTag and releases the pin, and Agent Substrate can collect the snapshot once no tag names it. +1. Delete the checkpoint. Deleting removes the ActorSnapshotTag and releases the pin, and Agent Substrate can collect the snapshot whenever no tag names it. ```bash grpcurl -plaintext \ -d '{"namespace":"kagent","checkpointId":"'"$CHECKPOINT_ID"'"}' \ localhost:8084 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint ``` -2. Delete both AgentInstances. +2. Delete the fork. A fork is an AgentInstance in its own right, so deleting the checkpoint that it started from does not remove it. ```bash kagent delete agent-instance $FORK_ID - kagent delete agent-instance $INSTANCE_ID - ``` - -3. Delete the AgentTemplate and the Harness. - ```bash - kubectl delete agenttemplate my-first-agent -n kagent - kubectl delete harness my-first-harness -n kagent ``` ## Next steps From ada03932f5ee0ad2f1d576a7470fb944b92624e5 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 31 Aug 2026 15:08:19 -0500 Subject: [PATCH 34/70] Phase 3 - your first MCP tool Signed-off-by: Rachael Graham --- .../1.x/get-started/your-first-agent.md | 11 +- .../1.x/get-started/your-first-mcp-tool.md | 191 ++++++++++++++++++ 2 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 9eb4e4eb..6d22f3b8 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -151,9 +151,16 @@ The `invoke` command takes a few more options that are useful beyond a first con ## Clean up -1. Delete the AgentInstance. Deleting the Harness and the AgentTemplate does not delete the AgentInstances that you created from them, so delete the AgentInstance first. +> [!IMPORTANT] +> Other guides build on the Harness, AgentTemplate, and AgentInstance that you created here, including [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}) and [Agent Substrate]({{< link path="examples/agent-substrate" >}}). Leave the resources in place unless you are finished with the kagent guides. + +To remove the resources, follow these steps. + +1. Delete every AgentInstance that was created from the AgentTemplate. Later guides create their own instances from the same pair, so delete them all rather than only the one that you saved. Deleting the Harness and the AgentTemplate does not delete the AgentInstances that you created from them, so delete the instances first. ```bash - kagent delete agent-instance $INSTANCE_ID + kagent get agent-instance -o json \ + | jq -r '.agentInstances[] | select(.agentTemplate.name == "my-first-agent") | .id' \ + | xargs -n1 kagent delete agent-instance ``` 2. Delete the AgentTemplate and the Harness. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md new file mode 100644 index 00000000..f8f582b5 --- /dev/null +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -0,0 +1,191 @@ +--- +title: Your first MCP tool +description: Give an agent a Model Context Protocol tool by binding an MCP server to its AgentTemplate. +weight: 20 +author: kagent.dev +--- + +A system prompt tells an agent how to behave. Tools tell it what it can do. This guide binds a Model Context Protocol (MCP) tool to the agent that you built in [Your first agent]({{< link path="get-started/your-first-agent" >}}), so that the agent can read live data out of your cluster instead of answering from the model alone. For the full tool binding schema, including binding one agent as another agent's tool, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). + +## Before you begin + +1. Complete [Your first agent]({{< link path="get-started/your-first-agent" >}}). This guide edits the `my-first-agent` AgentTemplate that the agent guide creates, so keep that AgentTemplate and the `my-first-harness` Harness in place. + +2. Confirm that you have the kagent CLI and [`jq`](https://jqlang.org/download/) installed. + +## Bind the tool to your AgentTemplate + +kagent ships an MCP server of its own, and installs a `RemoteMCPServer` that points at it, so the built-in server is the shortest path to a working tool. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} takes tools through an `mcp` binding, which names one server and the tools to take from it. Naming the tools is required, because a binding never takes a server's whole catalog. + +The names must come from the server's own documentation rather than from the cluster, because kagent does not populate a server's discovered tools. This guide binds `k8s_get_resources` and `k8s_get_pod_logs`. For the full catalog that the built-in server serves, see the [tools ecosystem reference]({{< link path="reference/tools-ecosystem" >}}). + +1. List the RemoteMCPServers in the `kagent` namespace. + ```bash + kubectl get remotemcpserver -n kagent + ``` + + Example output: The `ACCEPTED` column is empty because kagent does not yet write status back to a RemoteMCPServer. An empty column is expected, and does not mean that the server is unhealthy. + ```console + NAME PROTOCOL URL ACCEPTED AGE + kagent-tool-server STREAMABLE_HTTP http://kagent-tools.kagent:8084/mcp 14m + ``` + + > [!NOTE] + > The built-in server is installed only when the `kagent-tools.enabled` Helm value is `true`, which is the default. If the command returns no resources, either re-install with that value enabled, or use your own server as described in [Bind your own MCP server](#bind-your-own-mcp-server). + +2. Re-apply the `my-first-agent` AgentTemplate with a `spec.tools` list and a system prompt that tells the model what the tools are for. + ```yaml + kubectl apply -f - < [!WARNING] + > kagent resolves the server, but it does not check the tool names against the tools that the server actually serves. A misspelled tool name compiles into a ready revision, and the only symptom is an agent that never calls the tool that you expected. Check the spelling against the server's catalog when a bound tool appears to be missing. + +## Create an AgentInstance that has the tool + +An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} runs the revision that it was created from, and keeps running that revision for its whole life. The instance from the agent guide still runs the revision without tools, so create a second instance to pick up the binding. + +1. Create a second AgentInstance from the same Harness and AgentTemplate pair. The command is the one that you ran in the agent guide, but the pair has a newer revision now, so this instance picks up the tools. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template my-first-agent + ``` + + Example output: + ```console + +--------------------------------------+----------------+------------------+-------+----------------------+ + | ID | AGENT TEMPLATE | HARNESS | STATE | CREATED | + +--------------------------------------+----------------+------------------+-------+----------------------+ + | 0198c4e2-8b3f-7d45-a1c6-9e2f4b8d6a03 | my-first-agent | my-first-harness | READY | 2026-08-31T16:20:38Z | + +--------------------------------------+----------------+------------------+-------+----------------------+ + ``` + +2. Save the new AgentInstance's ID to an environment variable. + ```bash + export TOOL_INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "my-first-agent")] | sort_by(.createdAt) | last | .id') + echo $TOOL_INSTANCE_ID + ``` + +3. Ask the agent something that it can answer only by calling a tool. + ```bash + kagent invoke --agent-instance $TOOL_INSTANCE_ID --task "Which pods are running in the kagent namespace?" + ``` + + The agent calls `k8s_get_resources` and answers from the result rather than from the model's own knowledge. + +4. Ask a follow-up question that uses the second tool. The AgentInstance holds the transcript of the conversation, so the agent can act on the pods that it just listed. + ```bash + kagent invoke --agent-instance $TOOL_INSTANCE_ID --task "Show me the last few log lines from the kagent controller pod." + ``` + +## Bind your own MCP server + +A `RemoteMCPServer` points at any MCP server that the cluster can reach, whether it runs in the cluster or outside it. Create one, then bind it in the same way that you bound the built-in server. + +1. Apply a `RemoteMCPServer` for your own server. + ```yaml + kubectl apply -f - < [!IMPORTANT] +> Leave the Harness, AgentTemplate, and AgentInstances in place. Other guides build on them, and [Your first agent]({{< link path="get-started/your-first-agent#clean-up-the-get-started-resources" >}}) covers removing them when you are finished with the kagent guides. Leave `kagent-tool-server` in place as well, because the kagent installation owns it. + +If you created a RemoteMCPServer of your own in [Bind your own MCP server](#bind-your-own-mcp-server), delete it. + +```bash +kubectl delete remotemcpserver my-mcp-server -n kagent +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Read the full tool binding schema, including binding one agent as another agent's tool." >}} + {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities that no MCP server provides." >}} + {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch your agent's Actor suspend between turns, then checkpoint and fork the conversation." >}} +{{< /cards >}} From 8da3384af76741560e44c1f5684d82c7f1360575 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 31 Aug 2026 16:32:26 -0500 Subject: [PATCH 35/70] glossary updates Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 6 +-- .../content/kagent/1.x/about/architecture.md | 2 +- .../content/kagent/1.x/about/core-concepts.md | 8 ++-- .../kagent/1.x/examples/agent-substrate.md | 10 ++--- .../1.x/get-started/your-first-agent.md | 8 ++-- .../1.x/get-started/your-first-mcp-tool.md | 8 ++-- .../kagent/1.x/skills-and-mcp/about-tools.md | 4 +- .../kagent/1.x/skills-and-mcp/plugins.md | 2 +- .../kagent/1.x/skills-and-mcp/skills.md | 6 +-- .../1.x/substrate-runtime/sandboxing.md | 4 +- .../substrate-runtime/suspend-and-resume.md | 4 +- docs-site/data/glossary.yaml | 39 +++++++++++++++++++ 12 files changed, 70 insertions(+), 31 deletions(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 29ed404c..1d6512d6 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -5,13 +5,13 @@ weight: 40 author: kagent.dev --- -The [kagent architecture]({{< link path="about/architecture" >}}) page established that every {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the atespace that identifies it, the sandbox that isolates it, and the snapshot cycle that lets it suspend when idle and resume on demand. +The [kagent architecture]({{< link path="about/architecture" >}}) page established that every {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} runs on an Actor. This page explains what an Actor is built from and what it runs on: the ActorTemplate that it is created from, the compute that hosts it, the atespace that identifies it, the sandbox that isolates it, and the {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} cycle that lets it suspend when idle and resume on demand. ## ActorTemplate Every Actor is created from an **ActorTemplate**, the compiled definition that the kagent controller produces from a {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} pair. -What Substrate adds is enforcement. Substrate rejects any change to an ActorTemplate's spec after it is created, so immutability is a property of the resource itself rather than a convention that the controller follows. That immutability requires the controller to create a new ActorTemplate for every compiled revision instead of editing an existing one, and allows the controller to safely reclaim an old ActorTemplate once no AgentInstance references it. +What Substrate adds is enforcement. Substrate rejects any change to an ActorTemplate's spec after it is created, so immutability is a property of the resource itself rather than a convention that the controller follows. That immutability requires the controller to create a new ActorTemplate for every compiled {{< gloss "Revision" >}}revision{{< /gloss >}} instead of editing an existing one, and allows the controller to safely reclaim an old ActorTemplate once no AgentInstance references it. ## Workers and WorkerPools @@ -31,7 +31,7 @@ kagent names each atespace after the Kubernetes namespace of the AgentInstance w Because an Actor often runs a model-directed agent that calls tools and executes commands, Substrate runs each Actor in an isolated sandbox rather than a plain container. A WorkerPool's `sandboxClass` field selects the sandbox technology for its Workers: [gVisor](https://gvisor.dev) or a micro-VM technology such as [Kata Containers](https://katacontainers.io). Both technologies isolate an Actor from its Worker's host kernel, and both support suspend and resume operations. -kagent compiles every ActorTemplate to the `gvisor` class, so a kagent agent runs in a gVisor sandbox today and the micro-VM class is a Substrate capability that kagent does not yet select. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. For what each class isolates, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). +kagent compiles every ActorTemplate to the `gvisor` class, so a kagent agent runs in a {{< gloss "gVisor" >}}gVisor{{< /gloss >}} sandbox today and the micro-VM class is a Substrate capability that kagent does not yet select. Keep a WorkerPool that backs kagent Harnesses on `gvisor`. For what each class isolates, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). ## Suspend, snapshot, and resume diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 59230b3a..343cfa07 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -60,7 +60,7 @@ Follow the **Kubernetes plane** first. An operator applies a Harness and an Agen The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an {{< gloss "Actor" >}}Actor{{< /gloss >}}. -From there, the caller holds a conversation with the AgentInstance over the A2A (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance. This means that the caller only ever needs to know an AgentInstance's identity, never which Actor or {{< gloss "Worker" >}}Worker{{< /gloss >}} is behind it. +From there, the caller holds a conversation with the AgentInstance over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol. The A2A gateway routes each request to the Actor running behind the target AgentInstance. This means that the caller only ever needs to know an AgentInstance's identity, never which Actor or {{< gloss "Worker" >}}Worker{{< /gloss >}} is behind it. ## Why two planes 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 cbf990cb..00564874 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -44,7 +44,7 @@ A **Harness** is a Kubernetes custom resource that defines _how an agent is allo - **Runtime**: The engine that executes the agent. A Harness selects exactly one of `kagent`, `codex`, or `claude`. kagent compiles only the `kagent` runtime, which runs kagent's own Go and Python engines. - **Workload**: The container image and environment the runtime runs in. -- **Substrate policy**: The [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their snapshots are stored. +- **Substrate policy**: The [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their {{< gloss "Snapshot" >}}snapshots{{< /gloss >}} are stored. - **Allowed AgentTemplates**: A selector that names which AgentTemplates are permitted to run on this Harness. That last point is a one-way match, not a mutual handshake. An AgentTemplate has no field naming a Harness. Instead, a Harness's `allowedAgentTemplates` selector matches on labels, and any AgentTemplate in the same namespace carrying a matching label becomes eligible to run on it. Whoever controls a Harness's selector decides which AgentTemplates it accepts. @@ -65,7 +65,7 @@ An **AgentTemplate** is a Kubernetes custom resource that defines _what an agent - **Model configuration**: The large language model (LLM) provider and model the agent uses. This is the only field an AgentTemplate strictly requires. - **System prompt**: A literal prompt, or a Go-templated one that can `include` shared ConfigMaps. -- **Tools**: A list of tool bindings the agent can call. Each binding is either a Model Context Protocol (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated)). +- **Tools**: A list of {{< gloss "Tool binding" >}}tool bindings{{< /gloss >}} that the agent can call. Each binding is either a {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) server, or another AgentTemplate used as an agent tool (see [Agent tools](#agent-tools-shared-vs-dedicated)). - **Skills** and **plugins**: Reusable capability packages, sourced from an Open Container Initiative (OCI) registry, Git, or S3. An AgentTemplate does nothing on its own. It becomes runnable once it is paired with a Harness whose `allowedAgentTemplates` selector accepts it. @@ -83,11 +83,11 @@ This split is deliberate, not an implementation detail to work around: Under the hood, the kagent controller watches for valid Harness and AgentTemplate pairs and compiles each pair into an `ActorTemplate`, a Substrate resource that holds everything Substrate needs to start an Actor. -Each compile produces one **revision**, identified by a digest: a SHA-256 hash of the compiled configuration. Because that digest is derived from the configuration itself, editing a Harness or AgentTemplate compiles to a different digest, and therefore becomes a separate ActorTemplate. kagent never rewrites an existing one. +Each compile produces one **{{< gloss "Revision" >}}revision{{< /gloss >}}**, identified by a digest: a SHA-256 hash of the compiled configuration. Because that digest is derived from the configuration itself, editing a Harness or AgentTemplate compiles to a different digest, and therefore becomes a separate ActorTemplate. kagent never rewrites an existing one. That immutability is what keeps running conversations stable. When you create an AgentInstance, kagent looks up the newest revision that compiled successfully for that Harness and AgentTemplate pair, and then creates an Actor from that revision. Editing the Harness or AgentTemplate afterward does not disturb that AgentInstance, which keeps running on the revision that it was created from. Only AgentInstances created after the edit use the new revision. -Once created, an AgentInstance talks to callers over the A2A (Agent-to-Agent) protocol, through kagent's A2A gateway. The gateway resolves each request to the right AgentInstance and forwards it to the Actor running behind it. +Once created, an AgentInstance talks to callers over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol, through kagent's A2A gateway. The gateway resolves each request to the right AgentInstance and forwards it to the Actor running behind it. For the AgentInstance gRPC service definition, see the [API reference]({{< link path="reference/api-ref" >}}). diff --git a/docs-site/content/kagent/1.x/examples/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md index a9360582..e07ed813 100644 --- a/docs-site/content/kagent/1.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -7,7 +7,7 @@ author: kagent.dev [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs every agent as an Actor: a sandboxed unit of compute that holds a {{< gloss "Worker" >}}Worker{{< /gloss >}} only while a turn is in progress, and whose state you can pin and branch. This example follows one agent through all three behaviors. -The Actor that these steps follow is also the isolation boundary. Every Actor runs in its own gVisor sandbox rather than sharing one with its neighbors, which is why a model can safely run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). +The Actor that these steps follow is also the isolation boundary. Every Actor runs in its own {{< gloss "gVisor" >}}gVisor{{< /gloss >}} sandbox rather than sharing one with its neighbors, which is why a model can safely run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). ## Before you begin @@ -18,7 +18,7 @@ The Actor that these steps follow is also the isolation boundary. Every Actor ru export INSTANCE_ID= ``` -3. Install [grpcurl](https://github.com/fullstorydev/grpcurl), and confirm that your kagent installation sets `controller.grpc.reflection`. Checkpoints and forks have no kagent CLI commands yet, so this example calls `CheckpointService` directly. +3. Install [grpcurl](https://github.com/fullstorydev/grpcurl), and confirm that your kagent installation sets `controller.grpc.reflection`. Checkpoints and {{< gloss "Fork" >}}forks{{< /gloss >}} have no kagent CLI commands yet, so this example calls `CheckpointService` directly. 4. Port-forward the controller's gRPC port to your local machine. ```bash @@ -88,9 +88,9 @@ The AgentInstance stays `READY` throughout all steps. A suspended agent remains ## Pin the conversation with a checkpoint -Each suspend writes a snapshot, and Agent Substrate is free to collect that snapshot once a newer one supersedes it. A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} pins a snapshot so that you can come back to it. +Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent Substrate is free to collect that snapshot once a newer one supersedes it. A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} pins a snapshot so that you can come back to it. -1. Create a checkpoint. The checkpoint records the snapshot it pinned and how far the transcript had advanced. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. +1. Create a checkpoint. The checkpoint records the snapshot that it pinned and how far the {{< gloss "Transcript" >}}transcript{{< /gloss >}} had advanced. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. ```bash grpcurl -plaintext \ -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'","requestId":"'"$(uuidgen)"'"}' \ @@ -182,7 +182,7 @@ Forking creates a second AgentInstance that starts from the pinned snapshot, wit +--------------------------------------+----------------+------------------+-------+----------------------+ ``` -A fork runs the compiled revision that its checkpoint was taken on, not whatever revision the AgentTemplate resolves to now. Editing the AgentTemplate after checkpointing does not change what a fork of that checkpoint runs, which is what makes a fork a faithful continuation rather than a fresh start with an old transcript. +A fork runs the compiled {{< gloss "Revision" >}}revision{{< /gloss >}} that its checkpoint was taken on, not whatever revision the AgentTemplate resolves to now. Editing the AgentTemplate after checkpointing does not change what a fork of that checkpoint runs, which is what makes a fork a faithful continuation rather than a fresh start with an old transcript. > [!NOTE] > A checkpoint can only be forked when its snapshot captured durable data alone. kagent compiles every ActorTemplate to take a `Data`-scope snapshot on commit, so a checkpoint taken on a suspended AgentInstance is forkable. A checkpoint whose snapshot also captured process state is rejected with `Checkpoint includes process state and cannot be forked`, because process memory belongs to the one Actor that produced it. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 6d22f3b8..ba21f692 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -49,7 +49,7 @@ This guide walks you through creating an agent, from applying a Harness and an A > [!NOTE] > An `AgentTemplate` has no field naming this Harness. The `kagent.dev/harness: my-first-harness` selector is a convention that this guide uses to match the `kagent.dev/harness` label in the next step. However, you can choose any label key and value, as long as the Harness selector and the AgentTemplate's labels match. -2. Apply an `AgentTemplate` that is labeled to match the Harness's `allowedAgentTemplates` selector. The `modelConfig` field references the `default-model-config` ModelConfig that was automatically created for the model provider API key that you provided during kagent installation. +2. Apply an `AgentTemplate` that is labeled to match the Harness's `allowedAgentTemplates` selector. The `modelConfig` field references the `default-model-config` {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} that was automatically created for the model provider API key that you provided during kagent installation. ```yaml apiVersion: kagent.dev/v1alpha3 kind: AgentTemplate @@ -67,7 +67,7 @@ This guide walks you through creating an agent, from applying a Harness and an A systemPrompt: You are a concise, helpful assistant. ``` -3. Confirm that the pair is ready. The `HARNESS` column lists each Harness that admitted this AgentTemplate, and `READY` reports whether kagent compiled a runtime revision for that pairing. +3. Confirm that the pair is ready. The `HARNESS` column lists each Harness that admitted this AgentTemplate, and `READY` reports whether kagent compiled a runtime {{< gloss "Revision" >}}revision{{< /gloss >}} for that pairing. ```bash kagent get agent-template my-first-agent ``` @@ -117,7 +117,7 @@ An AgentInstance is one running conversation. Creating it starts an Actor on the ## Talk to your agent -1. Send a message to the AgentInstance. The CLI holds the conversation over the A2A (Agent-to-Agent) protocol. +1. Send a message to the AgentInstance. The CLI holds the conversation over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol. ```bash kagent invoke --agent-instance $INSTANCE_ID --task "What is 2+2?" ``` @@ -127,7 +127,7 @@ An AgentInstance is one running conversation. Creating it starts an Actor on the 4 ``` -2. Send a follow-up message to the same AgentInstance. An AgentInstance holds the transcript of its conversation, so the agent answers with the earlier turns in context. +2. Send a follow-up message to the same AgentInstance. An AgentInstance holds the {{< gloss "Transcript" >}}transcript{{< /gloss >}} of its conversation, so the agent answers with the earlier turns in context. ```bash kagent invoke --agent-instance $INSTANCE_ID --task "What did I just ask you?" ``` diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md index f8f582b5..4fca8229 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -5,7 +5,7 @@ weight: 20 author: kagent.dev --- -A system prompt tells an agent how to behave. Tools tell it what it can do. This guide binds a Model Context Protocol (MCP) tool to the agent that you built in [Your first agent]({{< link path="get-started/your-first-agent" >}}), so that the agent can read live data out of your cluster instead of answering from the model alone. For the full tool binding schema, including binding one agent as another agent's tool, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). +A system prompt tells an agent how to behave. Tools tell it what it can do. This guide binds a {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) tool to the agent that you built in [Your first agent]({{< link path="get-started/your-first-agent" >}}), so that the agent can read live data out of your cluster instead of answering from the model alone. For the full {{< gloss "Tool binding" >}}tool binding{{< /gloss >}} schema, including binding one agent as another agent's tool, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). ## Before you begin @@ -19,7 +19,7 @@ kagent ships an MCP server of its own, and installs a `RemoteMCPServer` that poi The names must come from the server's own documentation rather than from the cluster, because kagent does not populate a server's discovered tools. This guide binds `k8s_get_resources` and `k8s_get_pod_logs`. For the full catalog that the built-in server serves, see the [tools ecosystem reference]({{< link path="reference/tools-ecosystem" >}}). -1. List the RemoteMCPServers in the `kagent` namespace. +1. List the {{< gloss "RemoteMCPServer" >}}RemoteMCPServers{{< /gloss >}} in the `kagent` namespace. ```bash kubectl get remotemcpserver -n kagent ``` @@ -68,7 +68,7 @@ The names must come from the server's own documentation rather than from the clu | `mcp.server.name` | The server's name. A binding resolves in the AgentTemplate's own namespace, so it cannot reach a server in another namespace. | | `mcp.tools` | The names of the tools to bind, between 1 and 50. An AgentTemplate takes at most 50 bindings in total. | -3. Confirm that kagent compiled a new revision for the edited AgentTemplate. Every edit produces a new desired revision, and the pair is current when the latest successful revision matches it. +3. Confirm that kagent compiled a new {{< gloss "Revision" >}}revision{{< /gloss >}} for the edited AgentTemplate. Every edit produces a new desired revision, and the pair is current when the latest successful revision matches it. ```bash kubectl get agenttemplate my-first-agent -n kagent \ -o jsonpath='{range .status.harnesses[*]}{.harness}{"\t"}{.desiredRevision}{"\t"}{.latestSuccessfulRevision}{"\n"}{end}' @@ -116,7 +116,7 @@ An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} runs the revision th The agent calls `k8s_get_resources` and answers from the result rather than from the model's own knowledge. -4. Ask a follow-up question that uses the second tool. The AgentInstance holds the transcript of the conversation, so the agent can act on the pods that it just listed. +4. Ask a follow-up question that uses the second tool. The AgentInstance holds the {{< gloss "Transcript" >}}transcript{{< /gloss >}} of the conversation, so the agent can act on the pods that it just listed. ```bash kagent invoke --agent-instance $TOOL_INSTANCE_ID --task "Show me the last few log lines from the kagent controller pod." ``` 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 9441fee6..fcf803db 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,7 +5,7 @@ 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 **tool binding**, and every binding selects exactly one source: a Model Context Protocol (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 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. - `mcp`: Binds tools from an MCP server. - `agent`: Binds another AgentTemplate, so that the agent can hand work to it. @@ -66,7 +66,7 @@ The isolation setting determines whether a bound agent runs inside its parent's ### What a Shared tree allows -A `Shared` 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 revision rather than a failure at run time. +A `Shared` 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. - **One level of nesting.** A bound agent cannot itself bind another agent. A second consecutive binding is rejected as exceeding the kagent runtime boundary. - **No cycles.** An AgentTemplate cannot reach itself through a chain of bindings. 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 4f34fb79..41ed0f4d 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 @@ -5,7 +5,7 @@ weight: 30 author: kagent.dev --- -A **plugin package** is a bundle that an AgentTemplate attaches with `spec.plugins`. The package carries skills and can also declare Model Context Protocol (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 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" >}}). ## What a package holds 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 6cfd1ba2..5408c813 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,7 +5,7 @@ weight: 20 author: kagent.dev --- -A **skill** 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 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. ## About @@ -13,11 +13,11 @@ A skill is a directory whose root holds a `SKILL.md` file. That file carries fro The description is what 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. -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 Model Context Protocol (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 [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" >}}). ## 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 plugin package. +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 >}}. ```yaml apiVersion: kagent.dev/v1alpha3 diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index d919773b..f1b7773a 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -75,8 +75,8 @@ spec: The sandbox draws a boundary in three places. -- **Process and kernel**: The Actor's processes run against the sandbox runtime rather than the Worker node's kernel. A system call that the workload makes is handled by gVisor's user-space kernel, or by the guest kernel inside a micro-VM, instead of reaching the host directly. -- **Filesystem**: The Actor sees the filesystem assembled from its container image, plus whatever durable volume its ActorTemplate declares. Writes to the root filesystem are a layer on top of the image, captured in a `Full` snapshot and discarded by a `Data` one. For what each scope keeps, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). +- **Process and kernel**: The Actor's processes run against the sandbox runtime rather than the Worker node's kernel. A system call that the workload makes is handled by {{< gloss "gVisor" >}}gVisor{{< /gloss >}}'s user-space kernel, or by the guest kernel inside a micro-VM, instead of reaching the host directly. +- **Filesystem**: The Actor sees the filesystem assembled from its container image, plus whatever durable volume its ActorTemplate declares. Writes to the root filesystem are a layer on top of the image, captured in a `Full` {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} and discarded by a `Data` one. For what each scope keeps, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). - **Network**: The Actor does not share the Worker pod's network position. The node agent gives the active Actor a private, point-to-point virtual network inside the Worker pod, so reaching the Actor means going through Agent Substrate's own network path rather than connecting to the Worker directly. ## How traffic reaches a sandboxed Actor diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index da935da6..56130369 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -5,7 +5,7 @@ weight: 20 author: kagent.dev --- -An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, the unit that it suspends and resumes, and it treats that idle time as reclaimable: it suspends an idle Actor into a snapshot, frees the {{< gloss "Worker" >}}Worker{{< /gloss >}} that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. +An agent spends most of its life waiting. It waits on a person to reply, and it waits on a large language model (LLM) to answer. [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs each agent inside an **Actor**, the unit that it suspends and resumes, and it treats that idle time as reclaimable: it suspends an idle Actor into a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, frees the {{< gloss "Worker" >}}Worker{{< /gloss >}} that the Actor was running on, and restores the Actor when traffic arrives for it. This page explains what a snapshot captures, when kagent suspends an Actor, and what happens when a suspended Actor is addressed again. ## Actor lifecycle operations @@ -34,7 +34,7 @@ An {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}}'s snapshot configura Scopes describe only what a snapshot captures, and they are configured per trigger. The `onPause` setting selects what a pause captures on the node, and `onCommit` selects what a suspend uploads to snapshot storage. What `onCommit` captures must be a subset of what `onPause` captures. -A **DurableDir volume** is the per-Actor application data surface. Its contents are preserved by the `Data` scope, so they survive a suspend and resume cycle independently of process memory. How many volumes an ActorTemplate can declare depends on its sandbox class. A `microvm` template can declare several, because they are subdirectories of a single shared filesystem. A `gvisor` template is limited to one, until gVisor accepts more than a single durable mount. +A **DurableDir volume** is the per-Actor application data surface. Its contents are preserved by the `Data` scope, so they survive a suspend and resume cycle independently of process memory. How many volumes an ActorTemplate can declare depends on its sandbox class. A `microvm` template can declare several, because they are subdirectories of a single shared filesystem. A `gvisor` template is limited to one, until {{< gloss "gVisor" >}}gVisor{{< /gloss >}} accepts more than a single durable mount. When an Actor resumes from a `Data`-scope snapshot, the ActorTemplate's `onResume.fromData` setting decides where the rest of the guest state comes from. The default is `ColdBoot`, which starts the containers fresh from the container image with the durable volume contents restored over them. diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index d95ee706..b790ae18 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -48,3 +48,42 @@ Worker: WorkerPool: short: "A Kubernetes custom resource declaring how many Workers to keep running and which sandbox class they use. An operator must provision one before any Harness can create AgentInstances." + +# Added when the glossary widened from Substrate and Harness-model vocabulary to +# any important concept. Same rules apply: gloss the first instance on a page only. + +ModelConfig: + short: "A Kubernetes custom resource naming one model at one provider, along with the credentials to reach it. An AgentTemplate references one by name, and every agent compiled from that template calls the model that it names." + +RemoteMCPServer: + short: "A Kubernetes custom resource pointing at a Model Context Protocol server that the cluster can reach. It is the only server kind that an AgentTemplate tool binding accepts." + +Revision: + short: "The compiled, immutable output of one Harness and AgentTemplate pairing, identified by a content digest. An AgentInstance runs the revision it was created from for its whole life, so editing either resource affects only instances created afterward." + +Snapshot: + short: "The stored state that an Actor suspends to, held in object storage. Resuming restores the Actor from its most recent snapshot, which is what makes suspending idle agents cheap." + +Fork: + short: "A second AgentInstance created from a checkpoint, starting with the transcript and state that the checkpoint pinned. A fork inherits the checkpoint's revision, so later edits to the AgentTemplate do not change what it runs." + +Transcript: + short: "The record of an AgentInstance'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." + +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." + +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." + +Model Context Protocol: + short: "An open protocol for exposing tools and resources to a model. kagent reaches an MCP server through a RemoteMCPServer resource, and an AgentTemplate binds individual tools from it." + +A2A: + short: "The Agent-to-Agent protocol, which callers and other agents use to talk to an AgentInstance. The conversation's context identifier is the AgentInstance ID, so a second message on the same ID continues the same conversation." + +gVisor: + short: "A user-space kernel that isolates a workload from the host kernel by intercepting its system calls. kagent compiles every ActorTemplate to the gvisor sandbox class." From c31bb9671f5b7ef3cd0001403ab44ad79500682e Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 2 Sep 2026 11:07:30 -0500 Subject: [PATCH 36/70] Phase 3 - Model providers Signed-off-by: Rachael Graham --- .../1.x/setup/model-providers/_index.md | 6 + .../model-providers/about-model-providers.md | 47 ++++++ .../setup/model-providers/amazon-bedrock.md | 123 +++++++++++++++ .../1.x/setup/model-providers/anthropic.md | 74 +++++++++ .../setup/model-providers/azure-ai-foundry.md | 119 ++++++++++++++ .../1.x/setup/model-providers/azure-openai.md | 92 +++++++++++ .../setup/model-providers/byo-agentgateway.md | 149 ++++++++++++++++++ .../1.x/setup/model-providers/byo-openai.md | 132 ++++++++++++++++ .../1.x/setup/model-providers/gemini.md | 74 +++++++++ .../setup/model-providers/google-vertexai.md | 34 ++++ .../1.x/setup/model-providers/ollama.md | 127 +++++++++++++++ .../1.x/setup/model-providers/openai.md | 85 ++++++++++ .../1.x/setup/model-providers/sap-ai-core.md | 73 +++++++++ .../kagent/1.x/setup/model-providers/xai.md | 65 ++++++++ 14 files changed, 1200 insertions(+) create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/_index.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/anthropic.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/azure-openai.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/byo-openai.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/gemini.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/ollama.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/openai.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md create mode 100644 docs-site/content/kagent/1.x/setup/model-providers/xai.md diff --git a/docs-site/content/kagent/1.x/setup/model-providers/_index.md b/docs-site/content/kagent/1.x/setup/model-providers/_index.md new file mode 100644 index 00000000..ac0685e1 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/_index.md @@ -0,0 +1,6 @@ +--- +title: Configure model providers +description: Connect kagent to a LLM provider by creating a ModelConfig resource. +weight: 20 +author: kagent.dev +--- diff --git a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md new file mode 100644 index 00000000..be54a2f2 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md @@ -0,0 +1,47 @@ +--- +title: About model providers +description: Understand how a ModelConfig connects kagent to a LLM provider, and which configurations a Harness can run. +weight: 10 +author: kagent.dev +--- + +A `ModelConfig` is a Kubernetes custom resource that names one model at one provider, along with the credentials to reach it. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} references a {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} by name in its `spec.modelConfig.name` field, and every agent compiled from that template calls the model that the ModelConfig names. + +The kagent installation creates a `default-model-config` ModelConfig from the provider API key that you supply at install time, so a first agent needs no extra setup. Create additional ModelConfigs when you want to use a different provider, a different model, or a different set of credentials. + +## How a ModelConfig reaches an agent + +Every ModelConfig shares the same three parts, regardless of the provider that it names. + +| Field | Description | +| ----- | ----------- | +| `provider` | The provider to use. Accepted values are `OpenAI`, `Anthropic`, `AzureOpenAI`, `Ollama`, `Gemini`, `GeminiVertexAI`, `AnthropicVertexAI`, `Bedrock`, `SAPAICore`, and `Foundry`. Defaults to `OpenAI`. | +| `model` | The model name, as the provider spells it. | +| Provider block | A block named after the provider, such as `openAI` or `bedrock`, holding the settings that only that provider takes. An empty block is valid when the provider needs no extra settings. | + +Credentials come from a Kubernetes Secret in the same namespace as the ModelConfig. The `apiKeySecret` field names the Secret, and `apiKeySecretKey` names the key within that Secret. To forward the bearer token from the incoming request to the provider instead, set `apiKeyPassthrough: true`. A ModelConfig cannot set both `apiKeyPassthrough` and `apiKeySecret`. For every ModelConfig field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#modelconfigspec" >}}). + +**Credential files** + +kagent passes model credentials to an agent as environment variables. A ModelConfig that instead requires a credential **file** mounted into the agent does not compile. The AgentTemplate reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`. kagent compiles no revision from that AgentTemplate, so no agent runs from it, and any AgentInstance that already exists keeps running the last revision that compiled. Three configurations encounter this today. +- **The Vertex AI providers.** `GeminiVertexAI` and `AnthropicVertexAI` mount the Google credentials file that `apiKeySecret` names. Leaving `apiKeySecret` unset compiles, but a Substrate Actor does not inherit cloud workload identity, so the agent still has no credentials to send. Both providers are unavailable in practice. For the alternatives, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). +- **A private certificate authority (CA), on any provider.** Setting `tls.caCertSecretRef` mounts the CA bundle as a file. Every provider accepts the `tls` block, so this affects all of them, not only the Vertex AI providers. You cannot reach a provider endpoint that presents a certificate from a private CA, unless you set `tls.disableVerify: true`, which skips certificate verification entirely and belongs only in a test environment. +- **OpenAI token exchange.** The `openAI.tokenExchange` block acquires a bearer token by reading a mounted service account file, so a ModelConfig that sets it never compiles. An OpenAI-compatible endpoint has to accept a static API key instead. See [OpenAI]({{< link path="setup/model-providers/openai" >}}). + +## Use a ModelConfig + +Reference the ModelConfig by name in an AgentTemplate. The ModelConfig must be in the same namespace as the AgentTemplate. + +```yaml +apiVersion: kagent.dev/v1alpha3 +kind: AgentTemplate +metadata: + name: my-agent + namespace: kagent +spec: + modelConfig: + name: default-model-config + systemPrompt: You are a concise, helpful assistant. +``` + +Editing a ModelConfig produces a new compiled {{< gloss "Revision" >}}revision{{< /gloss >}} for every AgentTemplate that references it. An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} keeps running the revision that it was created from, so create a new AgentInstance to pick up a changed model. diff --git a/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md new file mode 100644 index 00000000..dc3b4f34 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md @@ -0,0 +1,123 @@ +--- +title: Amazon Bedrock +description: Configure kagent to use models served through AWS Bedrock, with either the native Bedrock provider or its OpenAI-compatible API. +weight: 20 +author: kagent.dev +--- + +Amazon Bedrock serves models from several families behind one AWS API. kagent reaches it two ways: the native `Bedrock` provider, which is the fuller integration, and Bedrock's OpenAI-compatible endpoint through the `OpenAI` provider. + +Prefer the native provider. Use the OpenAI-compatible path when you need the OpenAI request format, or an inference profile that only that endpoint exposes. + +> [!IMPORTANT] +> Both paths authenticate with credentials from a Kubernetes Secret. Attaching an AWS IAM role to the agent, such as with [EKS IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html), is not currently supported: an agent runs as a Substrate Actor rather than as a pod that kagent controls, so there is no per-agent ServiceAccount to attach a role to. + +## Before you begin + +1. Create an IAM user or role with permissions for Bedrock. At minimum you need `bedrock:InvokeModel` for the models that you use. For more information, see the [AWS Bedrock model access docs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html). + +2. Choose an AWS region and a Bedrock model, and confirm that your account has access to that model in that region. For the available models, see the [AWS Bedrock supported models docs](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html). + +## Native Bedrock provider + +1. Create a Kubernetes Secret that stores your AWS access keys. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic bedrock-credentials -n kagent \ + --from-literal AWS_ACCESS_KEY_ID= \ + --from-literal AWS_SECRET_ACCESS_KEY= + ``` + +2. Create a `ModelConfig` that uses the `Bedrock` provider. + ```yaml + kubectl apply -f - <}}). + +| Field | Description | +| ----- | ----------- | +| `region` | The AWS region that serves the model. Required. | +| `additionalModelRequestFields` | Extra request fields to pass through to the model, as arbitrary JSON. Use this field for parameters that only one model family accepts. | +| `promptCaching` | Whether to cache prompt prefixes across requests. Defaults to `false`. | +| `cacheTTL` | How long a cached prefix lives, either `5m` or `1h`. Defaults to `5m`. | +| `guardrail` | An AWS Bedrock guardrail to apply, given as an `identifier` and a `version`, with an optional `trace` of `disabled`, `enabled`, or `enabled_full`. | +| `readTimeout` | How long to wait on a response, in seconds. | +| `connectTimeout` | How long to wait on a connection, in seconds. | + +## OpenAI-compatible endpoint + +Bedrock also serves an [OpenAI-compatible chat completions API](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-chat-completions.html), which the `OpenAI` provider can call. + +1. Follow the [AWS Bedrock API keys guide](https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started-api-keys.html) to create an API key, and save it as an environment variable. + ```bash + export AWS_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. + ```bash + kubectl create secret generic kagent-bedrock -n kagent --from-literal AWS_API_KEY=$AWS_API_KEY + ``` + +3. Create a `ModelConfig` that uses the `OpenAI` provider and points at the Bedrock endpoint for your region. + ```yaml + kubectl apply -f - <.amazonaws.com/openai/v1`. | + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: bedrock-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md b/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md new file mode 100644 index 00000000..2ec6dd7a --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md @@ -0,0 +1,74 @@ +--- +title: Anthropic +description: Configure kagent to use Anthropic Claude models by creating a ModelConfig for the Anthropic provider. +weight: 20 +author: kagent.dev +--- + +The `Anthropic` provider calls the Anthropic API directly. To reach Claude models through Google Cloud instead, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). + +## Create the ModelConfig + +1. Save your [Anthropic API key](https://console.anthropic.com/settings/keys) as an environment variable. + ```bash + export ANTHROPIC_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic kagent-anthropic -n kagent --from-literal ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY + ``` + +3. Create a `ModelConfig` that references the Secret. + ```yaml + kubectl apply -f - <}}). + +| Field | Description | +| ----- | ----------- | +| `baseUrl` | An alternative API endpoint, for a proxy or a compatible service. | +| `maxTokens` | A cap on the tokens generated in one response. | +| `temperature` | How much randomness the model applies when it picks the next token. | +| `topP` | The nucleus sampling cutoff. | +| `topK` | How many candidate tokens to sample from. | + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: anthropic-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md new file mode 100644 index 00000000..db9bf617 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md @@ -0,0 +1,119 @@ +--- +title: Azure AI Foundry +description: Configure kagent to use models served through an Azure AI Foundry deployment. +weight: 20 +author: kagent.dev +--- + +The `Foundry` provider calls a model deployment in an Azure AI Foundry resource. The chat model has to be reachable through Foundry's OpenAI-compatible chat completions API. + +## Create the ModelConfig + +1. Save your Azure AI Foundry API key as an environment variable. + ```bash + export FOUNDRY_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic foundry-api-key -n kagent --from-literal api-key=$FOUNDRY_API_KEY + ``` + +3. Create a `ModelConfig` for your Foundry deployment. + ```yaml + kubectl apply -f - <.cognitiveservices.azure.com/ + deployment: gpt-4-1-nano + apiVersion: "2024-10-21" + EOF + ``` + + | Field | Description | + | ----- | ----------- | + | `apiKeySecret` | The name of the Kubernetes Secret that stores the API key, in the same namespace as this ModelConfig. | + | `apiKeySecretKey` | The key within that Secret that holds the API key. | + | `model` | The model that the deployment serves. | + | `provider` | The provider to use, `Foundry`. | + | `foundry.endpoint` | The endpoint of your Foundry account. | + | `foundry.deployment` | The name of the deployment within the account. This field is required. | + | `foundry.apiVersion` | The Foundry API version to call. Defaults to `2024-10-21`. | + +## Azure AI Foundry provider settings + +The `foundry` block takes the following settings. For every field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#foundryconfig" >}}). + +| Field | Description | +| ----- | ----------- | +| `deployment` | The deployment name within the Foundry account. Required. | +| `endpoint` | The endpoint of the Foundry account. | +| `endpointFrom` | Read the endpoint from a key in a ConfigMap instead of setting it inline. Use this field when the endpoint differs per environment and is published by a platform team. | +| `apiVersion` | The Foundry API version. Defaults to `2024-10-21`. | + +### Read the endpoint from a ConfigMap + +Set `endpointFrom` in place of `endpoint` to take the endpoint from a ConfigMap in the same namespace. + +```yaml +spec: + provider: Foundry + model: gpt-4.1-nano + apiKeySecret: foundry-api-key + apiKeySecretKey: api-key + foundry: + endpointFrom: + name: foundry-endpoint + key: endpoint + deployment: gpt-4-1-nano +``` + +When the named ConfigMap or key does not exist, the {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} reports `Accepted` as `False`. Inspect it to find which reference failed. + +```bash +kubectl describe modelconfig foundry-model-config -n kagent +``` + +## Authentication + +| Configuration | Credential | +| ------------- | ---------- | +| `apiKeySecret` is set | The API key from the referenced Secret. | +| `apiKeyPassthrough: true` | The bearer token from the caller's request, forwarded to Foundry as the API key. Mutually exclusive with `apiKeySecret`. | + +> [!WARNING] +> **Azure Workload Identity is not currently supported.** In earlier versions of kagent, omitting the credential fields fell back to Azure Workload Identity, which depended on an annotated ServiceAccount on the agent's pod. An agent now runs as a Substrate Actor rather than as a pod that kagent controls, so there is no per-agent ServiceAccount to federate an Azure identity onto. Supply an API key instead. + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: foundry-model-config +``` + +## Troubleshooting + +| Symptom | Cause | +| ------- | ----- | +| The ModelConfig reports `Accepted` as `False` | A referenced Secret or `endpointFrom` ConfigMap does not exist, or does not hold the named key. Run `kubectl describe modelconfig` to see which one. | +| Foundry returns `401 Unauthorized` or `403 Forbidden` | The API key does not have access to the resource. | +| The AgentTemplate reports `Compatible` as `False` | The resolved configuration cannot run on the Harness. Read the condition message for the specific reason. | + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/azure-openai" >}}` title="Azure OpenAI" subtitle="Reach OpenAI models hosted directly on Azure OpenAI." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/azure-openai.md b/docs-site/content/kagent/1.x/setup/model-providers/azure-openai.md new file mode 100644 index 00000000..676de7d9 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/azure-openai.md @@ -0,0 +1,92 @@ +--- +title: Azure OpenAI +description: Configure kagent to use OpenAI models hosted on Azure by creating a ModelConfig for the AzureOpenAI provider. +weight: 20 +author: kagent.dev +--- + +The `AzureOpenAI` provider calls an Azure OpenAI deployment. It differs from the [OpenAI]({{< link path="setup/model-providers/openai" >}}) provider in that it addresses a named deployment in your own Azure resource rather than a model on OpenAI's API. + +## Create the ModelConfig + +1. Save your Azure OpenAI API key as an environment variable. + ```bash + export AZURE_OPENAI_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic azure-openai-api-key -n kagent --from-literal api-key=$AZURE_OPENAI_API_KEY + ``` + +3. Create a `ModelConfig` for your Azure OpenAI deployment. + ```yaml + kubectl apply -f - <.openai.azure.com/ + apiVersion: "2025-03-01-preview" + azureDeployment: gpt-4o-mini + EOF + ``` + + | Field | Description | + | ----- | ----------- | + | `apiKeySecret` | The name of the Kubernetes Secret that stores the API key, in the same namespace as this ModelConfig. | + | `apiKeySecretKey` | The key within that Secret that holds the API key. | + | `model` | The model that the deployment serves. | + | `provider` | The provider to use, `AzureOpenAI`. | + | `azureOpenAI.azureEndpoint` | The endpoint of your Azure OpenAI resource. This field is required. | + | `azureOpenAI.apiVersion` | The Azure OpenAI API version to call. This field is required. | + | `azureOpenAI.azureDeployment` | The name of the deployment within the resource. | + +## Azure OpenAI provider settings + +The `azureOpenAI` block takes the following settings. For every field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#azureopenaiconfig" >}}). + +| Field | Description | +| ----- | ----------- | +| `azureEndpoint` | The endpoint of the Azure OpenAI resource. Required. | +| `apiVersion` | The Azure OpenAI API version. Required. | +| `azureDeployment` | The deployment name within the resource. | +| `azureAdToken` | A Microsoft Entra ID token to send instead of an API key. | +| `temperature` | How much randomness the model applies when it picks the next token. | +| `topP` | The nucleus sampling cutoff. | +| `maxTokens` | A cap on the tokens generated in one response. | + +## Authentication + +| Configuration | Credential | +| ------------- | ---------- | +| `apiKeySecret` is set | The API key from the referenced Secret. | +| `azureOpenAI.azureAdToken` is set | The Microsoft Entra ID token given in the field. | +| `apiKeyPassthrough: true` | The bearer token from the caller's request, forwarded to Azure OpenAI as the API key. This is not Microsoft Entra ID authentication, and it is mutually exclusive with `apiKeySecret`. | + +> [!WARNING] +> **Azure Workload Identity is not currently supported.** In earlier versions of kagent, omitting the credential fields fell back to Azure Workload Identity, which depended on an annotated ServiceAccount on the agent's pod. An agent now runs as a Substrate Actor rather than as a pod that kagent controls, so there is no per-agent ServiceAccount to federate an Azure identity onto. Supply a credential with one of the configurations in the preceding table. + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: azure-openai-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/azure-ai-foundry" >}}` title="Azure AI Foundry" subtitle="Reach models served through an Azure AI Foundry deployment." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md b/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md new file mode 100644 index 00000000..f3ed013f --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md @@ -0,0 +1,149 @@ +--- +title: agentgateway +description: Route kagent model requests through an agentgateway deployment for traffic management, observability, and security. +weight: 20 +author: kagent.dev +--- + +[agentgateway](https://agentgateway.dev/docs/) is an AI-native proxy that adds traffic management, observability, and security to large language model calls. It serves an OpenAI-compatible API, so a {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} for agentgateway sets `provider: OpenAI` and points `openAI.baseUrl` at the Gateway service. + +## Set up agentgateway model routing + +> [!NOTE] +> The `AgentgatewayModel` feature is experimental and disabled by default. Enable it when you install agentgateway by passing `--set agentgatewayModels.enabled=true` to the control plane Helm chart. + +1. Install agentgateway in your cluster, adding `--set agentgatewayModels.enabled=true` to the Helm command for the control plane. For more information, see the [agentgateway documentation](https://agentgateway.dev/docs/kubernetes/latest/setup/). + +2. Create a `Gateway` resource for model routing. + ```yaml + kubectl apply -f - <}} +{{% tab name="No authentication" %}} +When your agentgateway deployment enforces no API key authentication, the ModelConfig needs no Secret. + +```yaml +kubectl apply -f - < + kubectl create secret generic kagent-agentgateway-key -n kagent \ + --from-literal AGENTGATEWAY_API_KEY=$AGENTGATEWAY_API_KEY + ``` + +2. Create the `ModelConfig`. + ```yaml + kubectl apply -f - <}} + +For every `openAI` field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#openaiconfig" >}}). + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: agentgateway-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/byo-openai" >}}` title="BYO OpenAI-compatible endpoint" subtitle="Point the OpenAI provider at any other compatible service." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/byo-openai.md b/docs-site/content/kagent/1.x/setup/model-providers/byo-openai.md new file mode 100644 index 00000000..580c336a --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/byo-openai.md @@ -0,0 +1,132 @@ +--- +title: BYO OpenAI-compatible endpoint +description: Configure kagent to use any provider that serves the OpenAI API, including a self-hosted gateway in front of your own models. +weight: 40 +author: kagent.dev +--- + +Many providers serve the [OpenAI API](https://platform.openai.com/docs/api-reference/introduction) rather than an API of their own. To use one, set `provider: OpenAI` and point `openAI.baseUrl` at the provider's endpoint. This is the same mechanism behind the [xAI]({{< link path="setup/model-providers/xai" >}}) and [Amazon Bedrock]({{< link path="setup/model-providers/amazon-bedrock" >}}) OpenAI-compatible paths. + +## Create the ModelConfig + +The following example uses [Cohere](https://cohere.com/), which serves an OpenAI-compatible endpoint. + +1. Save the API key from your provider as an environment variable. + ```bash + export PROVIDER_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic kagent-my-provider -n kagent --from-literal PROVIDER_API_KEY=$PROVIDER_API_KEY + ``` + +3. Create a `ModelConfig` that points at your provider's endpoint. + ```yaml + kubectl apply -f - <}}). Not every compatible provider honors every setting, so check your provider's documentation before setting one. For every `openAI` field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#openaiconfig" >}}). + +## Self-hosted vLLM behind a gateway + +A common self-hosted pattern puts an OpenAI-compatible gateway such as [Bifrost](https://github.com/maximhq/bifrost) or [LiteLLM](https://docs.litellm.ai/) in front of a [vLLM](https://docs.vllm.ai/) server, so that requests travel from kagent to the gateway to vLLM. Configure the gateway as an OpenAI-compatible provider in the same way, with two extra things to get right. + +### 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. + +```bash +vllm serve Qwen/Qwen2.5-7B-Instruct \ + --enable-auto-tool-choice \ + --tool-call-parser hermes +``` + +The correct `--tool-call-parser` depends on your model family. Qwen2.5 uses `hermes` and Llama 3.1 uses `llama3_json`. Parser names change across vLLM releases, so check the [vLLM tool calling docs](https://docs.vllm.ai/en/latest/features/tool_calling.html) for the current name for your model. + +### Use the gateway's model identifier + +Set `model` to the identifier that your gateway routes on, which is often provider-prefixed and can differ from the bare model name that vLLM serves internally. Point `openAI.baseUrl` at the gateway. LiteLLM defaults to port `4000`, and Bifrost to `8080`. + +```yaml +spec: + apiKeySecret: kagent-my-provider + apiKeySecretKey: PROVIDER_API_KEY + model: vllm/Qwen/Qwen2.5-7B-Instruct + provider: OpenAI + openAI: + baseUrl: http://litellm.kagent.svc.cluster.local:4000/v1 +``` + +### Troubleshooting a 400 from the provider + +When every agent message fails with a generic `provider API error (status 400)`, the most common cause is a vLLM server started without `--enable-auto-tool-choice` and a matching `--tool-call-parser`. Because kagent always sends `tool_choice: "auto"`, vLLM rejects the request until automatic tool choice is enabled. Restart vLLM with both flags and try again. + +## TLS + +A provider on your own network may present a certificate that the agent does not already trust. The `tls` block adjusts how the agent verifies it. + +| Field | Description | +| ----- | ----------- | +| `disableVerify` | Turns off certificate verification entirely. Defaults to `false`. | +| `disableSystemCAs` | Trusts only the named CA bundle rather than the system trust store. Defaults to `false`. | +| `caCertSecretRef` | The name of a Secret holding a PEM certificate authority bundle. | +| `caCertSecretKey` | The key within that Secret that holds the bundle. | + +> [!WARNING] +> **Pinning a certificate authority is not currently supported.** Setting `tls.caCertSecretRef` and `tls.caCertSecretKey` makes kagent mount the bundle as a file, and an agent running on {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} cannot mount files. The AgentTemplate reports the `Compatible` condition as `False` with the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`. Use a certificate that chains to a public authority, or terminate TLS at a gateway that the agent can trust. + +Turning verification off does not mount anything, so it does compile. + +```yaml +spec: + apiKeySecret: kagent-my-provider + apiKeySecretKey: PROVIDER_API_KEY + model: command-a-03-2025 + provider: OpenAI + openAI: + baseUrl: https://llm.internal.example.com/v1 + tls: + disableVerify: true +``` + +> [!WARNING] +> Disabling verification removes the guarantee that the agent is talking to the server that it thinks it is. Use it for local testing, never in production. + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: my-provider-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/byo-agentgateway" >}}` title="agentgateway" subtitle="Route model traffic through an agentgateway deployment." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/gemini.md b/docs-site/content/kagent/1.x/setup/model-providers/gemini.md new file mode 100644 index 00000000..ab539f3b --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/gemini.md @@ -0,0 +1,74 @@ +--- +title: Gemini +description: Configure kagent to use Google Gemini models through the Google AI Studio API. +weight: 20 +author: kagent.dev +--- + +The `Gemini` provider reaches Google's Gemini models through the Google AI Studio API, authenticating with a single API key. To reach Gemini through Google Cloud instead, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). + +## Before you begin + +Make sure that your Google Cloud account has a project with the Gemini API enabled. + +## Create the ModelConfig + +1. Get an API key from [Google AI Studio](https://ai.google.dev/), and save it as an environment variable. + ```bash + export GOOGLE_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic kagent-gemini -n kagent --from-literal GOOGLE_API_KEY=$GOOGLE_API_KEY + ``` + +3. Create a `ModelConfig` that references the Secret. + ```yaml + kubectl apply -f - <}}). + +| Field | Description | +| ----- | ----------- | +| `maxOutputTokens` | A cap on the tokens generated in one response. | + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: gemini-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md b/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md new file mode 100644 index 00000000..04154b3a --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md @@ -0,0 +1,34 @@ +--- +title: Google Vertex AI +description: Understand why the Google Vertex AI providers do not currently run on a kagent Harness. +weight: 20 +author: kagent.dev +--- + +The `GeminiVertexAI` and `AnthropicVertexAI` providers reach Gemini and Claude models through Google Cloud Vertex AI. Both providers exist in the {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} schema, but neither currently runs on a kagent {{< gloss "Harness" >}}Harness{{< /gloss >}}. + +> [!WARNING] +> **Vertex AI is not currently supported.** Vertex AI authenticates with a Google Application Default Credentials file rather than with an API key. When `apiKeySecret` is set, kagent mounts that credentials file into the agent, and mounting a file is not something an agent running on {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} can do. The AgentTemplate reports the `Compatible` condition as `False` with the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`, and no runtime {{< gloss "Revision" >}}revision{{< /gloss >}} is compiled. + +## Why the configuration fails + +kagent passes model credentials to an agent as environment variables. Every provider whose credential is a string, such as an API key, works on a Harness. Vertex AI is different: the Google credentials are a JSON file, so kagent sets `GOOGLE_APPLICATION_CREDENTIALS` to a path and mounts the Secret at that path. An agent runs as a Substrate Actor rather than as a pod that kagent controls, so there is nowhere to mount it. + +Omitting `apiKeySecret` avoids the mount, because kagent then expects Google credentials to be already present in the agent's environment. An Actor's sandbox does not inherit cloud workload identity from the node, so that path does not authenticate either. + +For the full explanation of which configurations a Harness can run, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). + +## What to use instead + +| Goal | Alternative | +| ---- | ----------- | +| Gemini models | Use the [Gemini]({{< link path="setup/model-providers/gemini" >}}) provider, which reaches the same model family through the Google AI Studio API with an API key. | +| Claude models | Use the [Anthropic]({{< link path="setup/model-providers/anthropic" >}}) provider, or reach Claude through [Amazon Bedrock]({{< link path="setup/model-providers/amazon-bedrock" >}}). | +| Vertex AI specifically | Route Vertex AI through a gateway that presents an OpenAI-compatible API and authenticates to Google itself, then point an [OpenAI-compatible endpoint]({{< link path="setup/model-providers/byo-openai" >}}) ModelConfig at the gateway. | + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="setup/model-providers/gemini" >}}` title="Gemini" subtitle="Reach Gemini models with an API key instead." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand which provider configurations a Harness can run." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/ollama.md b/docs-site/content/kagent/1.x/setup/model-providers/ollama.md new file mode 100644 index 00000000..a8a33d11 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/ollama.md @@ -0,0 +1,127 @@ +--- +title: Ollama +description: Configure kagent to use models that you run yourself with Ollama, in the cluster or on your own machine. +weight: 20 +author: kagent.dev +--- + +[Ollama](https://ollama.com) runs large language models on hardware that you control. The `Ollama` provider points kagent at an Ollama server rather than at a hosted API, so it needs a host address instead of an API key. + +> [!IMPORTANT] +> kagent agents call tools, so choose a model that supports function calling. A model without tool support connects successfully and then fails to use any tool that you bind to it. + +## Run Ollama in the cluster + +Skip this section if you already have an Ollama server that your cluster can reach. + +1. Create a namespace for Ollama. + ```bash + kubectl create namespace ollama + ``` + +2. Create the Ollama Deployment and Service. + ```yaml + kubectl apply -f - <}}). + +| Field | Description | +| ----- | ----------- | +| `host` | The address of the Ollama server. | +| `options` | Ollama runtime options, as a map of string keys to string values. Use this field for the parameters that Ollama accepts per request, such as `num_ctx`. | + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: llama3-model-config +``` + +> [!NOTE] +> An agent runs inside a sandboxed Actor with controlled egress, so the Ollama server has to be reachable from the cluster network. An Ollama server on your laptop is not reachable from an agent, even when `kubectl port-forward` makes it reachable from your terminal. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/openai.md b/docs-site/content/kagent/1.x/setup/model-providers/openai.md new file mode 100644 index 00000000..e2b0ba2a --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/openai.md @@ -0,0 +1,85 @@ +--- +title: OpenAI +description: Configure kagent to use OpenAI models by creating a ModelConfig for the OpenAI provider. +weight: 10 +author: kagent.dev +--- + +The `OpenAI` provider calls the OpenAI API directly. It also backs every OpenAI-compatible endpoint, so several other providers in this section set `provider: OpenAI` and point `openAI.baseUrl` somewhere else. + +## Create the ModelConfig + +1. Save your [OpenAI API key](https://platform.openai.com/api-keys) as an environment variable. + ```bash + export OPENAI_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic kagent-openai -n kagent --from-literal OPENAI_API_KEY=$OPENAI_API_KEY + ``` + +3. Create a `ModelConfig` that references the Secret. + ```yaml + kubectl apply -f - <}}). + +| Field | Description | +| ----- | ----------- | +| `baseUrl` | An alternative API endpoint. Set this to point the OpenAI provider at an OpenAI-compatible service rather than at OpenAI. | +| `organization` | The OpenAI organization to bill requests to. | +| `apiFormat` | Which OpenAI HTTP API to call, either `chatCompletions` or `responses`. Defaults to `chatCompletions`. Use `responses` for gateways and models that require the Responses API. | +| `maxTokens` | A cap on the tokens generated in one response, sent as the deprecated `max_tokens` parameter. Reasoning models reject it. Mutually exclusive with `maxCompletionTokens`. | +| `maxCompletionTokens` | A cap on visible output plus reasoning tokens, sent as `max_completion_tokens`. Reasoning models require this field in place of `maxTokens`. Mutually exclusive with `maxTokens`. | +| `reasoningEffort` | How many reasoning tokens the model generates before it answers. Accepted values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Support varies by model, and some models require `none` to use tools through the Chat Completions API. | +| `temperature` | How much randomness the model applies when it picks the next token. | +| `topP` | The nucleus sampling cutoff. | +| `frequencyPenalty` | How strongly to discourage repeating tokens that already appeared. | +| `presencePenalty` | How strongly to discourage reusing topics that already appeared. | +| `seed` | A fixed seed, for more repeatable output. | +| `n` | How many completions to request. | +| `timeout` | How long to wait on a request to the provider. | + +> [!WARNING] +> The `openAI` block also accepts `tokenExchange`, which acquires a bearer token from a mounted service account file. That configuration mounts a credential file into the agent, so it does not compile on a Harness. See [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}) for the full list of configurations that this affects. + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: openai-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/byo-openai" >}}` title="BYO OpenAI-compatible endpoint" subtitle="Point the OpenAI provider at a different service." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md b/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md new file mode 100644 index 00000000..d9e6c2e0 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md @@ -0,0 +1,73 @@ +--- +title: SAP AI Core +description: Configure kagent to use models served through the SAP AI Core Orchestration Service. +weight: 20 +author: kagent.dev +--- + +kagent reaches SAP AI Core through its [Orchestration Service](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/orchestration), a single endpoint that serves models from several families, including Anthropic, OpenAI, Gemini, Amazon, Meta, and Mistral. Authentication uses OAuth2 client credentials from your SAP AI Core service key. + +## Create the ModelConfig + +1. Save the OAuth2 client credentials from your SAP AI Core service key as environment variables. + ```bash + export SAP_AI_CORE_CLIENT_ID= + export SAP_AI_CORE_CLIENT_SECRET= + ``` + +2. Create a Kubernetes Secret that stores both credentials. The Secret has to contain the keys `client_id` and `client_secret` under exactly those names. + ```bash + kubectl create secret generic kagent-sapaicore -n kagent \ + --from-literal client_id=$SAP_AI_CORE_CLIENT_ID \ + --from-literal client_secret=$SAP_AI_CORE_CLIENT_SECRET + ``` + + > [!NOTE] + > SAP AI Core is the one provider that does not use `apiKeySecretKey`. kagent reads `client_id` and `client_secret` directly from the Secret that `apiKeySecret` names, so setting `apiKeySecretKey` has no effect. + +3. Create a `ModelConfig` that references the Secret. The endpoint, resource group, and OAuth2 token endpoint all come from your SAP AI Core service key. + ```yaml + kubectl apply -f - <.authentication.eu10.hana.ondemand.com + resourceGroup: default + EOF + ``` + + | Field | Description | + | ----- | ----------- | + | `apiKeySecret` | The name of the Kubernetes Secret that holds `client_id` and `client_secret`. | + | `model` | The model to use, in the Orchestration Service naming convention, such as `anthropic--claude-4.5-sonnet`, `gpt-5-mini`, or `gemini-3-pro-preview`. For the full list, see the [SAP AI Core models docs](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/models-and-scenarios-in-generative-ai-hub). | + | `provider` | The provider to use, `SAPAICore`. | + | `sapAICore.baseUrl` | The base URL for the SAP AI Core API. This field is required. | + | `sapAICore.authUrl` | The OAuth2 token endpoint. | + | `sapAICore.resourceGroup` | The resource group within SAP AI Core. Defaults to `default`. | + + For every `sapAICore` field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#sapaicoreconfig" >}}). + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: sapaicore-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/xai.md b/docs-site/content/kagent/1.x/setup/model-providers/xai.md new file mode 100644 index 00000000..4e60bebd --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/xai.md @@ -0,0 +1,65 @@ +--- +title: xAI +description: Configure kagent to use xAI Grok models through xAI's OpenAI-compatible API. +weight: 20 +author: kagent.dev +--- + +xAI's Grok models are served through an OpenAI-compatible API, so a {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} for xAI sets `provider: OpenAI` and points `openAI.baseUrl` at xAI. There is no separate xAI provider value. + +## Create the ModelConfig + +1. Save your [xAI API key](https://console.x.ai/) as an environment variable. + ```bash + export XAI_API_KEY= + ``` + +2. Create a Kubernetes Secret that stores the API key. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic kagent-xai -n kagent --from-literal XAI_API_KEY=$XAI_API_KEY + ``` + +3. Create a `ModelConfig` that references the Secret and sets the xAI base URL. + ```yaml + kubectl apply -f - <}}). For every `openAI` field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#openaiconfig" >}}). + +## Use the ModelConfig + +Reference the ModelConfig by name from an AgentTemplate in the same namespace. + +```yaml +spec: + modelConfig: + name: grok-model-config +``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Create an agent that uses this model, and hold a conversation with it." >}} + {{< card link=`{{< link path="setup/model-providers/byo-openai" >}}` title="BYO OpenAI-compatible endpoint" subtitle="Point the OpenAI provider at any other compatible service." >}} +{{< /cards >}} From 4a84a88132bc86657b6dc41f8aeb0ca13f13d075 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 2 Sep 2026 11:52:50 -0500 Subject: [PATCH 37/70] code updates Signed-off-by: Rachael Graham --- .../kagent-docs/versions/agent-substrate.md | 2 +- .../content/kagent/1.x/about/architecture.md | 23 +++++++++++-------- .../kagent/1.x/about/what-is-kagent.md | 4 ++-- .../1.x/get-started/your-first-mcp-tool.md | 12 +++++++--- .../content/kagent/1.x/setup/installation.md | 2 +- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/docs-site/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md index 8ade5faa..a9de7678 100644 --- a/docs-site/assets/kagent-docs/versions/agent-substrate.md +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -1 +1 @@ -{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.20{{< /version >}} \ No newline at end of file +{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.22{{< /version >}} \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 343cfa07..03bf8b18 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -25,14 +25,19 @@ flowchart TB harness["Harness"] template["AgentTemplate"] controller["kagent controller"] - actortemplate["ActorTemplate (Substrate)"] operator --> harness operator --> template harness --> controller template --> controller - controller -->|compiles the pair into| actortemplate end + %% Declared outside both subgraphs on purpose. An ActorTemplate is a Substrate + %% resource reached over gRPC, not a Kubernetes object, so it belongs to + %% neither plane. A node joins whichever subgraph first references it, so both + %% of its edges have to live out here too. + actortemplate["ActorTemplate (Substrate)"] + controller -->|compiles the pair into| actortemplate + subgraph kagentplane["kagent plane (gRPC auth)"] caller["Caller"] gateway["A2A gateway"] @@ -44,19 +49,19 @@ flowchart TB instance -->|runs on| actor end - %% Declared outside both subgraphs on purpose: a node belongs to whichever - %% subgraph first references it, so putting this edge inside the kagent plane - %% would pull ActorTemplate out of the Kubernetes plane. actortemplate -->|instantiated as| instance - %% Invisible link: forces the kagent plane to sit fully below the Kubernetes - %% plane. Without it, the layout engine staggers the two planes diagonally. - %% actortemplate ~~~ caller + %% Invisible link: forces the kagent plane to sit fully below the ActorTemplate, + %% and the ActorTemplate below the Kubernetes plane. Without it the layout engine + %% staggers the two planes diagonally, which both wastes width and scrambles the + %% reading order. Anchor it to actortemplate, not controller: anchoring higher + %% loses the stacking. Verified by rendering. + actortemplate ~~~ caller classDef crd stroke:#a78bfa,stroke-width:2px class harness,template crd ``` -Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. +Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. The ActorTemplate sits outside both planes in the diagram because that is where it sits in reality: it is a Substrate resource that the controller creates over gRPC, not a Kubernetes object, so no Kubernetes role grants access to it. The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an {{< gloss "Actor" >}}Actor{{< /gloss >}}. diff --git a/docs-site/content/kagent/1.x/about/what-is-kagent.md b/docs-site/content/kagent/1.x/about/what-is-kagent.md index 302f5259..bbd31e6e 100644 --- a/docs-site/content/kagent/1.x/about/what-is-kagent.md +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -5,7 +5,7 @@ weight: 10 author: kagent.dev --- -kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability that you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and with every major large language model (LLM) provider. Agents run on kagent's own Go and Python engines. +kagent is an open-source, Kubernetes-native platform for running AI agents. It defines an agent's runtime and behavior as ordinary Kubernetes custom resources, governed by the same role-based access control (RBAC), GitOps, and observability that you already use for your other workloads, and runs each agent's conversation inside [Agent Substrate]({{< link path="about/agent-substrate" >}}), a sandboxed, suspend-and-resume compute layer built for bursty, mostly idle agent workloads. kagent works with agent frameworks such as Google's Agent Development Kit (ADK), LangGraph, and CrewAI, and with every major large language model (LLM) provider. Agents run on kagent's own Go and Python engines, on the Codex or Claude coding agents, or on an image of your own. kagent was created at [Solo.io](https://www.solo.io) in 2025 and is a [Cloud Native Computing Foundation](https://www.cncf.io) sandbox project. @@ -45,7 +45,7 @@ Everything works with a single `helm install`. No add-ons, no extra databases, n {{< feature-card title="Agent lifecycle via CRDs" desc="Define, version, and roll out Harnesses and AgentTemplates with kubectl and GitOps, the same workflow as every other workload." >}} {{< feature-card title="Sandboxed by default" desc="Every AgentInstance runs on a Substrate Actor, isolated from the host kernel by a gVisor sandbox. Run untrusted, model-directed code safely." >}} {{< feature-card title="Suspend and resume" desc="Idle AgentInstances suspend and free their compute, then resume on demand. Run far more agents than you have capacity for at any one moment." >}} -{{< feature-card title="Pluggable agent runtimes" desc="A Harness selects the engine behind an agent. kagent runs its own Go and Python engines, and the Harness API defines Codex and Claude runtime selectors." >}} +{{< feature-card title="Pluggable agent runtimes" desc="A Harness selects the engine behind an agent: kagent's own Go and Python engines, the Codex or Claude coding agents, or any image of your own that speaks kagent's A2A contract." >}} {{< feature-card title="Agent tools" desc="Compose agents from other agents. A Shared binding nests an agent inside its parent's Actor, one level deep." >}} {{< feature-card title="Long-term memory" desc="Persistent, vector-backed memory across sessions. Agents remember context, not just the last prompt." >}} {{< feature-card title="Human-in-the-loop" desc="Tool approval gates and agent-initiated questions keep a person in control of consequential actions." >}} diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md index 4fca8229..f7a6e932 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -17,17 +17,23 @@ A system prompt tells an agent how to behave. Tools tell it what it can do. This kagent ships an MCP server of its own, and installs a `RemoteMCPServer` that points at it, so the built-in server is the shortest path to a working tool. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} takes tools through an `mcp` binding, which names one server and the tools to take from it. Naming the tools is required, because a binding never takes a server's whole catalog. -The names must come from the server's own documentation rather than from the cluster, because kagent does not populate a server's discovered tools. This guide binds `k8s_get_resources` and `k8s_get_pod_logs`. For the full catalog that the built-in server serves, see the [tools ecosystem reference]({{< link path="reference/tools-ecosystem" >}}). +kagent records what it discovered on the server's status, so the tool names come from the cluster. This guide binds `k8s_get_resources` and `k8s_get_pod_logs`. For the full catalog that the built-in server serves, see the [tools ecosystem reference]({{< link path="reference/tools-ecosystem" >}}). 1. List the {{< gloss "RemoteMCPServer" >}}RemoteMCPServers{{< /gloss >}} in the `kagent` namespace. ```bash kubectl get remotemcpserver -n kagent ``` - Example output: The `ACCEPTED` column is empty because kagent does not yet write status back to a RemoteMCPServer. An empty column is expected, and does not mean that the server is unhealthy. + Example output: The `ACCEPTED` column reports whether kagent reached the server and read its catalog. No tool can be bound from a server that is not `True`. ```console NAME PROTOCOL URL ACCEPTED AGE - kagent-tool-server STREAMABLE_HTTP http://kagent-tools.kagent:8084/mcp 14m + kagent-tool-server STREAMABLE_HTTP http://kagent-tools.kagent:8084/mcp True 14m + ``` + + To see the tools that the server offers, read the discovered set from its status. + ```bash + kubectl get remotemcpserver kagent-tool-server -n kagent \ + -o jsonpath='{range .status.discoveredTools[*]}{.name}{"\t"}{.description}{"\n"}{end}' ``` > [!NOTE] diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index b7a438ff..b5af88fe 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -221,7 +221,7 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker substrateWorkerPool: create: true replicas: 1 - ateomImage: "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" + workerImage: "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" EOF ``` > [!NOTE] From ec3d55fd9cdc8cde0a2cf19db130067d01c9dda8 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 2 Sep 2026 14:41:08 -0500 Subject: [PATCH 38/70] Phase 3 - Agent harness Signed-off-by: Rachael Graham --- .../content/kagent/1.x/about/core-concepts.md | 6 +- docs-site/content/kagent/1.x/agents/_index.md | 6 + .../kagent/1.x/agents/agent-harness.md | 159 ++++++++++++++++++ .../model-providers/about-model-providers.md | 16 +- .../setup/model-providers/amazon-bedrock.md | 3 + .../1.x/setup/model-providers/anthropic.md | 5 +- .../setup/model-providers/google-vertexai.md | 80 +++++++-- .../1.x/setup/model-providers/openai.md | 7 +- 8 files changed, 261 insertions(+), 21 deletions(-) create mode 100644 docs-site/content/kagent/1.x/agents/_index.md create mode 100644 docs-site/content/kagent/1.x/agents/agent-harness.md 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 00564874..b1886db4 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -42,7 +42,7 @@ The Harness and AgentTemplate are the only two resources that an operator applie A **Harness** is a Kubernetes custom resource that defines _how an agent is allowed to run_. It specifies: -- **Runtime**: The engine that executes the agent. A Harness selects exactly one of `kagent`, `codex`, or `claude`. kagent compiles only the `kagent` runtime, which runs kagent's own Go and Python engines. +- **Runtime**: The engine that executes the agent. A Harness selects exactly one of `kagent`, `codex`, `claude`, or `byo`, and kagent compiles all four. `kagent` runs kagent's own Go and Python engines, `codex` and `claude` run those coding agents, and `byo` runs any image that implements kagent's A2A contract. - **Workload**: The container image and environment the runtime runs in. - **Substrate policy**: The [WorkerPool]({{< link path="about/agent-substrate#workers-and-workerpools" >}}) that the Harness's Actors are scheduled onto, and where their {{< gloss "Snapshot" >}}snapshots{{< /gloss >}} are stored. - **Allowed AgentTemplates**: A selector that names which AgentTemplates are permitted to run on this Harness. @@ -50,7 +50,9 @@ A **Harness** is a Kubernetes custom resource that defines _how an agent is allo That last point is a one-way match, not a mutual handshake. An AgentTemplate has no field naming a Harness. Instead, a Harness's `allowedAgentTemplates` selector matches on labels, and any AgentTemplate in the same namespace carrying a matching label becomes eligible to run on it. Whoever controls a Harness's selector decides which AgentTemplates it accepts. > [!NOTE] -> The `codex` and `claude` runtimes are part of the Harness API, so the Kubernetes API server accepts a Harness that selects either one. However, kagent currently has no compiler for them, so the pair then reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and the message `Harness runtime is not supported by any compiler`. +> Each runtime accepts a different subset of configuration. The `codex` and `claude` runtimes support fewer model providers than `kagent` does, and neither accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. A Harness and AgentTemplate pair that asks for something its runtime cannot do reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and a message naming the specific setting. + +A `byo` Harness has one extra requirement: it must set `spec.workload.command`, because kagent has no default entrypoint for an image that it does not build. A Harness owns no running compute by itself. Applying one registers a runtime and policy that an AgentTemplate can pair with. diff --git a/docs-site/content/kagent/1.x/agents/_index.md b/docs-site/content/kagent/1.x/agents/_index.md new file mode 100644 index 00000000..e07add1a --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/_index.md @@ -0,0 +1,6 @@ +--- +title: Agents +description: Configure how an agent runs and what it knows, from the runtime behind it to its prompt and memory. +weight: 40 +author: kagent.dev +--- diff --git a/docs-site/content/kagent/1.x/agents/agent-harness.md b/docs-site/content/kagent/1.x/agents/agent-harness.md new file mode 100644 index 00000000..4f3f335e --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/agent-harness.md @@ -0,0 +1,159 @@ +--- +title: Agent harness +description: Configure a Harness, the resource that defines which runtime executes an agent and what infrastructure it runs on. +weight: 10 +author: kagent.dev +--- + +This page is the configuration reference for the `Harness` resource: every field it takes, the four runtimes it can select, and what each runtime supports. For what a Harness *is* and why it is separate from an AgentTemplate, see [Core concepts]({{< link path="about/core-concepts#harness" >}}). + +## Configure a Harness + +A complete Harness. Only `workload`, `substrate`, and one runtime block are required. + +```yaml +kubectl apply -f - <@sha256: + env: + - name: LOG_LEVEL + value: info + - name: MY_API_KEY + credentialRef: + name: my-secret + key: api-key + substrate: + workerPoolRef: + name: kagent-default + snapshotPolicy: + location: gs:///kagent/ + allowedAgentTemplates: + selector: + matchLabels: + kagent.dev/harness: my-harness +EOF +``` + +| Field | Required | Description | +| ----- | -------- | ----------- | +| One of `kagent`, `codex`, `claude`, `byo` | Yes | The runtime that executes the agent. Naming none, or more than one, is rejected. See [Choose a runtime](#choose-a-runtime). | +| `workload.image` | Yes | The runtime image, pinned by `sha256` digest. A tag alone is rejected, because a revision has to be reproducible. | +| `workload.command` | For `byo` | Overrides the image entrypoint, up to 32 entries. Required for the `byo` runtime, optional otherwise. | +| `workload.args` | No | Overrides the image arguments, up to 64 entries. | +| `env` | No | Environment variables for the runtime, up to 100. Each entry sets either a literal `value` or a `credentialRef` naming a key in a same-namespace Secret, never both. | +| `substrate.workerPoolRef.name` | Yes | The {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} that this Harness's Actors are scheduled onto. An operator has to provision one before any agent can run. | +| `substrate.snapshotPolicy.location` | Yes | The object storage location for Actor {{< gloss "Snapshot" >}}snapshots{{< /gloss >}}. | +| `allowedAgentTemplates.selector` | No | A label selector naming which AgentTemplates this Harness admits. Omitting it admits none, which makes the Harness unusable. | + +Admission is a one-way match. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} has no field naming a Harness, so whoever controls a Harness's selector decides what it accepts. + +For every field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#harness" >}}). + +## Choose a runtime + +| Runtime | What it runs | Use it when | +| ------- | ------------ | ----------- | +| `kagent` | kagent's own Go and Python engines. | You want the full feature set: every model provider, agent-as-tool composition, skills, plugins, and long-term memory. | +| `codex` | The Codex coding agent. | You want Codex to do the work, and your model is OpenAI or an OpenAI-compatible Bedrock deployment. | +| `claude` | The Claude coding agent. | You want Claude to do the work, with Anthropic, Bedrock, or Anthropic on Vertex AI as the model. | +| `byo` | Any container image of your own that implements kagent's A2A contract. | You have an agent framework kagent does not adapt, and you would rather bring the image than the integration. See [Bring your own agent]({{< link path="agents/bring-your-own-agent" >}}). | + +The `kagent` and `byo` runtimes compile through the same path, so they accept the same model providers and the same AgentTemplate features. The `codex` and `claude` runtimes are purpose-built adapters, and each accepts a narrower slice. + +### Runtime-specific settings + +`spec.kagent` is the only runtime block that takes settings of its own. The rest are empty. + +```yaml +spec: + kagent: + memory: + modelConfigRef: + name: embedding-model-config + ttlDays: 30 +``` + +| Field | Description | +| ----- | ----------- | +| `memory.modelConfigRef.name` | The ModelConfig supplying the embedding model, in the Harness's namespace. Required when `memory` is set. | +| `memory.ttlDays` | How many days a stored memory entry stays valid. Minimum 1. Omit it to keep entries indefinitely. | + +Setting `memory` gives every agent on this Harness memory that persists across conversations. For how agents store and retrieve it, see [Agent memory]({{< link path="agents/agent-memory" >}}). + +## Model provider support + +The runtime that a Harness selects decides which ModelConfig its AgentTemplates can use. + +| Provider | `kagent` | `byo` | `codex` | `claude` | +| -------- | :------: | :---: | :-----: | :------: | +| `OpenAI` | Yes | Yes | Yes | No | +| `Anthropic` | Yes | Yes | No | Yes | +| `Bedrock` | Yes | Yes | Yes | Yes | +| `AnthropicVertexAI` | No | No | No | Yes | +| `GeminiVertexAI` | No | No | No | No | +| `AzureOpenAI` | Yes | Yes | No | No | +| `Gemini` | Yes | Yes | No | No | +| `Ollama` | Yes | Yes | No | No | +| `SAPAICore` | Yes | Yes | No | No | +| `Foundry` | Yes | Yes | No | No | + +Some combinations that the table marks `Yes` still carry restrictions. + +| Combination | Restriction | +| ----------- | ----------- | +| `codex` with `OpenAI` | Requires `openAI.apiFormat: responses`, and accepts no other `openAI` settings beyond `baseUrl`. | +| `codex` with `Bedrock` | Accepts only OpenAI `gpt-*` model IDs, and no `bedrock` settings beyond `region`. | +| `claude` with `Anthropic` | Accepts no `anthropic` settings beyond `baseUrl`. | +| `claude` with `Bedrock` | Accepts no `bedrock` settings beyond `region`. | +| `claude` with `AnthropicVertexAI` | Accepts only `projectID` and `location`. The Secret has to hold a `service_account` key whose `project_id` matches and whose `token_uri` is `https://oauth2.googleapis.com`. | + +> [!IMPORTANT] +> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string, which is what rules out both Vertex AI providers there. For that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). + +## Tool and skill support + +The coding-agent runtimes also constrain what an AgentTemplate can ask for. + +| Constraint | Applies to | +| ---------- | ---------- | +| A `Shared` agent-tool binding cannot itself carry tools, skills, plugins, or nested agents, and has to use the same provider and credentials as the agent that binds it. | `codex`, `claude` | +| An MCP server is bound whole. Claude does not support partial tool selection, so the agent sees every tool the server offers rather than only the ones a binding names. The compiler warns rather than failing. | `claude` | +| A `RemoteMCPServer` has to use the `STREAMABLE_HTTP` protocol. `SSE` is rejected. | `codex` | + +The `kagent` and `byo` runtimes take the full set. See [About tools]({{< link path="skills-and-mcp/about-tools" >}}). + +## Check that a Harness is ready + +```bash +kubectl get harness -n kagent +``` + +Example output: +```console +NAME READY AGE +my-first-harness True 4m +``` + +A Harness that is not `Ready` has a dependency that does not resolve, most often a WorkerPool that does not exist yet. Read its conditions for the specific reason. + +```bash +kubectl describe harness my-first-harness -n kagent +``` + +`Ready` covers the Harness's own dependencies, not whether any given agent will run on it. Whether an AgentTemplate compiles against this Harness is reported on the AgentTemplate, under `status.harnesses`. A pair that asks for something the runtime cannot do reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and a message naming the specific setting. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and an AgentTemplate, then talk to the AgentInstance they produce." >}} + {{< card link=`{{< link path="agents/agent-memory" >}}` title="Agent memory" subtitle="Give agents on this Harness memory that outlasts a single conversation." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md index be54a2f2..23652a3a 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md @@ -24,9 +24,21 @@ Credentials come from a Kubernetes Secret in the same namespace as the ModelConf **Credential files** kagent passes model credentials to an agent as environment variables. A ModelConfig that instead requires a credential **file** mounted into the agent does not compile. The AgentTemplate reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`. kagent compiles no revision from that AgentTemplate, so no agent runs from it, and any AgentInstance that already exists keeps running the last revision that compiled. Three configurations encounter this today. -- **The Vertex AI providers.** `GeminiVertexAI` and `AnthropicVertexAI` mount the Google credentials file that `apiKeySecret` names. Leaving `apiKeySecret` unset compiles, but a Substrate Actor does not inherit cloud workload identity, so the agent still has no credentials to send. Both providers are unavailable in practice. For the alternatives, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). +- **The Vertex AI providers, on the `kagent` and `byo` runtimes.** `GeminiVertexAI` and `AnthropicVertexAI` mount the Google credentials file that `apiKeySecret` names. Leaving `apiKeySecret` unset compiles, but a Substrate Actor does not inherit cloud workload identity, so the agent still has no credentials to send. The `claude` runtime is the exception: it passes the same credentials as an environment variable, so `AnthropicVertexAI` works there. For more information, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). - **A private certificate authority (CA), on any provider.** Setting `tls.caCertSecretRef` mounts the CA bundle as a file. Every provider accepts the `tls` block, so this affects all of them, not only the Vertex AI providers. You cannot reach a provider endpoint that presents a certificate from a private CA, unless you set `tls.disableVerify: true`, which skips certificate verification entirely and belongs only in a test environment. -- **OpenAI token exchange.** The `openAI.tokenExchange` block acquires a bearer token by reading a mounted service account file, so a ModelConfig that sets it never compiles. An OpenAI-compatible endpoint has to accept a static API key instead. See [OpenAI]({{< link path="setup/model-providers/openai" >}}). +- **OpenAI token exchange.** The `openAI.tokenExchange` block acquires a bearer token by reading a mounted service account file, so a ModelConfig that sets it never compiles. An OpenAI-compatible endpoint has to accept a static API key instead. For more information, see [OpenAI]({{< link path="setup/model-providers/openai" >}}). + +## The Harness runtime decides which providers are available + +A ModelConfig is only half of the decision. The runtime that a {{< gloss "Harness" >}}Harness{{< /gloss >}} selects also constrains which providers an agent can use, because each runtime integrates a different set. + +- The **`kagent`** runtime supports every provider, and the **`byo`** runtime supports the same set, because both compile through the same path. +- The **`codex`** runtime supports only `OpenAI` and `Bedrock`. +- The **`claude`** runtime supports only `Anthropic`, `Bedrock`, and `AnthropicVertexAI`. + +Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`, and each narrows the provider settings it takes. A pair that asks for a provider its runtime does not integrate fails to compile, and the AgentTemplate reports the `Compatible` condition as `False` with the reason `UnsupportedConfiguration`. + +For the full matrix, including the per-combination restrictions, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). ## Use a ModelConfig diff --git a/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md index dc3b4f34..ade87850 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md @@ -9,6 +9,9 @@ Amazon Bedrock serves models from several families behind one AWS API. kagent re Prefer the native provider. Use the OpenAI-compatible path when you need the OpenAI request format, or an inference profile that only that endpoint exposes. +> [!NOTE] +> Bedrock is the only provider that every runtime supports. A `codex` Harness accepts only OpenAI `gpt-*` model IDs, and both `codex` and `claude` accept no `bedrock` settings beyond `region`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). + > [!IMPORTANT] > Both paths authenticate with credentials from a Kubernetes Secret. Attaching an AWS IAM role to the agent, such as with [EKS IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html), is not currently supported: an agent runs as a Substrate Actor rather than as a pod that kagent controls, so there is no per-agent ServiceAccount to attach a role to. diff --git a/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md b/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md index 2ec6dd7a..3958d33c 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md @@ -5,7 +5,10 @@ weight: 20 author: kagent.dev --- -The `Anthropic` provider calls the Anthropic API directly. To reach Claude models through Google Cloud instead, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). +The `Anthropic` provider calls the Anthropic API directly. + +> [!NOTE] +> This provider works on the `kagent`, `byo`, and `claude` runtimes, but not on `codex`. A `claude` Harness accepts no `anthropic` settings beyond `baseUrl`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). To reach Claude models through Google Cloud instead, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). ## Create the ModelConfig diff --git a/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md b/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md index 04154b3a..aeac47b6 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md @@ -1,30 +1,82 @@ --- title: Google Vertex AI -description: Understand why the Google Vertex AI providers do not currently run on a kagent Harness. +description: Configure kagent to use Claude models through Google Cloud Vertex AI on a Claude harness. weight: 20 author: kagent.dev --- -The `GeminiVertexAI` and `AnthropicVertexAI` providers reach Gemini and Claude models through Google Cloud Vertex AI. Both providers exist in the {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} schema, but neither currently runs on a kagent {{< gloss "Harness" >}}Harness{{< /gloss >}}. +Google Cloud Vertex AI serves both Gemini and Claude models, and the {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} schema has a provider for each: `GeminiVertexAI` and `AnthropicVertexAI`. Which of them works depends on the runtime that your {{< gloss "Harness" >}}Harness{{< /gloss >}} selects. -> [!WARNING] -> **Vertex AI is not currently supported.** Vertex AI authenticates with a Google Application Default Credentials file rather than with an API key. When `apiKeySecret` is set, kagent mounts that credentials file into the agent, and mounting a file is not something an agent running on {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} can do. The AgentTemplate reports the `Compatible` condition as `False` with the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`, and no runtime {{< gloss "Revision" >}}revision{{< /gloss >}} is compiled. +| Provider | Harness runtime | Supported | +| -------- | --------------- | --------- | +| `AnthropicVertexAI` | `claude` | Yes | +| `AnthropicVertexAI` | `kagent` or `byo` | No | +| `GeminiVertexAI` | any | No | -## Why the configuration fails +For the full provider matrix across all four runtimes, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). -kagent passes model credentials to an agent as environment variables. Every provider whose credential is a string, such as an API key, works on a Harness. Vertex AI is different: the Google credentials are a JSON file, so kagent sets `GOOGLE_APPLICATION_CREDENTIALS` to a path and mounts the Secret at that path. An agent runs as a Substrate Actor rather than as a pod that kagent controls, so there is nowhere to mount it. +The difference is how each runtime receives the Google credentials. Vertex AI authenticates with a service account key, which is a JSON document rather than a single string. The `claude` runtime takes that document as an environment variable. The `kagent` runtime instead writes it to a file and mounts it, and an agent running on {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} cannot mount files. -Omitting `apiKeySecret` avoids the mount, because kagent then expects Google credentials to be already present in the agent's environment. An Actor's sandbox does not inherit cloud workload identity from the node, so that path does not authenticate either. +## Claude models on a Claude harness -For the full explanation of which configurations a Harness can run, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). +1. Create a [Google service account key](https://cloud.google.com/iam/docs/keys-create-delete) with access to Vertex AI, and store the JSON in a Kubernetes Secret. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`. + ```bash + kubectl create secret generic kagent-vertex -n kagent \ + --from-file=credentials.json=.json + ``` -## What to use instead +2. Create a `ModelConfig` that uses the `AnthropicVertexAI` provider. + ```yaml + kubectl apply -f - <}}) provider, which reaches the same model family through the Google AI Studio API with an API key. | -| Claude models | Use the [Anthropic]({{< link path="setup/model-providers/anthropic" >}}) provider, or reach Claude through [Amazon Bedrock]({{< link path="setup/model-providers/amazon-bedrock" >}}). | -| Vertex AI specifically | Route Vertex AI through a gateway that presents an OpenAI-compatible API and authenticates to Google itself, then point an [OpenAI-compatible endpoint]({{< link path="setup/model-providers/byo-openai" >}}) ModelConfig at the gateway. | + | Field | Description | + | ----- | ----------- | + | `apiKeySecret` | The name of the Kubernetes Secret that holds the service account key. | + | `apiKeySecretKey` | The key within that Secret that holds the JSON document. | + | `model` | The Vertex AI model ID, such as `claude-sonnet-4@20250514`. | + | `provider` | The provider to use, `AnthropicVertexAI`. | + | `anthropicVertexAI.projectID` | Your Google Cloud project ID. This field is required, and has to match the `project_id` inside the service account key. | + | `anthropicVertexAI.location` | The Vertex AI region, such as `us-east5`. This field is required. | + + The `claude` runtime accepts no other settings in the `anthropicVertexAI` block yet, and rejects a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. For every field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#anthropicvertexaiconfig" >}}). + +3. Pair the ModelConfig with a Harness that selects the `claude` runtime. + ```yaml + spec: + claude: {} + workload: + image: @sha256: + ``` + +### What kagent checks before it compiles + +kagent validates the service account key at compile time rather than failing at run time, so a malformed credential surfaces on the AgentTemplate's `Compatible` condition. + +- The Secret key has to hold valid JSON. +- The document has to be a `service_account` key. Other credential types are not accepted yet. +- Its `project_id` has to match `anthropicVertexAI.projectID`. +- Its `token_uri` has to be `https://oauth2.googleapis.com`. + +## Gemini models on Vertex AI + +The `GeminiVertexAI` provider does not compile on any runtime. On a `kagent` Harness it fails with `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`, and the `claude` runtime does not accept the provider at all. + +To reach Gemini models, use the [Gemini]({{< link path="setup/model-providers/gemini" >}}) provider, which serves the same model family through the Google AI Studio API and authenticates with an ordinary API key. ## Next steps diff --git a/docs-site/content/kagent/1.x/setup/model-providers/openai.md b/docs-site/content/kagent/1.x/setup/model-providers/openai.md index e2b0ba2a..93c725c4 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/openai.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/openai.md @@ -5,7 +5,10 @@ weight: 10 author: kagent.dev --- -The `OpenAI` provider calls the OpenAI API directly. It also backs every OpenAI-compatible endpoint, so several other providers in this section set `provider: OpenAI` and point `openAI.baseUrl` somewhere else. +The `OpenAI` provider calls the OpenAI API directly. + +> [!NOTE] +> This provider works on the `kagent`, `byo`, and `codex` runtimes, but not on `claude`. A `codex` Harness additionally requires `openAI.apiFormat: responses` and accepts no other `openAI` settings beyond `baseUrl`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). It also backs every OpenAI-compatible endpoint, so several other providers in this section set `provider: OpenAI` and point `openAI.baseUrl` somewhere else. ## Create the ModelConfig @@ -65,7 +68,7 @@ The `openAI` block takes the following optional settings. For every field, inclu | `timeout` | How long to wait on a request to the provider. | > [!WARNING] -> The `openAI` block also accepts `tokenExchange`, which acquires a bearer token from a mounted service account file. That configuration mounts a credential file into the agent, so it does not compile on a Harness. See [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}) for the full list of configurations that this affects. +> The `openAI` block also accepts `tokenExchange`, which acquires a bearer token from a mounted service account file. That configuration mounts a credential file into the agent, so it does not compile on a Harness. For the full list of configurations that this affects, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). ## Use the ModelConfig From e19a2f23b4e923d7033ab3a25a5082e61709216f Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 2 Sep 2026 15:31:59 -0500 Subject: [PATCH 39/70] Phase 3 - agent pages Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/_index.md | 2 +- .../kagent/1.x/agents/agent-harness.md | 71 +++--- .../content/kagent/1.x/agents/agent-memory.md | 215 ++++++++++++++++++ .../kagent/1.x/agents/system-prompts.md | 142 ++++++++++++ .../setup/model-providers/azure-ai-foundry.md | 22 ++ 5 files changed, 411 insertions(+), 41 deletions(-) create mode 100644 docs-site/content/kagent/1.x/agents/agent-memory.md create mode 100644 docs-site/content/kagent/1.x/agents/system-prompts.md diff --git a/docs-site/content/kagent/1.x/_index.md b/docs-site/content/kagent/1.x/_index.md index d7e05c80..1f780c8f 100644 --- a/docs-site/content/kagent/1.x/_index.md +++ b/docs-site/content/kagent/1.x/_index.md @@ -8,4 +8,4 @@ author: kagent.dev kagent 1.0 moves the runtime from Kubernetes Deployments to [Agent Substrate](https://github.com/agent-substrate/substrate), introducing Harness, AgentTemplate, and AgentInstance as the new API surface. -This section is under active development ahead of the 1.0 release. Pages here may be incomplete, and content may change without notice. See the [0.x docs]({{< relref "/kagent/0.x" >}}) for the current stable release. +This section is under active development ahead of the 1.0 release. Pages here may be incomplete, and content may change without notice. For the current stable release, see the [0.x docs]({{< relref "/kagent/0.x" >}}). diff --git a/docs-site/content/kagent/1.x/agents/agent-harness.md b/docs-site/content/kagent/1.x/agents/agent-harness.md index 4f3f335e..1b9e4c5e 100644 --- a/docs-site/content/kagent/1.x/agents/agent-harness.md +++ b/docs-site/content/kagent/1.x/agents/agent-harness.md @@ -5,11 +5,11 @@ weight: 10 author: kagent.dev --- -This page is the configuration reference for the `Harness` resource: every field it takes, the four runtimes it can select, and what each runtime supports. For what a Harness *is* and why it is separate from an AgentTemplate, see [Core concepts]({{< link path="about/core-concepts#harness" >}}). +Review configuration guidelines and reference for the `Harness` resource: every field it takes, the four runtimes it can select, and what each runtime supports. To understand a Harness and why it is separate from an AgentTemplate, see the [core concepts]({{< link path="about/core-concepts#harness" >}}). ## Configure a Harness -A complete Harness. Only `workload`, `substrate`, and one runtime block are required. +The following configuration is for a complete Harness resource. Only `workload`, `substrate`, and one runtime block are required. ```yaml kubectl apply -f - <}} For more information, see the [API reference]({{< link path="reference/api-ref#agentharness" >}}). + | Field | Required | Description | | ----- | -------- | ----------- | -| One of `kagent`, `codex`, `claude`, `byo` | Yes | The runtime that executes the agent. Naming none, or more than one, is rejected. See [Choose a runtime](#choose-a-runtime). | +| One of `kagent`, `codex`, `claude`, `byo` | Yes | The runtime that executes the agent. Naming none, or more than one, is rejected. For the available runtimes, see [Choose a runtime](#choose-a-runtime). | | `workload.image` | Yes | The runtime image, pinned by `sha256` digest. A tag alone is rejected, because a revision has to be reproducible. | | `workload.command` | For `byo` | Overrides the image entrypoint, up to 32 entries. Required for the `byo` runtime, optional otherwise. | | `workload.args` | No | Overrides the image arguments, up to 64 entries. | | `env` | No | Environment variables for the runtime, up to 100. Each entry sets either a literal `value` or a `credentialRef` naming a key in a same-namespace Secret, never both. | | `substrate.workerPoolRef.name` | Yes | The {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} that this Harness's Actors are scheduled onto. An operator has to provision one before any agent can run. | | `substrate.snapshotPolicy.location` | Yes | The object storage location for Actor {{< gloss "Snapshot" >}}snapshots{{< /gloss >}}. | -| `allowedAgentTemplates.selector` | No | A label selector naming which AgentTemplates this Harness admits. Omitting it admits none, which makes the Harness unusable. | - -Admission is a one-way match. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} has no field naming a Harness, so whoever controls a Harness's selector decides what it accepts. - -For every field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#harness" >}}). +| `allowedAgentTemplates.selector` | No | A label selector naming which AgentTemplates this Harness admits. Omitting it admits none, which makes the Harness unusable. Admission is a one-way match. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} has no field naming a Harness, so whoever controls a Harness's selector decides what it accepts. | ## Choose a runtime -| Runtime | What it runs | Use it when | +A Harness names exactly one of the following four runtimes, and that choice decides what executes an agent and how much of kagent's feature set the agent can use. + +| Runtime | What it runs | When to use it | | ------- | ------------ | ----------- | -| `kagent` | kagent's own Go and Python engines. | You want the full feature set: every model provider, agent-as-tool composition, skills, plugins, and long-term memory. | -| `codex` | The Codex coding agent. | You want Codex to do the work, and your model is OpenAI or an OpenAI-compatible Bedrock deployment. | -| `claude` | The Claude coding agent. | You want Claude to do the work, with Anthropic, Bedrock, or Anthropic on Vertex AI as the model. | -| `byo` | Any container image of your own that implements kagent's A2A contract. | You have an agent framework kagent does not adapt, and you would rather bring the image than the integration. See [Bring your own agent]({{< link path="agents/bring-your-own-agent" >}}). | +| `kagent` | kagent's own Go and Python engines | You want the full feature set: every model provider, agent-as-tool composition, skills, plugins, and long-term memory. | +| `codex` | The Codex coding agent | You want Codex to do the work, and your model is OpenAI or an OpenAI-compatible Bedrock deployment. | +| `claude` | The Claude coding agent | You want Claude to do the work, with Anthropic, Bedrock, or Anthropic on Vertex AI as the model. | +| `byo` | Any container image of your own that implements kagent's A2A contract | You have an agent framework kagent does not adapt, and you would rather bring the image than the integration. For more information, see [Bring your own agent]({{< link path="agents/bring-your-own-agent" >}}). | The `kagent` and `byo` runtimes compile through the same path, so they accept the same model providers and the same AgentTemplate features. The `codex` and `claude` runtimes are purpose-built adapters, and each accepts a narrower slice. @@ -84,7 +84,7 @@ spec: | Field | Description | | ----- | ----------- | | `memory.modelConfigRef.name` | The ModelConfig supplying the embedding model, in the Harness's namespace. Required when `memory` is set. | -| `memory.ttlDays` | How many days a stored memory entry stays valid. Minimum 1. Omit it to keep entries indefinitely. | +| `memory.ttlDays` | How many days a stored memory entry stays valid. Minimum 1. When omitted, the server applies a default of 15 days. | Setting `memory` gives every agent on this Harness memory that persists across conversations. For how agents store and retrieve it, see [Agent memory]({{< link path="agents/agent-memory" >}}). @@ -94,18 +94,18 @@ The runtime that a Harness selects decides which ModelConfig its AgentTemplates | Provider | `kagent` | `byo` | `codex` | `claude` | | -------- | :------: | :---: | :-----: | :------: | -| `OpenAI` | Yes | Yes | Yes | No | -| `Anthropic` | Yes | Yes | No | Yes | -| `Bedrock` | Yes | Yes | Yes | Yes | -| `AnthropicVertexAI` | No | No | No | Yes | -| `GeminiVertexAI` | No | No | No | No | -| `AzureOpenAI` | Yes | Yes | No | No | -| `Gemini` | Yes | Yes | No | No | -| `Ollama` | Yes | Yes | No | No | -| `SAPAICore` | Yes | Yes | No | No | -| `Foundry` | Yes | Yes | No | No | - -Some combinations that the table marks `Yes` still carry restrictions. +| `OpenAI` | ✅ | ✅ | ✅ | ❌ | +| `Anthropic` | ✅ | ✅ | ❌ | ✅ | +| `Bedrock` | ✅ | ✅ | ✅ | ✅ | +| `AnthropicVertexAI` | ❌ | ❌ | ❌ | ✅ | +| `GeminiVertexAI` | ❌ | ❌ | ❌ | ❌ | +| `AzureOpenAI` | ✅ | ✅ | ❌ | ❌ | +| `Gemini` | ✅ | ✅ | ❌ | ❌ | +| `Ollama` | ✅ | ✅ | ❌ | ❌ | +| `SAPAICore` | ✅ | ✅ | ❌ | ❌ | +| `Foundry` | ✅ | ✅ | ❌ | ❌ | + +Some supported combinations still carry restrictions. | Combination | Restriction | | ----------- | ----------- | @@ -116,7 +116,7 @@ Some combinations that the table marks `Yes` still carry restrictions. | `claude` with `AnthropicVertexAI` | Accepts only `projectID` and `location`. The Secret has to hold a `service_account` key whose `project_id` matches and whose `token_uri` is `https://oauth2.googleapis.com`. | > [!IMPORTANT] -> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string, which is what rules out both Vertex AI providers there. For that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). +> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string, which is what rules out both Vertex AI providers there. For more information about that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). ## Tool and skill support @@ -128,27 +128,18 @@ The coding-agent runtimes also constrain what an AgentTemplate can ask for. | An MCP server is bound whole. Claude does not support partial tool selection, so the agent sees every tool the server offers rather than only the ones a binding names. The compiler warns rather than failing. | `claude` | | A `RemoteMCPServer` has to use the `STREAMABLE_HTTP` protocol. `SSE` is rejected. | `codex` | -The `kagent` and `byo` runtimes take the full set. See [About tools]({{< link path="skills-and-mcp/about-tools" >}}). +The `kagent` and `byo` runtimes take the full set. For more information about what an AgentTemplate can bind, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). ## Check that a Harness is ready +The `READY` column reports whether a Harness's dependencies resolved. ```bash kubectl get harness -n kagent ``` -Example output: -```console -NAME READY AGE -my-first-harness True 4m -``` - -A Harness that is not `Ready` has a dependency that does not resolve, most often a WorkerPool that does not exist yet. Read its conditions for the specific reason. - -```bash -kubectl describe harness my-first-harness -n kagent -``` +A Harness that is not `Ready` most often names a WorkerPool that does not exist yet. For the specific reason, read its conditions with `kubectl describe harness -n kagent`. -`Ready` covers the Harness's own dependencies, not whether any given agent will run on it. Whether an AgentTemplate compiles against this Harness is reported on the AgentTemplate, under `status.harnesses`. A pair that asks for something the runtime cannot do reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and a message naming the specific setting. +`Ready` covers the Harness's own dependencies, not whether a given agent runs on it. Whether an AgentTemplate compiles against this Harness is reported on the AgentTemplate, under `status.harnesses`. For that check and the conditions it reports, see [Your first agent]({{< link path="get-started/your-first-agent" >}}). ## Next steps diff --git a/docs-site/content/kagent/1.x/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md new file mode 100644 index 00000000..b662fa30 --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -0,0 +1,215 @@ +--- +title: Agent memory +description: Give agents long-term memory that persists across conversations, backed by vector similarity search. +weight: 40 +author: kagent.dev +--- + +An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} remembers its own conversation, because it holds the {{< gloss "Transcript" >}}transcript{{< /gloss >}}. Long-term memory is different: it carries what an agent learned in one conversation into later ones. kagent stores those memories as vectors and retrieves them by similarity to whatever the user just said. Each agent on a {{< gloss "Harness" >}}Harness{{< /gloss >}} keeps its own memories, scoped to the user who created them. + +Memory is configured on the Harness rather than on an AgentTemplate, so it applies to every agent that the Harness runs. + +## How an agent uses memory + +Enabling memory adds three tools to every agent on the Harness, and appends a short instruction to its system prompt telling it that the tools exist. + +| Tool | What it does | +| ---- | ------------ | +| `save_memory` | Stores a specific fact, preference, or finding for later. | +| `load_memory` | Searches stored memories by query when the agent needs context it does not have. | +| `prefetch_memory` | Retrieves memories relevant to the current message before the agent answers. | + +Retrieval works by similarity rather than by keyword. kagent encodes the query as a vector, compares it against stored memories by cosine similarity, and puts the closest matches into the agent's context. A search returns at most five memories, and only those that score above 0.3. The agent also saves memories from a finished session on its own, so a user does not have to ask it to remember anything. + +Memories are scoped to the agent and to the user who created them, and carry the time that kagent wrote them. One agent cannot read another agent's memories, even on the same Harness. + +## Before you begin + +> [!IMPORTANT] +> Memory requires an **external** PostgreSQL database with the [pgvector](https://github.com/pgvector/pgvector) extension installed. kagent's bundled database uses the stock `postgres` image, which does not ship pgvector, so it cannot store memories. Point kagent at your own database first. + +1. Store the connection string for your database in a Kubernetes Secret, in the same namespace as the kagent controller. The key that you choose becomes the file name that kagent reads, so `db-url` produces the path `/var/secrets/db-url`. + ```bash + kubectl create secret generic my-postgres-url-secret -n kagent \ + --from-literal=db-url='postgres://:@:5432/?sslmode=require' + ``` + +2. Save the following values, which point kagent at your database, mount the Secret into the controller, and run the migration that creates the pgvector extension. + ```yaml + cat > kagent-memory-values.yaml <}} \ + --namespace kagent --timeout 10m --reuse-values \ + -f kagent-memory-values.yaml + ``` + +4. Wait for the controller to roll out with the new configuration. + ```bash + kubectl rollout status deployment/kagent-controller -n kagent --timeout=300s + ``` + +## Choose an embedding model + +Any provider that the `kagent` runtime supports can serve the embedding model, so the choice typically depends on whichever provider already holds your credentials. The embedding ModelConfig is resolved in the same way that a chat ModelConfig is, which means that the same [provider limitations]({{< link path="setup/model-providers/about-model-providers" >}}) apply to it. + +kagent stores every memory as a **768-dimensional** vector. Models that produce wider vectors are truncated and re-normalized to that width, so no dimension setting is needed and models of different widths can coexist. + +An Amazon Bedrock embedding model, for example, looks like the following: + +```yaml +spec: + provider: Bedrock + model: amazon.titan-embed-text-v2:0 + bedrock: + region: us-east-1 +``` + +## Enable memory + +Add memory to a Harness that already exists. The examples in these steps use `my-first-harness` in the `kagent` namespace, which you create in [Your first agent]({{< link path="get-started/your-first-agent" >}}). + +1. Create a `ModelConfig` for the embedding model in the same namespace as your Harness. The model is an embedding model rather than a chat model. + ```yaml + kubectl apply -f - <}} To review other available Harness fields, see [Agent harness]({{< link path="agents/agent-harness" >}}). + | Field | Description | + | ----- | ----------- | + | `memory.modelConfigRef.name` | The ModelConfig supplying the embedding model, in the Harness's namespace. Required when `memory` is set. | + | `memory.ttlDays` | How many days a stored memory stays valid. Minimum 1. When omitted, the server applies a default of 15 days. | + +3. Create a new {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} from the Harness and an AgentTemplate that it admits. Editing the Harness compiles a new {{< gloss "Revision" >}}revision{{< /gloss >}}, and an existing AgentInstance keeps running the revision it was created from, so an agent that was already running does not gain memory until you recreate it. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template my-first-agent + ``` + + The command returns output only after the AgentInstance reaches the `READY` state. Example output: + ```console + +--------------------------------------+----------------+------------------+-------+----------------------+ + | ID | AGENT TEMPLATE | HARNESS | STATE | CREATED | + +--------------------------------------+----------------+------------------+-------+----------------------+ + | 0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10 | my-first-agent | my-first-harness | READY | 2026-08-31T15:02:10Z | + +--------------------------------------+----------------+------------------+-------+----------------------+ + ``` + +> [!NOTE] +> Only the `kagent` runtime supports memory. `spec.kagent` is the one runtime block that takes settings, so a Harness selecting `codex`, `claude`, or `byo` has nowhere to configure it. + +## Verify that memory works + +Memory is working when a fact from one conversation reaches a later one. An AgentInstance holds the transcript of its own conversation, so the check needs a second AgentInstance that never saw the first. + +1. Save the ID of the AgentInstance that you created. The command selects the most recently created AgentInstance for the AgentTemplate. + ```bash + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "my-first-agent")] | sort_by(.createdAt) | last | .id') + ``` + +2. Tell the agent a fact that is worth remembering. + ```bash + kagent invoke --agent-instance $INSTANCE_ID \ + --task "Remember that I deploy to the staging cluster on Fridays." + ``` + +3. Create a second AgentInstance from the same Harness and AgentTemplate pair. The new AgentInstance starts with an empty transcript. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template my-first-agent + ``` + +4. Save the ID of the new AgentInstance. + ```bash + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "my-first-agent")] | sort_by(.createdAt) | last | .id') + ``` + +5. Ask the new AgentInstance about the fact. An answer that includes the fact can only have come from memory, because this AgentInstance never saw the earlier conversation. + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "When do I deploy to staging?" + ``` + + Example output: + ```console + You deploy to the staging cluster on Fridays. + ``` + +### What kagent stored + +Each memory is one row in the `memory` table of the database that you connected. Query the table to read what an agent saved. + +```sql +SELECT agent_name, user_id, content, created_at, expires_at +FROM memory ORDER BY created_at DESC LIMIT 10; +``` + +| Column | What it holds | +| ------ | ------------- | +| `content` | The text that the agent saved, which is what retrieval returns to a later conversation. | +| `agent_name` | The agent that owns the memory, written as `__NS__` with every hyphen replaced by an underscore. | +| `user_id` | The user that the memory belongs to. | +| `embedding` | The 768-dimensional vector that similarity search compares a query against. | +| `created_at` and `expires_at` | When kagent wrote the memory, and `ttlDays` after that. | +| `access_count` | How many times retrieval has returned this memory. | + +A memory that the agent saves at the end of a session is summarized first, so one conversation usually produces several short rows rather than one long one. + +## Memory lifetime + +A memory expires `ttlDays` after it is written, defaulting to 15 days. Expiry is per memory rather than per session, so an old preference ages out while a recent one survives. + +Changing `ttlDays` on the Harness applies to memories written by AgentInstances created after the change, because the value is compiled into the revision. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Configure the rest of the Harness that memory is enabled on." >}} + {{< card link=`{{< link path="setup/model-providers/about-model-providers" >}}` title="About model providers" subtitle="Understand how a ModelConfig reaches a running agent." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/agents/system-prompts.md b/docs-site/content/kagent/1.x/agents/system-prompts.md new file mode 100644 index 00000000..bf54bf5f --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/system-prompts.md @@ -0,0 +1,142 @@ +--- +title: System prompts +description: Set an agent's system prompt inline or from a ConfigMap, and template it with values that kagent resolves at compile time. +weight: 30 +author: kagent.dev +--- + +An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s system prompt defines the agent's role and how it should behave. kagent resolves the prompt when it compiles a {{< gloss "Revision" >}}revision{{< /gloss >}}, so the text an agent runs with is fixed for the life of an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}}: editing the prompt affects instances created after the edit compiles, not ones already running. + +## Write an effective prompt + +A prompt that works tends to carry four things, in roughly this order. + +- **Role.** What the agent is, in a sentence. `You are a Kubernetes assistant.` +- **Scope.** What it should and should not take on, which matters more as you give it more tools. +- **Instructions.** How to behave in the cases you care about: when to ask for clarification, what to do when a tool fails, when to refuse. +- **Response format.** What a good answer looks like. Ask for Markdown, or for a summary before detail, if that is what you want. + +Two things are worth stating explicitly, because models otherwise guess: what the agent should do when it does not know an answer, and whether it should act or ask first when an action is consequential. For approval gates that the runtime enforces rather than the prompt, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). + +## Set the prompt inline + +```yaml +spec: + systemPrompt: |- + You are a Kubernetes assistant. You help users understand what is running in their cluster. + + # Instructions + - Ask for clarification before running a tool when a request is ambiguous. + - Answer from tool output rather than from memory of how clusters usually look. + - Say so plainly when a question cannot be answered with the tools you have. +``` + +## Store the prompt in a ConfigMap + +Use `systemPromptFrom` to keep the prompt outside the AgentTemplate, which lets several AgentTemplates share one prompt, or lets a prompt change without editing the agent. + +1. Create a ConfigMap holding the prompt. + ```yaml + kubectl apply -f - < [!NOTE] +> A prompt can come only from a ConfigMap. Earlier versions of kagent also accepted a Secret, through a `systemMessageFrom.type` field that v1alpha3 does not have. A system prompt is not a credential, so keep secrets out of it and pass them to the runtime as [Harness environment variables]({{< link path="agents/agent-harness" >}}) instead. + +## Template the prompt + +Set `spec.promptTemplate` to run the prompt through [Go templates](https://pkg.go.dev/text/template) before it reaches the model. Templating applies to whichever prompt you set, inline or from a ConfigMap. + +```yaml +spec: + description: Answers questions about a Kubernetes cluster. + systemPrompt: |- + You are {{ .AgentTemplateName }}. {{ .Description }} + + You have these tools available: {{ .ToolNames }} + + {{ include "shared-prompts/response-format" }} + promptTemplate: + dataSources: + - name: shared-prompts +``` + +### Values available to a template + +| Value | Description | +| ----- | ----------- | +| `.AgentTemplateName` | The AgentTemplate's `metadata.name`. | +| `.AgentTemplateNamespace` | The AgentTemplate's `metadata.namespace`. | +| `.Description` | The AgentTemplate's `spec.description`. | +| `.ToolNames` | The tool names selected from every MCP server the AgentTemplate binds. Agents bound as tools are not included. | + +`.ToolNames` is worth using rather than listing tools by hand, because it cannot drift from the bindings that the AgentTemplate actually declares. + +> [!NOTE] +> A prompt template can reach only these values and the ConfigMaps that `dataSources` names. Templates cannot read arbitrary Kubernetes objects. + +### Include text from a ConfigMap + +The `include` function pulls in one key from a ConfigMap that `dataSources` lists. Its argument is `"/"`, where the source is the ConfigMap's name. + +```yaml +spec: + promptTemplate: + dataSources: + - name: shared-prompts + - name: house-style + alias: style +``` + +| Field | Description | +| ----- | ----------- | +| `dataSources[].name` | A ConfigMap in the AgentTemplate's namespace. Up to 20 entries. | +| `dataSources[].alias` | An alternative identifier to use in `include` paths. The ConfigMap is still looked up by `name`. | + +An alias only changes what you type. With the preceding configuration, `include "house-style/tone"` fails and `include "style/tone"` succeeds. + +Every key in every listed ConfigMap becomes available, so two sources that share a key name collide. kagent rejects that at compile time rather than picking one. + +## Troubleshooting + +Prompt problems surface on the AgentTemplate's `ResolvedRefs` condition, because they are reference failures rather than runtime errors. No revision compiles, so no new AgentInstance can start. + +| Message | Cause | +| ------- | ----- | +| `resolve systemPromptFrom: ConfigMap "x" not found` | The ConfigMap does not exist in the AgentTemplate's namespace. | +| `resolve systemPromptFrom: ConfigMap "x" does not contain key "y"` | The ConfigMap exists but has no such key. | +| `resolve prompt source "x": ConfigMap not found` | A `dataSources` entry names a ConfigMap that does not exist. | +| `duplicate prompt template identifier "x/y"` | Two data sources expose the same `source/key` path. Give one of them an `alias`. | +| `prompt template "x/y" not found, available: [...]` | An `include` path does not match any available key. The error lists every path that is available. | +| `parse system message template: ...` | The template is not valid Go template syntax. | + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Bind the tools that a prompt can refer to." >}} + {{< card link=`{{< link path="agents/agent-memory" >}}` title="Agent memory" subtitle="Let an agent carry what it learned into later conversations." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md index db9bf617..fb10e251 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md @@ -103,6 +103,28 @@ spec: name: foundry-model-config ``` +## Memory embeddings + +A Foundry deployment can also serve the embedding model behind [long-term memory]({{< link path="agents/agent-memory" >}}). Point a second ModelConfig at your embedding deployment, then name it from the Harness's `spec.kagent.memory.modelConfigRef`. + +```yaml +kubectl apply -f - <.cognitiveservices.azure.com/ + deployment: text-embedding-3-small +EOF +``` + ## Troubleshooting | Symptom | Cause | From ff48368e97ebb4fd38614aaa5eb17ea7390ed71f Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 2 Sep 2026 23:17:52 -0500 Subject: [PATCH 40/70] Phase 3 - sys prompts & agent memory Signed-off-by: Rachael Graham --- .../content/kagent/1.x/agents/agent-memory.md | 76 ++++++++++++++----- .../kagent/1.x/agents/system-prompts.md | 73 ++++++++++++------ .../1.x/get-started/your-first-mcp-tool.md | 4 +- .../kagent/1.x/skills-and-mcp/about-tools.md | 4 +- 4 files changed, 113 insertions(+), 44 deletions(-) diff --git a/docs-site/content/kagent/1.x/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md index b662fa30..b3ac4f01 100644 --- a/docs-site/content/kagent/1.x/agents/agent-memory.md +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -59,7 +59,7 @@ Memories are scoped to the agent and to the user who created them, and carry the EOF ``` -3. Upgrade your kagent installation with the file. The `--reuse-values` flag keeps every value that you installed kagent with, such as the Agent Substrate settings, and adds only the values in this file. +3. Upgrade your kagent installation with the values file. The `--reuse-values` flag keeps every value that you installed kagent with, such as the Agent Substrate settings, and adds only the values in this file. ```bash helm upgrade kagent \ oci://ghcr.io/kagent-dev/kagent/helm/kagent \ @@ -142,7 +142,7 @@ Add memory to a Harness that already exists. The examples in these steps use `my ``` > [!NOTE] -> Only the `kagent` runtime supports memory. `spec.kagent` is the one runtime block that takes settings, so a Harness selecting `codex`, `claude`, or `byo` has nowhere to configure it. +> Only the `kagent` runtime supports memory. The `spec.kagent` runtime block is the only runtimes that has settings, so a Harness that selects `codex`, `claude`, or `byo` has settings to configure memory. ## Verify that memory works @@ -183,30 +183,72 @@ Memory is working when a fact from one conversation reaches a later one. An Agen ### What kagent stored -Each memory is one row in the `memory` table of the database that you connected. Query the table to read what an agent saved. +Each memory is one row in the `memory` table, which the vector migration created in your database. A memory that the agent saves at the end of a session is summarized first, so one conversation typically produces several short rows rather than one long one. -```sql -SELECT agent_name, user_id, content, created_at, expires_at -FROM memory ORDER BY created_at DESC LIMIT 10; -``` +1. Connect to the database with the connection string that you stored in the Secret. Any PostgreSQL client works. + ```bash + psql 'postgres://:@:5432/?sslmode=require' + ``` + +2. Read what an agent saved. + ```sql + SELECT agent_name, user_id, content, created_at, expires_at + FROM memory ORDER BY created_at DESC LIMIT 10; + ``` + + Review the following table to understand the `memory` table output. + | Column | What it holds | + | ------ | ------------- | + | `content` | The text that the agent saved, which is what retrieval returns to a later conversation. | + | `agent_name` | The agent that owns the memory, written as `__NS__` with every hyphen replaced by an underscore. | + | `user_id` | The user that the memory belongs to. | + | `embedding` | The 768-dimensional vector that similarity search compares a query against. | + | `created_at` and `expires_at` | When kagent wrote the memory, and `ttlDays` after that. | + | `access_count` | How many times retrieval has returned this memory. | + +## Manage memories + +The SQL query only reads the table. To list or clear memories, call the `MemoryService` that the kagent controller serves over gRPC. + +No CLI command wraps the service yet, so these examples call it with [grpcurl](https://github.com/fullstorydev/grpcurl), and both calls take the `agent_name` exactly as the memory table stores it. + +1. Port-forward the controller's gRPC port, and confirm that your kagent installation sets `controller.grpc.reflection=true`. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + +2. List the memories that an agent stores for one user. + ```bash + grpcurl -plaintext -d '{ + "agent_name": "kagent__NS__my_first_agent", + "user_id": "admin@kagent.dev" + }' localhost:8084 kagent.api.v1alpha1.MemoryService/List + ``` -| Column | What it holds | -| ------ | ------------- | -| `content` | The text that the agent saved, which is what retrieval returns to a later conversation. | -| `agent_name` | The agent that owns the memory, written as `__NS__` with every hyphen replaced by an underscore. | -| `user_id` | The user that the memory belongs to. | -| `embedding` | The 768-dimensional vector that similarity search compares a query against. | -| `created_at` and `expires_at` | When kagent wrote the memory, and `ttlDays` after that. | -| `access_count` | How many times retrieval has returned this memory. | + Each entry returns the `id`, `content`, `access_count`, `created_at`, and `expires_at` fields. Results are ranked by how often retrieval has returned them, so the most-used memories appear first. -A memory that the agent saves at the end of a session is summarized first, so one conversation usually produces several short rows rather than one long one. +3. Delete the memories for an agent and user. + ```bash + grpcurl -plaintext -d '{ + "agent_name": "kagent__NS__my_first_agent", + "user_id": "admin@kagent.dev" + }' localhost:8084 kagent.api.v1alpha1.MemoryService/Delete + ``` + +The memory service also exposes `Search`, `AddSession`, and `AddSessionBatch`. Each method takes a 768-dimensional vector rather than text, because kagent does not embed on the caller's behalf. Call them from a program that already has an embedding model, rather than by hand. ## Memory lifetime -A memory expires `ttlDays` after it is written, defaulting to 15 days. Expiry is per memory rather than per session, so an old preference ages out while a recent one survives. +A memory expires `ttlDays` after it is written, which defaults to 15 days. Expiry is per memory rather than per session, so an old preference ages out while a recent one survives. Changing `ttlDays` on the Harness applies to memories written by AgentInstances created after the change, because the value is compiled into the revision. +## Known limitations + +- **Memories are deleted for an agent and user together.** `Delete` clears everything for that pair, and no call removes a single memory. +- **Memories are not shared between agents.** Each agent has its own store, so one agent cannot read what another learned, even on the same Harness and for the same user. +- **The memory implementation is not pluggable.** kagent builds on the Google Agent Development Kit (ADK) memory implementation, and it cannot be swapped for another memory system. To use an alternative, run it as a Model Context Protocol (MCP) server, [bind it as a tool]({{< link path="skills-and-mcp/about-tools" >}}), and instruct the agent to use that instead of the built-in tools. + ## Next steps {{< cards >}} diff --git a/docs-site/content/kagent/1.x/agents/system-prompts.md b/docs-site/content/kagent/1.x/agents/system-prompts.md index bf54bf5f..edb75112 100644 --- a/docs-site/content/kagent/1.x/agents/system-prompts.md +++ b/docs-site/content/kagent/1.x/agents/system-prompts.md @@ -5,21 +5,23 @@ weight: 30 author: kagent.dev --- -An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s system prompt defines the agent's role and how it should behave. kagent resolves the prompt when it compiles a {{< gloss "Revision" >}}revision{{< /gloss >}}, so the text an agent runs with is fixed for the life of an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}}: editing the prompt affects instances created after the edit compiles, not ones already running. +An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s system prompt defines the agent's role and how it should behave. kagent resolves the prompt when it compiles a {{< gloss "Revision" >}}revision{{< /gloss >}}, so the text that an agent runs with is fixed for the life of an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}}. Editing the prompt affects instances created after the edit compiles, but not ones that are already running. ## Write an effective prompt A prompt that works tends to carry four things, in roughly this order. -- **Role.** What the agent is, in a sentence. `You are a Kubernetes assistant.` -- **Scope.** What it should and should not take on, which matters more as you give it more tools. -- **Instructions.** How to behave in the cases you care about: when to ask for clarification, what to do when a tool fails, when to refuse. -- **Response format.** What a good answer looks like. Ask for Markdown, or for a summary before detail, if that is what you want. +- **Role.** What the agent is, in a sentence, such as `You are a Kubernetes assistant.` +- **Scope.** What the agent should and should not take on, which matters more as you give it more tools. +- **Instructions.** How the agent should behave in the cases that you care about: when to ask for clarification, what to do when a tool fails, and when to refuse. +- **Response format.** What a good answer looks like. For example, ask for Markdown, or for a summary before detail. Two things are worth stating explicitly, because models otherwise guess: what the agent should do when it does not know an answer, and whether it should act or ask first when an action is consequential. For approval gates that the runtime enforces rather than the prompt, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). ## Set the prompt inline +Set `spec.systemPrompt` to keep the prompt in the AgentTemplate itself, so that the prompt and the rest of the agent's configuration change together. Inline suits a prompt that only one AgentTemplate uses. + ```yaml spec: systemPrompt: |- @@ -31,6 +33,8 @@ spec: - Say so plainly when a question cannot be answered with the tools you have. ``` +Write the value as a YAML block scalar, such as the `|-` in the example, so that the blank lines, headings, and lists that structure the prompt reach the model as written. A folded scalar collapses them into a single paragraph. + ## Store the prompt in a ConfigMap Use `systemPromptFrom` to keep the prompt outside the AgentTemplate, which lets several AgentTemplates share one prompt, or lets a prompt change without editing the agent. @@ -62,14 +66,14 @@ Use `systemPromptFrom` to keep the prompt outside the AgentTemplate, which lets | `systemPromptFrom.name` | The ConfigMap holding the prompt, in the AgentTemplate's namespace. | | `systemPromptFrom.key` | The key within that ConfigMap. | -`systemPrompt` and `systemPromptFrom` are mutually exclusive, and an AgentTemplate that sets both is rejected. +`systemPrompt` and `systemPromptFrom` are mutually exclusive, and an AgentTemplate that sets both is rejected. If you omit both fields, the revision compiles with no system prompt at all, and the agent runs on its harness's default behavior. > [!NOTE] > A prompt can come only from a ConfigMap. Earlier versions of kagent also accepted a Secret, through a `systemMessageFrom.type` field that v1alpha3 does not have. A system prompt is not a credential, so keep secrets out of it and pass them to the runtime as [Harness environment variables]({{< link path="agents/agent-harness" >}}) instead. ## Template the prompt -Set `spec.promptTemplate` to run the prompt through [Go templates](https://pkg.go.dev/text/template) before it reaches the model. Templating applies to whichever prompt you set, inline or from a ConfigMap. +Set `spec.promptTemplate` to run the prompt through [Go templates](https://pkg.go.dev/text/template) before it reaches the model. Templating applies to both inline prompts or prompts set in a ConfigMap. ```yaml spec: @@ -85,26 +89,30 @@ spec: - name: shared-prompts ``` -### Values available to a template +The following values are available to a template. | Value | Description | | ----- | ----------- | | `.AgentTemplateName` | The AgentTemplate's `metadata.name`. | | `.AgentTemplateNamespace` | The AgentTemplate's `metadata.namespace`. | | `.Description` | The AgentTemplate's `spec.description`. | -| `.ToolNames` | The tool names selected from every MCP server the AgentTemplate binds. Agents bound as tools are not included. | +| `.ToolNames` | The tool names selected from every MCP server the AgentTemplate binds. Agents bound as tools are not included. Prefer this value over listing tools by hand, because it cannot drift from the bindings that the AgentTemplate declares. | -`.ToolNames` is worth using rather than listing tools by hand, because it cannot drift from the bindings that the AgentTemplate actually declares. +Additionally, the `include` function pulls in one key from a ConfigMap that `dataSources` lists. The argument is formatted `"/"`, where the source is the ConfigMap's name. Every key in every listed ConfigMap becomes available, so two sources that share a key name collide. kagent rejects that at compile time rather than picking one. -> [!NOTE] -> A prompt template can reach only these values and the ConfigMaps that `dataSources` names. Templates cannot read arbitrary Kubernetes objects. - -### Include text from a ConfigMap +| Field | Description | +| ----- | ----------- | +| `dataSources[].name` | A ConfigMap in the AgentTemplate's namespace, up to 20 entries. | +| `dataSources[].alias` | An alternative identifier to use in `include` paths. The ConfigMap is still looked up by `name`. | -The `include` function pulls in one key from a ConfigMap that `dataSources` lists. Its argument is `"/"`, where the source is the ConfigMap's name. +An alias only changes what you type. In this example configuration, `include "house-style/tone"` fails and `include "style/tone"` succeeds. ```yaml spec: + systemPrompt: |- + {{ include "shared-prompts/response-format" }} + + {{ include "style/tone" }} promptTemplate: dataSources: - name: shared-prompts @@ -112,18 +120,37 @@ spec: alias: style ``` -| Field | Description | -| ----- | ----------- | -| `dataSources[].name` | A ConfigMap in the AgentTemplate's namespace. Up to 20 entries. | -| `dataSources[].alias` | An alternative identifier to use in `include` paths. The ConfigMap is still looked up by `name`. | +> [!NOTE] +> A prompt template can reach only the supported values and the ConfigMaps that `dataSources` names. Templates cannot read arbitrary Kubernetes objects. -An alias only changes what you type. With the preceding configuration, `include "house-style/tone"` fails and `include "style/tone"` succeeds. +## Troubleshooting -Every key in every listed ConfigMap becomes available, so two sources that share a key name collide. kagent rejects that at compile time rather than picking one. +Prompt problems surface on the `ResolvedRefs` condition, because they are reference failures rather than runtime errors. No revision compiles, so no new AgentInstance can start. -## Troubleshooting +An AgentTemplate reports one set of conditions for each Harness that admits it, under `status.harnesses`. To check the condition for your Harness, run the following command. + +```bash +kubectl get agenttemplate my-first-agent -n kagent -o json \ + | jq '.status.harnesses[] | {harness, conditions: [.conditions[] | select(.type == "ResolvedRefs")]}' +``` -Prompt problems surface on the AgentTemplate's `ResolvedRefs` condition, because they are reference failures rather than runtime errors. No revision compiles, so no new AgentInstance can start. +In the output, a failure sets the reason to `ReferenceResolutionFailed` and the resolve error is listed in the message. Example output: + +```json +{ + "harness": "my-first-harness", + "conditions": [ + { + "type": "ResolvedRefs", + "status": "False", + "observedGeneration": 2, + "lastTransitionTime": "2026-08-31T15:02:10Z", + "reason": "ReferenceResolutionFailed", + "message": "resolve systemPromptFrom: ConfigMap \"shared-prompts\" does not contain key \"kubernetes-assistant\"" + } + ] +} +``` | Message | Cause | | ------- | ----- | diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md index f7a6e932..b3651a2b 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -15,7 +15,7 @@ A system prompt tells an agent how to behave. Tools tell it what it can do. This ## Bind the tool to your AgentTemplate -kagent ships an MCP server of its own, and installs a `RemoteMCPServer` that points at it, so the built-in server is the shortest path to a working tool. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} takes tools through an `mcp` binding, which names one server and the tools to take from it. Naming the tools is required, because a binding never takes a server's whole catalog. +kagent ships an MCP server of its own, and installs a `RemoteMCPServer` that points at it, so the built-in server is the shortest path to a working tool. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} takes tools through an `mcp` binding, which names one server and, optionally, the tools to take from it. This guide names the tools specifically, so that the agent gets only the two tools it needs rather than the server's whole catalog. kagent records what it discovered on the server's status, so the tool names come from the cluster. This guide binds `k8s_get_resources` and `k8s_get_pod_logs`. For the full catalog that the built-in server serves, see the [tools ecosystem reference]({{< link path="reference/tools-ecosystem" >}}). @@ -72,7 +72,7 @@ kagent records what it discovered on the server's status, so the tool names come | ----- | ----------- | | `mcp.server.kind` | The kind of server resource. `RemoteMCPServer` is the only accepted value. | | `mcp.server.name` | The server's name. A binding resolves in the AgentTemplate's own namespace, so it cannot reach a server in another namespace. | - | `mcp.tools` | The names of the tools to bind, between 1 and 50. An AgentTemplate takes at most 50 bindings in total. | + | `mcp.tools` | Optional. The names of the tools to bind, up to 50. An omitted or empty list exposes every tool on the server. An AgentTemplate takes at most 50 bindings in total. | 3. Confirm that kagent compiled a new {{< gloss "Revision" >}}revision{{< /gloss >}} for the edited AgentTemplate. Every edit produces a new desired revision, and the pair is current when the latest successful revision matches it. ```bash 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 fcf803db..f0eeaecc 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 @@ -14,7 +14,7 @@ Both kinds resolve within the AgentTemplate's own namespace, so a binding cannot ## MCP tools -An `mcp` binding names a server and the tools to take from it. Naming the tools is required. A binding takes between 1 and 50 named tools, never the server's whole catalog. +An `mcp` binding names a server, and optionally the tools to take from it. Listing tools narrows the binding to those tools. Omitting the list, or leaving it empty, exposes every tool that the server offers. ```yaml tools: @@ -31,7 +31,7 @@ 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` | The names of the tools to bind, between 1 and 50. Duplicates in the list are collapsed. | +| `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. | ## Agents as tools From 7b7971d0a3da0265570e2af5e12158dff0fe0b78 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 3 Sep 2026 10:32:33 -0500 Subject: [PATCH 41/70] Phase 3 - HITL Signed-off-by: Rachael Graham --- .../kagent/1.x/agents/human-in-the-loop.md | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 docs-site/content/kagent/1.x/agents/human-in-the-loop.md diff --git a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md new file mode 100644 index 00000000..f122a503 --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md @@ -0,0 +1,155 @@ +--- +title: Human in the loop +description: Understand how an agent pauses to ask a question or to get a tool call approved, and what a client does to answer it. +weight: 50 +author: kagent.dev +--- + +An agent that only answers questions can run unattended. An agent that takes action often should not. The human in the loop (HITL) mechanism lets an agent stop mid-turn, return a question or a pending tool call to a person, and continue once that person answers. + +> [!IMPORTANT] +> HITL is negotiated by the **client**, per call, rather than configured on an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}. There is no field to switch it on. A client that does not ask for the extension still gets the pause: the agent stops, and the task waits. What it loses is the ability to answer, because the request reaches it as bare text with no correlation `id`. This differs from kagent 0.x, where a `requireApproval` list on the `Agent` resource decided which tools paused. + +## How a pause works + +The following diagram traces one turn in which the agent stops for a person. + +```mermaid +flowchart TB + caller["Client sends a message
      requesting the HITL extension"] + working["Agent works on the turn"] + decision{"Does the agent need
      a person?"} + pause["Task state becomes
      INPUT_REQUIRED"] + request["Status message carries a
      tool_approval_request
      or ask_user_request"] + answer["Client sends a response message
      on the same task"] + done["Agent finishes the turn"] + + caller --> working + working --> decision + decision -->|no| done + decision -->|yes| pause + pause --> request + request --> answer + answer --> working +``` + +The client opens the turn by sending a message that requests the HITL extension. The agent works until it either finishes, in which case the turn ends, or needs a person. When it needs a person, the task moves to `INPUT_REQUIRED` and its status message carries either a `tool_approval_request` or an `ask_user_request`. The client answers by sending a response message on the same task, and the agent resumes the turn where it left off. + +## Pause kinds + +An agent pauses either to get permission before it acts or to ask a question. Each case raises its own request. + +| Request | Raised when | The client answers with | +| ------- | ----------- | ----------------------- | +| `tool_approval_request` | The agent wants to call a tool that asked for confirmation before it runs. | `tool_approval_response` | +| `ask_user_request` | The agent calls the built-in `ask_user` tool because it needs information only a person has. | `ask_user_response` | + +Both use the same pause and resume mechanism, so a client that handles one can handle the other with a different payload. + +The runtime's tool-confirmation mechanism decides which tool calls raise an approval, rather than kagent configuration. kagent does not keep a list of tools that need approval. + +## Negotiate the extension + +HITL is an [A2A](https://a2a-protocol.org) message extension, identified by a versioned URI. A client requests it by setting that URI as the `A2A-Extensions` header on the call that sends a message. + +```http +A2A-Extensions: https://kagent.dev/extensions/hitl/v1 +``` + +kagent activates the extension only for calls that request it, and echoes the activated URI back. A client that never requests the extension sees ordinary turns until the agent needs a person. The turn then pauses like any other, and that client has no way to answer the request. + +A call from outside the cluster addresses the agent with two more headers, because the gateway routes on metadata rather than on a path. Port-forward the controller's gRPC port first, as in [Install kagent]({{< link path="setup/installation" >}}). + +```bash +grpcurl -plaintext \ + -H 'A2A-Extensions: https://kagent.dev/extensions/hitl/v1' \ + -H 'x-kagent-agent-instance-namespace: kagent' \ + -H 'x-kagent-agent-instance-id: ' \ + -d '{ + "message": { + "message_id": "msg-1", + "role": "ROLE_USER", + "parts": [{"text": "Delete the obsolete pod in the production namespace."}] + } + }' localhost:8084 lf.a2a.v1.A2AService/SendStreamingMessage +``` + +When the agent pauses, the payload arrives in the status message's `metadata`, keyed by the extension URI. The URI is also listed in the message's `extensions` array. Each payload carries a `type` field that specifies its shape. + +| Type | Direction | +| ---- | --------- | +| `tool_approval_request` | Agent to client | +| `ask_user_request` | Agent to client | +| `tool_approval_response` | Client to agent | +| `ask_user_response` | Client to agent | + +> [!WARNING] +> In case of failure, both halves of this negotiation fail silently, and neither failure reports anything. +- **A send that omits the header produces a pause that cannot be answered.** The turn still stops, but its status message carries the question as prose, with no `metadata` and no correlation `id`, so there is nothing to render and no `id` to answer with. Re-reading that task with the header does not recover it, because the payload was never attached. Send the header on every call: it is harmless on a read, and unrecoverable if missed on a send. An attached payload is stored with the task, so a later read returns it whether or not that read requests the extension. +- **A response that omits the `extensions` array is delivered as ordinary text.** kagent ignores the `metadata` payload unless the message itself lists the extension URI in `extensions`. The task resumes and the agent replies, so the call looks like it worked, but the structured decision never reached the agent. + +### Approving or rejecting a tool + +A `tool_approval_request` lists the pending calls, each with an `id`, the tool `name`, and the `args` the agent chose. The response decides every listed call. + +```json +{ + "type": "tool_approval_response", + "approvals": [ + { "id": "", "approved": true }, + { "id": "", "approved": false, "rejection_reason": "Deleting that namespace is out of scope." } + ] +} +``` + +A response must decide every call in the request. A rejection reason is optional but worth sending, because the agent receives it and can adapt rather than simply failing. + +### Answering a question + +An `ask_user_request` carries an `id` and a list of `questions`. The response echoes the same `id` and answers them in order. + +```json +{ + "type": "ask_user_response", + "id": "", + "answers": [ + { "answer": ["us-east-1"] } + ] +} +``` + +## Resume a paused task + +A paused task waits. To resume, the client sends a message on the same task and context, carrying the response payload. kagent rejects a resume attempt on a task that is not waiting, with `task is not waiting for input`. + +Because the {{< gloss "Transcript" >}}transcript{{< /gloss >}} only grows, the question and the answer both stay in the task history, so a later reader can see what was asked and what a person decided. + +## Task states + +An A2A task moves through several states over its life. Two of them mean that the task has stopped and is waiting on a person, rather than working. + +| State | Meaning | +| ----- | ------- | +| `INPUT_REQUIRED` | The agent is waiting for a person. This is the state that a tool approval or a question produces. | +| `AUTH_REQUIRED` | The agent is waiting for credentials. kagent's own runtimes never set this state, but its gateway accepts a resume from it, so a `byo` runtime that produces it works. | + +## Agents bound as tools + +An agent that a parent binds as a tool can raise a pause of its own. The request then carries a `nested` block naming the subagent, along with its task and context, so a client can tell the person which agent is actually asking rather than attributing it to the parent. + +## Client support + +Because the client negotiates HITL rather than the agent offering it, what a person can do with a pause depends on which client raised the turn. + +| Client | HITL | +| ------ | ---- | +| Your own A2A client | Full. Request the extension URI and handle the four payload types. | +| An MCP client that supports tasks | Supported. `invoke_agent_instance` returns a task, and input requests surface as MCP elicitations. | +| The kagent CLI | Not supported, and a turn that pauses is stranded. `kagent invoke` does not request the extension, so an agent that needs a person parks the task at `INPUT_REQUIRED` with nothing to answer it by. The CLI reports `Input required to continue this AgentInstance.` and stops there. Send the turn again from a client that requests the extension. | + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Bind the tools that an approval request would cover." >}} + {{< card link=`{{< link path="agents/system-prompts" >}}` title="System prompts" subtitle="Tell an agent when to ask rather than act." >}} +{{< /cards >}} From 759c82cd39f2835ab1e416aea0dc5316957cbd04 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 3 Sep 2026 14:39:30 -0500 Subject: [PATCH 42/70] Phase 3 - Observability Signed-off-by: Rachael Graham --- .../kagent-docs/versions/agent-substrate.md | 2 +- .../kagent/1.x/observability/_index.md | 8 + .../kagent/1.x/observability/audit-prompts.md | 375 ++++++++++++++++++ .../kagent/1.x/observability/tracing.md | 216 ++++++++++ .../content/kagent/1.x/setup/installation.md | 4 +- 5 files changed, 602 insertions(+), 3 deletions(-) create mode 100644 docs-site/content/kagent/1.x/observability/_index.md create mode 100644 docs-site/content/kagent/1.x/observability/audit-prompts.md create mode 100644 docs-site/content/kagent/1.x/observability/tracing.md diff --git a/docs-site/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md index a9de7678..536cf0b3 100644 --- a/docs-site/assets/kagent-docs/versions/agent-substrate.md +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -1 +1 @@ -{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.22{{< /version >}} \ No newline at end of file +{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.24{{< /version >}} \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/observability/_index.md b/docs-site/content/kagent/1.x/observability/_index.md new file mode 100644 index 00000000..7a1e9e10 --- /dev/null +++ b/docs-site/content/kagent/1.x/observability/_index.md @@ -0,0 +1,8 @@ +--- +title: Observability +description: Trace agent requests across the controller and the Actors that run your agents, and audit the prompts your agents send. +weight: 70 +author: kagent.dev +--- + +See what your agents are doing, from the shape of a single request to the content of every prompt and reply. diff --git a/docs-site/content/kagent/1.x/observability/audit-prompts.md b/docs-site/content/kagent/1.x/observability/audit-prompts.md new file mode 100644 index 00000000..45b0e545 --- /dev/null +++ b/docs-site/content/kagent/1.x/observability/audit-prompts.md @@ -0,0 +1,375 @@ +--- +title: Audit prompts +description: Export the prompts and replies that your agents exchange with a model as OpenTelemetry log events, then query them in a logging backend. +weight: 30 +author: kagent.dev +--- + +Audit every prompt (input) and reply (output) that passes between your agents and their models. Security and compliance teams use these records to review how people use your kagent environment. For example, you can confirm that no request sends personally identifiable information (PII) to a model. You can also reconstruct the instructions that an agent received in an earlier conversation. + +## About prompt auditing + +The agent runtime emits each message as an OpenTelemetry (OTel) log event. You export these events over the OpenTelemetry Protocol (OTLP) to a logging backend or to a security information and event management (SIEM) system. + +The runtime emits each event from inside the model call. When you also enable tracing, the event records the trace ID and the span ID of the request that produced it. Those IDs let you match an audit record to the trace of the same request. When tracing is disabled, the runtime still emits audit events, but it sets both IDs to zeros, because no span is recording. For more information, see [Tracing]({{< link path="observability/tracing" >}}). + +The runtime emits three event names for each model call. The system prompt and the model's reply each produce one event. The message history produces one event for every entry that it holds. + +| Event name | What it holds | +| ---------- | ------------- | +| `gen_ai.system.message` | The system prompt for the request, as one concatenated string. | +| `gen_ai.user.message` | One entry from the request's message history. The entry holds a person's message, an earlier agent turn, or a tool result. | +| `gen_ai.choice` | The model's reply, with the reply content and a `finish_reason`. | + +> [!NOTE] +> The runtime labels every history entry `gen_ai.user.message`, including the agent's own earlier turns and tool results. The `content.role` field in the event body names the speaker. To select only the messages that a person sent, filter on `content.role` instead of on the event name. Each turn also re-emits the full history, so a long conversation produces repeated events. Account for that volume when you set a retention period. + +Two environment variables on the agent runtime control the audit output. + +- **`OTEL_LOGGING_ENABLED`**: Whether the runtime installs a log exporter. The default value is `false`, and the runtime then emits no audit events. +- **`OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`**: Whether the events include message content. The default value for log events is `false`, and the runtime then replaces each message body with ``. The event metadata remains. + +> [!IMPORTANT] +> The `otel.logging` settings in the kagent Helm chart configure the controller only. The controller passes a fixed list of tracing variables to the agent runtimes that it starts. That list holds no logging variable. As a result, `otel.logging.enabled=true` alone produces no audit events for an AgentInstance. Set the logging variables on the {{< gloss "Harness" >}}Harness{{< /gloss >}} instead, as the following steps do. A Harness `spec.env` entry for a logging variable takes effect as written. An entry for a tracing variable does not, because the controller's own value overrides it. + +Only the `kagent` runtime emits these events. The runtime emits them from the model call itself, not from a provider-specific instrumentation library. Auditing therefore covers every model provider that the `kagent` runtime supports. For the available runtimes, see [Choose a runtime]({{< link path="agents/agent-harness#choose-a-runtime" >}}). + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have a Harness and an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} to configure. + +## Install an OpenTelemetry collector + +Export the audit events to an OpenTelemetry collector, not directly to the logging backend. The collector holds the rules for which content and metadata leave your cluster. Audit events carry prompt text, so those rules matter more than they do for other telemetry. The collector also lets you change the rules without creating a new AgentInstance. + +1. Add the OpenTelemetry Helm repository. + ```bash + helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts + helm repo update + ``` + +2. Install a logging backend that accepts OTLP. These steps install Grafana Loki in single-binary mode, which supports the manual queries in this guide. Datadog, Splunk, and other OTLP-compatible systems work in the same way. + ```yaml + helm upgrade --install loki loki \ + --repo https://grafana.github.io/helm-charts \ + --version {{< reuse "kagent-docs/versions/loki.md" >}} \ + --namespace telemetry \ + --create-namespace \ + --values - < otel-collector-audit.yaml <@sha256: + env: + - name: OTEL_LOGGING_ENABLED + value: "true" + - name: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT + value: http://opentelemetry-collector-audit.telemetry.svc.cluster.local:4317 + - name: OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT + value: "true" + substrate: + workerPoolRef: + name: kagent-default + snapshotPolicy: + location: gs:///kagent/ + allowedAgentTemplates: + selector: + matchLabels: + kagent.dev/harness: my-first-harness + EOF + ``` + + {{< reuse "kagent-docs/snippets/review-table.md" >}} The first two variables enable auditing and set its destination. The third variable controls whether the events include message content. For every other field that a Harness takes, see [Agent harness]({{< link path="agents/agent-harness" >}}). + + | Variable | Description | + | -------- | ----------- | + | `OTEL_LOGGING_ENABLED` | Installs the log exporter in the agent runtime. If omitted, the runtime emits no audit events, regardless of the other variables. | + | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | The address that the runtime exports events to. Set it to the address of the collector. To export over HTTP instead of gRPC, set `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` to `http/protobuf` and use port `4318`. | + | `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` | Includes message content in the events. If omitted, each event body reads ``, and the runtime exports only the metadata and the trace IDs. Those fields still record which agent handled a request, and when. | + +2. Confirm that kagent compiled a new {{< gloss "Revision" >}}revision{{< /gloss >}} for the edited Harness. An environment change produces a new desired revision. The Harness is current when `latestSuccessfulRevision` matches `desiredRevision`. + ```bash + kubectl get agenttemplate my-first-agent -n kagent \ + -o jsonpath='{range .status.harnesses[*]}{.harness}{"\t"}{.desiredRevision}{"\t"}{.latestSuccessfulRevision}{"\n"}{end}' + ``` + + Example output: + ```console + my-first-harness 4b8e1d3f5a7c9e2b0d4f6a8c1e3b5d7f9a2c4e6b8d0f2a4c6e8b0d2f4a6c8e0b 4b8e1d3f5a7c9e2b0d4f6a8c1e3b5d7f9a2c4e6b8d0f2a4c6e8b0d2f4a6c8e0b + ``` + +3. Create a new AgentInstance. An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} pins the revision that it was created from, so an existing instance continues to run without the audit variables. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template my-first-agent + ``` + +## Verify the setup + +1. Send a request to the new AgentInstance to produce audit events. + ```bash + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "my-first-agent")] | sort_by(.createdAt) | last | .id') + kagent invoke --agent-instance $INSTANCE_ID --task "What is 2+2?" + ``` + +2. Check that the collector received the events. + ```bash + kubectl -n telemetry logs -l app.kubernetes.io/name=opentelemetry-collector --tail=100 + ``` + Example output: + ```console + LogRecord #0 + ObservedTimestamp: 2026-09-03 14:22:11.278948633 +0000 UTC + Timestamp: 2026-09-03 14:22:11.278943258 +0000 UTC + SeverityText: + SeverityNumber: Unspecified(0) + EventName: gen_ai.user.message + Body: Map({"content":{"parts":[{"text":"What is 2+2?"}],"role":"user"}}) + Trace ID: c421bc11e93daaceee59b9e5ff8aa6d0 + Span ID: 02552aea76988990 + ``` + +3. Forward the Loki query port. Leave the command running. + ```bash + kubectl port-forward -n telemetry svc/loki 3100:3100 + ``` + +4. Query the events for the agent's service. The runtime builds the service name from the AgentTemplate name and the Harness name, and replaces each hyphen with an underscore. For example, `my-first-agent` on `my-first-harness` reports as `my_first_agent_my_first_harness`. + ```bash + curl -s -G 'http://localhost:3100/loki/api/v1/query_range' \ + --data-urlencode 'query={service_name="my_first_agent_my_first_harness"}' \ + --data-urlencode "start=$(( $(date +%s) - 3600 ))000000000" \ + --data-urlencode "end=$(date +%s)000000000" | jq + ``` + + Each entry holds the message content in the log line. The `stream` labels hold the agent identity, the event name, and the trace IDs. Example output: + ```json + { + "status": "success", + "data": { + "resultType": "streams", + "result": [ + { + "stream": { + "service_name": "my_first_agent_my_first_harness", + "service_namespace": "kagent", + "event_name": "gen_ai.user.message", + "trace_id": "c421bc11e93daaceee59b9e5ff8aa6d0", + "span_id": "02552aea76988990" + }, + "values": [ + [ + "1779893787755324418", + "{\"content\":{\"parts\":[{\"text\":\"What is 2+2?\"}],\"role\":\"user\"}}" + ] + ] + }, + { + "stream": { + "service_name": "my_first_agent_my_first_harness", + "service_namespace": "kagent", + "event_name": "gen_ai.choice", + "trace_id": "c421bc11e93daaceee59b9e5ff8aa6d0", + "span_id": "02552aea76988990" + }, + "values": [ + [ + "1779893788912004217", + "{\"content\":{\"parts\":[{\"text\":\"4\"}],\"role\":\"model\"},\"finish_reason\":\"STOP\",\"index\":0}" + ] + ] + } + ] + } + } + ``` + +## Refine audit queries + +An audit usually needs a narrower set of events than the full message history of one agent. The following three examples use the Loki query language. Adapt each example to the query language of your own backend. + +- Return only the model's replies, by filtering on the `event_name` label. + ```bash + curl -s -G 'http://localhost:3100/loki/api/v1/query_range' \ + --data-urlencode 'query={service_namespace="kagent"} | event_name="gen_ai.choice"' \ + --data-urlencode "start=$(( $(date +%s) - 3600 ))000000000" \ + --data-urlencode "end=$(date +%s)000000000" | jq + ``` + +- Return only the messages that a person sent, and exclude the agent's replayed history. The filter reads `content.role` from the event body, because the event name does not separate the two. + ```bash + curl -s -G 'http://localhost:3100/loki/api/v1/query_range' \ + --data-urlencode 'query={service_namespace="kagent"} | event_name="gen_ai.user.message" | json role="content.role" | role="user"' \ + --data-urlencode "start=$(( $(date +%s) - 3600 ))000000000" \ + --data-urlencode "end=$(date +%s)000000000" | jq + ``` + +- Return every message from every agent that contains a given string. For example, this query checks whether a request sent a credential to a model. + ```bash + curl -s -G 'http://localhost:3100/loki/api/v1/query_range' \ + --data-urlencode 'query={service_namespace="kagent"} |= "password"' \ + --data-urlencode "start=$(( $(date +%s) - 3600 ))000000000" \ + --data-urlencode "end=$(date +%s)000000000" | jq + ``` + +To follow a request from its audit records into its trace, take the `trace_id` from any entry and look it up in your tracing backend. The `trace_id` holds a usable value only when [tracing]({{< link path="observability/tracing" >}}) is also enabled. + +## Turn off audit logging + +1. Remove the three environment variables from the `spec.env` field of the Harness. + +2. Create a new AgentInstance, so that its Actor starts without the audit variables. + +3. Remove the collector and the logging backend. + ```bash + helm uninstall opentelemetry-collector-audit -n telemetry + helm uninstall loki -n telemetry + kubectl delete namespace telemetry + ``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="observability/tracing" >}}` title="Tracing" subtitle="Follow one request from the controller through to the Actor that ran your agent." >}} + {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Review every field that a Harness takes, including the environment that its runtime receives." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/observability/tracing.md b/docs-site/content/kagent/1.x/observability/tracing.md new file mode 100644 index 00000000..53ed060a --- /dev/null +++ b/docs-site/content/kagent/1.x/observability/tracing.md @@ -0,0 +1,216 @@ +--- +title: Tracing +description: Enable OpenTelemetry tracing for kagent, then read a trace that runs from the controller through to the Actor that executed your agent. +weight: 20 +author: kagent.dev +--- + +A trace records one agent request as a tree of timed spans, so you can see where a slow or failed request spent its time and which model and tool calls it made along the way. In kagent 1.0 a single request crosses two processes, the controller and the {{< gloss "Actor" >}}Actor{{< /gloss >}} that runs the agent, and a trace ties both halves together. + +## About trace coverage + +Tracing spans two processes, and the link between them is a W3C Trace Context header that the controller passes to the Actor. The following diagram traces one request through both. +

      + +```mermaid +flowchart LR + caller["Caller"] + subgraph controllerproc["kagent controller"] + grpc["gRPC API"] + gateway["A2A gateway"] + end + subgraph actorproc["Actor"] + runtime["Agent runtime"] + end + %% Cross-subgraph edges are declared outside every subgraph block, because + %% mermaid assigns a node to the subgraph that first references it. + caller --> grpc + grpc --> gateway + gateway -->|traceparent| runtime + classDef boundary fill:#a78bfa26,stroke:#a78bfa,stroke-width:2px + classDef inner fill:#80808033,stroke:#9ca3af,stroke-width:1px + class controllerproc,actorproc boundary + class grpc,gateway,runtime inner +``` + +A caller reaches the gRPC API on the kagent controller, which starts the trace. The controller hands the request to its A2A gateway, which opens an {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) connection to the AgentInstance's Actor and injects a `traceparent` header into that call. The agent runtime inside the Actor reads the header and continues the same trace, so the model and tool spans it produces hang off the controller's spans rather than starting a trace of their own. + +> [!IMPORTANT] +> The controller passes its tracing configuration only to the `kagent` runtime. An agent on the `codex`, `claude`, or `byo` runtime produces no runtime spans, and its half of the trace is missing. For a `byo` image that implements OTel itself, set the exporter variables in the Harness `spec.env` instead. For the available runtimes, see [Choose a runtime]({{< link path="agents/agent-harness#choose-a-runtime" >}}). + +Both processes report themselves as separate OpenTelemetry (OTel) services, which is how a tracing backend groups the spans. + +- **The controller** reports as `kagent-controller` in the `kagent` service namespace. Its spans also carry the pod, node, and namespace that the controller runs on. +- **Each agent runtime** reports as its own service, named for the {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} and {{< gloss "Harness" >}}Harness{{< /gloss >}} pair it was compiled from, with hyphens replaced by underscores. The `my-first-agent` template on the `my-first-harness` Harness reports as `my_first_agent_my_first_harness`. + +> [!NOTE] +> A service per template and Harness pair is a change from kagent 0.x, where every agent reported under one `kagent` service. A backend that you filter by service now shows one entry for each pair, and adding an agent adds a service. + +### Spans + +The agent runtime names its spans after the operation rather than the agent, so the same three names appear for every agent. Filter to a particular agent by service name instead. + +| Span | When it is created | +| ---- | ------------------ | +| `invocation` | Once per request, as the root of the runtime's half of the trace. | +| `generate_content ` | Once per model call, named for the model that was called. | +| `execute_tool ` | Once per tool call, named for the tool that was called. | +| `execute_tool (merged)` | In place of the individual spans when the agent runs more than one tool call at once. | + +### Correlation attributes + +A trace tells you which request you are looking at through attributes on its spans, not through the span names. The runtime stamps the following four attributes onto its root span and copies them onto every descendant span. A search on any one of these attributes returns the whole subtree rather than a single span. + +| Attribute | Value | +| --------- | ----- | +| `gen_ai.task.id` | The A2A task ID, which identifies one turn of a conversation. | +| `gen_ai.conversation.id` | The A2A context ID, which identifies the conversation and is stable across its turns. | +| `kagent.app_name` | The AgentTemplate, as `__NS__` with hyphens replaced by underscores. | +| `kagent.user_id` | The authenticated caller, or `A2A_USER_` for an unauthenticated one. | + +The runtime also adds each scalar value in the A2A message's metadata as an `a2a.message.metadata.` attribute, so a client can tag a request and search for it later. Unlike the four correlation attributes, these tags stay on the `invocation` span alone, so a search on one returns that span instead of the whole subtree. + +> [!WARNING] +> Spans for a model call carry the full serialized request and response as the `gcp.vertex.agent.llm_request` and `gcp.vertex.agent.llm_response` attributes. Prompts and replies therefore reach your tracing backend. Payloads larger than 32 KiB are truncated to a prefix. To keep this content out of traces, set `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` to `false` in the Harness `spec.env`. Note that the same variable has the opposite default for audit logging, where content is withheld until you set it to `true`. For more information, see [Audit prompts]({{< link path="observability/audit-prompts" >}}). + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} to send a request to. + +## Install Jaeger + +Install a backend that accepts OpenTelemetry Protocol (OTLP) traces. The following steps install [Jaeger](https://www.jaegertracing.io/) in all-in-one mode, which stores traces in memory and needs no other components. + +1. Create a `jaeger.yaml` configuration file. + ```yaml + cat << 'EOF' > jaeger.yaml + provisionDataStore: + cassandra: false + allInOne: + enabled: true + storage: + type: memory + agent: + enabled: false + collector: + enabled: false + query: + enabled: false + EOF + ``` + +2. Install Jaeger. + ```bash + helm repo add jaegertracing https://jaegertracing.github.io/helm-charts + helm repo update + helm upgrade --install jaeger jaegertracing/jaeger \ + --namespace jaeger --create-namespace \ + --history-max 3 \ + --values jaeger.yaml \ + --version {{< reuse "kagent-docs/versions/jaeger.md" >}} + ``` + +## Enable tracing + +Tracing is off by default. Turning it on is a Helm change, because the controller reads its tracing configuration from the environment and passes it to the agent runtimes it starts. + +1. Get your current Helm values for kagent. + ```shell + helm get values kagent -n kagent -o yaml > values.yaml + ``` + +2. Add the tracing settings to the values file, pointing the exporter at Jaeger. + ```yaml + otel: + tracing: + enabled: true + exporter: + otlp: + endpoint: http://jaeger.jaeger.svc.cluster.local:4317 + protocol: grpc + timeout: 15000 + insecure: true + ``` + + {{< reuse "kagent-docs/snippets/review-table.md" >}} + + | Field | Description | + | ----- | ----------- | + | `enabled` | Whether to export traces at all. Defaults to `false`. | + | `exporter.otlp.endpoint` | The OTLP endpoint to export to. Empty by default, which leaves the exporter on the OTel default of `localhost:4317`. | + | `exporter.otlp.protocol` | `grpc` or `http/protobuf`. Defaults to `grpc`, which matches the port `4317` in the example endpoint. Point `http/protobuf` at port `4318` instead. | + | `exporter.otlp.timeout` | The export timeout in milliseconds. Defaults to `15000`. | + | `exporter.otlp.insecure` | Whether to skip Transport Layer Security (TLS) for the exporter connection. Defaults to `true`. | + +3. Upgrade the kagent Helm release. + ```bash + helm upgrade kagent \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ + --namespace kagent \ + --values values.yaml + ``` + +4. Create a new AgentInstance, so that its Actor starts from a runtime that has the tracing configuration. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template my-first-agent + ``` + +## Review a trace + +1. Send a request to the AgentInstance to produce a trace. + ```bash + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "my-first-agent")] | sort_by(.createdAt) | last | .id') + kagent invoke --agent-instance $INSTANCE_ID --task "What is 2+2?" + ``` + +2. Forward the Jaeger query port, and leave the command running. + ```bash + kubectl port-forward -n jaeger svc/jaeger 16686:16686 + ``` + +3. In your browser, open the Jaeger user interface at [http://localhost:16686](http://localhost:16686). + +4. From the **Service** dropdown, select `my_first_agent_my_first_harness`, the service that the AgentTemplate and Harness pair reports as. Selecting `kagent-controller` instead returns the same traces from the controller's side. + +5. Leave **Operation** on `all`, or select `invocation` to start from the root of the runtime's half of the trace, and click **Find Traces**. + +6. Click a trace to open it. The span tree shows the controller's gRPC and gateway spans, followed by the `invocation` and the `generate_content` and `execute_tool` spans. + +7. To narrow a search to one conversation, put a correlation attribute in the **Tags** field, such as `gen_ai.conversation.id=`. + +## Traces from a suspended Actor + +Agent Substrate {{< gloss "Checkpoint" >}}checkpoints{{< /gloss >}} an Actor as soon as the response body closes, which is sooner than a batching span exporter normally sends its buffer. Spans still in the buffer at that moment freeze inside the {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} and reach the backend only when the session next resumes, or never at all for a conversation's last message. + +To avoid losing them, the controller sets `KAGENT_PRE_RESPONSE_TRACE_FLUSH` to `true` on every agent runtime it starts, and the runtime flushes its span buffer before each response completes. The flush waits up to three seconds, which you can change with `KAGENT_TRACE_FLUSH_TIMEOUT_MS` in the Harness `spec.env`. + +This behavior allows a kagent trace to arrive promptly rather than on the exporter's own schedule. To understand what suspension does to an Actor, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + +## Turn tracing off + +1. Disable tracing in the kagent Helm release. + ```bash + helm upgrade kagent \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ + --namespace kagent --reuse-values \ + --set otel.tracing.enabled=false + ``` + +2. Create a new AgentInstance to pick up the change, because an existing Actor keeps the configuration it started with. + +3. Remove Jaeger. + ```bash + helm uninstall jaeger -n jaeger + kubectl delete namespace jaeger + ``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="observability/audit-prompts" >}}` title="Audit prompts" subtitle="Export every prompt and reply as a log event for security and compliance review." >}} + {{< card link=`{{< link path="substrate-runtime/suspend-and-resume" >}}` title="Suspend and resume" subtitle="Learn what happens to an Actor between the turns of a conversation." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index b5af88fe..c9848591 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -23,7 +23,7 @@ kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-subs kubectl ate --help ``` -2. Set your model provider API key. The examples in this guide use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/configure-model-providers" >}}). +2. Set your model provider API key. The examples in this guide use OpenAI. For other providers, see [Configure model providers]({{< link path="setup/model-providers" >}}). ```bash export OPENAI_API_KEY="your-api-key-here" ``` @@ -281,5 +281,5 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker {{< cards >}} {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} - {{< card link=`{{< link path="setup/configure-model-providers" >}}` title="Configure model providers" subtitle="Point kagent at OpenAI, Anthropic, Gemini, or a provider of your own." >}} + {{< card link=`{{< link path="setup/model-providers" >}}` title="Configure model providers" subtitle="Point kagent at OpenAI, Anthropic, Gemini, or a provider of your own." >}} {{< /cards >}} From 662a763fb6f818e24d13e8bd6c43f876e6697558 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 3 Sep 2026 15:48:50 -0500 Subject: [PATCH 43/70] observability testing Signed-off-by: Rachael Graham --- .../kagent-docs/versions/otel-collector.md | 1 + .../kagent/1.x/observability/audit-prompts.md | 108 ++++++++++-------- .../kagent/1.x/observability/tracing.md | 12 +- 3 files changed, 68 insertions(+), 53 deletions(-) create mode 100644 docs-site/assets/kagent-docs/versions/otel-collector.md diff --git a/docs-site/assets/kagent-docs/versions/otel-collector.md b/docs-site/assets/kagent-docs/versions/otel-collector.md new file mode 100644 index 00000000..e992169d --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/otel-collector.md @@ -0,0 +1 @@ +0.172.0 \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/observability/audit-prompts.md b/docs-site/content/kagent/1.x/observability/audit-prompts.md index 45b0e545..8d19d531 100644 --- a/docs-site/content/kagent/1.x/observability/audit-prompts.md +++ b/docs-site/content/kagent/1.x/observability/audit-prompts.md @@ -11,7 +11,11 @@ Audit every prompt (input) and reply (output) that passes between your agents an The agent runtime emits each message as an OpenTelemetry (OTel) log event. You export these events over the OpenTelemetry Protocol (OTLP) to a logging backend or to a security information and event management (SIEM) system. -The runtime emits each event from inside the model call. When you also enable tracing, the event records the trace ID and the span ID of the request that produced it. Those IDs let you match an audit record to the trace of the same request. When tracing is disabled, the runtime still emits audit events, but it sets both IDs to zeros, because no span is recording. For more information, see [Tracing]({{< link path="observability/tracing" >}}). +### Trace correlation + +The runtime emits each event from inside the model call. Each event records the trace ID and the span ID of the request that produced it. Those IDs let you match an audit record to the trace of the same request. The runtime populates both IDs whether or not you enable tracing, but only an enabled tracing pipeline exports the matching trace. With tracing disabled, a lookup of the trace ID in your tracing backend returns nothing. For more information, see [Tracing]({{< link path="observability/tracing" >}}). + +### Events The runtime emits three event names for each model call. The system prompt and the model's reply each produce one event. The message history produces one event for every entry that it holds. @@ -19,10 +23,14 @@ The runtime emits three event names for each model call. The system prompt and t | ---------- | ------------- | | `gen_ai.system.message` | The system prompt for the request, as one concatenated string. | | `gen_ai.user.message` | One entry from the request's message history. The entry holds a person's message, an earlier agent turn, or a tool result. | -| `gen_ai.choice` | The model's reply, with the reply content and a `finish_reason`. | +| `gen_ai.choice` | The model's reply, with the reply content and a `finish_reason`. On a turn that calls a tool, the reply content holds the tool call and its arguments instead of text. | + +An audit returns more than the prompts that your team wrote. A `gen_ai.system.message` body holds the `systemPrompt` field of your AgentTemplate followed by instructions that the runtime appends, which name the agent and repeat its description. Tool traffic is included as well, because a tool call reaches the log with its arguments, and the tool's output returns as a `gen_ai.user.message` that holds the tool response. > [!NOTE] -> The runtime labels every history entry `gen_ai.user.message`, including the agent's own earlier turns and tool results. The `content.role` field in the event body names the speaker. To select only the messages that a person sent, filter on `content.role` instead of on the event name. Each turn also re-emits the full history, so a long conversation produces repeated events. Account for that volume when you set a retention period. +> The runtime labels every history entry as `gen_ai.user.message`, including the agent's own earlier turns and tool results. The `content.role` field in the event body names the speaker. To select only the messages that a person sent, filter on `content.role` instead of on the event name. Each turn also re-emits the full history, so a long conversation produces repeated events. Account for that volume when you set a retention period. + +### Environment variables Two environment variables on the agent runtime control the audit output. @@ -30,7 +38,9 @@ Two environment variables on the agent runtime control the audit output. - **`OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT`**: Whether the events include message content. The default value for log events is `false`, and the runtime then replaces each message body with ``. The event metadata remains. > [!IMPORTANT] -> The `otel.logging` settings in the kagent Helm chart configure the controller only. The controller passes a fixed list of tracing variables to the agent runtimes that it starts. That list holds no logging variable. As a result, `otel.logging.enabled=true` alone produces no audit events for an AgentInstance. Set the logging variables on the {{< gloss "Harness" >}}Harness{{< /gloss >}} instead, as the following steps do. A Harness `spec.env` entry for a logging variable takes effect as written. An entry for a tracing variable does not, because the controller's own value overrides it. +> The `otel.logging` settings in the kagent Helm chart configure the controller only. The controller passes a fixed list of tracing variables to the agent runtimes that it starts. That list holds no logging variable. As a result, `otel.logging.enabled=true` alone produces no audit events for an AgentInstance. Set the logging variables on the {{< gloss "Harness" >}}Harness{{< /gloss >}} instead, as shown in the following steps. A Harness `spec.env` entry for a logging variable takes effect as written. An entry for a tracing variable does not, because the controller's own value overrides it. + +### Runtime support Only the `kagent` runtime emits these events. The runtime emits them from the model call itself, not from a provider-specific instrumentation library. Auditing therefore covers every model provider that the `kagent` runtime supports. For the available runtimes, see [Choose a runtime]({{< link path="agents/agent-harness#choose-a-runtime" >}}). @@ -39,9 +49,11 @@ Only the `kagent` runtime emits these events. The runtime emits them from the mo 1. [Install kagent]({{< link path="setup/installation" >}}). 2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have a Harness and an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} to configure. -## Install an OpenTelemetry collector +## Install a collector and a logging backend -Export the audit events to an OpenTelemetry collector, not directly to the logging backend. The collector holds the rules for which content and metadata leave your cluster. Audit events carry prompt text, so those rules matter more than they do for other telemetry. The collector also lets you change the rules without creating a new AgentInstance. +Set up the path that audit events take from the agent runtime to a logging backend. The runtime exports to an OpenTelemetry collector, and the collector forwards the events to the backend. These steps install Grafana Loki as that backend, because Loki supports the queries that this guide runs later. Datadog, Splunk, and other OTLP-compatible systems work in the same way. + +Export to a collector rather than directly to the backend. The collector holds the rules for which content and metadata leave your cluster. Audit events carry prompt text, so those rules matter more than they do for other telemetry. The collector also lets you change the rules without creating a new AgentInstance. 1. Add the OpenTelemetry Helm repository. ```bash @@ -49,7 +61,7 @@ Export the audit events to an OpenTelemetry collector, not directly to the loggi helm repo update ``` -2. Install a logging backend that accepts OTLP. These steps install Grafana Loki in single-binary mode, which supports the manual queries in this guide. Datadog, Splunk, and other OTLP-compatible systems work in the same way. +2. Install Loki in single-binary mode. The values file disables the two Loki memcached caches, because the chart requests roughly 10 GB of memory for them by default and a single-node cluster cannot schedule that request. ```yaml helm upgrade --install loki loki \ --repo https://grafana.github.io/helm-charts \ @@ -85,6 +97,10 @@ Export the audit events to an OpenTelemetry collector, not directly to the loggi installOperator: false lokiCanary: enabled: false + chunksCache: + enabled: false + resultsCache: + enabled: false limits_config: allow_structured_metadata: true memberlist: @@ -124,11 +140,9 @@ Export the audit events to an OpenTelemetry collector, not directly to the loggi ``` Example output: ```console - NAME READY STATUS RESTARTS AGE - loki-0 2/2 Running 0 112s - loki-chunks-cache-0 2/2 Running 0 112s - loki-minio-0 1/1 Running 0 112s - loki-results-cache-0 2/2 Running 0 112s + NAME READY STATUS RESTARTS AGE + loki-0 2/2 Running 0 112s + loki-minio-0 1/1 Running 0 112s ``` 4. Create a Helm values file for the collector. The `debug` exporter prints each received event to the collector's own log. Use that log to confirm that events arrive, before you query the backend. @@ -152,7 +166,7 @@ Export the audit events to an OpenTelemetry collector, not directly to the loggi exporters: debug: verbosity: detailed - otlphttp: + otlp_http: endpoint: "http://loki.telemetry.svc.cluster.local:3100/otlp" tls: insecure: true @@ -161,16 +175,17 @@ Export the audit events to an OpenTelemetry collector, not directly to the loggi logs: receivers: [otlp] processors: [batch] - exporters: [debug, otlphttp] + exporters: [debug, otlp_http] EOF ``` - To use a backend other than Loki, replace the `otlphttp` endpoint with the OTLP address of that backend. For example, Datadog uses `https://api.datadoghq.com`. + To use a backend other than Loki, replace the `otlp_http` endpoint with the OTLP address of that backend. For example, Datadog uses `https://api.datadoghq.com`. 5. Install the collector with the values file that you created. ```bash helm install opentelemetry-collector-audit open-telemetry/opentelemetry-collector \ --namespace telemetry \ + --version {{< reuse "kagent-docs/versions/otel-collector.md" >}} \ --values otel-collector-audit.yaml ``` @@ -227,7 +242,7 @@ Add the audit variables to the Harness that your agents run on. The runtime then | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | The address that the runtime exports events to. Set it to the address of the collector. To export over HTTP instead of gRPC, set `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` to `http/protobuf` and use port `4318`. | | `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT` | Includes message content in the events. If omitted, each event body reads ``, and the runtime exports only the metadata and the trace IDs. Those fields still record which agent handled a request, and when. | -2. Confirm that kagent compiled a new {{< gloss "Revision" >}}revision{{< /gloss >}} for the edited Harness. An environment change produces a new desired revision. The Harness is current when `latestSuccessfulRevision` matches `desiredRevision`. +2. Confirm that kagent compiled a new {{< gloss "Revision" >}}revision{{< /gloss >}} for the edited Harness. The Harness is current when `latestSuccessfulRevision` matches `desiredRevision`. ```bash kubectl get agenttemplate my-first-agent -n kagent \ -o jsonpath='{range .status.harnesses[*]}{.harness}{"\t"}{.desiredRevision}{"\t"}{.latestSuccessfulRevision}{"\n"}{end}' @@ -252,23 +267,30 @@ Add the audit variables to the Harness that your agents run on. The runtime then kagent invoke --agent-instance $INSTANCE_ID --task "What is 2+2?" ``` -2. Check that the collector received the events. +2. Check that the collector received the events. The collector logs its own metrics to the same stream, so filter the output for the audit records. ```bash - kubectl -n telemetry logs -l app.kubernetes.io/name=opentelemetry-collector --tail=100 + kubectl -n telemetry logs -l app.kubernetes.io/name=opentelemetry-collector --tail=200 \ + | grep -B 5 -A 4 "EventName: gen_ai" ``` Example output: ```console - LogRecord #0 - ObservedTimestamp: 2026-09-03 14:22:11.278948633 +0000 UTC - Timestamp: 2026-09-03 14:22:11.278943258 +0000 UTC + LogRecord #1 + ObservedTimestamp: 2026-09-03 19:26:18.48324493 +0000 UTC + Timestamp: 1970-01-01 00:00:00 +0000 UTC SeverityText: SeverityNumber: Unspecified(0) EventName: gen_ai.user.message Body: Map({"content":{"parts":[{"text":"What is 2+2?"}],"role":"user"}}) - Trace ID: c421bc11e93daaceee59b9e5ff8aa6d0 - Span ID: 02552aea76988990 + Trace ID: 3d34d2f1b74f30a5cce0d5ed8571e928 + Span ID: 12671255711f5511 + Flags: 1 ``` + The runtime leaves the `Timestamp` field unset, so every record reports `1970-01-01 00:00:00`. Read `ObservedTimestamp` instead, which records when the collector received the event. + + > [!NOTE] + > The runtime buffers audit events and exports them in batches, and Agent Substrate suspends an Actor as soon as its response completes. A short conversation can therefore finish before the runtime exports its events, and this command then returns nothing. Send another request to the AgentInstance and check again. + 3. Forward the Loki query port. Leave the command running. ```bash kubectl port-forward -n telemetry svc/loki 3100:3100 @@ -282,7 +304,7 @@ Add the audit variables to the Harness that your agents run on. The runtime then --data-urlencode "end=$(date +%s)000000000" | jq ``` - Each entry holds the message content in the log line. The `stream` labels hold the agent identity, the event name, and the trace IDs. Example output: + Each entry holds the message content in the log line. The `stream` object holds the agent identity in the `service_name` and `service_namespace` labels, and holds the trace IDs as structured metadata. Loki does not record the event name, so the response carries no `event_name` field, and every event from one request shares a single stream. Example output: ```json { "status": "success", @@ -293,29 +315,19 @@ Add the audit variables to the Harness that your agents run on. The runtime then "stream": { "service_name": "my_first_agent_my_first_harness", "service_namespace": "kagent", - "event_name": "gen_ai.user.message", - "trace_id": "c421bc11e93daaceee59b9e5ff8aa6d0", - "span_id": "02552aea76988990" + "scope_name": "gcp.vertex.agent", + "trace_id": "3d34d2f1b74f30a5cce0d5ed8571e928", + "span_id": "12671255711f5511", + "flags": "1" }, "values": [ [ - "1779893787755324418", + "1788463578483244930", "{\"content\":{\"parts\":[{\"text\":\"What is 2+2?\"}],\"role\":\"user\"}}" - ] - ] - }, - { - "stream": { - "service_name": "my_first_agent_my_first_harness", - "service_namespace": "kagent", - "event_name": "gen_ai.choice", - "trace_id": "c421bc11e93daaceee59b9e5ff8aa6d0", - "span_id": "02552aea76988990" - }, - "values": [ + ], [ - "1779893788912004217", - "{\"content\":{\"parts\":[{\"text\":\"4\"}],\"role\":\"model\"},\"finish_reason\":\"STOP\",\"index\":0}" + "1788463578483063303", + "{\"content\":\"You are a concise, helpful assistant. ...\"}" ] ] } @@ -326,20 +338,20 @@ Add the audit variables to the Harness that your agents run on. The runtime then ## Refine audit queries -An audit usually needs a narrower set of events than the full message history of one agent. The following three examples use the Loki query language. Adapt each example to the query language of your own backend. +An audit usually needs a narrower set of events than the full message history of one agent. Loki does not index the event name, so each of the following examples selects an event type by a field in the event body instead. The examples use the Loki query language. Adapt each example to the query language of your own backend. -- Return only the model's replies, by filtering on the `event_name` label. +- Return only the model's replies. Only a `gen_ai.choice` event carries a `finish_reason` field, so that field selects the replies. ```bash curl -s -G 'http://localhost:3100/loki/api/v1/query_range' \ - --data-urlencode 'query={service_namespace="kagent"} | event_name="gen_ai.choice"' \ + --data-urlencode 'query={service_namespace="kagent"} | json reason="finish_reason" | reason != ""' \ --data-urlencode "start=$(( $(date +%s) - 3600 ))000000000" \ --data-urlencode "end=$(date +%s)000000000" | jq ``` -- Return only the messages that a person sent, and exclude the agent's replayed history. The filter reads `content.role` from the event body, because the event name does not separate the two. +- Return only the messages that a person sent, and exclude the agent's replayed history. The filter reads `content.role` from the event body, because only a person's message sets that field to `user`. ```bash curl -s -G 'http://localhost:3100/loki/api/v1/query_range' \ - --data-urlencode 'query={service_namespace="kagent"} | event_name="gen_ai.user.message" | json role="content.role" | role="user"' \ + --data-urlencode 'query={service_namespace="kagent"} | json role="content.role" | role="user"' \ --data-urlencode "start=$(( $(date +%s) - 3600 ))000000000" \ --data-urlencode "end=$(date +%s)000000000" | jq ``` @@ -352,7 +364,7 @@ An audit usually needs a narrower set of events than the full message history of --data-urlencode "end=$(date +%s)000000000" | jq ``` -To follow a request from its audit records into its trace, take the `trace_id` from any entry and look it up in your tracing backend. The `trace_id` holds a usable value only when [tracing]({{< link path="observability/tracing" >}}) is also enabled. +To follow a request from its audit records into its trace, take the `trace_id` from any entry and look it up in your tracing backend. The lookup returns a trace only when [tracing]({{< link path="observability/tracing" >}}) is also enabled. With tracing disabled, the record still carries a trace ID, but no pipeline exported the trace that the ID names. ## Turn off audit logging diff --git a/docs-site/content/kagent/1.x/observability/tracing.md b/docs-site/content/kagent/1.x/observability/tracing.md index 53ed060a..3cb0ce4d 100644 --- a/docs-site/content/kagent/1.x/observability/tracing.md +++ b/docs-site/content/kagent/1.x/observability/tracing.md @@ -48,14 +48,16 @@ Both processes report themselves as separate OpenTelemetry (OTel) services, whic ### Spans -The agent runtime names its spans after the operation rather than the agent, so the same three names appear for every agent. Filter to a particular agent by service name instead. +The agent runtime creates the same spans for every agent, and most span names describe the operation rather than the agent. The `invoke_agent` span is the exception, because its name carries the service name of the agent that ran. To narrow a search to one agent, filter by service name rather than by span name. The following spans appear in nesting order, from the span that accepts the request down to the model and tool calls that serve it. | Span | When it is created | | ---- | ------------------ | -| `invocation` | Once per request, as the root of the runtime's half of the trace. | +| `POST /lf.a2a.v1.A2AService/SendMessage` | Once per request, as the root of the runtime's half of the trace. The runtime creates it when it accepts the A2A call from the controller. | +| `invocation` | Once per request, as the parent of the agent's own work. | +| `invoke_agent ` | Once per request, named for the AgentTemplate and Harness pair that serves it. | | `generate_content ` | Once per model call, named for the model that was called. | | `execute_tool ` | Once per tool call, named for the tool that was called. | -| `execute_tool (merged)` | In place of the individual spans when the agent runs more than one tool call at once. | +| `execute_tool (merged)` | Once per model turn that calls more than one tool, as the parent of that turn's `execute_tool` spans. A turn that calls a single tool creates no merged span. | ### Correlation attributes @@ -175,9 +177,9 @@ Tracing is off by default. Turning it on is a Helm change, because the controlle 4. From the **Service** dropdown, select `my_first_agent_my_first_harness`, the service that the AgentTemplate and Harness pair reports as. Selecting `kagent-controller` instead returns the same traces from the controller's side. -5. Leave **Operation** on `all`, or select `invocation` to start from the root of the runtime's half of the trace, and click **Find Traces**. +5. Leave **Operation** on `all`, or select `invocation` to start from the agent's own work rather than from the A2A call that carries it, and click **Find Traces**. -6. Click a trace to open it. The span tree shows the controller's gRPC and gateway spans, followed by the `invocation` and the `generate_content` and `execute_tool` spans. +6. Click a trace to open it. The span tree shows the controller's gRPC and gateway spans, followed by the runtime's `POST /lf.a2a.v1.A2AService/SendMessage` span, and finlly the `invocation`, `invoke_agent`, `generate_content`, and `execute_tool` spans. 7. To narrow a search to one conversation, put a correlation attribute in the **Tags** field, such as `gen_ai.conversation.id=`. From 57847f5ccb6c7b640fbe83752541df7a753e2241 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 4 Sep 2026 09:51:55 -0500 Subject: [PATCH 44/70] Rview glossary, wording, & forks Signed-off-by: Rachael Graham --- .../kagent/1.x/agents/agent-harness.md | 4 +- .../kagent/1.x/agents/human-in-the-loop.md | 2 +- .../kagent/1.x/agents/system-prompts.md | 2 +- .../kagent/1.x/examples/agent-substrate.md | 19 +- .../kagent/1.x/examples/agents-via-mcp.md | 211 ++++++++++++++++++ .../1.x/get-started/your-first-mcp-tool.md | 2 +- .../kagent/1.x/observability/tracing.md | 2 +- .../substrate-runtime/suspend-and-resume.md | 4 +- docs-site/data/glossary.yaml | 5 +- 9 files changed, 234 insertions(+), 17 deletions(-) create mode 100644 docs-site/content/kagent/1.x/examples/agents-via-mcp.md diff --git a/docs-site/content/kagent/1.x/agents/agent-harness.md b/docs-site/content/kagent/1.x/agents/agent-harness.md index 1b9e4c5e..dc9a409c 100644 --- a/docs-site/content/kagent/1.x/agents/agent-harness.md +++ b/docs-site/content/kagent/1.x/agents/agent-harness.md @@ -116,7 +116,7 @@ Some supported combinations still carry restrictions. | `claude` with `AnthropicVertexAI` | Accepts only `projectID` and `location`. The Secret has to hold a `service_account` key whose `project_id` matches and whose `token_uri` is `https://oauth2.googleapis.com`. | > [!IMPORTANT] -> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string, which is what rules out both Vertex AI providers there. For more information about that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). +> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string. This restriction rules out both Vertex AI providers there. For more information about that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). ## Tool and skill support @@ -125,7 +125,7 @@ The coding-agent runtimes also constrain what an AgentTemplate can ask for. | Constraint | Applies to | | ---------- | ---------- | | A `Shared` agent-tool binding cannot itself carry tools, skills, plugins, or nested agents, and has to use the same provider and credentials as the agent that binds it. | `codex`, `claude` | -| An MCP server is bound whole. Claude does not support partial tool selection, so the agent sees every tool the server offers rather than only the ones a binding names. The compiler warns rather than failing. | `claude` | +| An {{< gloss "MCP" >}}MCP{{< /gloss >}} server is bound whole. Claude does not support partial tool selection, so the agent sees every tool the server offers rather than only the ones a binding names. The compiler warns rather than failing. | `claude` | | A `RemoteMCPServer` has to use the `STREAMABLE_HTTP` protocol. `SSE` is rejected. | `codex` | The `kagent` and `byo` runtimes take the full set. For more information about what an AgentTemplate can bind, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). diff --git a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md index f122a503..bdcd825f 100644 --- a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md +++ b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md @@ -144,7 +144,7 @@ Because the client negotiates HITL rather than the agent offering it, what a per | Client | HITL | | ------ | ---- | | Your own A2A client | Full. Request the extension URI and handle the four payload types. | -| An MCP client that supports tasks | Supported. `invoke_agent_instance` returns a task, and input requests surface as MCP elicitations. | +| An {{< gloss "MCP" >}}MCP{{< /gloss >}} client that supports tasks | Supported. `invoke_agent_instance` returns a task, and input requests surface as MCP elicitations. | | The kagent CLI | Not supported, and a turn that pauses is stranded. `kagent invoke` does not request the extension, so an agent that needs a person parks the task at `INPUT_REQUIRED` with nothing to answer it by. The CLI reports `Input required to continue this AgentInstance.` and stops there. Send the turn again from a client that requests the extension. | ## Next steps diff --git a/docs-site/content/kagent/1.x/agents/system-prompts.md b/docs-site/content/kagent/1.x/agents/system-prompts.md index edb75112..079209b2 100644 --- a/docs-site/content/kagent/1.x/agents/system-prompts.md +++ b/docs-site/content/kagent/1.x/agents/system-prompts.md @@ -96,7 +96,7 @@ The following values are available to a template. | `.AgentTemplateName` | The AgentTemplate's `metadata.name`. | | `.AgentTemplateNamespace` | The AgentTemplate's `metadata.namespace`. | | `.Description` | The AgentTemplate's `spec.description`. | -| `.ToolNames` | The tool names selected from every MCP server the AgentTemplate binds. Agents bound as tools are not included. Prefer this value over listing tools by hand, because it cannot drift from the bindings that the AgentTemplate declares. | +| `.ToolNames` | The tool names selected from every {{< gloss "MCP" >}}MCP{{< /gloss >}} server the AgentTemplate binds. Agents bound as tools are not included. Prefer this value over listing tools by hand, because it cannot drift from the bindings that the AgentTemplate declares. | Additionally, the `include` function pulls in one key from a ConfigMap that `dataSources` lists. The argument is formatted `"/"`, where the source is the ConfigMap's name. Every key in every listed ConfigMap becomes available, so two sources that share a key name collide. kagent rejects that at compile time rather than picking one. diff --git a/docs-site/content/kagent/1.x/examples/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md index e07ed813..88487f71 100644 --- a/docs-site/content/kagent/1.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -1,13 +1,13 @@ --- title: Agent Substrate -description: Watch an agent's Actor suspend between turns, pin the conversation with a checkpoint, and fork it into two independent branches. +description: Watch an agent's Actor suspend between turns, pin its state with a checkpoint, and fork that checkpoint into a second agent. weight: 10 author: kagent.dev --- [Agent Substrate]({{< link path="about/agent-substrate" >}}) runs every agent as an Actor: a sandboxed unit of compute that holds a {{< gloss "Worker" >}}Worker{{< /gloss >}} only while a turn is in progress, and whose state you can pin and branch. This example follows one agent through all three behaviors. -The Actor that these steps follow is also the isolation boundary. Every Actor runs in its own {{< gloss "gVisor" >}}gVisor{{< /gloss >}} sandbox rather than sharing one with its neighbors, which is why a model can safely run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). +The Actor that these steps follow is also the isolation boundary. Every Actor runs in its own {{< gloss "gVisor" >}}gVisor{{< /gloss >}} sandbox rather than sharing one with its neighbors. This isolation allows a model to safely run tools and execute commands. For what the sandbox blocks, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). ## Before you begin @@ -129,9 +129,12 @@ Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent Underneath, the checkpoint attaches an ActorSnapshotTag named `checkpoint-` to the snapshot, and Agent Substrate does not collect a snapshot while a tag names it. You can see the tag by running `kubectl ate get actor-snapshot-tag`. -## Fork the conversation into a second agent +## Fork a checkpoint into a second agent -Forking creates a second AgentInstance that starts from the pinned snapshot, with the transcript up to the checkpoint's position already in place. The original is untouched, so the two conversations diverge from that point. +Forking creates a second AgentInstance from the pinned snapshot, running the revision that the checkpoint was taken on. The original is untouched, so you end up with two independent AgentInstances that started from the same state. + +> [!IMPORTANT] +> A fork does not carry the conversation. It inherits the Actor's durable state as of the checkpoint, and it runs the checkpoint's pinned revision, but it starts its own {{< gloss "Transcript" >}}transcript{{< /gloss >}} rather than continuing the original's. A transcript belongs to the AgentInstance that produced it, so asking a fork about earlier turns returns nothing. Expect this to change: carrying the conversation across a fork is the behavior the API is shaped for, and it is not what the current build does. 1. Fork the checkpoint. ```bash @@ -162,12 +165,12 @@ Forking creates a second AgentInstance that starts from the pinned snapshot, wit 2. Save the fork's ID, then send it down a different path than the original. ```bash export FORK_ID= - kagent invoke --agent-instance $FORK_ID --task "What did I ask you first?" + kagent invoke --agent-instance $FORK_ID --task "List the pods in the kagent namespace." ``` - The fork answers from the transcript it inherited, which is what distinguishes a fork from a new AgentInstance that happens to use the same AgentTemplate. + The fork answers as a new conversation. Send the original a different question and the two diverge from here, each holding its own transcript. -3. List your AgentInstances to verify that both branches appear as separate conversations. +3. List your AgentInstances to verify that both appear as separate AgentInstances. ```bash kagent get agent-instance ``` @@ -182,7 +185,7 @@ Forking creates a second AgentInstance that starts from the pinned snapshot, wit +--------------------------------------+----------------+------------------+-------+----------------------+ ``` -A fork runs the compiled {{< gloss "Revision" >}}revision{{< /gloss >}} that its checkpoint was taken on, not whatever revision the AgentTemplate resolves to now. Editing the AgentTemplate after checkpointing does not change what a fork of that checkpoint runs, which is what makes a fork a faithful continuation rather than a fresh start with an old transcript. +A fork runs the compiled {{< gloss "Revision" >}}revision{{< /gloss >}} that its checkpoint was taken on, not whatever revision the AgentTemplate resolves to now. Editing the AgentTemplate after checkpointing does not change what a fork of that checkpoint runs. That stability is the point of a checkpoint: it holds a known-good configuration you can return to, rather than tracking the template as it moves on. > [!NOTE] > A checkpoint can only be forked when its snapshot captured durable data alone. kagent compiles every ActorTemplate to take a `Data`-scope snapshot on commit, so a checkpoint taken on a suspended AgentInstance is forkable. A checkpoint whose snapshot also captured process state is rejected with `Checkpoint includes process state and cannot be forked`, because process memory belongs to the one Actor that produced it. diff --git a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md new file mode 100644 index 00000000..d553ca2c --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -0,0 +1,211 @@ +--- +title: Use agents from an MCP client +description: Connect Claude Code, Cursor, or another agent to kagent's MCP server, then discover and invoke your AgentInstances as tools. +weight: 20 +author: kagent.dev +--- + +The kagent controller runs a {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) server that exposes your {{< gloss "AgentInstance" >}}AgentInstances{{< /gloss >}} as tools. Any MCP client can then discover the agents in your cluster and delegate work to them. This mechanism allows one agent to orchestrate another as a sub-agent. + +This example runs in the opposite direction to [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}). There, kagent is the MCP client and an external server provides the tools. Here, kagent is the MCP server and your agents are the tools. + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have at least one AgentInstance in the `READY` state. The MCP server lists ready instances only. + +## About the endpoint + +The MCP server is part of the controller's HTTP port rather than a separate deployment, so a default installation already serves it at `/mcp` on port `8083`. + +- **Transport**: Streamable HTTP only. Server-Sent Events (SSE) as a standalone transport and stdio are both unsupported, so a client that offers a transport choice has to use Streamable HTTP. +- **Sessions**: The handler is stateless, so each request stands alone and no session has to be established first. +- **Extensions**: The server advertises the `io.modelcontextprotocol/tasks` extension, which changes how invocations behave. For more information, see [Invoke without waiting](#invoke-without-waiting). + +> [!WARNING] +> The open source build does not authenticate this endpoint. Every request is accepted, and the caller's identity is read from an `X-User-Id` header that the caller sets itself, defaulting to `admin@kagent.dev`. Because the endpoint can invoke agents, create checkpoints, and create AgentInstances, do not expose port `8083` outside the cluster. For the wider identity model and what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). + +## Connect a client + +1. Forward the controller's HTTP port, and leave the command running. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 + ``` + +2. Add `http://localhost:8083/mcp` to your client. + {{< tabs >}} + {{% tab name="Claude Code" %}} + ```bash + claude mcp add --transport http kagent http://localhost:8083/mcp + ``` + Add `--scope project` to limit the entry to the current project rather than your user configuration. + {{% /tab %}} + {{% tab name="Cursor" %}} + Add the server to your Cursor MCP settings. + ```json + { + "mcpServers": { + "kagent": { + "url": "http://localhost:8083/mcp" + } + } + } + ``` + {{% /tab %}} + {{% tab name="curl" %}} + Useful for confirming the endpoint before you configure a client. Streamable HTTP replies are framed as events, so each response arrives on a `data:` line. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}' + ``` + Example output: + ```console + event: message + data: {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"extensions":{"io.modelcontextprotocol/tasks":{}},"tools":{"listChanged":true}},"protocolVersion":"2025-06-18","serverInfo":{"name":"kagent","version":"v1.0.0"}}} + ``` + {{% /tab %}} + {{< /tabs >}} + +## Tools + +The server exposes five tools. Two cover discovery and conversation, and three expose the {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} operations, so a client can pin and branch an agent's state as well as talk to it. Every tool takes a `namespace`, because an AgentInstance is scoped to one. + +| Tool | Required arguments | What it does | +| ---- | ------------------ | ------------ | +| `list_agent_instances` | `namespace` | Lists the ready AgentInstances that the caller created. Takes `match_labels`, `page_size`, and `page_token`. | +| `invoke_agent_instance` | `namespace`, `agent_instance_id`, `message` | Sends a message and returns the agent's reply. Takes `message_id` for idempotency. | +| `create_agent_instance_checkpoint` | `namespace`, `agent_instance_id` | Pins the conversation at a turn boundary. Takes `request_id` for idempotency. | +| `list_agent_instance_checkpoints` | `namespace`, `agent_instance_id` | Lists that instance's checkpoints. Takes `page_size` and `page_token`. | +| `fork_agent_instance` | `namespace`, `checkpoint_id` | Creates a new AgentInstance from a checkpoint. Takes `request_id` for idempotency. | + +> [!NOTE] +> The tools take no session or conversation argument, because an AgentInstance **is** the conversation. Sending a second message to the same `agent_instance_id` continues where the first left off, and the reply's `context_id` matches the instance's own ID. To hold two independent conversations on one AgentTemplate, create two AgentInstances. + +## List and invoke an agent + +1. Ask your client to list the agents in the `kagent` namespace. A client calls `list_agent_instances`, which returns one line per instance plus the same data as structured content. Example output: + ```console + kagent/01a068e3-aeb6-7abc-8d6f-5ba9becd3143 (my-first-agent via my-first-harness) + ``` + + An empty list where you expect instances is almost always creator scoping rather than a missing agent. The tool returns only the instances that the calling identity created, and it has no option to widen that. The kagent command line interface and this endpoint both default to `admin@kagent.dev`, so they see each other's instances. If you created the instance with `kagent --user-id `, send a matching `X-User-Id` header from the client. + +2. Ask the agent a question, naming the instance you want. A client calls `invoke_agent_instance` and blocks until the agent answers. + ```json + { + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "message": "What is 2+2? Answer with just the number." + } + ``` + + The reply text comes back as the tool's content, with the task identifiers alongside it. Example output: + ```json + { + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "task_id": "01a0690e-65d2-7d62-b69d-2ecdcc8064b2", + "context_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "state": "TASK_STATE_COMPLETED", + "text": "4" + } + ``` + +3. Ask a follow-up question against the same instance to confirm that the conversation continues. The agent answers with the earlier turns in context, because the transcript belongs to the AgentInstance rather than to the client. + +## Invoke without waiting + +A client that declares the `io.modelcontextprotocol/tasks` extension gets a different result from the same tool. Rather than blocking, `invoke_agent_instance` returns immediately with a task to poll. This behavior keeps a long agent run from holding a request open. + +The task carries an opaque ID of the form `v1.` that identifies the namespace, the instance, and the A2A task together, so pass it back verbatim rather than parsing it. Example output: +```json +{ + "taskId": "v1.eyJuYW1lc3BhY2UiOiJrYWdlbnQiLCJpbnN0YW5jZUlkIjoi...", + "status": "working", + "createdAt": "2026-09-03T20:56:27.277853198Z", + "lastUpdatedAt": "2026-09-03T20:56:27.277853198Z", + "ttlMs": null, + "pollIntervalMs": 1000, + "resultType": "task" +} +``` + +Poll it with `tasks/get`. The status reports `working`, `input_required`, `completed`, or `cancelled`, and `pollIntervalMs` suggests waiting a second between calls. Once the run finishes, `resultType` changes to `complete` and a `result` field holds the same content that a blocking call would have returned. +```json +{ + "status": "completed", + "statusMessage": "One, two, three.", + "resultType": "complete", + "result": { + "content": [{ "type": "text", "text": "One, two, three." }] + } +} +``` + +Two more methods complete the set. `tasks/cancel` stops a run that is still working, and `tasks/update` answers an agent that is waiting on a person. + +> [!NOTE] +> A `working` task's `statusMessage` holds the raw task record rather than a readable sentence, because the agent has not produced any text yet. Read `status` to decide whether to keep polling, and take the answer from `result` once `resultType` is `complete`. + +## Answer an agent's question + +When an agent pauses to ask something, the task's status becomes `input_required` and `tasks/get` returns an `inputRequests` entry describing what the agent needs. kagent renders that as an MCP elicitation, so a client presents its own prompt and sends the answer back with `tasks/update`. + +The schema kagent builds depends on what the agent asked for. + +- **A question** becomes one string field per question, named `response` when the agent asks one question and `response_1`, `response_2`, and so on when it asks more than one. A question with a fixed set of choices restricts the field to those values, and one that accepts more than one answer takes an array. +- **A tool approval** becomes one boolean field per tool, named `approve_1`, `approve_2`, and so on. A response has to decide every tool in the request. + +An elicitation result of `accept` sends the answers on, while `decline` and `cancel` tell the agent that the person refused, which the agent can then adapt to rather than treating as an error. + +This is the same pause that any other client sees, reached through MCP instead of A2A. For the pause types, the approval model, and what the agent receives, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). + +> [!IMPORTANT] +> Only a client that declares the tasks extension can answer an agent. A blocking `invoke_agent_instance` call has nowhere to surface the question, so an agent that pauses leaves that call waiting. + +## Checkpoint and fork from a client + +The three checkpoint tools give an MCP client the same operations that the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}) performs from the command line. A client might pin a known-good point before letting an agent try something risky, then start a second agent from that point later, on the revision the checkpoint captured rather than whatever the AgentTemplate has become. + +Note that a fork begins its own conversation rather than continuing the original's, so plan for the two AgentInstances to share a starting state and nothing else. For what a fork does and does not inherit, see the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). + +1. Create a checkpoint with `create_agent_instance_checkpoint`. The result identifies the checkpoint and the turn it pinned. Example output: + ```json + { + "checkpoint": { + "id": "01a0690f-5548-7935-b7ca-70919fc9c221", + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "head_task_id": "01a0690f-058d-7d29-a880-9b5d6d30b772", + "history_sequence": 91, + "state": "CHECKPOINT_STATE_READY" + } + } + ``` + +2. Fork it with `fork_agent_instance`, passing the `checkpoint_id`. The result is a new AgentInstance with its own ID, already `READY`. Example output: + ```json + { + "agent_instance": { + "id": "01a0690f-6df2-78fc-b956-5fd1d42f02c2", + "namespace": "kagent", + "harness": "my-first-harness", + "agent_template": "my-first-agent", + "state": "AGENT_INSTANCE_STATE_READY" + } + } + ``` + +3. Invoke the fork with `invoke_agent_instance` and its new ID. The fork runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. + +For what a checkpoint captures and why a checkpoint taken on a suspended instance is the forkable kind, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Follow suspend, checkpoint, and fork from the command line instead." >}} + {{< card link=`{{< link path="agents/human-in-the-loop" >}}` title="Human in the loop" subtitle="Understand the pauses an agent can raise and how a client answers them." >}} + {{< card link=`{{< link path="get-started/your-first-mcp-tool" >}}` title="Your first MCP tool" subtitle="Point kagent at an MCP server so that your agent gains tools of its own." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md index b3651a2b..1c7fd798 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -193,5 +193,5 @@ kubectl delete remotemcpserver my-mcp-server -n kagent {{< cards >}} {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Read the full tool binding schema, including binding one agent as another agent's tool." >}} {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities that no MCP server provides." >}} - {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch your agent's Actor suspend between turns, then checkpoint and fork the conversation." >}} + {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch your agent's Actor suspend between turns, then checkpoint and fork its state." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/observability/tracing.md b/docs-site/content/kagent/1.x/observability/tracing.md index 3cb0ce4d..e4fd3eba 100644 --- a/docs-site/content/kagent/1.x/observability/tracing.md +++ b/docs-site/content/kagent/1.x/observability/tracing.md @@ -38,7 +38,7 @@ A caller reaches the gRPC API on the kagent controller, which starts the trace. > [!IMPORTANT] > The controller passes its tracing configuration only to the `kagent` runtime. An agent on the `codex`, `claude`, or `byo` runtime produces no runtime spans, and its half of the trace is missing. For a `byo` image that implements OTel itself, set the exporter variables in the Harness `spec.env` instead. For the available runtimes, see [Choose a runtime]({{< link path="agents/agent-harness#choose-a-runtime" >}}). -Both processes report themselves as separate OpenTelemetry (OTel) services, which is how a tracing backend groups the spans. +Both processes report themselves as separate OpenTelemetry (OTel) services. A tracing backend uses these service names to group the spans. - **The controller** reports as `kagent-controller` in the `kagent` service namespace. Its spans also carry the pod, node, and namespace that the controller runs on. - **Each agent runtime** reports as its own service, named for the {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} and {{< gloss "Harness" >}}Harness{{< /gloss >}} pair it was compiled from, with hyphens replaced by underscores. The `my-first-agent` template on the `my-first-harness` Harness reports as `my_first_agent_my_first_harness`. diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 56130369..3e2a0c58 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -45,7 +45,7 @@ When an Actor resumes from a `Data`-scope snapshot, the ActorTemplate's `onResum Two kinds of snapshot serve different purposes, and both appear in a normal installation. -- **Golden snapshot**: Captured once, when an ActorTemplate is created, from a temporary golden boot of the workload. Every Actor of that template is first restored from this one shared snapshot, so a new Actor starts from an already-booted image rather than a cold start. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} is not ready until its golden snapshot exists, which is why the kagent controller reports `waiting for the ActorTemplate golden snapshot` while Agent Substrate captures it. +- **Golden snapshot**: Captured once, when an ActorTemplate is created, from a temporary golden boot of the workload. Every Actor of that template is first restored from this one shared snapshot, so a new Actor starts from an already-booted image rather than a cold start. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} is not ready until its golden snapshot exists. Until then, the kagent controller reports `waiting for the ActorTemplate golden snapshot` while Agent Substrate captures it. - **Last snapshot**: The most recent per-Actor snapshot, written on every suspend and used to restore that specific Actor on its next resume. Because it carries the Actor's own accumulated state, the conversation continues from where it stopped. Snapshots are persisted to object storage, either Google Cloud Storage or Amazon Simple Storage Service (S3), so that Actor state is durable and portable across the cluster. A {{< gloss "Harness" >}}Harness{{< /gloss >}} names the location for its Actors' snapshots in its `substrate.snapshotPolicy` section. @@ -85,4 +85,4 @@ Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the Agen An AgentInstance must be a turn boundary to be checkpointed, because the turn boundary is captured. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. -A checkpoint also records where the conversation had reached, which lets you start a second AgentInstance from that point. To create a checkpoint and fork an AgentInstance from it, work through the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). +A checkpoint also records how far the conversation had advanced, and it lets you start a second AgentInstance from the state it pinned. That second AgentInstance, a {{< gloss "Fork" >}}fork{{< /gloss >}}, begins its own conversation rather than continuing the original's. To create a checkpoint and fork an AgentInstance from it, work through the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index b790ae18..86007713 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -65,7 +65,7 @@ Snapshot: short: "The stored state that an Actor suspends to, held in object storage. Resuming restores the Actor from its most recent snapshot, which is what makes suspending idle agents cheap." Fork: - short: "A second AgentInstance created from a checkpoint, starting with the transcript and state that the checkpoint pinned. A fork inherits the checkpoint's revision, so later edits to the AgentTemplate do not change what it runs." + short: "A second AgentInstance created from a checkpoint, starting from the durable state that the checkpoint pinned. A fork inherits the checkpoint's revision, so later edits to the AgentTemplate do not change what it runs, and it begins its own transcript rather than continuing the original's." Transcript: short: "The record of an AgentInstance's conversation, held server-side and append-only. It survives the Actor suspending between turns, and a resumed runtime cannot shrink it." @@ -82,6 +82,9 @@ Tool binding: Model Context Protocol: short: "An open protocol for exposing tools and resources to a model. kagent reaches an MCP server through a RemoteMCPServer resource, and an AgentTemplate binds individual tools from it." +MCP: + short: "Model Context Protocol, an open protocol for exposing tools and resources to a model. kagent reaches an MCP server through a RemoteMCPServer resource, and an AgentTemplate binds individual tools from it." + A2A: short: "The Agent-to-Agent protocol, which callers and other agents use to talk to an AgentInstance. The conversation's context identifier is the AgentInstance ID, so a second message on the same ID continues the same conversation." From 2d9d2cddd85fd60470d7aa36186084026fdaf30f Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 4 Sep 2026 11:19:19 -0500 Subject: [PATCH 45/70] more wording Signed-off-by: Rachael Graham --- .../kagent/1.x/about/agent-substrate.md | 2 +- .../content/kagent/1.x/about/core-concepts.md | 2 +- .../content/kagent/1.x/agents/agent-memory.md | 10 +- .../kagent/1.x/examples/agents-via-mcp.md | 480 +++++++++++++++--- .../kagent/1.x/skills-and-mcp/skills.md | 2 +- .../1.x/substrate-runtime/sandboxing.md | 4 +- .../substrate-runtime/suspend-and-resume.md | 4 +- 7 files changed, 417 insertions(+), 87 deletions(-) diff --git a/docs-site/content/kagent/1.x/about/agent-substrate.md b/docs-site/content/kagent/1.x/about/agent-substrate.md index 1d6512d6..613c5707 100644 --- a/docs-site/content/kagent/1.x/about/agent-substrate.md +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -11,7 +11,7 @@ The [kagent architecture]({{< link path="about/architecture" >}}) page establish Every Actor is created from an **ActorTemplate**, the compiled definition that the kagent controller produces from a {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} pair. -What Substrate adds is enforcement. Substrate rejects any change to an ActorTemplate's spec after it is created, so immutability is a property of the resource itself rather than a convention that the controller follows. That immutability requires the controller to create a new ActorTemplate for every compiled {{< gloss "Revision" >}}revision{{< /gloss >}} instead of editing an existing one, and allows the controller to safely reclaim an old ActorTemplate once no AgentInstance references it. +Substrate adds enforcement. It rejects any change to an ActorTemplate's spec after it is created, so immutability is a property of the resource itself rather than a convention that the controller follows. That immutability requires the controller to create a new ActorTemplate for every compiled {{< gloss "Revision" >}}revision{{< /gloss >}} instead of editing an existing one, and allows the controller to safely reclaim an old ActorTemplate once no AgentInstance references it. ## Workers and WorkerPools 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 b1886db4..f1294057 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -87,7 +87,7 @@ Under the hood, the kagent controller watches for valid Harness and AgentTemplat Each compile produces one **{{< gloss "Revision" >}}revision{{< /gloss >}}**, identified by a digest: a SHA-256 hash of the compiled configuration. Because that digest is derived from the configuration itself, editing a Harness or AgentTemplate compiles to a different digest, and therefore becomes a separate ActorTemplate. kagent never rewrites an existing one. -That immutability is what keeps running conversations stable. When you create an AgentInstance, kagent looks up the newest revision that compiled successfully for that Harness and AgentTemplate pair, and then creates an Actor from that revision. Editing the Harness or AgentTemplate afterward does not disturb that AgentInstance, which keeps running on the revision that it was created from. Only AgentInstances created after the edit use the new revision. +That immutability keeps running conversations stable. When you create an AgentInstance, kagent looks up the newest revision that compiled successfully for that Harness and AgentTemplate pair, and then creates an Actor from that revision. Editing the Harness or AgentTemplate afterward does not disturb that AgentInstance, which keeps running on the revision that it was created from. Only AgentInstances created after the edit use the new revision. Once created, an AgentInstance talks to callers over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol, through kagent's A2A gateway. The gateway resolves each request to the right AgentInstance and forwards it to the Actor running behind it. diff --git a/docs-site/content/kagent/1.x/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md index b3ac4f01..8643f0be 100644 --- a/docs-site/content/kagent/1.x/agents/agent-memory.md +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -199,8 +199,8 @@ Each memory is one row in the `memory` table, which the vector migration created Review the following table to understand the `memory` table output. | Column | What it holds | | ------ | ------------- | - | `content` | The text that the agent saved, which is what retrieval returns to a later conversation. | - | `agent_name` | The agent that owns the memory, written as `__NS__` with every hyphen replaced by an underscore. | + | `content` | The text that the agent saved. Retrieval returns it to a later conversation. | + | `agent_name` | The agent that owns the memory, written as `__NS___` with every hyphen replaced by an underscore. The AgentTemplate and Harness pair identifies a runtime, so the same AgentTemplate on two Harnesses owns two separate sets of memories. | | `user_id` | The user that the memory belongs to. | | `embedding` | The 768-dimensional vector that similarity search compares a query against. | | `created_at` and `expires_at` | When kagent wrote the memory, and `ttlDays` after that. | @@ -210,7 +210,7 @@ Each memory is one row in the `memory` table, which the vector migration created The SQL query only reads the table. To list or clear memories, call the `MemoryService` that the kagent controller serves over gRPC. -No CLI command wraps the service yet, so these examples call it with [grpcurl](https://github.com/fullstorydev/grpcurl), and both calls take the `agent_name` exactly as the memory table stores it. +No CLI command wraps the service yet, so these examples call it with [grpcurl](https://github.com/fullstorydev/grpcurl), and both calls take the `agent_name` exactly as the memory table stores it. Be sure to copy the value out of the table rather than assembling it by hand, because an incorrect name fails silently. 1. Port-forward the controller's gRPC port, and confirm that your kagent installation sets `controller.grpc.reflection=true`. ```bash @@ -220,7 +220,7 @@ No CLI command wraps the service yet, so these examples call it with [grpcurl](h 2. List the memories that an agent stores for one user. ```bash grpcurl -plaintext -d '{ - "agent_name": "kagent__NS__my_first_agent", + "agent_name": "kagent__NS__my_first_agent_my_first_harness", "user_id": "admin@kagent.dev" }' localhost:8084 kagent.api.v1alpha1.MemoryService/List ``` @@ -230,7 +230,7 @@ No CLI command wraps the service yet, so these examples call it with [grpcurl](h 3. Delete the memories for an agent and user. ```bash grpcurl -plaintext -d '{ - "agent_name": "kagent__NS__my_first_agent", + "agent_name": "kagent__NS__my_first_agent_my_first_harness", "user_id": "admin@kagent.dev" }' localhost:8084 kagent.api.v1alpha1.MemoryService/Delete ``` diff --git a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md index d553ca2c..f341cd4d 100644 --- a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -9,22 +9,27 @@ The kagent controller runs a {{< gloss "Model Context Protocol" >}}Model Context This example runs in the opposite direction to [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}). There, kagent is the MCP client and an external server provides the tools. Here, kagent is the MCP server and your agents are the tools. -## Before you begin - -1. [Install kagent]({{< link path="setup/installation" >}}). -2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have at least one AgentInstance in the `READY` state. The MCP server lists ready instances only. +You can do this work from an MCP client such as Claude Code or Cursor, which builds the calls for you, or with raw `curl` requests when you want to see those calls or drive the endpoint without a client. -## About the endpoint +## About the kagent MCP server The MCP server is part of the controller's HTTP port rather than a separate deployment, so a default installation already serves it at `/mcp` on port `8083`. -- **Transport**: Streamable HTTP only. Server-Sent Events (SSE) as a standalone transport and stdio are both unsupported, so a client that offers a transport choice has to use Streamable HTTP. -- **Sessions**: The handler is stateless, so each request stands alone and no session has to be established first. +- **Transport**: Streamable HTTP only. Server-Sent Events (SSE) as a standalone transport and stdio are both unsupported, so a client that offers a transport choice must use Streamable HTTP. +- **Sessions**: The handler is stateless, so each request stands alone and a client does not need to establish a session first. - **Extensions**: The server advertises the `io.modelcontextprotocol/tasks` extension, which changes how invocations behave. For more information, see [Invoke without waiting](#invoke-without-waiting). +> [!NOTE] +> The tools take no session or conversation argument, because an AgentInstance **is** the conversation. Sending a second message to the same `agent_instance_id` continues where the first left off, and the reply's `context_id` matches the instance's own ID. To hold two independent conversations on one AgentTemplate, create two AgentInstances. + > [!WARNING] > The open source build does not authenticate this endpoint. Every request is accepted, and the caller's identity is read from an `X-User-Id` header that the caller sets itself, defaulting to `admin@kagent.dev`. Because the endpoint can invoke agents, create checkpoints, and create AgentInstances, do not expose port `8083` outside the cluster. For the wider identity model and what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have at least one AgentInstance in the `READY` state. The MCP server lists ready instances only. + ## Connect a client 1. Forward the controller's HTTP port, and leave the command running. @@ -35,10 +40,12 @@ The MCP server is part of the controller's HTTP port rather than a separate depl 2. Add `http://localhost:8083/mcp` to your client. {{< tabs >}} {{% tab name="Claude Code" %}} + Add `--scope project` to limit the entry to the current project rather than your user configuration. ```bash claude mcp add --transport http kagent http://localhost:8083/mcp ``` - Add `--scope project` to limit the entry to the current project rather than your user configuration. + + Continue with the steps in [Use agents from Claude Code or Cursor](#use-agents-from-claude-code-or-cursor). {{% /tab %}} {{% tab name="Cursor" %}} Add the server to your Cursor MCP settings. @@ -51,9 +58,11 @@ The MCP server is part of the controller's HTTP port rather than a separate depl } } ``` + + Continue with the steps in [Use agents from Claude Code or Cursor](#use-agents-from-claude-code-or-cursor). {{% /tab %}} {{% tab name="curl" %}} - Useful for confirming the endpoint before you configure a client. Streamable HTTP replies are framed as events, so each response arrives on a `data:` line. + Nothing needs to be registered, because each request stands alone. Confirm the endpoint before you continue. Streamable HTTP replies are framed as events, so each response arrives on a `data:` line. ```bash curl -s -X POST http://localhost:8083/mcp \ -H 'Content-Type: application/json' \ @@ -65,131 +74,407 @@ The MCP server is part of the controller's HTTP port rather than a separate depl event: message data: {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"extensions":{"io.modelcontextprotocol/tasks":{}},"tools":{"listChanged":true}},"protocolVersion":"2025-06-18","serverInfo":{"name":"kagent","version":"v1.0.0"}}} ``` + + Continue with the steps in [Use agents from curl](#use-agents-from-curl). {{% /tab %}} {{< /tabs >}} -## Tools +## Use agents from Claude Code or Cursor -The server exposes five tools. Two cover discovery and conversation, and three expose the {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} operations, so a client can pin and branch an agent's state as well as talk to it. Every tool takes a `namespace`, because an AgentInstance is scoped to one. +Claude Code and Cursor read the tool schemas and build each call, so you work in plain language rather than JSON. You discover the agents in your cluster, hold a conversation with one, answer the agent when it stops to ask you something, and pin its state so that a second agent can start from that point. -| Tool | Required arguments | What it does | -| ---- | ------------------ | ------------ | -| `list_agent_instances` | `namespace` | Lists the ready AgentInstances that the caller created. Takes `match_labels`, `page_size`, and `page_token`. | -| `invoke_agent_instance` | `namespace`, `agent_instance_id`, `message` | Sends a message and returns the agent's reply. Takes `message_id` for idempotency. | -| `create_agent_instance_checkpoint` | `namespace`, `agent_instance_id` | Pins the conversation at a turn boundary. Takes `request_id` for idempotency. | -| `list_agent_instance_checkpoints` | `namespace`, `agent_instance_id` | Lists that instance's checkpoints. Takes `page_size` and `page_token`. | -| `fork_agent_instance` | `namespace`, `checkpoint_id` | Creates a new AgentInstance from a checkpoint. Takes `request_id` for idempotency. | +### List and invoke an agent + +1. Ask for the agents in the `kagent` namespace. The client calls `list_agent_instances` and reports one line per instance. + ```console + > List the kagent agents in the kagent namespace. + ``` + + An unexpectedly empty list is typically due to creator scoping rather than a missing agent. The tool returns only the instances that the calling identity created, and has no option to widen that scope. The kagent command line interface and this endpoint both default to `admin@kagent.dev`, so they see each other's instances. If you created the instance with `kagent --user-id `, send a matching `X-User-Id` header from the client. + +2. Ask the agent a question by naming the instance you want to use. The client calls `invoke_agent_instance` and fills in the arguments from the tool schema. + ```console + > Ask kagent agent instance 01a068e3-aeb6-7abc-8d6f-5ba9becd3143 in the + kagent namespace: what is 2+2? Answer with just the number. + ``` + +3. Ask a follow-up that depends on the previous answer, such as `Multiply that by 10.`, against the same instance. The word "that" resolves only when the earlier turns are in context, because the transcript belongs to the AgentInstance rather than to the client. > [!NOTE] -> The tools take no session or conversation argument, because an AgentInstance **is** the conversation. Sending a second message to the same `agent_instance_id` continues where the first left off, and the reply's `context_id` matches the instance's own ID. To hold two independent conversations on one AgentTemplate, create two AgentInstances. +> Nothing here configures whether an invocation blocks or returns a task to poll, because a client declares its own capabilities on each request. A reply means your client did not declare the `io.modelcontextprotocol/tasks` extension and the call waited for the agent to finish. A task ID means it did, and the client polls in the background so that a long agent run never holds a request open. + +### Answer an agent's question + +When an agent pauses to ask something, kagent returns the question as an MCP elicitation and your client presents its own prompt: the agent's question, and a fixed set of choices where the agent offered them. When you answer it, the agent resumes the turn where it left off. When you refuse it, the agent is told that the person declined, which it can adapt to rather than treating it as an error. + +> [!IMPORTANT] +> Only a client that declares the tasks extension can answer an agent. A blocking `invoke_agent_instance` call has nowhere to surface the question, so an agent that pauses leaves that call waiting. + +This is the same pause that any other client sees, reached through MCP instead of A2A. For the pause types, the approval model, and what the agent receives, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). + +### Checkpoint and fork + +Ask the client to checkpoint an instance before letting an agent try something risky, then to fork that checkpoint later to start a second agent from the pinned state. The client calls the three {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} tools, which give it the same operations that the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}) performs from the command line. + +```console +> Checkpoint kagent agent instance 01a068e3-aeb6-7abc-8d6f-5ba9becd3143, + then fork that checkpoint and ask the fork what 10+5 is. +``` -## List and invoke an agent +A fork begins its own conversation rather than continuing the original's, so plan for the two AgentInstances to share a starting state and nothing else. It also runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. -1. Ask your client to list the agents in the `kagent` namespace. A client calls `list_agent_instances`, which returns one line per instance plus the same data as structured content. Example output: +## Use agents from curl + +With `curl` you build each request yourself, so every field is visible: the tool name, its arguments, and the `_meta` that decides whether a call blocks or returns a task to poll. You list the agents in your cluster, hold a conversation with one, answer the agent when it pauses, and checkpoint an instance to fork a second agent from it. Every request is a `tools/call` to `/mcp` unless it names a `tasks/` method, and none of them needs an `initialize` handshake first. + +> [!NOTE] +> Do not put `io.modelcontextprotocol/protocolVersion` in a request's `_meta`. The server then requires a matching `Mcp-Protocol-Version` header and rejects the call without one. Neither field is necessary for any of these requests. + +### List and invoke an agent + +1. List the ready AgentInstances in the namespace. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 1, + "method": "tools/call", + "params": { + "name": "list_agent_instances", + "arguments": { "namespace": "kagent" } + } + }' + ``` + + The reply carries one line per instance as text, plus the same data as structured content. Example output: ```console kagent/01a068e3-aeb6-7abc-8d6f-5ba9becd3143 (my-first-agent via my-first-harness) ``` - An empty list where you expect instances is almost always creator scoping rather than a missing agent. The tool returns only the instances that the calling identity created, and it has no option to widen that. The kagent command line interface and this endpoint both default to `admin@kagent.dev`, so they see each other's instances. If you created the instance with `kagent --user-id `, send a matching `X-User-Id` header from the client. +2. Send a message and wait for the reply. A blocking call needs no `_meta`, because the tool's default behavior asks nothing of the client. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": { + "name": "invoke_agent_instance", + "arguments": { + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "message": "What is 2+2? Answer with just the number." + } + } + }' + ``` -2. Ask the agent a question, naming the instance you want. A client calls `invoke_agent_instance` and blocks until the agent answers. + The reply text comes back as the tool's content, with the task identifiers alongside it. Example output: ```json { "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", - "message": "What is 2+2? Answer with just the number." + "task_id": "01a06d0d-5fcf-7b07-aae3-1f470a8ee157", + "context_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "state": "TASK_STATE_COMPLETED", + "text": "4" } ``` - The reply text comes back as the tool's content, with the task identifiers alongside it. Example output: +3. Send the same request again with `Multiply that by 10.` as the `message`. The word "that" resolves only when the earlier turns are in context. Note that `context_id` is unchanged while `task_id` is new, so the second turn joined the first conversation instead of starting its own. Example output: ```json { "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", - "task_id": "01a0690e-65d2-7d62-b69d-2ecdcc8064b2", + "task_id": "01a06d0d-6864-79f1-a4cb-8547f77638ba", "context_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", "state": "TASK_STATE_COMPLETED", - "text": "4" + "text": "40" } ``` -3. Ask a follow-up question against the same instance to confirm that the conversation continues. The agent answers with the earlier turns in context, because the transcript belongs to the AgentInstance rather than to the client. +### Invoke without waiting -## Invoke without waiting +Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's result. Rather than blocking, `invoke_agent_instance` returns immediately with a task to poll, which keeps a long agent run from holding a request open. Because the handler is stateless, the declaration travels in the `_meta` of every request rather than being established once, and that includes each poll. -A client that declares the `io.modelcontextprotocol/tasks` extension gets a different result from the same tool. Rather than blocking, `invoke_agent_instance` returns immediately with a task to poll. This behavior keeps a long agent run from holding a request open. +1. Invoke the agent with the extension declared in `params._meta`. Leave the declaration out and the tool blocks instead, as in [List and invoke an agent](#list-and-invoke-an-agent-1). + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 3, + "method": "tools/call", + "params": { + "name": "invoke_agent_instance", + "arguments": { + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "message": "Count to three." + }, + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { "io.modelcontextprotocol/tasks": {} } + } + } + } + }' + ``` -The task carries an opaque ID of the form `v1.` that identifies the namespace, the instance, and the A2A task together, so pass it back verbatim rather than parsing it. Example output: -```json -{ - "taskId": "v1.eyJuYW1lc3BhY2UiOiJrYWdlbnQiLCJpbnN0YW5jZUlkIjoi...", - "status": "working", - "createdAt": "2026-09-03T20:56:27.277853198Z", - "lastUpdatedAt": "2026-09-03T20:56:27.277853198Z", - "ttlMs": null, - "pollIntervalMs": 1000, - "resultType": "task" -} -``` + The task carries an opaque ID of the form `v1.` that identifies the namespace, the instance, and the A2A task together, so pass it back verbatim rather than parsing it. Example output: + ```json + { + "taskId": "v1.eyJuYW1lc3BhY2UiOiJrYWdlbnQiLCJpbnN0YW5jZUlkIjoi...", + "status": "working", + "createdAt": "2026-09-04T15:35:25.722159606Z", + "lastUpdatedAt": "2026-09-04T15:35:25.722159606Z", + "ttlMs": null, + "pollIntervalMs": 1000, + "resultType": "task" + } + ``` -Poll it with `tasks/get`. The status reports `working`, `input_required`, `completed`, or `cancelled`, and `pollIntervalMs` suggests waiting a second between calls. Once the run finishes, `resultType` changes to `complete` and a `result` field holds the same content that a blocking call would have returned. -```json -{ - "status": "completed", - "statusMessage": "One, two, three.", - "resultType": "complete", - "result": { - "content": [{ "type": "text", "text": "One, two, three." }] - } -} -``` +2. Poll the task with `tasks/get`, waiting the interval that `pollIntervalMs` suggests between calls. Carry the same `_meta` declaration on every poll: a request that omits it is rejected with `-32021 tasks capability required but not declared by client` rather than falling back to a blocking read. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 4, + "method": "tasks/get", + "params": { + "taskId": "", + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { "io.modelcontextprotocol/tasks": {} } + } + } + } + }' + ``` + + Read `status` to decide whether to keep polling: it reports `working`, `input_required`, `completed`, or `cancelled`. A status of `input_required` means the agent is waiting on a person, which [Answer an agent's question](#answer-an-agents-question-1) covers. + +3. Take the answer once `status` reads `completed`. The `result` field holds the same content that a blocking call would have returned, as both `content` and `structuredContent`. Example output: + ```json + { + "status": "completed", + "statusMessage": "1, 2, 3.", + "resultType": "complete", + "result": { + "content": [{ "type": "text", "text": "1, 2, 3." }] + } + } + ``` Two more methods complete the set. `tasks/cancel` stops a run that is still working, and `tasks/update` answers an agent that is waiting on a person. +> [!WARNING] +> Read `status` rather than `resultType` to decide that a run is over. A paused task reports `resultType` as `complete` while its `status` is still `input_required`, so `resultType` alone does not mean an answer is waiting. + > [!NOTE] -> A `working` task's `statusMessage` holds the raw task record rather than a readable sentence, because the agent has not produced any text yet. Read `status` to decide whether to keep polling, and take the answer from `result` once `resultType` is `complete`. +> `statusMessage` changes meaning with the status. On a `working` task it holds the raw task record rather than a readable sentence, because the agent has not produced any text yet, so do not present it to a person as progress text. On an `input_required` task it holds the agent's question, and on a `completed` task it holds the reply. -## Answer an agent's question +### Answer an agent's question -When an agent pauses to ask something, the task's status becomes `input_required` and `tasks/get` returns an `inputRequests` entry describing what the agent needs. kagent renders that as an MCP elicitation, so a client presents its own prompt and sends the answer back with `tasks/update`. +When an agent pauses to ask something, the task's status becomes `input_required` and `tasks/get` returns an `inputRequests` object describing what the agent needs. kagent builds that as an MCP elicitation, and answering it is a `tasks/update` call. -The schema kagent builds depends on what the agent asked for. +1. Poll the paused task and read `inputRequests`. It is keyed by request ID, and each entry is an `elicitation/create` call whose `requestedSchema` is the schema kagent built for the pause. Note the key, because answering needs it. Example output: + ```json + { + "status": "input_required", + "statusMessage": "Which database should we use?", + "inputRequests": { + "01a06d12-4832-7e1f-873d-c25bc6b6b70b": { + "method": "elicitation/create", + "params": { + "mode": "form", + "message": "Which database should we use?", + "requestedSchema": { + "type": "object", + "properties": { + "response": { + "type": "string", + "description": "Which database should we use?", + "enum": ["PostgreSQL", "MySQL"] + } + }, + "required": ["response"], + "additionalProperties": false + } + } + } + } + } + ``` -- **A question** becomes one string field per question, named `response` when the agent asks one question and `response_1`, `response_2`, and so on when it asks more than one. A question with a fixed set of choices restricts the field to those values, and one that accepts more than one answer takes an array. -- **A tool approval** becomes one boolean field per tool, named `approve_1`, `approve_2`, and so on. A response has to decide every tool in the request. + The schema's shape depends on what the agent asked for. + - **A question** becomes one string field per question, named `response` when the agent asks one question and `response_1`, `response_2`, and so on when it asks more than one. A question with a fixed set of choices restricts the field to those values with `enum`, and one that accepts more than one answer takes an array. + - **A tool approval** becomes one boolean field per tool, named `approve_1`, `approve_2`, and so on. A response must decide every tool in the request. -An elicitation result of `accept` sends the answers on, while `decline` and `cancel` tell the agent that the person refused, which the agent can then adapt to rather than treating as an error. +2. Send the answer with `tasks/update`, keying `inputResponses` by the same request ID. An elicitation result of `accept` sends the answers on, while `decline` and `cancel` tell the agent that the person refused. An agent can adapt to a refusal rather than treating it as an error. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 5, + "method": "tasks/update", + "params": { + "taskId": "", + "inputResponses": { + "01a06d12-4832-7e1f-873d-c25bc6b6b70b": { + "action": "accept", + "content": { "response": "PostgreSQL" } + } + }, + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { "io.modelcontextprotocol/tasks": {} } + } + } + } + }' + ``` -This is the same pause that any other client sees, reached through MCP instead of A2A. For the pause types, the approval model, and what the agent receives, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). + The reply confirms only that the update was accepted, and carries no agent output. Example output: + ```json + { "resultType": "complete" } + ``` -> [!IMPORTANT] -> Only a client that declares the tasks extension can answer an agent. A blocking `invoke_agent_instance` call has nowhere to surface the question, so an agent that pauses leaves that call waiting. +3. Poll the task again to collect the resumed turn. The agent picks up where it paused, so the status returns to `working` and then `completed` with the answer your response produced. Example output: + ```json + { + "status": "completed", + "statusMessage": "You chose PostgreSQL as the database to use.", + "resultType": "complete", + "result": { + "content": [{ "type": "text", "text": "You chose PostgreSQL as the database to use." }] + } + } + ``` + +> [!WARNING] +> A response whose key does not match the `inputRequests` key is discarded silently. The call still returns `{ "resultType": "complete" }`, but the agent never receives the answer and the task stays `input_required` until something answers it under the right key or cancels it. Read the key from `tasks/get` rather than reusing a task ID or a checkpoint ID. + +For the pause types, the approval model, and what the agent receives, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). -## Checkpoint and fork from a client +### Checkpoint and fork -The three checkpoint tools give an MCP client the same operations that the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}) performs from the command line. A client might pin a known-good point before letting an agent try something risky, then start a second agent from that point later, on the revision the checkpoint captured rather than whatever the AgentTemplate has become. +The three checkpoint tools pin an instance's state and start a second agent from it. None of them needs the tasks extension, so none carries `_meta`. -Note that a fork begins its own conversation rather than continuing the original's, so plan for the two AgentInstances to share a starting state and nothing else. For what a fork does and does not inherit, see the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). +1. Create a checkpoint. The `request_id` is an idempotency key, so repeating the call with the same value returns the checkpoint that the first call created rather than pinning a second one. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 6, + "method": "tools/call", + "params": { + "name": "create_agent_instance_checkpoint", + "arguments": { + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "request_id": "my-first-checkpoint" + } + } + }' + ``` -1. Create a checkpoint with `create_agent_instance_checkpoint`. The result identifies the checkpoint and the turn it pinned. Example output: + The result identifies the checkpoint and the turn it pinned. Example output: ```json { "checkpoint": { - "id": "01a0690f-5548-7935-b7ca-70919fc9c221", + "id": "01a06d19-540a-7040-befb-ec4499c96ff2", "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", - "head_task_id": "01a0690f-058d-7d29-a880-9b5d6d30b772", - "history_sequence": 91, - "state": "CHECKPOINT_STATE_READY" + "head_task_id": "01a06d13-2504-7245-9eaf-9c1870c51d26", + "history_sequence": 398, + "state": "CHECKPOINT_STATE_READY", + "created_at": "2026-09-04T15:46:11.594634Z" } } ``` -2. Fork it with `fork_agent_instance`, passing the `checkpoint_id`. The result is a new AgentInstance with its own ID, already `READY`. Example output: +2. List the instance's checkpoints to confirm what you can fork from. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 7, + "method": "tools/call", + "params": { + "name": "list_agent_instance_checkpoints", + "arguments": { + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143" + } + } + }' + ``` + + The result is a `checkpoints` array of the same records, oldest first. Example output: + ```json + { + "checkpoints": [ + { + "id": "01a0690f-5548-7935-b7ca-70919fc9c221", + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "head_task_id": "01a0690f-058d-7d29-a880-9b5d6d30b772", + "history_sequence": 91, + "state": "CHECKPOINT_STATE_READY", + "created_at": "2026-09-03T20:56:47.689204Z" + }, + { + "id": "01a06d19-540a-7040-befb-ec4499c96ff2", + "namespace": "kagent", + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "head_task_id": "01a06d13-2504-7245-9eaf-9c1870c51d26", + "history_sequence": 398, + "state": "CHECKPOINT_STATE_READY", + "created_at": "2026-09-04T15:46:11.594634Z" + } + ] + } + ``` + +3. Fork the checkpoint into a second AgentInstance. This call takes `checkpoint_id` rather than an instance ID, because the checkpoint already identifies the instance it was taken on. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 8, + "method": "tools/call", + "params": { + "name": "fork_agent_instance", + "arguments": { + "namespace": "kagent", + "checkpoint_id": "01a06d19-540a-7040-befb-ec4499c96ff2", + "request_id": "my-first-fork" + } + } + }' + ``` + + The result is a new AgentInstance with its own ID, already `READY`, on the same Harness and AgentTemplate as the original. Example output: ```json { "agent_instance": { - "id": "01a0690f-6df2-78fc-b956-5fd1d42f02c2", + "id": "01a06d19-7eec-797b-87b8-7397a96b1544", "namespace": "kagent", "harness": "my-first-harness", "agent_template": "my-first-agent", @@ -198,9 +483,54 @@ Note that a fork begins its own conversation rather than continuing the original } ``` -3. Invoke the fork with `invoke_agent_instance` and its new ID. The fork runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. +4. Invoke the fork with `invoke_agent_instance` and its new ID. Note that `context_id` matches the fork's own ID rather than the original's, so the fork holds a separate conversation from the moment it is created. Example output: + ```json + { + "namespace": "kagent", + "agent_instance_id": "01a06d19-7eec-797b-87b8-7397a96b1544", + "task_id": "01a06d19-80e7-7554-8288-377eda9e861b", + "context_id": "01a06d19-7eec-797b-87b8-7397a96b1544", + "state": "TASK_STATE_COMPLETED", + "text": "15" + } + ``` + +A fork runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. For what a checkpoint captures, why a checkpoint taken on a suspended instance is the forkable kind, and what a fork does and does not inherit, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) and the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). -For what a checkpoint captures and why a checkpoint taken on a suspended instance is the forkable kind, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). +## Clean up + +1. Delete the fork that you created. No MCP tool deletes an AgentInstance, so use the kagent command line interface. + ```bash + kagent delete agent-instance + ``` + +2. Forward the controller's gRPC port, and leave the command running. Deleting a checkpoint has neither an MCP tool nor a kagent command, so it goes through `CheckpointService` on a different port from the one that serves MCP. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + +3. Delete the checkpoint that you created, with [grpcurl](https://github.com/fullstorydev/grpcurl). The call reads the service definition from the server, so it needs your installation to set `controller.grpc.reflection`. + ```bash + grpcurl -plaintext \ + -d '{"namespace":"kagent","checkpointId":""}' \ + localhost:8084 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint + ``` + +4. Remove the server entry from your client. In Claude Code, run `claude mcp remove kagent`. In Cursor, delete the `kagent` entry from your MCP settings. + +5. Stop both port-forwards with `Ctrl+C`. + +## MCP tool reference + +The server exposes five tools. Two cover discovery and conversation, and three expose the {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} operations, so a client can pin and branch an agent's state as well as talk to it. Every tool takes a `namespace`, because an AgentInstance is scoped to one. Nothing here deletes an object, so removing an AgentInstance or a checkpoint means leaving MCP for the command line. + +| Tool | Required arguments | What it does | +| ---- | ------------------ | ------------ | +| `list_agent_instances` | `namespace` | Lists the ready AgentInstances that the caller created. Takes `match_labels`, `page_size`, and `page_token`. | +| `invoke_agent_instance` | `namespace`, `agent_instance_id`, `message` | Sends a message and returns the agent's reply. Takes `message_id` for idempotency. | +| `create_agent_instance_checkpoint` | `namespace`, `agent_instance_id` | Pins the conversation at a turn boundary. Takes `request_id` for idempotency. | +| `list_agent_instance_checkpoints` | `namespace`, `agent_instance_id` | Lists that instance's checkpoints. Takes `page_size` and `page_token`. | +| `fork_agent_instance` | `namespace`, `checkpoint_id` | Creates a new AgentInstance from a checkpoint. Takes `request_id` for idempotency. | ## Next steps 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 5408c813..f02668a8 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 @@ -11,7 +11,7 @@ A **{{< gloss "Skill" >}}skill{{< /gloss >}}** packages a piece of know-how that 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 is what 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, 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. 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" >}}). diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index f1b7773a..48fce19d 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -39,7 +39,7 @@ A {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} selects its class through t A **SandboxConfig** is a cluster-scoped resource that holds the material needed to start one sandbox runtime family. It carries the runtime assets that the node agent fetches, keyed by processor architecture, along with the pause image that holds the sandbox's namespaces as its root container. One SandboxConfig can be marked as the cluster default for its class, and a WorkerPool that names no configuration explicitly resolves to that default. -Defining these assets in a cluster resource is what lets one configuration pin a runtime version for many ActorTemplates at once, rather than each template carrying its own copy. +Defining these assets in a cluster resource lets one configuration pin a runtime version for many ActorTemplates at once, rather than each template carrying its own copy. A default installation creates a single `gvisor-default` configuration, which looks like the following: @@ -81,7 +81,7 @@ The sandbox draws a boundary in three places. ## How traffic reaches a sandboxed Actor -Every Actor is addressed by its {{< gloss "Atespace" >}}atespace{{< /gloss >}} and name, at `..actors.resources.substrate.ate.dev`. Reaching it involves several hops, and each one is what keeps a sandboxed Actor addressable without exposing the Worker that it happens to be running on. +Every Actor is addressed by its {{< gloss "Atespace" >}}atespace{{< /gloss >}} and name, at `..actors.resources.substrate.ate.dev`. Reaching it involves several hops, and each one keeps a sandboxed Actor addressable without exposing the Worker that it happens to be running on. 1. Agent Substrate runs its own Domain Name System (DNS) service that answers queries for that address pattern with the address of the router, rather than any individual Worker. 2. The router reads the Actor name and atespace from the request, asks the Agent Substrate API to resume that Actor and report which Worker it is now assigned to, then selects that Worker as the destination. diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 3e2a0c58..3973be5b 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -23,7 +23,7 @@ The following diagram traces an Actor through those operations, and shows the fu An Actor reports its position in that cycle through its state, which is one of `RESUMING`, `RUNNING`, `SUSPENDING`, `SUSPENDED`, `PAUSING`, `PAUSED`, `CRASHED`, or `DELETING`. Only a suspended Actor can be deleted. > [!NOTE] -> Resume restores an Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that the Actor ran on before. Suspend and resume are what let a {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} carry far more Actors than it has Workers at any one moment. +> Resume restores an Actor onto whichever Worker in the pool is free, which is not necessarily the Worker that the Actor ran on before. Suspend and resume let a {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} carry far more Actors than it has Workers at any one moment. ## What a snapshot captures @@ -75,7 +75,7 @@ The {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}}'s own state does no Every Actor is reachable at a uniform address built from its {{< gloss "Atespace" >}}atespace{{< /gloss >}} and name, `..actors.resources.substrate.ate.dev`, resolved by Agent Substrate's own Domain Name System (DNS) server. Traffic sent to that name is routed to the right Worker, and an Actor that is currently suspended is resumed automatically to receive it. Nothing in the calling path needs to know whether the Actor was running beforehand. -Resume speed is what makes suspending at every turn boundary practical rather than costly. Agent Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. +Resume speed makes suspending at every turn boundary practical rather than costly. Agent Substrate's own target for this cycle is 100 milliseconds at the ninety-fifth percentile, measured from the moment traffic arrives for a suspended Actor to the moment that Actor can receive it. ## Checkpoints From d3f105a07ed367250069c9bb720a20726df32f42 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 4 Sep 2026 12:58:33 -0500 Subject: [PATCH 46/70] Update agents-via-mcp.md Signed-off-by: Rachael Graham --- .../kagent/1.x/examples/agents-via-mcp.md | 128 +++++++++++++----- 1 file changed, 95 insertions(+), 33 deletions(-) diff --git a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md index f341cd4d..8d491b43 100644 --- a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -27,9 +27,12 @@ The MCP server is part of the controller's HTTP port rather than a separate depl ## Before you begin -1. [Install kagent]({{< link path="setup/installation" >}}). +1. [Install kagent]({{< link path="setup/installation" >}}). Make sure that your installation sets `controller.grpc.reflection=true`. + 2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have at least one AgentInstance in the `READY` state. The MCP server lists ready instances only. +3. Install [grpcurl](https://github.com/fullstorydev/grpcurl). Deleting a checkpoint has neither an MCP tool nor a kagent command, so cleaning one up calls `CheckpointService` directly. + ## Connect a client 1. Forward the controller's HTTP port, and leave the command running. @@ -94,7 +97,7 @@ Claude Code and Cursor read the tool schemas and build each call, so you work in 2. Ask the agent a question by naming the instance you want to use. The client calls `invoke_agent_instance` and fills in the arguments from the tool schema. ```console - > Ask kagent agent instance 01a068e3-aeb6-7abc-8d6f-5ba9becd3143 in the + > Ask kagent agent instance in the kagent namespace: what is 2+2? Answer with just the number. ``` @@ -114,14 +117,32 @@ This is the same pause that any other client sees, reached through MCP instead o ### Checkpoint and fork -Ask the client to checkpoint an instance before letting an agent try something risky, then to fork that checkpoint later to start a second agent from the pinned state. The client calls the three {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} tools, which give it the same operations that the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}) performs from the command line. +You can checkpoint an instance before letting an agent try something risky, then fork that checkpoint to start a second agent from the pinned state. The client calls the three {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} tools, which give it the same operations that the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}) performs from the command line. + +1. Ask the client to checkpoint the instance. + ```console + > Checkpoint kagent agent instance . + ``` + + The client reports the checkpoint's own ID, the turn that it pinned, and a state of `CHECKPOINT_STATE_READY`. Because the client holds that result in context, you can refer to the checkpoint without repeating its ID. + +2. Ask the client to fork that checkpoint. + ```console + > Fork that checkpoint. + ``` + + The client reports a second AgentInstance with its own ID, already `READY`, on the same Harness and AgentTemplate as the original. + +3. Ask the fork a question. + ```console + > Ask that fork what 10+5 is. + ``` + + The fork answers `15`. Ask it about an earlier turn of the original conversation and it has nothing to report, because a fork begins its own conversation rather than continuing the original's. -```console -> Checkpoint kagent agent instance 01a068e3-aeb6-7abc-8d6f-5ba9becd3143, - then fork that checkpoint and ask the fork what 10+5 is. -``` +Plan for the two AgentInstances to share a starting state and nothing else. A fork also runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. -A fork begins its own conversation rather than continuing the original's, so plan for the two AgentInstances to share a starting state and nothing else. It also runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. +You can now safely [clean up these resources](#clean-up). ## Use agents from curl @@ -153,7 +174,12 @@ With `curl` you build each request yourself, so every field is visible: the tool kagent/01a068e3-aeb6-7abc-8d6f-5ba9becd3143 (my-first-agent via my-first-harness) ``` -2. Send a message and wait for the reply. A blocking call needs no `_meta`, because the tool's default behavior asks nothing of the client. +2. Save the ID of the instance that you want to use. + ```bash + export INSTANCE_ID= + ``` + +3. Send a message and wait for the reply. A blocking call needs no `_meta`, because the tool's default behavior asks nothing of the client. ```bash curl -s -X POST http://localhost:8083/mcp \ -H 'Content-Type: application/json' \ @@ -166,7 +192,7 @@ With `curl` you build each request yourself, so every field is visible: the tool "name": "invoke_agent_instance", "arguments": { "namespace": "kagent", - "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "agent_instance_id": "'"$INSTANCE_ID"'", "message": "What is 2+2? Answer with just the number." } } @@ -185,7 +211,26 @@ With `curl` you build each request yourself, so every field is visible: the tool } ``` -3. Send the same request again with `Multiply that by 10.` as the `message`. The word "that" resolves only when the earlier turns are in context. Note that `context_id` is unchanged while `task_id` is new, so the second turn joined the first conversation instead of starting its own. Example output: +4. Send the same request again with `Multiply that by 10.` as the `message`. The word "that" resolves only when the earlier turns are in context. Note that `context_id` is unchanged while `task_id` is new, so the second turn joined the first conversation instead of starting its own. + ```bash + curl -s -X POST http://localhost:8083/mcp \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": { + "name": "invoke_agent_instance", + "arguments": { + "namespace": "kagent", + "agent_instance_id": "'"$INSTANCE_ID"'", + "message": "Multiply that by 10." + } + } + }' + ``` + Example output: ```json { "namespace": "kagent", @@ -214,7 +259,7 @@ Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's "name": "invoke_agent_instance", "arguments": { "namespace": "kagent", - "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "agent_instance_id": "'"$INSTANCE_ID"'", "message": "Count to three." }, "_meta": { @@ -239,7 +284,12 @@ Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's } ``` -2. Poll the task with `tasks/get`, waiting the interval that `pollIntervalMs` suggests between calls. Carry the same `_meta` declaration on every poll: a request that omits it is rejected with `-32021 tasks capability required but not declared by client` rather than falling back to a blocking read. +2. Save the task ID. The value ends in base64, so quote it. + ```bash + export TASK_ID='' + ``` + +3. Poll the task with `tasks/get`. Carry the same `_meta` declaration on every poll: a request that omits it is rejected with `-32021 tasks capability required but not declared by client` rather than falling back to a blocking read. ```bash curl -s -X POST http://localhost:8083/mcp \ -H 'Content-Type: application/json' \ @@ -249,7 +299,7 @@ Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's "id": 4, "method": "tasks/get", "params": { - "taskId": "", + "taskId": "'"$TASK_ID"'", "_meta": { "io.modelcontextprotocol/clientCapabilities": { "extensions": { "io.modelcontextprotocol/tasks": {} } @@ -259,9 +309,9 @@ Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's }' ``` - Read `status` to decide whether to keep polling: it reports `working`, `input_required`, `completed`, or `cancelled`. A status of `input_required` means the agent is waiting on a person, which [Answer an agent's question](#answer-an-agents-question-1) covers. +4. If the `status` reports `working` or `cancelled`, send the request from the previous step again, waiting the interval that `pollIntervalMs` suggests between calls. A status of `input_required` means the agent is waiting on a person, which is explored in [Answer an agent's question](#answer-an-agents-question-1). -3. Take the answer once `status` reads `completed`. The `result` field holds the same content that a blocking call would have returned, as both `content` and `structuredContent`. Example output: +5. When the `status` reads `completed`, stop polling. The `result` field holds the same content that a blocking call would have returned as both `content` and `structuredContent`. Example output: ```json { "status": "completed", @@ -318,7 +368,12 @@ When an agent pauses to ask something, the task's status becomes `input_required - **A question** becomes one string field per question, named `response` when the agent asks one question and `response_1`, `response_2`, and so on when it asks more than one. A question with a fixed set of choices restricts the field to those values with `enum`, and one that accepts more than one answer takes an array. - **A tool approval** becomes one boolean field per tool, named `approve_1`, `approve_2`, and so on. A response must decide every tool in the request. -2. Send the answer with `tasks/update`, keying `inputResponses` by the same request ID. An elicitation result of `accept` sends the answers on, while `decline` and `cancel` tell the agent that the person refused. An agent can adapt to a refusal rather than treating it as an error. +2. Save the request ID that keys the entry. + ```bash + export INPUT_REQUEST_ID= + ``` + +3. Send the answer with `tasks/update`, keying `inputResponses` by the same request ID. An elicitation result of `accept` sends the answers on, while `decline` and `cancel` tell the agent that the person refused. An agent can adapt to a refusal rather than treating it as an error. ```bash curl -s -X POST http://localhost:8083/mcp \ -H 'Content-Type: application/json' \ @@ -328,9 +383,9 @@ When an agent pauses to ask something, the task's status becomes `input_required "id": 5, "method": "tasks/update", "params": { - "taskId": "", + "taskId": "'"$TASK_ID"'", "inputResponses": { - "01a06d12-4832-7e1f-873d-c25bc6b6b70b": { + "'"$INPUT_REQUEST_ID"'": { "action": "accept", "content": { "response": "PostgreSQL" } } @@ -349,7 +404,7 @@ When an agent pauses to ask something, the task's status becomes `input_required { "resultType": "complete" } ``` -3. Poll the task again to collect the resumed turn. The agent picks up where it paused, so the status returns to `working` and then `completed` with the answer your response produced. Example output: +4. Poll the task again to collect the resumed turn. The agent picks up where it paused, so the status returns to `working` and then `completed` with the answer your response produced. Example output: ```json { "status": "completed", @@ -383,7 +438,7 @@ The three checkpoint tools pin an instance's state and start a second agent from "name": "create_agent_instance_checkpoint", "arguments": { "namespace": "kagent", - "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "agent_instance_id": "'"$INSTANCE_ID"'", "request_id": "my-first-checkpoint" } } @@ -405,7 +460,12 @@ The three checkpoint tools pin an instance's state and start a second agent from } ``` -2. List the instance's checkpoints to confirm what you can fork from. +2. Save the checkpoint ID. + ```bash + export CHECKPOINT_ID= + ``` + +3. List the instance's checkpoints to confirm what you can fork from. ```bash curl -s -X POST http://localhost:8083/mcp \ -H 'Content-Type: application/json' \ @@ -418,7 +478,7 @@ The three checkpoint tools pin an instance's state and start a second agent from "name": "list_agent_instance_checkpoints", "arguments": { "namespace": "kagent", - "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143" + "agent_instance_id": "'"$INSTANCE_ID"'" } } }' @@ -450,7 +510,7 @@ The three checkpoint tools pin an instance's state and start a second agent from } ``` -3. Fork the checkpoint into a second AgentInstance. This call takes `checkpoint_id` rather than an instance ID, because the checkpoint already identifies the instance it was taken on. +4. Fork the checkpoint into a second AgentInstance. This call takes `checkpoint_id` rather than an instance ID, because the checkpoint already identifies the instance it was taken on. ```bash curl -s -X POST http://localhost:8083/mcp \ -H 'Content-Type: application/json' \ @@ -463,7 +523,7 @@ The three checkpoint tools pin an instance's state and start a second agent from "name": "fork_agent_instance", "arguments": { "namespace": "kagent", - "checkpoint_id": "01a06d19-540a-7040-befb-ec4499c96ff2", + "checkpoint_id": "'"$CHECKPOINT_ID"'", "request_id": "my-first-fork" } } @@ -483,7 +543,7 @@ The three checkpoint tools pin an instance's state and start a second agent from } ``` -4. Invoke the fork with `invoke_agent_instance` and its new ID. Note that `context_id` matches the fork's own ID rather than the original's, so the fork holds a separate conversation from the moment it is created. Example output: +5. Invoke the fork with `invoke_agent_instance` and its new ID. Note that `context_id` matches the fork's own ID rather than the original's, so the fork holds a separate conversation from the moment it is created. Example output: ```json { "namespace": "kagent", @@ -497,22 +557,24 @@ The three checkpoint tools pin an instance's state and start a second agent from A fork runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. For what a checkpoint captures, why a checkpoint taken on a suspended instance is the forkable kind, and what a fork does and does not inherit, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) and the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). +You can now safely [clean up these resources](#clean-up). + ## Clean up 1. Delete the fork that you created. No MCP tool deletes an AgentInstance, so use the kagent command line interface. ```bash - kagent delete agent-instance + kagent delete agent-instance ``` -2. Forward the controller's gRPC port, and leave the command running. Deleting a checkpoint has neither an MCP tool nor a kagent command, so it goes through `CheckpointService` on a different port from the one that serves MCP. +2. Forward the controller's gRPC port, and leave the command running. `CheckpointService` listens there rather than on the HTTP port that serves MCP. ```bash kubectl port-forward -n kagent svc/kagent-controller 8084:8084 ``` -3. Delete the checkpoint that you created, with [grpcurl](https://github.com/fullstorydev/grpcurl). The call reads the service definition from the server, so it needs your installation to set `controller.grpc.reflection`. +3. Delete the checkpoint that you created. ```bash grpcurl -plaintext \ - -d '{"namespace":"kagent","checkpointId":""}' \ + -d '{"namespace":"kagent","checkpointId":""}' \ localhost:8084 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint ``` @@ -522,7 +584,7 @@ A fork runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint wa ## MCP tool reference -The server exposes five tools. Two cover discovery and conversation, and three expose the {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} operations, so a client can pin and branch an agent's state as well as talk to it. Every tool takes a `namespace`, because an AgentInstance is scoped to one. Nothing here deletes an object, so removing an AgentInstance or a checkpoint means leaving MCP for the command line. +The server exposes five tools. Two cover discovery and conversation, and three expose the {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} operations, so a client can pin and branch an agent's state as well as talk to it. Every tool takes a `namespace` because an AgentInstance is scoped to one. No tool deletes an object, so removing an AgentInstance or a checkpoint means leaving MCP for the command line. | Tool | Required arguments | What it does | | ---- | ------------------ | ------------ | @@ -535,7 +597,7 @@ The server exposes five tools. Two cover discovery and conversation, and three e ## Next steps {{< cards >}} - {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Follow suspend, checkpoint, and fork from the command line instead." >}} - {{< card link=`{{< link path="agents/human-in-the-loop" >}}` title="Human in the loop" subtitle="Understand the pauses an agent can raise and how a client answers them." >}} + {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch the Actor beneath an agent suspend between turns and resume on demand." >}} + {{< card link=`{{< link path="agents/human-in-the-loop" >}}` title="Human in the loop" subtitle="Understand the pauses that an agent can raise and how a client answers them." >}} {{< card link=`{{< link path="get-started/your-first-mcp-tool" >}}` title="Your first MCP tool" subtitle="Point kagent at an MCP server so that your agent gains tools of its own." >}} {{< /cards >}} From 141f723c1e51435e05dd0da169609a36633a2cfc Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 4 Sep 2026 13:01:37 -0500 Subject: [PATCH 47/70] init Signed-off-by: Rachael Graham --- .../content/kagent/1.x/examples/a2a-agents.md | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 docs-site/content/kagent/1.x/examples/a2a-agents.md diff --git a/docs-site/content/kagent/1.x/examples/a2a-agents.md b/docs-site/content/kagent/1.x/examples/a2a-agents.md new file mode 100644 index 00000000..672abc69 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/a2a-agents.md @@ -0,0 +1,197 @@ +--- +title: Call an agent over A2A +description: Use the A2A service that the kagent controller serves to read an AgentInstance's agent card, send it a message, and stream a reply. +weight: 30 +author: kagent.dev +--- + +Every {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} is reachable over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol through the kagent controller. A2A is not a side door; it is how kagent talks to its own agents. The CLI, the [MCP server]({{< link path="examples/agents-via-mcp" >}}), and any client you write all take the same path. + +This example uses [grpcurl](https://github.com/fullstorydev/grpcurl) to show the requests and replies directly. Real callers use an A2A client library rather than assembling requests by hand. + +## About the kagent A2A service + +The controller serves `lf.a2a.v1.A2AService` on its gRPC port, `8084`, which is the same port and service that the kagent CLI uses. + +An AgentInstance is not addressed by a URL path. A caller names the instance in two pieces of request metadata, and the controller routes the call to that instance's Actor. + +| Metadata header | Value | +| --------------- | ----- | +| `x-kagent-agent-instance-namespace` | The namespace holding the AgentInstance. | +| `x-kagent-agent-instance-id` | The AgentInstance's ID. | + +> [!NOTE] +> Header routing replaces the `/api/a2a///` URL paths that kagent 0.x served over HTTP. The unit you address also changed: a 0.x caller addressed an agent, while a 1.x caller addresses one AgentInstance, which is one conversation with that agent. + +> [!WARNING] +> The open source build does not authenticate this port. Any caller that can reach it can invoke any AgentInstance, so do not expose port `8084` outside the cluster. For what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), and save the AgentInstance's ID. + ```bash + export INSTANCE_ID= + ``` + +3. Install [grpcurl](https://github.com/fullstorydev/grpcurl), and confirm that your kagent installation sets `controller.grpc.reflection=true`. Reflection lets grpcurl discover the service without a local copy of the A2A protocol buffer definitions. + +4. Port-forward the controller's gRPC port, and leave the command running. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` + +## Read the agent card + +An A2A client normally starts by reading the agent card, which tells it what the agent is and which protocol features the agent supports. + +1. Fetch the card for your AgentInstance. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + localhost:8084 lf.a2a.v1.A2AService/GetExtendedAgentCard + ``` + + Example output: + ```json + { + "name": "my_first_agent", + "description": "My first kagent agent", + "supportedInterfaces": [ + { + "url": "http://kagent-controller.kagent.svc:8084", + "protocolBinding": "GRPC", + "protocolVersion": "1.0" + } + ], + "version": "v1", + "capabilities": { + "streaming": true, + "pushNotifications": false, + "extensions": [ + { + "uri": "https://kagent.dev/extensions/hitl/v1", + "description": "Human in the loop for tool approval, ask user, and nested subagents" + } + ], + "extendedAgentCard": true + }, + "defaultInputModes": ["text"], + "defaultOutputModes": ["text"] + } + ``` + +2. Read the card for the three things a caller acts on. The `name` field is the {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s name with hyphens replaced by underscores, and `description` comes from the AgentTemplate's `spec.description`, so the description a caller sees is the one you wrote. The `supportedInterfaces` URL is the controller's in-cluster address rather than the Actor's, because a caller reaches the agent through the controller. The `extensions` list advertises human-in-the-loop support, which a client opts into per call. + +> [!NOTE] +> The card carries no `skills`. kagent 0.x let you declare agent card skills in an `a2aConfig` block, and v1alpha3 has no such field, so kagent generates the card from the AgentTemplate's name and description alone. An AgentTemplate's `spec.skills` field is a different feature: those are [Agent Skills]({{< link path="skills-and-mcp/skills" >}}) that the agent can use, not advertisements to a caller. + +## Send a message + +`SendMessage` blocks until the agent finishes, then returns the whole task. A message needs its own ID, a role, and at least one part. + +1. Send a message to the AgentInstance. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"What is 7 times 6? Answer with just the number."}]}}' \ + localhost:8084 lf.a2a.v1.A2AService/SendMessage + ``` + + The reply text arrives in `artifacts`, not in `status`. Example output, with the message history omitted: + ```json + { + "task": { + "id": "01a06cfb-a9ae-7ddb-be98-baaf17414998", + "contextId": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "status": { + "state": "TASK_STATE_COMPLETED", + "timestamp": "2026-09-04T15:13:52.990137169Z" + }, + "artifacts": [ + { + "artifactId": "01a06cfb-bf2c-70ea-8e65-e3ef15133a96", + "parts": [{ "text": "42" }] + } + ], + "history": [ ] + } + } + ``` + +2. Save the task ID to read the task again later. + ```bash + export TASK_ID= + ``` + +Two identifiers come back, and they mean different things. The `id` is one turn, and a new one appears on every message. The `contextId` is the conversation, and it is the AgentInstance's own ID, which is why a second message to the same instance continues the conversation rather than starting a new one. Each artifact also carries runtime metadata under `adk_` keys, including the token counts for that turn. + +## Stream a reply + +`SendStreamingMessage` takes the same request and returns a sequence of events instead of one result. A caller can then show a reply as the agent produces it. + +Send a message on the streaming method. +```bash +grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"Count from 1 to 3."}]}}' \ + localhost:8084 lf.a2a.v1.A2AService/SendStreamingMessage +``` + +The stream opens with the task at `TASK_STATE_SUBMITTED`, moves to `TASK_STATE_WORKING`, and then emits an artifact update for each chunk of the reply. Every chunk shares one `artifactId`, so a client appends them into a single artifact rather than treating each as a separate answer. Example output, abbreviated to the text of each event: +```console +"state": "TASK_STATE_SUBMITTED" +"state": "TASK_STATE_WORKING" +"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "1" +"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "," +"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": " " +"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "2" +``` + +## Read a task later + +A task outlives the call that created it, so a caller that lost its connection can read the result rather than asking the agent again. + +Read the task by ID. +```bash +grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"id":"'"$TASK_ID"'"}' \ + localhost:8084 lf.a2a.v1.A2AService/GetTask +``` + +The task comes back with the same `status`, `artifacts`, and `history` that `SendMessage` returned. A task that is still running reports `TASK_STATE_WORKING` and has no artifacts yet, and `CancelTask` takes the same `id` to stop it. + +## When an agent needs a person + +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, and the caller answers by sending a message that carries the same task ID. + +A client only sees these pauses if it requests the human-in-the-loop extension that the agent card advertises. A client that never requests it is never interrupted. For the pause types, the approval model, and what the agent receives back, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). + +## Clean up + +This example creates no Kubernetes resources, so there is nothing to delete. Stop the port-forward with `Ctrl+C`. The tasks that your messages created stay on the AgentInstance as part of its conversation, and deleting the AgentInstance removes them with it. + +## A2A method reference + +These are the methods that this example uses. The service defines more, including `ListTasks` and the push notification configuration calls, but an agent card that reports `pushNotifications` as `false` does not support being called back. + +| Method | What it does | +| ------ | ------------ | +| `GetExtendedAgentCard` | Returns the agent card describing the instance. | +| `SendMessage` | Sends a message and returns the finished task. | +| `SendStreamingMessage` | Sends a message and streams events as the agent works. | +| `GetTask` | Reads a task that a previous call created. | +| `CancelTask` | Stops a task that is still running. | + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="examples/agents-via-mcp" >}}` title="Use agents from an MCP client" subtitle="Reach the same agents through MCP instead, from Claude Code or Cursor." >}} + {{< card link=`{{< link path="agents/human-in-the-loop" >}}` title="Human in the loop" subtitle="Handle an agent that pauses to ask a question or request approval." >}} + {{< card link=`{{< link path="observability/tracing" >}}` title="Tracing" subtitle="Follow one A2A call from the controller through to the Actor that served it." >}} +{{< /cards >}} From 30d2122cf1d6a24f9e29d0516a14a68ab4806069 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 8 Sep 2026 12:12:47 -0500 Subject: [PATCH 48/70] Phase 3 - a2a agents Signed-off-by: Rachael Graham --- .../snippets/grpcurl-prerequisites.md | 13 ++ .../kagent-docs/versions/agent-substrate.md | 2 +- .../kagent/1.x/agents/human-in-the-loop.md | 2 +- .../content/kagent/1.x/examples/a2a-agents.md | 132 ++++++++++-------- .../kagent/1.x/examples/agent-substrate.md | 14 +- .../kagent/1.x/examples/agents-via-mcp.md | 6 +- .../kagent/1.x/observability/tracing.md | 2 +- .../content/kagent/1.x/setup/installation.md | 7 +- docs-site/go.mod | 5 +- docs-site/go.sum | 2 + 10 files changed, 107 insertions(+), 78 deletions(-) create mode 100644 docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md diff --git a/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md b/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md new file mode 100644 index 00000000..9e7ca913 --- /dev/null +++ b/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md @@ -0,0 +1,13 @@ +1. [Install kagent]({{< link path="setup/installation" >}}), and confirm that your installation sets `controller.grpc.reflection=true`. Reflection lets grpcurl discover the controller's methods without a local copy of kagent's protocol buffer definitions. + +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), then save the AgentInstance's ID to an environment variable. To find the ID, run `kagent get agent-instance` to list your AgentInstances and copy the value from the `ID` column. + ```bash + export INSTANCE_ID= + ``` + +3. Install [grpcurl](https://github.com/fullstorydev/grpcurl). + +4. Port-forward the controller's gRPC port, and leave the command running. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + ``` diff --git a/docs-site/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md index 536cf0b3..c4d8947d 100644 --- a/docs-site/assets/kagent-docs/versions/agent-substrate.md +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -1 +1 @@ -{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.24{{< /version >}} \ No newline at end of file +{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.25{{< /version >}} \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md index bdcd825f..82f54c75 100644 --- a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md +++ b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md @@ -67,7 +67,7 @@ grpcurl -plaintext \ -H 'x-kagent-agent-instance-id: ' \ -d '{ "message": { - "message_id": "msg-1", + "messageId": "msg-1", "role": "ROLE_USER", "parts": [{"text": "Delete the obsolete pod in the production namespace."}] } diff --git a/docs-site/content/kagent/1.x/examples/a2a-agents.md b/docs-site/content/kagent/1.x/examples/a2a-agents.md index 672abc69..b34512c1 100644 --- a/docs-site/content/kagent/1.x/examples/a2a-agents.md +++ b/docs-site/content/kagent/1.x/examples/a2a-agents.md @@ -5,7 +5,7 @@ weight: 30 author: kagent.dev --- -Every {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} is reachable over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol through the kagent controller. A2A is not a side door; it is how kagent talks to its own agents. The CLI, the [MCP server]({{< link path="examples/agents-via-mcp" >}}), and any client you write all take the same path. +Every {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} is reachable over the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) protocol through the kagent controller. kagent uses the A2A protocol for its own agent traffic, rather than an extra interface beside it. The CLI, the [MCP server]({{< link path="examples/agents-via-mcp" >}}), and any client you write all take the same path. This example uses [grpcurl](https://github.com/fullstorydev/grpcurl) to show the requests and replies directly. Real callers use an A2A client library rather than assembling requests by hand. @@ -26,24 +26,25 @@ An AgentInstance is not addressed by a URL path. A caller names the instance in > [!WARNING] > The open source build does not authenticate this port. Any caller that can reach it can invoke any AgentInstance, so do not expose port `8084` outside the cluster. For what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). -## Before you begin +### A2A methods -1. [Install kagent]({{< link path="setup/installation" >}}). -2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), and save the AgentInstance's ID. - ```bash - export INSTANCE_ID= - ``` +The following methods are used in this example. The service defines more, including `ListTasks` and the push notification configuration calls, but an agent card that reports `pushNotifications` as `false` does not support being called back. -3. Install [grpcurl](https://github.com/fullstorydev/grpcurl), and confirm that your kagent installation sets `controller.grpc.reflection=true`. Reflection lets grpcurl discover the service without a local copy of the A2A protocol buffer definitions. +| Method | What it does | +| ------ | ------------ | +| `GetExtendedAgentCard` | Returns the agent card describing the instance. | +| `SendMessage` | Sends a message and returns the finished task. | +| `SendStreamingMessage` | Sends a message and streams events as the agent works. | +| `GetTask` | Reads a task that a previous call created. | +| `CancelTask` | Stops a task that is still running. | -4. Port-forward the controller's gRPC port, and leave the command running. - ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 - ``` +## Before you begin + +{{< reuse "kagent-docs/snippets/grpcurl-prerequisites.md" >}} ## Read the agent card -An A2A client normally starts by reading the agent card, which tells it what the agent is and which protocol features the agent supports. +An A2A client typically starts by reading the agent card, which tells it what the agent is and which protocol features the agent supports. 1. Fetch the card for your AgentInstance. ```bash @@ -82,10 +83,13 @@ An A2A client normally starts by reading the agent card, which tells it what the } ``` -2. Read the card for the three things a caller acts on. The `name` field is the {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}'s name with hyphens replaced by underscores, and `description` comes from the AgentTemplate's `spec.description`, so the description a caller sees is the one you wrote. The `supportedInterfaces` URL is the controller's in-cluster address rather than the Actor's, because a caller reaches the agent through the controller. The `extensions` list advertises human-in-the-loop support, which a client opts into per call. +2. Read the card for what a caller acts on. + * Both `name` and `description` come from the {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}. `name` replaces hyphens with underscores, and `description` is `spec.description` verbatim, so a caller sees the description you wrote. + * The `supportedInterfaces` URL is the controller's in-cluster address rather than the Actor's, because a caller reaches the agent through the controller. + * The `capabilities.extensions` list advertises human-in-the-loop support, which a client opts into per call. > [!NOTE] -> The card carries no `skills`. kagent 0.x let you declare agent card skills in an `a2aConfig` block, and v1alpha3 has no such field, so kagent generates the card from the AgentTemplate's name and description alone. An AgentTemplate's `spec.skills` field is a different feature: those are [Agent Skills]({{< link path="skills-and-mcp/skills" >}}) that the agent can use, not advertisements to a caller. +> The card carries no `skills`. kagent 0.x let you declare agent card skills in an `a2aConfig` block. However, v1alpha3 has no such field, so kagent generates the card from the AgentTemplate's name and description alone. An AgentTemplate's `spec.skills` field is a different feature: those are [Agent Skills]({{< link path="skills-and-mcp/skills" >}}) that the agent can use, not advertisements to a caller. ## Send a message @@ -120,51 +124,73 @@ An A2A client normally starts by reading the agent card, which tells it what the } } ``` + The task returns two identifiers, `id` and `contextId`, and a caller uses them differently. + * The `id` identifies one turn, and every message returns a new one. + * The `contextId` identifies the conversation, and matches the AgentInstance's own ID. A second message to the same instance therefore continues the conversation rather than starting a new one. + + Each artifact also carries runtime metadata under `adk_` keys, including the token counts for that turn. -2. Save the task ID to read the task again later. +2. Save the task's `id` so that you can read the task again later. ```bash export TASK_ID= ``` -Two identifiers come back, and they mean different things. The `id` is one turn, and a new one appears on every message. The `contextId` is the conversation, and it is the AgentInstance's own ID, which is why a second message to the same instance continues the conversation rather than starting a new one. Each artifact also carries runtime metadata under `adk_` keys, including the token counts for that turn. - ## Stream a reply `SendStreamingMessage` takes the same request and returns a sequence of events instead of one result. A caller can then show a reply as the agent produces it. -Send a message on the streaming method. -```bash -grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ - -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ - -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"Count from 1 to 3."}]}}' \ - localhost:8084 lf.a2a.v1.A2AService/SendStreamingMessage -``` - -The stream opens with the task at `TASK_STATE_SUBMITTED`, moves to `TASK_STATE_WORKING`, and then emits an artifact update for each chunk of the reply. Every chunk shares one `artifactId`, so a client appends them into a single artifact rather than treating each as a separate answer. Example output, abbreviated to the text of each event: -```console -"state": "TASK_STATE_SUBMITTED" -"state": "TASK_STATE_WORKING" -"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "1" -"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "," -"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": " " -"artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "2" -``` +1. Send a message on the streaming method. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"Count from 1 to 3."}]}}' \ + localhost:8084 lf.a2a.v1.A2AService/SendStreamingMessage + ``` + +2. Read the event sequence. The stream opens with the task at `TASK_STATE_SUBMITTED`, moves to `TASK_STATE_WORKING`, and then emits an artifact update for each chunk of the reply. Every chunk shares one `artifactId`, so a client appends them into a single artifact rather than treating each as a separate answer. Example output, abbreviated to the text of each event: + ```console + "state": "TASK_STATE_SUBMITTED" + "state": "TASK_STATE_WORKING" + "artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "1" + "artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "," + "artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": " " + "artifactId": "01a06cfd-1c3c-7e65-8650-2e86f5d7f5eb", "text": "2" + ``` ## Read a task later A task outlives the call that created it, so a caller that lost its connection can read the result rather than asking the agent again. -Read the task by ID. -```bash -grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ - -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ - -d '{"id":"'"$TASK_ID"'"}' \ - localhost:8084 lf.a2a.v1.A2AService/GetTask -``` +1. Read the task by ID. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"id":"'"$TASK_ID"'"}' \ + localhost:8084 lf.a2a.v1.A2AService/GetTask + ``` -The task comes back with the same `status`, `artifacts`, and `history` that `SendMessage` returned. A task that is still running reports `TASK_STATE_WORKING` and has no artifacts yet, and `CancelTask` takes the same `id` to stop it. +2. Read the task's fields. `GetTask` returns the task itself, rather than wrapping it in a `task` field the way `SendMessage` does. The `status`, `artifacts`, and `history` values are the ones that the original call returned. + ```json + { + "id": "01a06cfb-a9ae-7ddb-be98-baaf17414998", + "contextId": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "status": { + "state": "TASK_STATE_COMPLETED", + "timestamp": "2026-09-04T15:13:52.990137169Z" + }, + "artifacts": [ + { + "artifactId": "01a06cfb-bf2c-70ea-8e65-e3ef15133a96", + "parts": [{ "text": "42" }] + } + ], + "history": [ ] + } + ``` + +A task that is still running reports `TASK_STATE_WORKING` and has no artifacts yet. To stop a task that is still running, call `CancelTask` with the same `id`. ## When an agent needs a person @@ -174,19 +200,9 @@ A client only sees these pauses if it requests the human-in-the-loop extension t ## Clean up -This example creates no Kubernetes resources, so there is nothing to delete. Stop the port-forward with `Ctrl+C`. The tasks that your messages created stay on the AgentInstance as part of its conversation, and deleting the AgentInstance removes them with it. - -## A2A method reference - -These are the methods that this example uses. The service defines more, including `ListTasks` and the push notification configuration calls, but an agent card that reports `pushNotifications` as `false` does not support being called back. - -| Method | What it does | -| ------ | ------------ | -| `GetExtendedAgentCard` | Returns the agent card describing the instance. | -| `SendMessage` | Sends a message and returns the finished task. | -| `SendStreamingMessage` | Sends a message and streams events as the agent works. | -| `GetTask` | Reads a task that a previous call created. | -| `CancelTask` | Stops a task that is still running. | +* This example creates no Kubernetes resources, so you have nothing to delete. +* You can stop the 8084 port-forward for the kagent-controller service with `Ctrl+C`. +* The tasks that your messages created stay on the AgentInstance as part of its conversation, and deleting the AgentInstance removes them. ## Next steps diff --git a/docs-site/content/kagent/1.x/examples/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md index 88487f71..51e79e84 100644 --- a/docs-site/content/kagent/1.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -11,19 +11,9 @@ The Actor that these steps follow is also the isolation boundary. Every Actor ru ## Before you begin -1. Complete [Your first agent]({{< link path="get-started/your-first-agent" >}}). The steps on this page continue from the Harness, AgentTemplate, and AgentInstance that the agent guide creates, and assumes that you have sent the agent at least one message. +Checkpoints and {{< gloss "Fork" >}}forks{{< /gloss >}} have no kagent CLI commands yet, so this example calls `CheckpointService` with grpcurl. The steps also assume that you have already sent your agent at least one message, because a checkpoint needs a completed turn to pin. -2. If you have not already, save the AgentInstance's ID to an environment variable. To find the ID, run `kagent get agent-instance` to list your AgentInstances and copy the value from the `ID` column. - ```bash - export INSTANCE_ID= - ``` - -3. Install [grpcurl](https://github.com/fullstorydev/grpcurl), and confirm that your kagent installation sets `controller.grpc.reflection`. Checkpoints and {{< gloss "Fork" >}}forks{{< /gloss >}} have no kagent CLI commands yet, so this example calls `CheckpointService` directly. - -4. Port-forward the controller's gRPC port to your local machine. - ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 - ``` +{{< reuse "kagent-docs/snippets/grpcurl-prerequisites.md" >}} ## Watch the Actor suspend between turns diff --git a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md index 8d491b43..4c98a17f 100644 --- a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -27,7 +27,7 @@ The MCP server is part of the controller's HTTP port rather than a separate depl ## Before you begin -1. [Install kagent]({{< link path="setup/installation" >}}). Make sure that your installation sets `controller.grpc.reflection=true`. +1. [Install kagent]({{< link path="setup/installation" >}}), and confirm that your installation sets `controller.grpc.reflection=true`. Reflection lets a gRPC client discover the controller's methods without a local copy of kagent's protocol buffer definitions. 2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have at least one AgentInstance in the `READY` state. The MCP server lists ready instances only. @@ -35,7 +35,7 @@ The MCP server is part of the controller's HTTP port rather than a separate depl ## Connect a client -1. Forward the controller's HTTP port, and leave the command running. +1. Port-forward the controller's HTTP port, and leave the command running. ```bash kubectl port-forward -n kagent svc/kagent-controller 8083:8083 ``` @@ -566,7 +566,7 @@ You can now safely [clean up these resources](#clean-up). kagent delete agent-instance ``` -2. Forward the controller's gRPC port, and leave the command running. `CheckpointService` listens there rather than on the HTTP port that serves MCP. +2. Port-forward the controller's gRPC port, and leave the command running. `CheckpointService` listens there rather than on the HTTP port that serves MCP. ```bash kubectl port-forward -n kagent svc/kagent-controller 8084:8084 ``` diff --git a/docs-site/content/kagent/1.x/observability/tracing.md b/docs-site/content/kagent/1.x/observability/tracing.md index e4fd3eba..cf2f984d 100644 --- a/docs-site/content/kagent/1.x/observability/tracing.md +++ b/docs-site/content/kagent/1.x/observability/tracing.md @@ -179,7 +179,7 @@ Tracing is off by default. Turning it on is a Helm change, because the controlle 5. Leave **Operation** on `all`, or select `invocation` to start from the agent's own work rather than from the A2A call that carries it, and click **Find Traces**. -6. Click a trace to open it. The span tree shows the controller's gRPC and gateway spans, followed by the runtime's `POST /lf.a2a.v1.A2AService/SendMessage` span, and finlly the `invocation`, `invoke_agent`, `generate_content`, and `execute_tool` spans. +6. Click a trace to open it. The span tree shows the controller's gRPC and gateway spans, followed by the runtime's `POST /lf.a2a.v1.A2AService/SendMessage` span, and finally the `invocation`, `invoke_agent`, `generate_content`, and `execute_tool` spans. 7. To narrow a search to one conversation, put a correlation attribute in the **Tags** field, such as `gen_ai.conversation.id=`. diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index c9848591..47bd00d9 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -32,7 +32,7 @@ kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-subs {{< tabs >}} {{% tab name="Local kind cluster" %}} - For local testing and development, create a [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) cluster at Kubernetes 1.37 or later. Enable the `certificates.k8s.io/v1beta1` API, which Agent Substrate depends on. + For local testing and development, create a [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) cluster at Kubernetes 1.37 or later. Use kind **v0.33.0 or later**, which is the first release that ships a Kubernetes 1.37 node image. Enable the `certificates.k8s.io/v1beta1` API, which Agent Substrate depends on. ```bash kind create cluster --image kindest/node:v1.37.0 --config=- < [!NOTE] > `controller.grpc.reflection` lets a gRPC client discover the controller's methods without a local copy of kagent's proto files. The kagent CLI does not need it, because the CLI ships with generated clients for every kagent API. Leave reflection on to explore the API with a general-purpose client such as [grpcurl](https://github.com/fullstorydev/grpcurl), and turn it off for a production installation. + + 3. Wait for the controller to roll out. ```bash kubectl rollout status deployment/kagent-controller -n kagent --timeout=300s diff --git a/docs-site/go.mod b/docs-site/go.mod index 64e3c587..69a97429 100644 --- a/docs-site/go.mod +++ b/docs-site/go.mod @@ -2,4 +2,7 @@ module github.com/kagent-dev/website-docs go 1.21 -require github.com/solo-io/docs-theme-extras v0.2.0 // indirect +require ( + github.com/imfing/hextra v0.12.3 // indirect + github.com/solo-io/docs-theme-extras v0.2.0 // indirect +) diff --git a/docs-site/go.sum b/docs-site/go.sum index 860f50b0..03224295 100644 --- a/docs-site/go.sum +++ b/docs-site/go.sum @@ -1,2 +1,4 @@ +github.com/imfing/hextra v0.12.3 h1:DZHY2rUWYteyzjlHi9r4n7Bb5e2Q+6LXe4C1Dqn0ZjM= +github.com/imfing/hextra v0.12.3/go.mod h1:vi+yhpq8YPp/aghvJlNKVnJKcPJ/VyAEcfC1BSV9ARo= github.com/solo-io/docs-theme-extras v0.2.0 h1:GShYCtM7oUC3UqHOqCPwPzsKe9jKdA1OXC0LVqo+h7w= github.com/solo-io/docs-theme-extras v0.2.0/go.mod h1:jjjYu/QoD+vMu30zgcpfEuTEGuJOJWs5qai/K18kltg= From 9af9032c4b96f99d8a2a5a7927971e23666b53ef Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 8 Sep 2026 13:59:38 -0500 Subject: [PATCH 49/70] Add skills Signed-off-by: Rachael Graham --- .../content/kagent/1.x/examples/skills.md | 344 ++++++++++++++++++ .../content/kagent/1.x/setup/installation.md | 22 +- 2 files changed, 346 insertions(+), 20 deletions(-) create mode 100644 docs-site/content/kagent/1.x/examples/skills.md diff --git a/docs-site/content/kagent/1.x/examples/skills.md b/docs-site/content/kagent/1.x/examples/skills.md new file mode 100644 index 00000000..1700b693 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -0,0 +1,344 @@ +--- +title: Add a skill to an agent +description: Package instructions and a script as a skill, publish it as an OCI image, and attach it to an AgentTemplate. +weight: 40 +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" >}}). + +## 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`. + +As a consquence, the following potential gotchas can occur. + +* **A wrong source still compiles.** kagent validates skill names before it accepts an AgentTemplate, but it never checks that the artifact exists or that it holds a `SKILL.md` file. A bad digest produces a revision that reports `Ready`, and the agent then fails to start. +* **Scripts run in the runtime image.** A skill's scripts get whatever the Harness image provides. The kagent runtime image is Alpine Linux with `bash`, `git`, and the standard Alpine utilities, and it does **not** include Python. + +### Skill tools + +On a `kagent` Harness, attaching a skill adds seven tools to the agent, whether or not the skill ships a script. The first three read skills, and the rest let the agent act on their files. The `claude` and `codex` Harness runtimes take the same skills and expose them through their own coding agent's tools instead. + +| Tool | What it does | +| ---- | ------------ | +| `list_skills` | Lists the attached skills with their names and descriptions. | +| `load_skill` | Reads a skill's full `SKILL.md` instructions. | +| `load_skill_resource` | Reads one file inside a skill directory, such as a reference document. | +| `read_file` | Reads a file from the skills directory or the session directory. | +| `write_file` | Writes a file to the session directory. | +| `edit_file` | Replaces an exact string in a file that the agent has already read. | +| `bash` | Runs a shell command in the session directory `/tmp/kagent//`. Commands time out after 30 seconds. | + +Attaching a skill also changes what the agent is told. The runtime appends the name and description of every attached skill to the model request, along with an instruction to call `load_skill` before acting on one, so a skill reaches the model even before any tool is called. + +> [!IMPORTANT] +> The `bash` tool gives the agent shell access inside its own Actor sandbox, and the sandbox is the boundary that contains it. Review a skill before you attach it, and treat the [egress]({{< link path="substrate-runtime/sandboxing" >}}) the Actor is granted as the reach the skill has. Writes are confined to the session directory, so a skill cannot modify `/skills` or another skill's files. + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). + +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have a Harness and an AgentTemplate to attach a skill to. + +3. Install [Docker](https://docs.docker.com/get-started/get-docker/) to build the skill image. + +4. Choose a container registry that your cluster can reach over HTTPS, and set it as an environment variable. Replace the example value with your own repository. + ```bash + export SKILL_REPO=ghcr.io//release-notes + ``` + + > [!WARNING] + > kagent pulls a skill image over HTTPS with certificate verification, and v1alpha3 has no option to disable it. kagent 0.x accepted an `insecureSkipVerify` flag for a local registry, and that field does not exist in 1.x. A plain HTTP registry, and a `localhost` registry that only the host can reach, both fail at agent startup. + +## Build the skill + +A skill is a directory whose root holds a `SKILL.md` file. Everything else in the directory is available to the agent through the skill tools. + +1. Create the skill directory. + ```bash + mkdir -p release-notes/scripts + cd release-notes + ``` + +2. Write `SKILL.md`. The YAML front matter must carry a `name` and a `description`, and the body holds the instructions the agent follows. + ```bash + cat > SKILL.md <<'EOF' + --- + name: release-notes + description: Group a list of conventional commit subjects into release notes with Added, Fixed, and Changed sections. Use this skill whenever the user supplies raw commit subjects and wants them turned into release notes. + --- + # Release notes + + Turn raw commit subjects into release notes grouped by change type. + + ## Instructions + + 1. Ask the user for the commit subjects if they have not supplied them. One subject per line. + 2. Write the subjects to `commits.txt` in your working directory with the `write_file` tool. + 3. Run `bash /skills/release-notes/scripts/group.sh commits.txt` with the `bash` tool. + 4. Return the script's output unchanged. Do not re-order or re-word the entries. + + ## Notes + + - The script reads conventional commit prefixes: `feat:` becomes Added, `fix:` becomes Fixed, and everything else becomes Changed. + - A section with no entries is omitted. + EOF + ``` + + The `description` decides whether the skill is ever used. The agent sees every attached skill's name and description, and chooses among them the same way it chooses any other tool, so state plainly when the skill applies. The instructions in the body are only read after the agent calls `load_skill`. + +3. Add the script that the instructions call. The script runs in the agent's runtime image, so it uses `bash` rather than Python. + ```bash + cat > scripts/group.sh <<'EOF' + #!/usr/bin/env bash + # Group conventional commit subjects into release note sections. + set -euo pipefail + + input="${1:?usage: group.sh }" + added="^feat(\([^)]*\))?!?:" + fixed="^fix(\([^)]*\))?!?:" + + section() { + local heading="$1" body="$2" + [ -n "$body" ] || return 0 + printf '### %s\n%s\n\n' "$heading" "$body" + } + + strip() { + sed -E 's/^[a-z]+(\([^)]*\))?!?: *//; s/^/- /' + } + + section Added "$(grep -E "$added" "$input" | strip || true)" + section Fixed "$(grep -E "$fixed" "$input" | strip || true)" + section Changed "$(grep -Ev "$added|$fixed" "$input" | strip || true)" + EOF + chmod +x scripts/group.sh + ``` + +4. Confirm that the script works before you publish it. The `bash` tool returns a failed command's error to the model rather than to you, so a broken script produces an unreliable answer rather than a failed resource. + ```bash + printf 'feat: add checkpoint API\nfix: correct revision digest\ndocs: update install guide\n' > /tmp/commits.txt + bash scripts/group.sh /tmp/commits.txt + ``` + + Example output: + ```console + ### Added + - add checkpoint API + + ### Fixed + - correct revision digest + + ### Changed + - update install guide + ``` + +## Publish the skill as an OCI image + +kagent pulls an `oci` source as a container image and unpacks its flattened filesystem, so the image holds the skill directory and nothing else. Build it from `scratch`, which produces an image whose root **is** the skill root. + +1. Create the Dockerfile. + ```bash + cat > Dockerfile <<'EOF' + FROM scratch + COPY . / + EOF + ``` + +2. Build and push the image. Build for the architecture your worker nodes run, because kagent pulls the `linux/amd64` or `linux/arm64` manifest that matches the node. + ```bash + docker buildx build --push --platform linux/amd64 -t "$SKILL_REPO:1.0.0" . + ``` + +3. Read the image digest. An `oci` source must be pinned to a digest, and a tag alone is rejected. + ```bash + docker buildx imagetools inspect "$SKILL_REPO:1.0.0" | awk '/^Digest:/{print $2}' + ``` + + Example output: + ```console + sha256:9f2c1e4a7b3d5086c1a2f4e7b9d0c3a5e8f1b4d7a0c3e6f9b2d5a8c1e4f7b0d3 + ``` + +4. Save the digest reference. + ```bash + export SKILL_OCI="$SKILL_REPO@sha256:" + ``` + +## Attach the skill to an AgentTemplate + +1. Add a `skills` entry to the AgentTemplate that your Harness admits. Keep the labels and the model configuration that your existing template uses, and change only the name and the skill. + ```bash + kubectl apply -f - <@sha256:`. | + +2. Confirm that the template compiled. The revision is ready when `desiredRevision` and `latestSuccessfulRevision` hold the same value. + ```bash + kubectl get agenttemplate release-writer -n kagent \ + -o jsonpath='{range .status.harnesses[*]}{.harness}{"\t"}{.desiredRevision}{"\t"}{.latestSuccessfulRevision}{"\n"}{end}' + ``` + + > [!NOTE] + > A ready revision means that kagent accepted the reference, not that the image exists. kagent fetches the skill when the agent starts, so a wrong digest surfaces in the next step rather than this one. + +3. Create an AgentInstance. An AgentInstance pins the revision it was created on, so an instance that already exists does not pick up the skill. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template release-writer + ``` + +4. Save the AgentInstance ID. + ```bash + export INSTANCE_ID= + ``` + +## Ask the agent to use the skill + +1. Send the agent a request that matches the skill's description. + ```bash + kagent invoke --agent-instance $INSTANCE_ID \ + --task "Turn these commit subjects into release notes. feat: add checkpoint API. fix: correct revision digest. docs: update install guide." + ``` + +2. Read the reply. The agent calls `load_skill` to read the instructions, `write_file` to stage the commit subjects, and `bash` to run the script, then returns the script's output. + + Example output: + ```console + ### Added + - add checkpoint API + + ### Fixed + - correct revision digest + + ### Changed + - update install guide + ``` + +3. Ask the agent what skills it holds, to confirm the attachment from the agent's own side. + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "What skills do you have?" + ``` + +## 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, so the AgentInstance never reaches a state where you can talk to it. + +1. Read the Actor's logs for the agent that will not start. + ```bash + kubectl logs -n kagent -l app.kubernetes.io/name=kagent-default --tail=50 | grep -i "materialize" + ``` + +2. Match the message to its cause. + + | Message | Cause | + | ------- | ----- | + | `pull : ... 401 Unauthorized` | The registry needs credentials that the cluster does not have. | + | `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. | + +> [!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. + +## Bundle the skill in a plugin package + +A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin package{{< /gloss >}} carries several, 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. + +1. Restructure the directory so that each skill sits under `skills/`, and add the manifest that makes it a package. + ```bash + cd .. + mkdir -p release-tools/skills + mv release-notes release-tools/skills/release-notes + cd release-tools + cat > plugin.json <<'EOF' + { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "release-tools" + } + EOF + ``` + + > [!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. + ```bash + export PLUGIN_REPO=ghcr.io//release-tools + mv skills/release-notes/Dockerfile . + docker buildx build --push --platform linux/amd64 -t "$PLUGIN_REPO:1.0.0" . + docker buildx imagetools inspect "$PLUGIN_REPO:1.0.0" | awk '/^Digest:/{print $2}' + ``` + +3. Attach the package with `plugins` instead of `skills`, and list the skills to enable. + ```yaml + spec: + plugins: + - source: + oci: + skills: + - release-notes + ``` + + > [!IMPORTANT] + > Attaching a package enables nothing on its own. Only the names in `plugins[].skills` are turned on, so a package that gains a skill in a later version does not grant it to your agent until you add the name. An omitted or empty list is accepted and enables no skills. + +## Publish a new version of the skill + +A source is immutable, so changing a skill is a two-step change: publish new content, then point the AgentTemplate at it. + +1. Edit the skill, then build and push it under a new tag and read the new digest. + ```bash + docker buildx build --push --platform linux/amd64 -t "$SKILL_REPO:1.1.0" . + docker buildx imagetools inspect "$SKILL_REPO:1.1.0" | awk '/^Digest:/{print $2}' + ``` + +2. Update `skills[].source.oci` on the AgentTemplate with the new digest, which compiles a new revision. + +3. Create a new AgentInstance. Agents that are already running keep the skill content they started with, because their revision is pinned. + +## Clean up + +* Delete the AgentInstances that you created. + ```bash + kagent delete agent-instance $INSTANCE_ID + ``` +* Delete the AgentTemplate. + ```bash + kubectl delete agenttemplate release-writer -n kagent + ``` +* Delete the skill image from your registry, and remove the `release-notes` directory from your machine. + +## 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/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/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index 47bd00d9..0f6eb3c0 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -32,7 +32,7 @@ kagent 1.0 runs every agent on [Agent Substrate]({{< link path="about/agent-subs {{< tabs >}} {{% tab name="Local kind cluster" %}} - For local testing and development, create a [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) cluster at Kubernetes 1.37 or later. Use kind **v0.33.0 or later**, which is the first release that ships a Kubernetes 1.37 node image. Enable the `certificates.k8s.io/v1beta1` API, which Agent Substrate depends on. + For local testing and development, create a [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) cluster at Kubernetes 1.37 or later. Use kind v0.32.0 or later. Enable the `certificates.k8s.io/v1beta1` API, which Agent Substrate depends on. ```bash kind create cluster --image kindest/node:v1.37.0 --config=- < [!WARNING] - > Changing these settings requires control over your control plane configuration. When planning a kagent installation on a managed Kubernetes service, confirm that the provider lets you set API server flags and kubelet configuration. - > If you cannot change the component configuration, use the **Local kind cluster** tab instead. - - * **kube-apiserver**: Add `--feature-gates=ClusterTrustBundle=true` and `--runtime-config=certificates.k8s.io/v1beta1=true`. - * **kube-controller-manager**: Add `--feature-gates=ClusterTrustBundle=true`. - * **kubelet, on every node**: Add all three gates to the kubelet configuration file. - ```yaml - featureGates: - ClusterTrustBundle: true - ClusterTrustBundleProjection: true - PodCertificateRequest: true - ``` - {{% /tab %}} {{< /tabs >}} ## Install Agent Substrate @@ -178,7 +160,7 @@ Deploy the Agent Substrate control plane and data plane into the `ate-system` na atenet-egress-66f5699886-6rgg9 2/2 Running 0 9m atenet-router-645bd98bdd-dlrv2 2/2 Running 0 9m dns-6bf4fff5bb-zqsnm 2/2 Running 0 9m - postgres-0 1/1 Running 0 9m + postgres-0 2/2 Running 0 9m rustfs-56cdbc9dcb-2ntck 1/1 Running 0 9m rustfs-bucket-init-4pxgt 0/1 Completed 0 9m ``` From 9710f85cb257032b28761eb35e92f474137f0858 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 8 Sep 2026 14:31:38 -0500 Subject: [PATCH 50/70] Phase 3 - skills review Signed-off-by: Rachael Graham --- .../content/kagent/1.x/examples/skills.md | 158 ++++++++++++------ 1 file changed, 107 insertions(+), 51 deletions(-) diff --git a/docs-site/content/kagent/1.x/examples/skills.md b/docs-site/content/kagent/1.x/examples/skills.md index 1700b693..c2bd0dd6 100644 --- a/docs-site/content/kagent/1.x/examples/skills.md +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -13,7 +13,7 @@ For the fields that attach a skill and the rules that govern their names, see [S 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`. -As a consquence, the following potential gotchas can occur. +Because kagent fetches a skill this late, review the following considerations. * **A wrong source still compiles.** kagent validates skill names before it accepts an AgentTemplate, but it never checks that the artifact exists or that it holds a `SKILL.md` file. A bad digest produces a revision that reports `Ready`, and the agent then fails to start. * **Scripts run in the runtime image.** A skill's scripts get whatever the Harness image provides. The kagent runtime image is Alpine Linux with `bash`, `git`, and the standard Alpine utilities, and it does **not** include Python. @@ -35,7 +35,7 @@ On a `kagent` Harness, attaching a skill adds seven tools to the agent, whether Attaching a skill also changes what the agent is told. The runtime appends the name and description of every attached skill to the model request, along with an instruction to call `load_skill` before acting on one, so a skill reaches the model even before any tool is called. > [!IMPORTANT] -> The `bash` tool gives the agent shell access inside its own Actor sandbox, and the sandbox is the boundary that contains it. Review a skill before you attach it, and treat the [egress]({{< link path="substrate-runtime/sandboxing" >}}) the Actor is granted as the reach the skill has. Writes are confined to the session directory, so a skill cannot modify `/skills` or another skill's files. +> The `bash` tool gives the agent shell access inside its own Actor sandbox, and the sandbox is the boundary that contains it. Review a skill before you attach it, and treat the [egress]({{< link path="substrate-runtime/sandboxing" >}}) that the Actor is granted as the reach that the skill has. Writes are confined to the session directory, so a skill cannot modify `/skills` or another skill's files. ## Before you begin @@ -51,7 +51,7 @@ Attaching a skill also changes what the agent is told. The runtime appends the n ``` > [!WARNING] - > kagent pulls a skill image over HTTPS with certificate verification, and v1alpha3 has no option to disable it. kagent 0.x accepted an `insecureSkipVerify` flag for a local registry, and that field does not exist in 1.x. A plain HTTP registry, and a `localhost` registry that only the host can reach, both fail at agent startup. + > kagent pulls a skill image over HTTPS with certificate verification, and v1alpha3 has no option to disable it. kagent 0.x accepted an `insecureSkipVerify` flag for a local registry, but that field does not exist in 1.x. A plain HTTP registry, and a `localhost` registry that only the host can reach, both fail at agent startup. ## Build the skill @@ -148,24 +148,20 @@ kagent pulls an `oci` source as a container image and unpacks its flattened file EOF ``` -2. Build and push the image. Build for the architecture your worker nodes run, because kagent pulls the `linux/amd64` or `linux/arm64` manifest that matches the node. +2. Build and push the image. Build for the architecture that your worker nodes run, because kagent pulls the `linux/amd64` or `linux/arm64` manifest that matches the node. ```bash docker buildx build --push --platform linux/amd64 -t "$SKILL_REPO:1.0.0" . ``` -3. Read the image digest. An `oci` source must be pinned to a digest, and a tag alone is rejected. +3. Read the image digest and save the pinned reference. An `oci` source must be pinned to a digest, and a tag alone is rejected. ```bash - docker buildx imagetools inspect "$SKILL_REPO:1.0.0" | awk '/^Digest:/{print $2}' + export SKILL_OCI="$SKILL_REPO@$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' "$SKILL_REPO:1.0.0")" + echo "$SKILL_OCI" ``` Example output: ```console - sha256:9f2c1e4a7b3d5086c1a2f4e7b9d0c3a5e8f1b4d7a0c3e6f9b2d5a8c1e4f7b0d3 - ``` - -4. Save the digest reference. - ```bash - export SKILL_OCI="$SKILL_REPO@sha256:" + ghcr.io/example-org/release-notes@sha256:3091b917d23de93c40e38a574aea1e5615989ca4d7b38f79431c87e04adfa58a ``` ## Attach the skill to an AgentTemplate @@ -208,14 +204,16 @@ kagent pulls an `oci` source as a container image and unpacks its flattened file > [!NOTE] > A ready revision means that kagent accepted the reference, not that the image exists. kagent fetches the skill when the agent starts, so a wrong digest surfaces in the next step rather than this one. -3. Create an AgentInstance. An AgentInstance pins the revision it was created on, so an instance that already exists does not pick up the skill. +3. Create an AgentInstance. An AgentInstance pins the revision that it was created on, so an instance that already exists does not pick up the skill. ```bash kagent create agent-instance --harness my-first-harness --agent-template release-writer ``` -4. Save the AgentInstance ID. +4. Save the AgentInstance's ID to an environment variable. ```bash - export INSTANCE_ID= + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "release-writer")] | sort_by(.createdAt) | last | .id') + echo $INSTANCE_ID ``` ## Ask the agent to use the skill @@ -245,31 +243,25 @@ kagent pulls an `oci` source as a container image and unpacks its flattened file kagent invoke --agent-instance $INSTANCE_ID --task "What skills do you have?" ``` -## Troubleshoot a skill that does not load +## Publish a new version of the skill -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, so the AgentInstance never reaches a state where you can talk to it. +A source is immutable, so changing a skill is a two-step change: publish new content, then point the AgentTemplate at it. + +1. Edit the skill. -1. Read the Actor's logs for the agent that will not start. +2. Build and push the skill under a new tag and read the new digest. ```bash - kubectl logs -n kagent -l app.kubernetes.io/name=kagent-default --tail=50 | grep -i "materialize" + docker buildx build --push --platform linux/amd64 -t "$SKILL_REPO:1.1.0" . + export SKILL_OCI="$SKILL_REPO@$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' "$SKILL_REPO:1.1.0")" ``` -2. Match the message to its cause. +3. Update `skills[].source.oci` on the AgentTemplate with the new digest, which compiles a new revision. - | Message | Cause | - | ------- | ----- | - | `pull : ... 401 Unauthorized` | The registry needs credentials that the cluster does not have. | - | `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. | - -> [!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. +4. Create a new AgentInstance. Agents that are already running keep the skill content they started with, because their revision is pinned. ## Bundle the skill in a plugin package -A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin package{{< /gloss >}} carries several, 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. +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. 1. Restructure the directory so that each skill sits under `skills/`, and add the manifest that makes it a package. ```bash @@ -293,47 +285,111 @@ A standalone source carries one skill. A {{< gloss "Plugin package" >}}plugin pa export PLUGIN_REPO=ghcr.io//release-tools mv skills/release-notes/Dockerfile . docker buildx build --push --platform linux/amd64 -t "$PLUGIN_REPO:1.0.0" . - docker buildx imagetools inspect "$PLUGIN_REPO:1.0.0" | awk '/^Digest:/{print $2}' + 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. - ```yaml + ```bash + kubectl apply -f - < + oci: ${PLUGIN_OCI} skills: - release-notes + EOF ``` > [!IMPORTANT] - > Attaching a package enables nothing on its own. Only the names in `plugins[].skills` are turned on, so a package that gains a skill in a later version does not grant it to your agent until you add the name. An omitted or empty list is accepted and enables no skills. + > 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" >}}). -## Publish a new version of the skill +4. Create an AgentInstance on the new revision, and confirm that the agent still has the skill. The instance from the previous section is pinned to the revision that carried the standalone skill. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template release-writer + export PLUGIN_INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "release-writer")] | sort_by(.createdAt) | last | .id') + kagent invoke --agent-instance $PLUGIN_INSTANCE_ID --task "What skills do you have?" + ``` -A source is immutable, so changing a skill is a two-step change: publish new content, then point the AgentTemplate at it. + 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. -1. Edit the skill, then build and push it under a new tag and read the new digest. +## 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. + +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. ```bash - docker buildx build --push --platform linux/amd64 -t "$SKILL_REPO:1.1.0" . - docker buildx imagetools inspect "$SKILL_REPO:1.1.0" | awk '/^Digest:/{print $2}' + kubectl get agenttemplate -n kagent \ + -o jsonpath='{range .status.harnesses[0].conditions[?(@.type=="Ready")]}{.status} {.reason} {.message}{end}' ``` -2. Update `skills[].source.oci` on the AgentTemplate with the new digest, which compiles a new revision. + Example output: + ```console + False ActorTemplatePending waiting for the ActorTemplate golden snapshot + ``` -3. Create a new AgentInstance. Agents that are already running keep the skill content they started with, because their revision is pinned. + > [!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. + ```bash + export WORKER_POOL=$(kubectl get harness my-first-harness -n kagent \ + -o jsonpath='{.spec.substrate.workerPoolRef.name}') + kubectl logs -n kagent -l ate.dev/worker-pool=$WORKER_POOL --tail=200 \ + | grep -i "materialize" + ``` + + Example output, abbreviated: + ```console + {"error":"materialize agent plugins: materialize skill \"release-notes\": pull ghcr.io/example-org/release-notes@sha256:3091b91...: Get \"https://ghcr.io/v2/\": EOF","labels":{"ate.atespace":"ate-golden","ate.template.name":"release-writer-my-first-harness-23c20dcb296d"},"level":"ERROR","msg":"failed to materialize Agent Plugins"} + ``` + + A pool runs the Workers for every agent on it, so filter by the `ate.template.name` label to find one agent. Its value is the AgentTemplate name, the Harness name, and the revision's short form, joined by hyphens. + +3. Match the message to its cause. + + | Message | Cause | + | ------- | ----- | + | `pull : ... 401 Unauthorized` | The registry needs credentials that the cluster does not have. | + | `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. | + +> [!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 -* Delete the AgentInstances that you created. - ```bash - kagent delete agent-instance $INSTANCE_ID - ``` -* Delete the AgentTemplate. - ```bash - kubectl delete agenttemplate release-writer -n kagent - ``` -* Delete the skill image from your registry, and remove the `release-notes` directory from your machine. +1. Delete the AgentInstances that you created. Deleting the AgentTemplate does not remove them. Skip the second command if you did not complete the plugin package section. + ```bash + kagent delete agent-instance $INSTANCE_ID + kagent delete agent-instance $PLUGIN_INSTANCE_ID + ``` + +2. Delete the AgentTemplate. + ```bash + 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. + ```bash + cd .. + rm -rf release-notes release-tools + ``` + +4. Delete the images that you pushed, `$SKILL_REPO` and `$PLUGIN_REPO`, using your registry's own tooling. ## Next steps From 28800cbd3382efb58ab1b6f06c45f26fc042a5f8 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 8 Sep 2026 15:04:19 -0500 Subject: [PATCH 51/70] has to -> must Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/agents/agent-harness.md | 10 +++++----- docs-site/content/kagent/1.x/agents/agent-memory.md | 2 +- .../1.x/setup/model-providers/about-model-providers.md | 2 +- .../1.x/setup/model-providers/azure-ai-foundry.md | 2 +- .../1.x/setup/model-providers/byo-agentgateway.md | 6 +++--- .../1.x/setup/model-providers/google-vertexai.md | 10 +++++----- .../content/kagent/1.x/setup/model-providers/ollama.md | 4 ++-- .../kagent/1.x/setup/model-providers/sap-ai-core.md | 2 +- .../content/kagent/1.x/skills-and-mcp/about-tools.md | 2 +- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs-site/content/kagent/1.x/agents/agent-harness.md b/docs-site/content/kagent/1.x/agents/agent-harness.md index dc9a409c..d4089091 100644 --- a/docs-site/content/kagent/1.x/agents/agent-harness.md +++ b/docs-site/content/kagent/1.x/agents/agent-harness.md @@ -47,11 +47,11 @@ EOF | Field | Required | Description | | ----- | -------- | ----------- | | One of `kagent`, `codex`, `claude`, `byo` | Yes | The runtime that executes the agent. Naming none, or more than one, is rejected. For the available runtimes, see [Choose a runtime](#choose-a-runtime). | -| `workload.image` | Yes | The runtime image, pinned by `sha256` digest. A tag alone is rejected, because a revision has to be reproducible. | +| `workload.image` | Yes | The runtime image, pinned by `sha256` digest. A tag alone is rejected, because a revision must be reproducible. | | `workload.command` | For `byo` | Overrides the image entrypoint, up to 32 entries. Required for the `byo` runtime, optional otherwise. | | `workload.args` | No | Overrides the image arguments, up to 64 entries. | | `env` | No | Environment variables for the runtime, up to 100. Each entry sets either a literal `value` or a `credentialRef` naming a key in a same-namespace Secret, never both. | -| `substrate.workerPoolRef.name` | Yes | The {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} that this Harness's Actors are scheduled onto. An operator has to provision one before any agent can run. | +| `substrate.workerPoolRef.name` | Yes | The {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} that this Harness's Actors are scheduled onto. An operator must provision one before any agent can run. | | `substrate.snapshotPolicy.location` | Yes | The object storage location for Actor {{< gloss "Snapshot" >}}snapshots{{< /gloss >}}. | | `allowedAgentTemplates.selector` | No | A label selector naming which AgentTemplates this Harness admits. Omitting it admits none, which makes the Harness unusable. Admission is a one-way match. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} has no field naming a Harness, so whoever controls a Harness's selector decides what it accepts. | @@ -113,7 +113,7 @@ Some supported combinations still carry restrictions. | `codex` with `Bedrock` | Accepts only OpenAI `gpt-*` model IDs, and no `bedrock` settings beyond `region`. | | `claude` with `Anthropic` | Accepts no `anthropic` settings beyond `baseUrl`. | | `claude` with `Bedrock` | Accepts no `bedrock` settings beyond `region`. | -| `claude` with `AnthropicVertexAI` | Accepts only `projectID` and `location`. The Secret has to hold a `service_account` key whose `project_id` matches and whose `token_uri` is `https://oauth2.googleapis.com`. | +| `claude` with `AnthropicVertexAI` | Accepts only `projectID` and `location`. The Secret must hold a `service_account` key whose `project_id` matches and whose `token_uri` is `https://oauth2.googleapis.com`. | > [!IMPORTANT] > Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string. This restriction rules out both Vertex AI providers there. For more information about that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). @@ -124,9 +124,9 @@ The coding-agent runtimes also constrain what an AgentTemplate can ask for. | Constraint | Applies to | | ---------- | ---------- | -| A `Shared` agent-tool binding cannot itself carry tools, skills, plugins, or nested agents, and has to use the same provider and credentials as the agent that binds it. | `codex`, `claude` | +| A `Shared` agent-tool binding cannot itself carry tools, skills, plugins, or nested agents, and must use the same provider and credentials as the agent that binds it. | `codex`, `claude` | | An {{< gloss "MCP" >}}MCP{{< /gloss >}} server is bound whole. Claude does not support partial tool selection, so the agent sees every tool the server offers rather than only the ones a binding names. The compiler warns rather than failing. | `claude` | -| A `RemoteMCPServer` has to use the `STREAMABLE_HTTP` protocol. `SSE` is rejected. | `codex` | +| A `RemoteMCPServer` must use the `STREAMABLE_HTTP` protocol. `SSE` is rejected. | `codex` | The `kagent` and `byo` runtimes take the full set. For more information about what an AgentTemplate can bind, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). diff --git a/docs-site/content/kagent/1.x/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md index 8643f0be..d607e8be 100644 --- a/docs-site/content/kagent/1.x/agents/agent-memory.md +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -19,7 +19,7 @@ Enabling memory adds three tools to every agent on the Harness, and appends a sh | `load_memory` | Searches stored memories by query when the agent needs context it does not have. | | `prefetch_memory` | Retrieves memories relevant to the current message before the agent answers. | -Retrieval works by similarity rather than by keyword. kagent encodes the query as a vector, compares it against stored memories by cosine similarity, and puts the closest matches into the agent's context. A search returns at most five memories, and only those that score above 0.3. The agent also saves memories from a finished session on its own, so a user does not have to ask it to remember anything. +Retrieval works by similarity rather than by keyword. kagent encodes the query as a vector, compares it against stored memories by cosine similarity, and puts the closest matches into the agent's context. A search returns at most five memories, and only those that score above 0.3. The agent also saves memories from a finished session on its own, so a user does not need to ask it to remember anything. Memories are scoped to the agent and to the user who created them, and carry the time that kagent wrote them. One agent cannot read another agent's memories, even on the same Harness. diff --git a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md index 23652a3a..562bff17 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md @@ -26,7 +26,7 @@ Credentials come from a Kubernetes Secret in the same namespace as the ModelConf kagent passes model credentials to an agent as environment variables. A ModelConfig that instead requires a credential **file** mounted into the agent does not compile. The AgentTemplate reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`. kagent compiles no revision from that AgentTemplate, so no agent runs from it, and any AgentInstance that already exists keeps running the last revision that compiled. Three configurations encounter this today. - **The Vertex AI providers, on the `kagent` and `byo` runtimes.** `GeminiVertexAI` and `AnthropicVertexAI` mount the Google credentials file that `apiKeySecret` names. Leaving `apiKeySecret` unset compiles, but a Substrate Actor does not inherit cloud workload identity, so the agent still has no credentials to send. The `claude` runtime is the exception: it passes the same credentials as an environment variable, so `AnthropicVertexAI` works there. For more information, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). - **A private certificate authority (CA), on any provider.** Setting `tls.caCertSecretRef` mounts the CA bundle as a file. Every provider accepts the `tls` block, so this affects all of them, not only the Vertex AI providers. You cannot reach a provider endpoint that presents a certificate from a private CA, unless you set `tls.disableVerify: true`, which skips certificate verification entirely and belongs only in a test environment. -- **OpenAI token exchange.** The `openAI.tokenExchange` block acquires a bearer token by reading a mounted service account file, so a ModelConfig that sets it never compiles. An OpenAI-compatible endpoint has to accept a static API key instead. For more information, see [OpenAI]({{< link path="setup/model-providers/openai" >}}). +- **OpenAI token exchange.** The `openAI.tokenExchange` block acquires a bearer token by reading a mounted service account file, so a ModelConfig that sets it never compiles. An OpenAI-compatible endpoint must accept a static API key instead. For more information, see [OpenAI]({{< link path="setup/model-providers/openai" >}}). ## The Harness runtime decides which providers are available diff --git a/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md index fb10e251..78f1f0d7 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md @@ -5,7 +5,7 @@ weight: 20 author: kagent.dev --- -The `Foundry` provider calls a model deployment in an Azure AI Foundry resource. The chat model has to be reachable through Foundry's OpenAI-compatible chat completions API. +The `Foundry` provider calls a model deployment in an Azure AI Foundry resource. The chat model must be reachable through Foundry's OpenAI-compatible chat completions API. ## Create the ModelConfig diff --git a/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md b/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md index f3ed013f..773bbdb4 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/byo-agentgateway.md @@ -39,7 +39,7 @@ author: kagent.dev EOF ``` -3. Create an `AgentgatewayModel` resource for each model that kagent should reach. The resource name becomes the model name that kagent sends in its requests, so it has to match the `model` field of the ModelConfig that you create later. The following example routes requests for `gpt-4o-mini` to OpenAI. For more provider and authentication options, see the [agentgateway model documentation](https://docs.solo.io/agentgateway/latest/llm/models/). +3. Create an `AgentgatewayModel` resource for each model that kagent should reach. The resource name becomes the model name that kagent sends in its requests, so it must match the `model` field of the ModelConfig that you create later. The following example routes requests for `gpt-4o-mini` to OpenAI. For more provider and authentication options, see the [agentgateway model documentation](https://docs.solo.io/agentgateway/latest/llm/models/). ```yaml kubectl apply -f - <}}). @@ -67,10 +67,10 @@ The difference is how each runtime receives the Google credentials. Vertex AI au kagent validates the service account key at compile time rather than failing at run time, so a malformed credential surfaces on the AgentTemplate's `Compatible` condition. -- The Secret key has to hold valid JSON. -- The document has to be a `service_account` key. Other credential types are not accepted yet. -- Its `project_id` has to match `anthropicVertexAI.projectID`. -- Its `token_uri` has to be `https://oauth2.googleapis.com`. +- The Secret key must hold valid JSON. +- The document must be a `service_account` key. Other credential types are not accepted yet. +- Its `project_id` must match `anthropicVertexAI.projectID`. +- Its `token_uri` must be `https://oauth2.googleapis.com`. ## Gemini models on Vertex AI diff --git a/docs-site/content/kagent/1.x/setup/model-providers/ollama.md b/docs-site/content/kagent/1.x/setup/model-providers/ollama.md index a8a33d11..c26d1fb5 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/ollama.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/ollama.md @@ -93,7 +93,7 @@ EOF | Field | Description | | ----- | ----------- | -| `model` | The name of the model as Ollama knows it, such as `llama3`. This has to be a model that you already pulled onto the server. | +| `model` | The name of the model as Ollama knows it, such as `llama3`. This must be a model that you already pulled onto the server. | | `provider` | The provider to use, `Ollama`. | | `ollama.host` | The address of the Ollama server. Use the in-cluster Service address when Ollama runs in the same cluster. | @@ -117,7 +117,7 @@ spec: ``` > [!NOTE] -> An agent runs inside a sandboxed Actor with controlled egress, so the Ollama server has to be reachable from the cluster network. An Ollama server on your laptop is not reachable from an agent, even when `kubectl port-forward` makes it reachable from your terminal. +> An agent runs inside a sandboxed Actor with controlled egress, so the Ollama server must be reachable from the cluster network. An Ollama server on your laptop is not reachable from an agent, even when `kubectl port-forward` makes it reachable from your terminal. ## Next steps diff --git a/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md b/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md index d9e6c2e0..10ace7aa 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/sap-ai-core.md @@ -15,7 +15,7 @@ kagent reaches SAP AI Core through its [Orchestration Service](https://help.sap. export SAP_AI_CORE_CLIENT_SECRET= ``` -2. Create a Kubernetes Secret that stores both credentials. The Secret has to contain the keys `client_id` and `client_secret` under exactly those names. +2. Create a Kubernetes Secret that stores both credentials. The Secret must contain the keys `client_id` and `client_secret` under exactly those names. ```bash kubectl create secret generic kagent-sapaicore -n kagent \ --from-literal client_id=$SAP_AI_CORE_CLIENT_ID \ 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 f0eeaecc..3e367857 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 @@ -72,4 +72,4 @@ A `Shared` binding nests one agent inside another's runtime, so kagent constrain - **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`. -- **The bound template must be admitted too.** A nested AgentTemplate has to match the same {{< gloss "Harness" >}}Harness{{< /gloss >}}'s `allowedAgentTemplates` selector. Binding a template that the Harness does not admit is rejected. +- **The bound template must be admitted too.** A nested AgentTemplate must match the same {{< gloss "Harness" >}}Harness{{< /gloss >}}'s `allowedAgentTemplates` selector. Binding a template that the Harness does not admit is rejected. From d9c08c117e3b0dea36ac97cd9b2cf11d8180fe05 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 8 Sep 2026 15:57:23 -0500 Subject: [PATCH 52/70] Phase 3 - agent delegation Signed-off-by: Rachael Graham --- .../content/kagent/1.x/examples/a2a-agents.md | 74 ++++++- .../kagent/1.x/examples/agent-delegation.md | 198 ++++++++++++++++++ .../kagent/1.x/examples/agents-via-mcp.md | 2 +- .../content/kagent/1.x/examples/skills.md | 2 +- 4 files changed, 270 insertions(+), 6 deletions(-) create mode 100644 docs-site/content/kagent/1.x/examples/agent-delegation.md diff --git a/docs-site/content/kagent/1.x/examples/a2a-agents.md b/docs-site/content/kagent/1.x/examples/a2a-agents.md index b34512c1..a547f384 100644 --- a/docs-site/content/kagent/1.x/examples/a2a-agents.md +++ b/docs-site/content/kagent/1.x/examples/a2a-agents.md @@ -33,7 +33,7 @@ The following methods are used in this example. The service defines more, includ | Method | What it does | | ------ | ------------ | | `GetExtendedAgentCard` | Returns the agent card describing the instance. | -| `SendMessage` | Sends a message and returns the finished task. | +| `SendMessage` | Sends a message and returns the task after the agent either finishes the turn or pauses for a person. | | `SendStreamingMessage` | Sends a message and streams events as the agent works. | | `GetTask` | Reads a task that a previous call created. | | `CancelTask` | Stops a task that is still running. | @@ -93,7 +93,7 @@ An A2A client typically starts by reading the agent card, which tells it what th ## Send a message -`SendMessage` blocks until the agent finishes, then returns the whole task. A message needs its own ID, a role, and at least one part. +`SendMessage` blocks until the agent finishes the turn, or pauses to ask a person, and then returns the whole task. A message needs its own ID, a role, and at least one part. 1. Send a message to the AgentInstance. ```bash @@ -194,9 +194,75 @@ A task that is still running reports `TASK_STATE_WORKING` and has no artifacts y ## When an agent needs a person -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, and the caller answers by sending a message that carries the same task ID. +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. Every kagent agent can raise the question kind, because the runtime gives each one a built-in `ask_user` tool, so a system prompt that tells an agent to ask before it answers is enough to see a pause. -A client only sees these pauses if it requests the human-in-the-loop extension that the agent card advertises. A client that never requests it is never interrupted. For the pause types, the approval model, and what the agent receives back, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). +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. + +1. Send a message that requests the extension. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -H "A2A-Extensions: https://kagent.dev/extensions/hitl/v1" \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","extensions":["https://kagent.dev/extensions/hitl/v1"],"parts":[{"text":"Should I increase the replica count?"}]}}' \ + localhost:8084 lf.a2a.v1.A2AService/SendMessage + ``` + +2. Read the pause. The task stops at `TASK_STATE_INPUT_REQUIRED`, and the status message's `metadata` holds the request, keyed by the extension URI. Example output: + ```json + { + "task": { + "id": "01a0828d-6bc4-700a-b27e-9115b3174827", + "status": { + "state": "TASK_STATE_INPUT_REQUIRED", + "message": { + "parts": [{ "text": "Which environment do you mean for increasing the replica count?" }], + "metadata": { + "https://kagent.dev/extensions/hitl/v1": { + "type": "ask_user_request", + "id": "adk-823f48ab-4a0b-4652-a23f-e9db9724d35f", + "questions": [ + { + "question": "Which environment do you mean for increasing the replica count?", + "choices": ["development", "staging", "production"], + "multiple": false + } + ] + } + }, + "extensions": ["https://kagent.dev/extensions/hitl/v1"] + } + } + } + } + ``` + +3. Save both identifiers to environment variables. The request `id` is within the extension metadata and starts with `adk-`. + ```bash + export PAUSED_TASK_ID= + export REQUEST_ID= + ``` + +4. Answer on the same task. The response goes in the same metadata key, names the request `id` it answers, and sets `taskId` so that it answers the paused task rather than starting a new turn. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-namespace: kagent" \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -H "A2A-Extensions: https://kagent.dev/extensions/hitl/v1" \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","taskId":"'"$PAUSED_TASK_ID"'","contextId":"'"$INSTANCE_ID"'","role":"ROLE_USER","extensions":["https://kagent.dev/extensions/hitl/v1"],"parts":[{"text":"staging"}],"metadata":{"https://kagent.dev/extensions/hitl/v1":{"type":"ask_user_response","id":"'"$REQUEST_ID"'","answers":[{"answer":["staging"]}]}}}}' \ + localhost:8084 lf.a2a.v1.A2AService/SendMessage + ``` + + The agent resumes where it paused and finishes the turn. Example output: + ```console + "state": "TASK_STATE_COMPLETED" + "text": "For the staging environment, I recommend increasing the replica count to ensure better load distribution and fault tolerance during testing." + ``` + +> [!IMPORTANT] +> A caller that does not request the extension is still interrupted. The task stops at `TASK_STATE_INPUT_REQUIRED` exactly as before, and the question arrives as ordinary text on the status message, but the metadata carries no request `id`. Without that `id` there is nothing to answer, so the task waits until something cancels it. Request the extension on any call to an agent that can pause. + +A tool approval works the same way with a different payload, `tool_approval_request` answered by `tool_approval_response`. For the pause kinds, the approval model, and what a nested agent's pause looks like, see [Human in the loop]({{< link path="agents/human-in-the-loop" >}}). ## Clean up diff --git a/docs-site/content/kagent/1.x/examples/agent-delegation.md b/docs-site/content/kagent/1.x/examples/agent-delegation.md new file mode 100644 index 00000000..52def8f2 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/agent-delegation.md @@ -0,0 +1,198 @@ +--- +title: Delegate work to another agent +description: Bind one AgentTemplate to another as an agent tool, and watch a front-line agent hand a conversation to a specialist. +weight: 50 +author: kagent.dev +--- + +An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} can bind another AgentTemplate as a tool, so that a general agent passes work to a specialist instead of answering itself. This example builds a front-line incident agent with two specialists behind it, and shows what a caller sees when a hand-off happens. + +For the binding fields, the isolation modes, and the rules that constrain a tree, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). For the Harness that all of these templates run on, see [Agent harness]({{< link path="agents/agent-harness" >}}). + +## About agent bindings + +A binding names a second AgentTemplate in the same namespace, describes when to use it, and picks an isolation mode. + +> [!IMPORTANT] +> **A `Shared` binding hands over the conversation rather than returning an answer.** kagent compiles the binding into a sub-agent of the parent and runs the whole tree in one Actor, so the parent's model can transfer the turn to it. Once that happens, the bound agent answers, and it keeps answering the turns that follow in the same conversation. The parent does not receive the bound agent's output and cannot summarize it or combine it with a second agent's. Plan a tree around routing a conversation to the right specialist, rather than around a coordinator that collects results. + +The first three fields are required. `isolation` is optional, and defaults to the only mode that the compiler accepts. + +| Field | Description | +| ----- | ----------- | +| `tools[].agent.name` | The name that the parent's model sees for this binding. It replaces the bound template's own name. | +| `tools[].agent.description` | What the binding is for. The parent's model reads this to decide when to hand work over, so it does the same job that a tool description does. | +| `tools[].agent.templateRef.name` | The AgentTemplate to bind, in the same namespace. | +| `tools[].agent.isolation` | Whether the bound agent runs inside the parent's {{< gloss "Actor" >}}Actor{{< /gloss >}}, as `Shared` does, or in an Actor of its own. See [Shared and Dedicated isolation]({{< link path="skills-and-mcp/about-tools#shared-and-dedicated-isolation" >}}). | + +> [!WARNING] +> `Dedicated`, the mode that would give a bound agent its own Actor and sandbox, is accepted by the schema and rejected by the compiler, with `Dedicated AgentTemplate tools are not supported yet`. A template that uses it never becomes ready. Leave `isolation` unset, or set it to `Shared`. + +Every template in the tree is an ordinary AgentTemplate. Each one compiles its own {{< gloss "Revision" >}}revision{{< /gloss >}} and needs the Harness to admit it, so the bound templates carry the same label as the parent. + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}). + +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}), so that you have a Harness and know which label it admits. This example uses a Harness named `my-first-harness` that admits the label `kagent.dev/harness: my-first-harness`. + +## Create specialist agents + +Apply two ordinary AgentTemplates. Nothing marks them as bound, because a template does not know that something binds it. + +1. Create the specialists. Each one labels itself for the same Harness, and each system prompt makes its replies recognizable so that you can tell which agent answered. + ```bash + kubectl apply -f - < [!NOTE] + > Deleting a bound specialist while the coordinator still binds it breaks the coordinator rather than the specialist. Its `ResolvedRefs` condition reports `resolve AgentTemplate "incident-researcher": not found`, and `Compatible` and `Ready` both report `blocked by ResolvedRefs`. Recreating the specialist, or removing the binding, clears it. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Read the binding fields, the isolation modes, and the rules that constrain an agent tree." >}} + {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Understand the Harness that every template in the tree runs on." >}} + {{< card link=`{{< link path="examples/a2a-agents" >}}` title="Call an agent over A2A" subtitle="Reach the same agents directly, and see what a hand-off looks like on the wire." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md index 4c98a17f..a5671d67 100644 --- a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -244,7 +244,7 @@ With `curl` you build each request yourself, so every field is visible: the tool ### Invoke without waiting -Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's result. Rather than blocking, `invoke_agent_instance` returns immediately with a task to poll, which keeps a long agent run from holding a request open. Because the handler is stateless, the declaration travels in the `_meta` of every request rather than being established once, and that includes each poll. +Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's result. Rather than blocking, `invoke_agent_instance` returns immediately with a task to poll, which keeps a long agent run from holding a request open. Because the handler is stateless, every request repeats the declaration in its `_meta` rather than establishing it once, and that includes each poll. 1. Invoke the agent with the extension declared in `params._meta`. Leave the declaration out and the tool blocks instead, as in [List and invoke an agent](#list-and-invoke-an-agent-1). ```bash diff --git a/docs-site/content/kagent/1.x/examples/skills.md b/docs-site/content/kagent/1.x/examples/skills.md index c2bd0dd6..513254f0 100644 --- a/docs-site/content/kagent/1.x/examples/skills.md +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -350,7 +350,7 @@ A skill that kagent cannot fetch stops the agent from starting at all, rather th | grep -i "materialize" ``` - Example output, abbreviated: + Example output: ```console {"error":"materialize agent plugins: materialize skill \"release-notes\": pull ghcr.io/example-org/release-notes@sha256:3091b91...: Get \"https://ghcr.io/v2/\": EOF","labels":{"ate.atespace":"ate-golden","ate.template.name":"release-writer-my-first-harness-23c20dcb296d"},"level":"ERROR","msg":"failed to materialize Agent Plugins"} ``` From dc76c23fe7e69bee12832861251916b8637c3fcf Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 9 Sep 2026 12:38:18 -0500 Subject: [PATCH 53/70] Latest updates Signed-off-by: Rachael Graham --- .../snippets/grpcurl-prerequisites.md | 2 +- .../kagent-docs/versions/agent-substrate.md | 2 +- .../content/kagent/1.x/agents/agent-memory.md | 6 +-- .../kagent/1.x/agents/human-in-the-loop.md | 3 +- .../content/kagent/1.x/examples/a2a-agents.md | 33 ++++++---------- .../kagent/1.x/examples/agent-substrate.md | 39 ++++++++++--------- .../kagent/1.x/examples/agents-via-mcp.md | 35 ++++++----------- .../1.x/get-started/your-first-agent.md | 2 +- .../1.x/get-started/your-first-mcp-tool.md | 2 +- .../content/kagent/1.x/setup/installation.md | 6 +-- .../substrate-runtime/suspend-and-resume.md | 2 +- docs-site/data/glossary.yaml | 2 +- 12 files changed, 55 insertions(+), 79 deletions(-) diff --git a/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md b/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md index 9e7ca913..f636f2b0 100644 --- a/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md +++ b/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md @@ -9,5 +9,5 @@ 4. Port-forward the controller's gRPC port, and leave the command running. ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 ``` diff --git a/docs-site/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md index c4d8947d..e9d19937 100644 --- a/docs-site/assets/kagent-docs/versions/agent-substrate.md +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -1 +1 @@ -{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.25{{< /version >}} \ No newline at end of file +{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.26{{< /version >}} \ No newline at end of file diff --git a/docs-site/content/kagent/1.x/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md index d607e8be..7dd31d31 100644 --- a/docs-site/content/kagent/1.x/agents/agent-memory.md +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -214,7 +214,7 @@ No CLI command wraps the service yet, so these examples call it with [grpcurl](h 1. Port-forward the controller's gRPC port, and confirm that your kagent installation sets `controller.grpc.reflection=true`. ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 ``` 2. List the memories that an agent stores for one user. @@ -222,7 +222,7 @@ No CLI command wraps the service yet, so these examples call it with [grpcurl](h grpcurl -plaintext -d '{ "agent_name": "kagent__NS__my_first_agent_my_first_harness", "user_id": "admin@kagent.dev" - }' localhost:8084 kagent.api.v1alpha1.MemoryService/List + }' localhost:8083 kagent.api.v1alpha1.MemoryService/List ``` Each entry returns the `id`, `content`, `access_count`, `created_at`, and `expires_at` fields. Results are ranked by how often retrieval has returned them, so the most-used memories appear first. @@ -232,7 +232,7 @@ No CLI command wraps the service yet, so these examples call it with [grpcurl](h grpcurl -plaintext -d '{ "agent_name": "kagent__NS__my_first_agent_my_first_harness", "user_id": "admin@kagent.dev" - }' localhost:8084 kagent.api.v1alpha1.MemoryService/Delete + }' localhost:8083 kagent.api.v1alpha1.MemoryService/Delete ``` The memory service also exposes `Search`, `AddSession`, and `AddSessionBatch`. Each method takes a 768-dimensional vector rather than text, because kagent does not embed on the caller's behalf. Call them from a program that already has an embedding model, rather than by hand. diff --git a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md index 82f54c75..d677b9d2 100644 --- a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md +++ b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md @@ -63,7 +63,6 @@ A call from outside the cluster addresses the agent with two more headers, becau ```bash grpcurl -plaintext \ -H 'A2A-Extensions: https://kagent.dev/extensions/hitl/v1' \ - -H 'x-kagent-agent-instance-namespace: kagent' \ -H 'x-kagent-agent-instance-id: ' \ -d '{ "message": { @@ -71,7 +70,7 @@ grpcurl -plaintext \ "role": "ROLE_USER", "parts": [{"text": "Delete the obsolete pod in the production namespace."}] } - }' localhost:8084 lf.a2a.v1.A2AService/SendStreamingMessage + }' localhost:8083 lf.a2a.v1.A2AService/SendStreamingMessage ``` When the agent pauses, the payload arrives in the status message's `metadata`, keyed by the extension URI. The URI is also listed in the message's `extensions` array. Each payload carries a `type` field that specifies its shape. diff --git a/docs-site/content/kagent/1.x/examples/a2a-agents.md b/docs-site/content/kagent/1.x/examples/a2a-agents.md index a547f384..347d4a15 100644 --- a/docs-site/content/kagent/1.x/examples/a2a-agents.md +++ b/docs-site/content/kagent/1.x/examples/a2a-agents.md @@ -11,20 +11,15 @@ This example uses [grpcurl](https://github.com/fullstorydev/grpcurl) to show the ## About the kagent A2A service -The controller serves `lf.a2a.v1.A2AService` on its gRPC port, `8084`, which is the same port and service that the kagent CLI uses. +The controller serves `lf.a2a.v1.A2AService` on port `8083`, alongside its REST API and its MCP endpoint. The kagent CLI reaches the same port and the same service. -An AgentInstance is not addressed by a URL path. A caller names the instance in two pieces of request metadata, and the controller routes the call to that instance's Actor. - -| Metadata header | Value | -| --------------- | ----- | -| `x-kagent-agent-instance-namespace` | The namespace holding the AgentInstance. | -| `x-kagent-agent-instance-id` | The AgentInstance's ID. | +An AgentInstance is not addressed by a URL path. A caller names the instance in the `x-kagent-agent-instance-id` request metadata header, carrying the AgentInstance's ID, and the controller routes the call to that instance's Actor. Exactly one such header is required. > [!NOTE] > Header routing replaces the `/api/a2a///` URL paths that kagent 0.x served over HTTP. The unit you address also changed: a 0.x caller addressed an agent, while a 1.x caller addresses one AgentInstance, which is one conversation with that agent. > [!WARNING] -> The open source build does not authenticate this port. Any caller that can reach it can invoke any AgentInstance, so do not expose port `8084` outside the cluster. For what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). +> The open source build does not authenticate this port. Any caller that can reach it can invoke any AgentInstance, so do not expose port `8083` outside the cluster. For what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). ### A2A methods @@ -49,9 +44,8 @@ An A2A client typically starts by reading the agent card, which tells it what th 1. Fetch the card for your AgentInstance. ```bash grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ - localhost:8084 lf.a2a.v1.A2AService/GetExtendedAgentCard + localhost:8083 lf.a2a.v1.A2AService/GetExtendedAgentCard ``` Example output: @@ -61,7 +55,7 @@ An A2A client typically starts by reading the agent card, which tells it what th "description": "My first kagent agent", "supportedInterfaces": [ { - "url": "http://kagent-controller.kagent.svc:8084", + "url": "http://kagent-controller.kagent.svc:8083", "protocolBinding": "GRPC", "protocolVersion": "1.0" } @@ -98,10 +92,9 @@ An A2A client typically starts by reading the agent card, which tells it what th 1. Send a message to the AgentInstance. ```bash grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"What is 7 times 6? Answer with just the number."}]}}' \ - localhost:8084 lf.a2a.v1.A2AService/SendMessage + localhost:8083 lf.a2a.v1.A2AService/SendMessage ``` The reply text arrives in `artifacts`, not in `status`. Example output, with the message history omitted: @@ -142,10 +135,9 @@ An A2A client typically starts by reading the agent card, which tells it what th 1. Send a message on the streaming method. ```bash grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"Count from 1 to 3."}]}}' \ - localhost:8084 lf.a2a.v1.A2AService/SendStreamingMessage + localhost:8083 lf.a2a.v1.A2AService/SendStreamingMessage ``` 2. Read the event sequence. The stream opens with the task at `TASK_STATE_SUBMITTED`, moves to `TASK_STATE_WORKING`, and then emits an artifact update for each chunk of the reply. Every chunk shares one `artifactId`, so a client appends them into a single artifact rather than treating each as a separate answer. Example output, abbreviated to the text of each event: @@ -165,10 +157,9 @@ A task outlives the call that created it, so a caller that lost its connection c 1. Read the task by ID. ```bash grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ -d '{"id":"'"$TASK_ID"'"}' \ - localhost:8084 lf.a2a.v1.A2AService/GetTask + localhost:8083 lf.a2a.v1.A2AService/GetTask ``` 2. Read the task's fields. `GetTask` returns the task itself, rather than wrapping it in a `task` field the way `SendMessage` does. The `status`, `artifacts`, and `history` values are the ones that the original call returned. @@ -201,11 +192,10 @@ Answering a pause needs the human-in-the-loop extension, which a caller requests 1. Send a message that requests the extension. ```bash grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ -H "A2A-Extensions: https://kagent.dev/extensions/hitl/v1" \ -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","extensions":["https://kagent.dev/extensions/hitl/v1"],"parts":[{"text":"Should I increase the replica count?"}]}}' \ - localhost:8084 lf.a2a.v1.A2AService/SendMessage + localhost:8083 lf.a2a.v1.A2AService/SendMessage ``` 2. Read the pause. The task stops at `TASK_STATE_INPUT_REQUIRED`, and the status message's `metadata` holds the request, keyed by the extension URI. Example output: @@ -246,11 +236,10 @@ Answering a pause needs the human-in-the-loop extension, which a caller requests 4. Answer on the same task. The response goes in the same metadata key, names the request `id` it answers, and sets `taskId` so that it answers the paused task rather than starting a new turn. ```bash grpcurl -plaintext \ - -H "x-kagent-agent-instance-namespace: kagent" \ -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ -H "A2A-Extensions: https://kagent.dev/extensions/hitl/v1" \ -d '{"message":{"messageId":"'"$(uuidgen)"'","taskId":"'"$PAUSED_TASK_ID"'","contextId":"'"$INSTANCE_ID"'","role":"ROLE_USER","extensions":["https://kagent.dev/extensions/hitl/v1"],"parts":[{"text":"staging"}],"metadata":{"https://kagent.dev/extensions/hitl/v1":{"type":"ask_user_response","id":"'"$REQUEST_ID"'","answers":[{"answer":["staging"]}]}}}}' \ - localhost:8084 lf.a2a.v1.A2AService/SendMessage + localhost:8083 lf.a2a.v1.A2AService/SendMessage ``` The agent resumes where it paused and finishes the turn. Example output: @@ -267,7 +256,7 @@ A tool approval works the same way with a different payload, `tool_approval_requ ## Clean up * This example creates no Kubernetes resources, so you have nothing to delete. -* You can stop the 8084 port-forward for the kagent-controller service with `Ctrl+C`. +* You can stop the 8083 port-forward for the kagent-controller service with `Ctrl+C`. * The tasks that your messages created stay on the AgentInstance as part of its conversation, and deleting the AgentInstance removes them. ## Next steps diff --git a/docs-site/content/kagent/1.x/examples/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md index 51e79e84..3a201f03 100644 --- a/docs-site/content/kagent/1.x/examples/agent-substrate.md +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -1,6 +1,6 @@ --- title: Agent Substrate -description: Watch an agent's Actor suspend between turns, pin its state with a checkpoint, and fork that checkpoint into a second agent. +description: Watch an agent's Actor suspend between turns, pin its state with a checkpoint, and fork that checkpoint into a second agent that continues the conversation. weight: 10 author: kagent.dev --- @@ -83,8 +83,8 @@ Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent 1. Create a checkpoint. The checkpoint records the snapshot that it pinned and how far the {{< gloss "Transcript" >}}transcript{{< /gloss >}} had advanced. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. ```bash grpcurl -plaintext \ - -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'","requestId":"'"$(uuidgen)"'"}' \ - localhost:8084 kagent.api.v1alpha1.CheckpointService/CreateCheckpoint + -d '{"agentInstanceId":"'"$INSTANCE_ID"'","requestId":"'"$(uuidgen)"'"}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/CreateCheckpoint ``` Example output: @@ -92,7 +92,6 @@ Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent { "checkpoint": { "id": "0198c3e2-8a41-7d05-b6c2-1f4e9a7b3c58", - "namespace": "kagent", "agentInstanceId": "0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10", "headTaskId": "0198c3d9-b7e3-7a24-8f10-6c2d5e8a1b47", "historySequence": "4", @@ -113,24 +112,24 @@ Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent 3. List the checkpoints on the AgentInstance at any time. Omit `limit` for the default page of 50, up to a maximum of 100. ```bash grpcurl -plaintext \ - -d '{"namespace":"kagent","agentInstanceId":"'"$INSTANCE_ID"'","page":{"limit":50}}' \ - localhost:8084 kagent.api.v1alpha1.CheckpointService/ListCheckpoints + -d '{"agentInstanceId":"'"$INSTANCE_ID"'","page":{"limit":50}}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/ListCheckpoints ``` Underneath, the checkpoint attaches an ActorSnapshotTag named `checkpoint-` to the snapshot, and Agent Substrate does not collect a snapshot while a tag names it. You can see the tag by running `kubectl ate get actor-snapshot-tag`. -## Fork a checkpoint into a second agent +## Fork the conversation into a second agent -Forking creates a second AgentInstance from the pinned snapshot, running the revision that the checkpoint was taken on. The original is untouched, so you end up with two independent AgentInstances that started from the same state. +Forking creates a second AgentInstance from the pinned snapshot, running the revision that the checkpoint was taken on. The fork continues the conversation from the checkpoint: it inherits the {{< gloss "Transcript" >}}transcript{{< /gloss >}} up to that point, along with the Actor's durable state. -> [!IMPORTANT] -> A fork does not carry the conversation. It inherits the Actor's durable state as of the checkpoint, and it runs the checkpoint's pinned revision, but it starts its own {{< gloss "Transcript" >}}transcript{{< /gloss >}} rather than continuing the original's. A transcript belongs to the AgentInstance that produced it, so asking a fork about earlier turns returns nothing. Expect this to change: carrying the conversation across a fork is the behavior the API is shaped for, and it is not what the current build does. +> [!NOTE] +> The two branches share everything up to the checkpoint and nothing after it. New turns append only to the AgentInstance that received them, so the original's history and the checkpoint itself stay unchanged no matter what the fork goes on to do. Each branch runs its own Actor. 1. Fork the checkpoint. ```bash grpcurl -plaintext \ - -d '{"namespace":"kagent","checkpointId":"'"$CHECKPOINT_ID"'","requestId":"'"$(uuidgen)"'"}' \ - localhost:8084 kagent.api.v1alpha1.CheckpointService/ForkAgentInstance + -d '{"checkpointId":"'"$CHECKPOINT_ID"'","requestId":"'"$(uuidgen)"'"}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/ForkAgentInstance ``` The response carries a new AgentInstance with its own ID. Example output: @@ -138,7 +137,6 @@ Forking creates a second AgentInstance from the pinned snapshot, running the rev { "agentInstance": { "id": "0198c3e5-1d62-7f38-a904-8b3c7e2f5d16", - "namespace": "kagent", "harness": { "namespace": "kagent", "name": "my-first-harness" @@ -147,18 +145,21 @@ Forking creates a second AgentInstance from the pinned snapshot, running the rev "namespace": "kagent", "name": "my-first-agent" }, - "state": "AGENT_INSTANCE_STATE_READY" + "state": "AGENT_INSTANCE_STATE_READY", + "contextId": "ce5a10b8-7789-4ba7-8395-e60a339de763" } } ``` -2. Save the fork's ID, then send it down a different path than the original. + The `contextId` is the fork's link to the conversation it inherited. It matches the source AgentInstance's `contextId`, while the two `id` values differ, so the branches address one shared conversation from separate instances. + +2. Save the fork's ID, then ask it about a turn that happened before the checkpoint. ```bash export FORK_ID= - kagent invoke --agent-instance $FORK_ID --task "List the pods in the kagent namespace." + kagent invoke --agent-instance $FORK_ID --task "What did I ask you first?" ``` - The fork answers as a new conversation. Send the original a different question and the two diverge from here, each holding its own transcript. + The fork answers from the conversation it inherited. That is the difference between a fork and a new AgentInstance that happens to use the same AgentTemplate. Send the original a different question and the two diverge from here. 3. List your AgentInstances to verify that both appear as separate AgentInstances. ```bash @@ -185,8 +186,8 @@ A fork runs the compiled {{< gloss "Revision" >}}revision{{< /gloss >}} that its 1. Delete the checkpoint. Deleting removes the ActorSnapshotTag and releases the pin, and Agent Substrate can collect the snapshot whenever no tag names it. ```bash grpcurl -plaintext \ - -d '{"namespace":"kagent","checkpointId":"'"$CHECKPOINT_ID"'"}' \ - localhost:8084 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint + -d '{"checkpointId":"'"$CHECKPOINT_ID"'"}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint ``` 2. Delete the fork. A fork is an AgentInstance in its own right, so deleting the checkpoint that it started from does not remove it. diff --git a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md index a5671d67..3d6742a6 100644 --- a/docs-site/content/kagent/1.x/examples/agents-via-mcp.md +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -20,7 +20,7 @@ The MCP server is part of the controller's HTTP port rather than a separate depl - **Extensions**: The server advertises the `io.modelcontextprotocol/tasks` extension, which changes how invocations behave. For more information, see [Invoke without waiting](#invoke-without-waiting). > [!NOTE] -> The tools take no session or conversation argument, because an AgentInstance **is** the conversation. Sending a second message to the same `agent_instance_id` continues where the first left off, and the reply's `context_id` matches the instance's own ID. To hold two independent conversations on one AgentTemplate, create two AgentInstances. +> The tools take no session or conversation argument, because an AgentInstance **is** the conversation. Sending a second message to the same `agent_instance_id` continues where the first left off. The reply's `context_id` names the durable conversation rather than the instance, so it differs from the `agent_instance_id` and is shared by any fork taken from it. To hold two independent conversations on one AgentTemplate, create two AgentInstances. > [!WARNING] > The open source build does not authenticate this endpoint. Every request is accepted, and the caller's identity is read from an `X-User-Id` header that the caller sets itself, defaulting to `admin@kagent.dev`. Because the endpoint can invoke agents, create checkpoints, and create AgentInstances, do not expose port `8083` outside the cluster. For the wider identity model and what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). @@ -138,9 +138,9 @@ You can checkpoint an instance before letting an agent try something risky, then > Ask that fork what 10+5 is. ``` - The fork answers `15`. Ask it about an earlier turn of the original conversation and it has nothing to report, because a fork begins its own conversation rather than continuing the original's. + The fork answers `15`. Ask it about an earlier turn and it answers from the conversation it inherited, because a fork continues from the checkpoint rather than starting fresh. -Plan for the two AgentInstances to share a starting state and nothing else. A fork also runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. +The two AgentInstances share everything up to the checkpoint and nothing after it, because new turns append only to the branch that received them. A fork also runs the {{< gloss "Revision" >}}revision{{< /gloss >}} its checkpoint was taken on, so editing the AgentTemplate afterwards does not change what the fork runs. You can now safely [clean up these resources](#clean-up). @@ -164,7 +164,7 @@ With `curl` you build each request yourself, so every field is visible: the tool "method": "tools/call", "params": { "name": "list_agent_instances", - "arguments": { "namespace": "kagent" } + "arguments": {} } }' ``` @@ -191,7 +191,6 @@ With `curl` you build each request yourself, so every field is visible: the tool "params": { "name": "invoke_agent_instance", "arguments": { - "namespace": "kagent", "agent_instance_id": "'"$INSTANCE_ID"'", "message": "What is 2+2? Answer with just the number." } @@ -202,10 +201,9 @@ With `curl` you build each request yourself, so every field is visible: the tool The reply text comes back as the tool's content, with the task identifiers alongside it. Example output: ```json { - "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", "task_id": "01a06d0d-5fcf-7b07-aae3-1f470a8ee157", - "context_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "context_id": "ce5a10b8-7789-4ba7-8395-e60a339de763", "state": "TASK_STATE_COMPLETED", "text": "4" } @@ -223,7 +221,6 @@ With `curl` you build each request yourself, so every field is visible: the tool "params": { "name": "invoke_agent_instance", "arguments": { - "namespace": "kagent", "agent_instance_id": "'"$INSTANCE_ID"'", "message": "Multiply that by 10." } @@ -233,10 +230,9 @@ With `curl` you build each request yourself, so every field is visible: the tool Example output: ```json { - "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", "task_id": "01a06d0d-6864-79f1-a4cb-8547f77638ba", - "context_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "context_id": "ce5a10b8-7789-4ba7-8395-e60a339de763", "state": "TASK_STATE_COMPLETED", "text": "40" } @@ -258,7 +254,6 @@ Declaring the `io.modelcontextprotocol/tasks` extension changes the same tool's "params": { "name": "invoke_agent_instance", "arguments": { - "namespace": "kagent", "agent_instance_id": "'"$INSTANCE_ID"'", "message": "Count to three." }, @@ -437,7 +432,6 @@ The three checkpoint tools pin an instance's state and start a second agent from "params": { "name": "create_agent_instance_checkpoint", "arguments": { - "namespace": "kagent", "agent_instance_id": "'"$INSTANCE_ID"'", "request_id": "my-first-checkpoint" } @@ -450,7 +444,6 @@ The three checkpoint tools pin an instance's state and start a second agent from { "checkpoint": { "id": "01a06d19-540a-7040-befb-ec4499c96ff2", - "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", "head_task_id": "01a06d13-2504-7245-9eaf-9c1870c51d26", "history_sequence": 398, @@ -477,7 +470,6 @@ The three checkpoint tools pin an instance's state and start a second agent from "params": { "name": "list_agent_instance_checkpoints", "arguments": { - "namespace": "kagent", "agent_instance_id": "'"$INSTANCE_ID"'" } } @@ -490,7 +482,6 @@ The three checkpoint tools pin an instance's state and start a second agent from "checkpoints": [ { "id": "01a0690f-5548-7935-b7ca-70919fc9c221", - "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", "head_task_id": "01a0690f-058d-7d29-a880-9b5d6d30b772", "history_sequence": 91, @@ -499,7 +490,6 @@ The three checkpoint tools pin an instance's state and start a second agent from }, { "id": "01a06d19-540a-7040-befb-ec4499c96ff2", - "namespace": "kagent", "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", "head_task_id": "01a06d13-2504-7245-9eaf-9c1870c51d26", "history_sequence": 398, @@ -522,7 +512,6 @@ The three checkpoint tools pin an instance's state and start a second agent from "params": { "name": "fork_agent_instance", "arguments": { - "namespace": "kagent", "checkpoint_id": "'"$CHECKPOINT_ID"'", "request_id": "my-first-fork" } @@ -535,7 +524,6 @@ The three checkpoint tools pin an instance's state and start a second agent from { "agent_instance": { "id": "01a06d19-7eec-797b-87b8-7397a96b1544", - "namespace": "kagent", "harness": "my-first-harness", "agent_template": "my-first-agent", "state": "AGENT_INSTANCE_STATE_READY" @@ -543,13 +531,12 @@ The three checkpoint tools pin an instance's state and start a second agent from } ``` -5. Invoke the fork with `invoke_agent_instance` and its new ID. Note that `context_id` matches the fork's own ID rather than the original's, so the fork holds a separate conversation from the moment it is created. Example output: +5. Invoke the fork with `invoke_agent_instance` and its new ID. Note that `context_id` matches the original's rather than the fork's own ID, because the fork continues the conversation that the checkpoint pinned. Example output: ```json { - "namespace": "kagent", "agent_instance_id": "01a06d19-7eec-797b-87b8-7397a96b1544", "task_id": "01a06d19-80e7-7554-8288-377eda9e861b", - "context_id": "01a06d19-7eec-797b-87b8-7397a96b1544", + "context_id": "ce5a10b8-7789-4ba7-8395-e60a339de763", "state": "TASK_STATE_COMPLETED", "text": "15" } @@ -568,14 +555,14 @@ You can now safely [clean up these resources](#clean-up). 2. Port-forward the controller's gRPC port, and leave the command running. `CheckpointService` listens there rather than on the HTTP port that serves MCP. ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 ``` 3. Delete the checkpoint that you created. ```bash grpcurl -plaintext \ - -d '{"namespace":"kagent","checkpointId":""}' \ - localhost:8084 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint + -d '{"checkpointId":""}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/DeleteCheckpoint ``` 4. Remove the server entry from your client. In Claude Code, run `claude mcp remove kagent`. In Cursor, delete the `kagent` entry from your MCP settings. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index ba21f692..7014bfb4 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -18,7 +18,7 @@ This guide walks you through creating an agent, from applying a Harness and an A 3. Install [`jq`](https://jqlang.org/download/), to read the AgentInstance ID out of the CLI's JSON output. > [!NOTE] -> The CLI reaches the kagent controller at `localhost:8083` and `localhost:8084`. When nothing serves those ports, the CLI runs `kubectl port-forward` against the `kagent-controller` service for you, and closes the forward when the command exits. Keep `kubectl` on your path, and keep your kubeconfig pointed at the cluster that runs kagent. +> The CLI reaches the kagent controller at `localhost:8083`. When nothing serves that port, the CLI runs `kubectl port-forward` against the `kagent-controller` service for you, and closes the forward when the command exits. Keep `kubectl` on your path, and keep your kubeconfig pointed at the cluster that runs kagent. ## Create a Harness and an AgentTemplate diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md index 1c7fd798..b3651a2b 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -193,5 +193,5 @@ kubectl delete remotemcpserver my-mcp-server -n kagent {{< cards >}} {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Read the full tool binding schema, including binding one agent as another agent's tool." >}} {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Give your agent capabilities that no MCP server provides." >}} - {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch your agent's Actor suspend between turns, then checkpoint and fork its state." >}} + {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch your agent's Actor suspend between turns, then checkpoint and fork the conversation." >}} {{< /cards >}} diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index 0f6eb3c0..f3bafe15 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -250,13 +250,13 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker 3. Get the address to reach the kagent gRPC API, which serves the AgentInstance lifecycle and conversation calls. The guide to [create your first agent]({{< link path="get-started/your-first-agent" >}}) assumes port-forwarding. {{< tabs >}} {{% tab name="Port-forward for local testing" %}} - Forward the gRPC port and leave the command running. The API is then available at `localhost:8084`. + Forward the controller port and leave the command running. The API is then available at `localhost:8083`. ```bash - kubectl port-forward -n kagent svc/kagent-controller 8084:8084 + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 ``` {{% /tab %}} {{% tab name="Cloud Provider LoadBalancer" %}} - Read the external address of the controller service. The gRPC API listens on port `8084`. + Read the external address of the controller service. The gRPC API listens on port `8083`. ```bash kubectl get svc -n kagent kagent-controller \ -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}" diff --git a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md index 3973be5b..2699fea6 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -85,4 +85,4 @@ Creating a checkpoint attaches an ActorSnapshotTag to the snapshot that the Agen An AgentInstance must be a turn boundary to be checkpointed, because the turn boundary is captured. An AgentInstance with a turn still in progress has no quiescent boundary to capture, and the request fails until the turn finishes. -A checkpoint also records how far the conversation had advanced, and it lets you start a second AgentInstance from the state it pinned. That second AgentInstance, a {{< gloss "Fork" >}}fork{{< /gloss >}}, begins its own conversation rather than continuing the original's. To create a checkpoint and fork an AgentInstance from it, work through the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). +A checkpoint also records how far the conversation had advanced, and it lets you start a second AgentInstance from the state it pinned. That second AgentInstance, a {{< gloss "Fork" >}}fork{{< /gloss >}}, continues the conversation from the point that the checkpoint pinned, and new turns append only to the fork. To create a checkpoint and fork an AgentInstance from it, work through the [Agent Substrate example]({{< link path="examples/agent-substrate" >}}). diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index 86007713..c74509cc 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -65,7 +65,7 @@ Snapshot: short: "The stored state that an Actor suspends to, held in object storage. Resuming restores the Actor from its most recent snapshot, which is what makes suspending idle agents cheap." Fork: - short: "A second AgentInstance created from a checkpoint, starting from the durable state that the checkpoint pinned. A fork inherits the checkpoint's revision, so later edits to the AgentTemplate do not change what it runs, and it begins its own transcript rather than continuing the original's." + short: "A second AgentInstance created from a checkpoint, continuing the conversation from the point that the checkpoint pinned. A fork inherits the checkpoint's revision, so later edits to the AgentTemplate do not change what it runs, and new turns append only to the fork, leaving the original's history untouched." Transcript: short: "The record of an AgentInstance's conversation, held server-side and append-only. It survives the Actor suspending between turns, and a resumed runtime cannot shrink it." From 240452c1b1342156980dbb6d89b8eec194a65adf Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Wed, 9 Sep 2026 13:40:28 -0500 Subject: [PATCH 54/70] Create documentation-agent.md Signed-off-by: Rachael Graham --- .../1.x/examples/documentation-agent.md | 317 ++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 docs-site/content/kagent/1.x/examples/documentation-agent.md diff --git a/docs-site/content/kagent/1.x/examples/documentation-agent.md b/docs-site/content/kagent/1.x/examples/documentation-agent.md new file mode 100644 index 00000000..ed45d58f --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/documentation-agent.md @@ -0,0 +1,317 @@ +--- +title: Build a documentation agent +description: Crawl a documentation site into a vector database, serve it over MCP, and give an agent semantic search over it. +weight: 60 +author: kagent.dev +--- + +An agent answers from its model unless you give it a source, such as in a vector database. This example crawls a documentation website into a vector database with [doc2vec](https://github.com/kagent-dev/doc2vec), serves that database over the {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP), and binds it to an agent so that the agent searches your documentation before it answers. + +Only the last two steps are kagent's. doc2vec and its MCP server are a separate project, so this guide treats them as a supplied tool server and spends its detail on the kagent side. To bind your first MCP tool without the crawl, see [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}). + +## About the pieces + +This guide installs the following components. +* **doc2vec**: A command line tool that crawls a website or repository, splits it into chunks, embeds each chunk, and writes the vectors to a database. You run it once, outside the cluster. +* **The doc2vec MCP server**: A published container image that reads that database and exposes semantic search as MCP tools. It runs in your cluster as an ordinary Deployment. +* **kagent**: A `RemoteMCPServer` that points at the MCP server, and an AgentTemplate that binds one or more of its tools. + +The MCP server exposes three tools, and an AgentTemplate names the ones it wants. + +| Tool | Function | +| ---- | -------- | +| `query_documentation` | Semantic search over the crawled documentation, filtered by product and version. | +| `query_code` | Semantic search over crawled source code. | +| `get_chunks` | Returns the chunks of one document, so an agent can read a page rather than a snippet. | + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}), and [create your first agent]({{< link path="get-started/your-first-agent" >}}) so that you have a Harness and know which label it admits. + +2. Install [Node.js](https://nodejs.org) 20 or later, to run doc2vec. + +3. Export the API key that doc2vec uses for embeddings. + > [!NOTE] + > The MCP server embeds each incoming query, so it needs its own Secret with a model provider key. The agent's ModelConfig does not supply this key, even when both point at the same provider and you reuse the same value. + ```bash + export OPENAI_API_KEY= + ``` + +## Crawl your documentation + +doc2vec reads a YAML file that names what to crawl and where to put the vectors. This example writes to [Qdrant](https://qdrant.tech), so that the cluster reads the vectors over the network rather than needing a database file inside the pod. + +1. Install Qdrant in your cluster. + ```bash + helm repo add qdrant https://qdrant.to/helm + helm repo update + helm upgrade --install qdrant qdrant/qdrant --namespace kagent --wait + ``` + +2. Forward the Qdrant port and leave the command running, so that doc2vec can write to it from your machine. + ```bash + kubectl port-forward -n kagent svc/qdrant 6333:6333 + ``` + +3. Write a doc2vec configuration. Each entry under `sources` becomes one crawl. + ```bash + cat > config.yaml <<'EOF' + embedding: + provider: 'openai' + dimension: 3072 + openai: + model: 'text-embedding-3-large' + + sources: + - type: website + product_name: 'kagent' + version: 'latest' + url: 'https://kagent.dev/docs/' + max_size: 1048576 + database_config: + type: 'qdrant' + params: + qdrant_url: 'http://localhost' + qdrant_port: 6333 + EOF + ``` + + | Field | Description | + | ----- | ----------- | + | `embedding.dimension` | Must match the model. `text-embedding-3-large` produces 3072 dimensions. | + | `product_name` and `version` | Stored on every chunk. The `query_documentation` tool filters on them, so an agent can search one product without seeing another. | + | `database_config.type` | `qdrant` or `sqlite`. Use `sqlite` only when the database file can sit beside the MCP server. | + +4. Run the crawl. The crawl embeds every chunk, so it costs model provider usage and takes longer for a large site. + ```bash + npx doc2vec config.yaml + ``` + +## Deploy the MCP server + +The doc2vec project publishes a prebuilt image of the MCP server, so you deploy it rather than build it from source. + +1. Store the embedding key that the server uses for incoming queries. + ```bash + kubectl create secret generic doc2vec-openai -n kagent \ + --from-literal=OPENAI_API_KEY="$OPENAI_API_KEY" + ``` + +2. Deploy the server and a Service for it. The `TRANSPORT_TYPE` must be `http`, because kagent speaks streamable HTTP to a remote MCP server. + + ```bash + kubectl apply -f - <<'EOF' + apiVersion: apps/v1 + kind: Deployment + metadata: + name: doc2vec-mcp + namespace: kagent + spec: + replicas: 1 + selector: + matchLabels: + app: doc2vec-mcp + template: + metadata: + labels: + app: doc2vec-mcp + spec: + containers: + - name: mcp + # Pin the image to 2.11.0. Tag v2.15.1 accepts a query + # and then fails every search with 'Error querying + # documentation: fetch failed', from an 'InvalidArgumentError: + # invalid onError method' inside the image. + image: ghcr.io/kagent-dev/doc2vec/mcp:2.11.0 + ports: + - containerPort: 3001 + env: + - name: TRANSPORT_TYPE + value: "http" + - name: PORT + value: "3001" + - name: VECTOR_DB_TYPE + value: "qdrant" + - name: QDRANT_URL + value: "http://qdrant.kagent:6333" + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: doc2vec-openai + key: OPENAI_API_KEY + --- + apiVersion: v1 + kind: Service + metadata: + name: doc2vec-mcp + namespace: kagent + spec: + selector: + app: doc2vec-mcp + ports: + - port: 3001 + targetPort: 3001 + EOF + ``` + +3. Confirm that the server is running on the HTTP transport. + ```bash + kubectl logs -n kagent -l app=doc2vec-mcp --tail=5 + ``` + + Example output: + ```console + Starting MCP server with HTTP transport... + MCP server is running on port 3001 with HTTP transport + Connect to: http://localhost:3001/mcp + ``` + +## Register the server with kagent + +A `RemoteMCPServer` gives kagent the address of the running MCP server. kagent connects to that address, reads the server's tool catalog, and records the tool names in the resource's status. An AgentTemplate then binds names from that list. + +1. Create a `RemoteMCPServer` pointing at the Service. The path is `/mcp`. + ```bash + kubectl apply -f - <<'EOF' + apiVersion: kagent.dev/v1alpha3 + kind: RemoteMCPServer + metadata: + name: doc2vec + namespace: kagent + spec: + description: Semantic search over crawled documentation. + protocol: STREAMABLE_HTTP + url: http://doc2vec-mcp.kagent:3001/mcp + timeout: 30s + EOF + ``` + +2. Confirm that kagent reached the server and read its catalog. `ACCEPTED` reports the result of that discovery. + ```bash + kubectl get remotemcpserver doc2vec -n kagent + ``` + + Example output: + ```console + NAME PROTOCOL URL ACCEPTED + doc2vec STREAMABLE_HTTP http://doc2vec-mcp.kagent:3001/mcp True + ``` + +3. Read the tool names from the cluster, rather than assuming them. + ```bash + kubectl get remotemcpserver doc2vec -n kagent \ + -o jsonpath='{.status.discoveredTools[*].name}{"\n"}' + ``` + + Example output: + ```console + get_chunks query_code query_documentation + ``` + +## Create the agent + +The AgentTemplate binds the tools and sets the system prompt that makes the agent search before it answers. This example binds `query_documentation` and `get_chunks`, and leaves out `query_code`, because the crawl covered a website rather than a repository. The prompt also names `productName` and `version` on every query, because `query_documentation` needs both filters together. Passing `productName` alone returns `Error querying documentation: Not Found`, an error that reads like a broken database rather than a missing filter. + +1. Apply an AgentTemplate that binds the search tools. Use the label that your Harness admits. + ```bash + kubectl apply -f - < [!IMPORTANT] + > Do not set `apiGroup` on `tools[].mcp.server`. The API rejects it with `spec.tools[0].mcp.server: Invalid value: apiGroup must be omitted`. Give the reference a `kind` and a `name` only. + + > [!WARNING] + > kagent resolves the server but never checks the tool names against what the server serves. A misspelled name compiles into a ready revision and fails silently at run time, so copy the names from `status.discoveredTools`. + +2. Create an AgentInstance and save its ID. + ```bash + kagent create agent-instance --harness my-first-harness --agent-template docs-agent + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "docs-agent")] | sort_by(.createdAt) | last | .id') + echo $INSTANCE_ID + ``` + +## Ask a question + +Ask the agent something that the crawled documentation covers, and then something that it does not, so that you can tell retrieval from recall. + +1. Ask a question that the crawl covers. + ```bash + kagent invoke --agent-instance $INSTANCE_ID \ + --task "What does a Harness do? Answer in two sentences." + ``` + + The agent calls `query_documentation`, receives the matching chunks, and answers from them. Example output: + ```console + A Harness is a Kubernetes custom resource that defines how an agent is allowed to run by + specifying the runtime engine, workload container image and environment, and substrate + policy for scheduling and storage. It selects exactly one runtime out of kagent, codex, + claude, or byo, and determines which AgentTemplates can run on it via a selector. + ``` + +2. Ask a question that the crawl does not cover, to confirm that the agent refuses rather than falling back on the model. + ```bash + kagent invoke --agent-instance $INSTANCE_ID \ + --task "How do I configure Istio ambient mode mTLS? Two sentences." + ``` + + Example output: + ```console + The provided documentation does not cover how to configure Istio ambient mode mTLS. + Would you like me to try another query or help with something else? + ``` + +## Clean up + +1. Delete the AgentInstance and the AgentTemplate. + ```bash + kagent delete agent-instance $INSTANCE_ID + kubectl delete agenttemplate docs-agent -n kagent + ``` + +2. Delete the tool server and its registration. + ```bash + kubectl delete remotemcpserver doc2vec -n kagent + kubectl delete deployment doc2vec-mcp -n kagent + kubectl delete service doc2vec-mcp -n kagent + kubectl delete secret doc2vec-openai -n kagent + ``` + +3. Uninstall Qdrant, and stop the port-forward with `Ctrl+C`. + ```bash + helm uninstall qdrant -n kagent + ``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="get-started/your-first-mcp-tool" >}}` title="Your first MCP tool" subtitle="Bind a tool from the MCP server that ships with kagent." >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools" >}}` title="About tools" subtitle="Read the binding fields and how kagent resolves a tool server." >}} + {{< card link=`{{< link path="examples/skills" >}}` title="Add a skill to an agent" subtitle="Give the same agent packaged instructions alongside its tools." >}} +{{< /cards >}} From a2b1974817446eb6dac3e8923747fb813f4d0a18 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 10 Sep 2026 15:43:55 -0500 Subject: [PATCH 55/70] Phase 3 - operations init Signed-off-by: Rachael Graham --- .../content/kagent/1.x/operations/_index.md | 6 + .../content/kagent/1.x/operations/debug.md | 192 ++++++++++++++++ .../1.x/operations/tune-agent-substrate.md | 211 ++++++++++++++++++ .../kagent/1.x/operations/uninstall.md | 105 +++++++++ .../1.x/substrate-runtime/sandboxing.md | 8 +- docs-site/data/glossary.yaml | 2 +- 6 files changed, 518 insertions(+), 6 deletions(-) create mode 100644 docs-site/content/kagent/1.x/operations/_index.md create mode 100644 docs-site/content/kagent/1.x/operations/debug.md create mode 100644 docs-site/content/kagent/1.x/operations/tune-agent-substrate.md create mode 100644 docs-site/content/kagent/1.x/operations/uninstall.md diff --git a/docs-site/content/kagent/1.x/operations/_index.md b/docs-site/content/kagent/1.x/operations/_index.md new file mode 100644 index 00000000..c752aa84 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/_index.md @@ -0,0 +1,6 @@ +--- +title: Operations +description: Run, tune, and maintain a kagent installation after it is up. +weight: 90 +author: kagent.dev +--- diff --git a/docs-site/content/kagent/1.x/operations/debug.md b/docs-site/content/kagent/1.x/operations/debug.md new file mode 100644 index 00000000..8924d97f --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/debug.md @@ -0,0 +1,192 @@ +--- +title: Debug +description: Find where kagent reports a failure, read the readiness conditions, and work back from a symptom to its cause. +weight: 30 +author: kagent.dev +--- + +Most kagent 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. + +## 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. + +```bash +kubectl get harness -n kagent +``` +Example output: +```console +NAME READY AGE +kagent 30h +``` + +The AgentTemplate list view carries no status column either, so a healthy template and a broken one look identical in it. + +```bash +kubectl get agenttemplate -n kagent +``` +Example output: +```console +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. + +```bash +kubectl get agenttemplate -n kagent \ + -o jsonpath='{range .status.harnesses[*]}{"Harness: "}{.harness}{"\n"}{range .conditions[*]}{" "}{.type}{"="}{.status}{" "}{.reason}{": "}{.message}{"\n"}{end}{end}' +``` +Example output from a healthy pairing: +```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 +``` + +## Read the readiness conditions + +The four conditions form a pipeline rather than an unordered set, so their order tells you how far preparation reached before it stopped. + +Each condition covers one stage, and a stage runs only when the stage before it succeeded. + +| 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. | + +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. + +**Read the first condition that is `False` and whose reason is not `Blocked`.** Everything after it is a consequence. + +In the following example, one missing ModelConfig is the whole problem, and the two conditions after it carry no 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 +``` + +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 reports no conditions + +An AgentTemplate that no Harness admits gets no `status.harnesses[]` entry at all, so the command in this page prints nothing. + +The status object holds an `observedGeneration` and nothing else. + +```console +status: + observedGeneration: 1 +``` + +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. + +```console +ERROR: + Code: FailedPrecondition + Message: AgentTemplate and Harness do 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. + +```bash +kubectl get harness kagent -n kagent -o jsonpath='{.spec.allowedAgentTemplates.selector}' +``` +Example output: +```console +{"matchLabels":{"kagent.dev/harness":"kagent"}} +``` + +Add the label that the selector expects, and the conditions appear within seconds. + +```yaml +apiVersion: kagent.dev/v1alpha3 +kind: AgentTemplate +metadata: + name: assistant + namespace: kagent + labels: + kagent.dev/harness: kagent +``` + +> [!NOTE] +> An empty `status.harnesses[]` and a genuinely broken template look nothing alike once you know the difference. No entry means admission never happened, so check the label first. An entry with a failing condition means admission succeeded and something later went wrong. + +## An agent turn times out + +A turn that fails with a timeout reports the same error whatever the underlying cause, so this symptom needs elimination rather than reading. + +```console +ERROR: + Code: Internal + Message: actor "ai-01a087c0-1d72-775a-9a32-566acac7b685" request timed out +``` + +Work through the causes in this order. + +1. **Check that the {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} has ready Workers.** A pool with too few Workers produces exactly this error and logs no capacity message anywhere. [Tune Agent Substrate]({{< link path="operations/tune-agent-substrate" >}}) covers how to recognize and size it. + ```bash + kubectl get workerpools -n kagent + ``` + +2. **Check the model provider.** A turn that reaches the model and waits on a slow or unreachable provider also times out. The agent's own logs name the provider error. + +3. **Check the {{< gloss "Actor" >}}Actor{{< /gloss >}} state.** An Actor stuck in `RESUMING`, or sitting in `CRASHED`, never answers. [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) lists the states, and `GetSubstrateStatus` reports the current one for every Actor. + +## An edit to an AgentTemplate has no effect + +An edit that appears to do nothing has two possible causes, and the 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. + +```bash +kubectl get agenttemplate -n kagent \ + -o jsonpath='{range .status.harnesses[*]}{.harness}{" desired="}{.desiredRevision}{" latestSuccessful="}{.latestSuccessfulRevision}{"\n"}{end}' +``` + +The second cause is deliberate. An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} runs the revision that it was created from for its whole life, so editing an AgentTemplate never changes an instance that already exists. Create a new AgentInstance to pick up the edit. + +## Collect logs + +Once the resource status is exhausted, the controller log is the next place to look, and it records every API call with its gRPC status code. + +```bash +kubectl logs -n kagent deployment/kagent-controller +``` + +A failing call appears as an `rpc completed` line whose `grpc_code` is not `OK`, which locates the failure without reading the whole log. + +```console +{"time":"2026-09-09T19:23:47.112233381Z","level":"INFO","msg":"rpc completed","component":"grpc","grpc_method":"/lf.a2a.v1.A2AService/SendMessage","rpc_type":"unary","peer":"127.0.0.1:49588","grpc_code":"Internal","duration_ms":5033} +``` + +Raise the controller's log level when the default does not say enough. + +```yaml +controller: + loglevel: debug +``` + +To gather everything at once, run `kagent bug-report`. The command writes the kagent resources in a namespace, the names of its secrets, and the logs of every pod into a timestamped directory. + +```bash +kagent bug-report -n kagent +``` + +> [!WARNING] +> A bug report contains your resource definitions and pod logs, which can hold prompts, tool output, and other sensitive material. Review the directory before you attach it to an issue. + +The report covers kagent's own resources rather than the Agent Substrate installation underneath it, so add the WorkerPool and the runtime status when a problem looks like a capacity or sandbox issue. + +```bash +kubectl get workerpools,sandboxconfigs -n kagent -o yaml +``` diff --git a/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md new file mode 100644 index 00000000..d06689a3 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md @@ -0,0 +1,211 @@ +--- +title: Tune Agent Substrate +description: Learn how to size a WorkerPool, configure snapshot storage, and keep Workers on the sandbox class that kagent requires. +weight: 20 +author: kagent.dev +--- + +kagent runs every agent on [Agent Substrate]({{< link path="about/agent-substrate" >}}), and a fresh installation is deliberately small: one {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} holding a single Worker, snapshots in whichever object storage the Agent Substrate installation was given, and the `gvisor` sandbox class. + +When preparing for real traffic to your agents, you can size the pool and check where snapshots land. Leave the sandbox class on `gvisor`. A pool set to any other class sits idle while turns time out. + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation" >}}), and confirm that your installation sets `controller.grpc.reflection=true`. Reflection lets a gRPC client discover the controller's methods without a local copy of kagent's protocol buffer definitions. + +2. Confirm that you have administrative access to the cluster, because this guide scales WorkerPools and reads cluster-scoped resources. + +3. Install [grpcurl](https://github.com/fullstorydev/grpcurl). `GetSubstrateStatus` has no kubectl or kagent command equivalent, so calling it directly is the only way to get the fuller view of the runtime. + +## Inspect the runtime + +Read the current state of the runtime before you change it. Three values from this section carry into the rest of this guide: the pool name and its `READY` count, the snapshot path that Actors are writing to, and the Worker image that the pool runs. + +1. Check the WorkerPool's Worker counts. These counts are the only place that capacity trouble surfaces. + ```bash + kubectl get workerpools -n kagent + ``` + Example output: + ```console + NAME DESIRED REPLICAS READY AGE + kagent-default 8 8 8 3h + ``` + `DESIRED` is the replica count that you asked for, `REPLICAS` counts the Worker pods that exist, and `READY` counts the pods that are serving. A gap between `DESIRED` and `REPLICAS` means the controller is not creating pods. A gap between `REPLICAS` and `READY` means the pods exist but are not starting. Raising the replica count helps only when all three counts agree. + +2. Port-forward the controller, and leave the command running in a second terminal. + ```bash + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 + ``` + +3. Call `GetSubstrateStatus`, which joins the WorkerPools, {{< gloss "ActorTemplate" >}}ActorTemplates{{< /gloss >}}, {{< gloss "Actor" >}}Actors{{< /gloss >}}, and Workers that kagent knows about into one response. + ```bash + grpcurl -plaintext -d '{"namespace":"kagent"}' \ + localhost:8083 kagent.api.v1alpha1.SystemService/GetSubstrateStatus + ``` + Example output, abbreviated to one Worker and one Actor: + ```json + { + "enabled": true, + "workerPools": [ + { + "namespace": "kagent", + "name": "kagent-default", + "replicas": 8, + "ateomImage": "ghcr.io/kagent-dev/substrate/ateom-gvisor:v0.0.26" + } + ], + "actors": [ + { + "actorId": "792f8f90-72a9-49e8-b720-cb3b96fd9a8b", + "atespace": "ate-golden", + "status": "Suspended", + "actorTemplateName": "assistant-kagent-2a786e2db23a", + "latestSnapshot": "s3://ate-snapshots/kagent/atespaces/ate-golden/actors/2d921676-80ad-48d3-8c2a-4059ef74da33/snapshots/503a07e3-ec49-433c-abdf-b2bb3cb36d5d" + } + ], + "workers": [ + { + "workerNamespace": "kagent", + "workerPool": "kagent-default", + "workerPod": "kagent-default-787547df77-4kvqf", + "ip": "10.244.0.104" + } + ] + } + ``` + +A Worker entry gains an `actorId` only while an Actor occupies it, so the Workers list doubles as a view of which capacity is busy. + +## Size a WorkerPool + +The replica count is the only capacity dial on a pool, and setting it well depends on knowing what actually consumes a Worker. + +A {{< gloss "Worker" >}}Worker{{< /gloss >}} hosts at most one Actor at a time, and it holds that Actor only while a turn is running. kagent suspends an Actor at every turn boundary and frees its Worker, as described in [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). An idle {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} therefore occupies no Worker at all. + +Size the pool for the number of turns that run at the same time, not for the number of agents or AgentInstances that you have created. A cluster with hundreds of AgentInstances that are each used occasionally needs far fewer Workers than the instance count suggests. + +Scale a pool in place with the standard Kubernetes scale command, because the WorkerPool exposes a scale subresource. Use the pool name that you read in [Inspect the runtime](#inspect-the-runtime). + +```bash +kubectl scale workerpool kagent-default -n kagent --replicas=8 +``` + +To change these settings in your Helm values instead, run an upgrade of your kagent installation with the following settings: + +```yaml +substrateWorkerPool: + replicas: 8 +``` + +### Recognize an undersized pool + +A pool with too few Workers does not report a capacity error anywhere. Turns that cannot get a Worker wait for one, and a turn that waits too long fails with a generic timeout that names neither capacity nor the pool. + +```console +ERROR: + Code: Internal + Message: actor "ai-01a087c0-1d72-775a-9a32-566acac7b685" request timed out +``` + +Because short turns release their Worker quickly, a pool under mild pressure absorbs the load and only sheds the requests that wait past the deadline. The result is intermittent timeouts under concurrency rather than a clean failure. Neither the kagent controller log nor the Agent Substrate API log records a capacity message when this happens, so diagnose it from the pool's `READY` count and raise the replica count. + +### Set resource requests on Workers + +Generated Worker pods carry no resource requests or limits unless you supply them, and the effect on scheduling is easy to miss. + +A Worker with no limits reports its node's entire allocatable capacity as its own. Every Worker on that node reports the same figures, so Agent Substrate cannot use resource capacity to place Actors, and Kubernetes cannot stop you from packing more Workers onto a node than it can carry. Set requests and limits on any pool that carries production traffic. + +```yaml +substrateWorkerPool: + template: + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + cpu: "2" + memory: 4Gi +``` + +The same `template` block also accepts `nodeSelector`, `tolerations`, `priorityClassName`, and `nodeAffinity`, so you can keep Workers on nodes that you set aside for them. + +## Configure snapshot storage + +Snapshot storage is configured in two independent places, and a mismatch between them breaks resume rather than install. + +The first place is the storage backend on the Agent Substrate components. Both the `atelet` DaemonSet and the `ate-api-server` Deployment read the same environment variables, and both must agree, because one writes snapshots and the other manages them. + +The following variables select the backend. `ATE_STORAGE_BACKEND` chooses the client, and the rest configure it. Leaving `ATE_STORAGE_BACKEND` unset selects Google Cloud Storage through application default credentials rather than disabling snapshots. + +| Variable | Purpose | +| -------- | ------- | +| `ATE_STORAGE_BACKEND` | `s3` selects the S3 client. Any other value, including unset, selects Google Cloud Storage. | +| `AWS_REGION` | Region for the S3 client. | +| `AWS_ENDPOINT_URL` | Endpoint for an S3-compatible store that is not Amazon S3. | +| `AWS_S3_USE_PATH_STYLE` | `true` selects path-style addressing, which most S3-compatible stores need. | +| `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` | Static credentials for the S3 client. | + +The second place is the location on each {{< gloss "Harness" >}}Harness{{< /gloss >}}, which names the bucket and prefix that its Actors' snapshots are written under. The field is required, and it must point into a bucket that the configured backend can reach. + +```yaml +spec: + substrate: + workerPoolRef: + name: kagent-default + snapshotPolicy: + location: s3://ate-snapshots/kagent/ +``` + +Agent Substrate builds a path per Actor under that prefix, so one bucket serves many Harnesses without collision. The `` segment is the Actor's `metadata.uid`, not the `actorId` that `GetSubstrateStatus` reports. Both values are UUIDs, so read `latestSnapshot` off the Actor rather than matching a path to an Actor by eye. + +```console +s3://ate-snapshots/kagent/atespaces//actors//snapshots/ +``` + +A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} takes a second shape. kagent creates an Agent Substrate Tag for each checkpoint, and tagging copies the Actor's snapshot into the Tag's own prefix. A Tag holds exactly one snapshot, so its objects sit directly under `tags/` with no `snapshots/` segment. The `` segment is the Tag's `metadata.uid`, so nothing in the path records the `checkpoint-` name that kagent gave the Tag. + +```console +s3://ate-snapshots/kagent/atespaces//tags/ +``` + +A backup or lifecycle policy must cover both prefixes, because one scoped to `actors/` omits every checkpoint and understates how much the bucket holds. + +Because the two places are configured independently, confirm the result rather than the intent. The `latestSnapshot` path in the [Inspect the runtime](#inspect-the-runtime) response is the bucket that an Actor last wrote to, so compare it against the `location` that you set. + +> [!WARNING] +> A development installation points at an in-cluster object store with well-known credentials, and it is not durable. Snapshots hold agent conversation state, so a production installation needs a real bucket, credentials that are not shared defaults, and a backup policy that matches how much conversation history you are willing to lose. + +## Keep pools on the gvisor class + +A pool's sandbox class decides which sandbox runtime its Workers provide, and kagent constrains the choice more tightly than Agent Substrate does. + +Agent Substrate supports the `gvisor` and `microvm` classes, as explained in [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). kagent compiles every ActorTemplate to the `gvisor` class and to a SandboxConfig named exactly `gvisor-default`. Placement never relaxes the class constraint, so Workers in a `microvm` pool accept no kagent Actor, and the pool sits idle while turns time out. + +Leave a pool that backs kagent Harnesses on `gvisor`, and keep the pool's image on the matching Worker build. + +```yaml +substrateWorkerPool: + sandboxClass: gvisor + workerImage: "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" +``` + +> [!NOTE] +> The `ateomImage` field in the [Inspect the runtime](#inspect-the-runtime) response reports this same setting, which the WorkerPool resource calls `workerImage`. Compare the two names when you check which build a pool is running. + +A cluster-scoped SandboxConfig named `gvisor-default` must also exist, because kagent names it directly rather than resolving a default. A missing one fails template preparation with `SandboxConfig "gvisor-default" not found`. + +```bash +kubectl get sandboxconfigs +``` +Example output: +```console +NAME CLASS AGE +gvisor-default gvisor 26h +``` + +Two further constraints apply when you change any of this on a running cluster. + +- **Snapshots do not move between sandbox classes.** An Actor cannot resume from a snapshot that a different class produced, so changing the class of a pool that holds live Actors strands their state. +- **Nodes fetch sandbox runtime assets from a public Google Cloud Storage URL**, named in the SandboxConfig, independently of the storage backend that you configured for snapshots. A cluster with restricted egress needs a path to that URL, or a SandboxConfig that points at a copy you host. + +Replacing `workerImage` rolls the Worker pods through the generated Deployment. The pods take a one-hour termination grace period, so an in-flight turn finishes rather than being cut off, and a rollout of a busy pool takes as long as its longest running turn. diff --git a/docs-site/content/kagent/1.x/operations/uninstall.md b/docs-site/content/kagent/1.x/operations/uninstall.md new file mode 100644 index 00000000..68bcb554 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/uninstall.md @@ -0,0 +1,105 @@ +--- +title: Uninstall +description: Remove kagent and Agent Substrate from a cluster, including the identity material and storage that Helm does not own. +weight: 50 +author: kagent.dev +--- + +A kagent installation has two layers, and removing it reverses the [install]({{< link path="setup/installation" >}}) in order: kagent first, then Agent Substrate underneath it. Helm removes most of each layer, but the identity material and some storage were never Helm's to begin with, so a complete uninstall ends with a manual pass. This page covers both. + +> [!CAUTION] +> Uninstalling deletes every kagent resource in every namespace, along with all agent conversation state and all stored snapshots. None of it can be recovered afterward. Back up anything you want to keep before you start. + +## Before you begin + +- Confirm that you have administrative access to the cluster. +- Back up any Harness, AgentTemplate, and ModelConfig definitions that you want to keep. +- Confirm that nothing outside kagent depends on the agents that you are about to remove. + +## What an uninstall removes + +Helm removes what its releases own, and the split matters because the material it leaves behind is exactly what blocks a later reinstall. + +| Removed by Helm | Left behind | +| --------------- | ----------- | +| Every `kagent.dev` and `ate.dev` custom resource definition, and with them every Harness, AgentTemplate, WorkerPool, and SandboxConfig in the cluster | The certificate authority and JSON Web Token pools that the install created with `kubectl ate` | +| kagent's bundled PostgreSQL volume, holding all conversation state | Agent Substrate's PostgreSQL volume, `data-postgres-0`, because a StatefulSet volume claim outlives its release | +| The object storage volume holding every Actor snapshot | The `kagent`, `ate-system`, and `podcertificate-controller-system` namespaces | + +## Uninstall kagent + +Remove the kagent release before the CRDs release, because deleting the definitions first strands the controller. + +1. Uninstall the kagent chart. + ```bash + helm uninstall kagent -n kagent + ``` + +2. Uninstall the CRDs chart. This step deletes every `kagent.dev` custom resource definition, and Kubernetes deletes every resource of those kinds across all namespaces with them. + ```bash + helm uninstall kagent-crds -n kagent + ``` + +> [!NOTE] +> The `kagent uninstall` command removes the same two releases in the same order, and it is a convenience rather than a different path. It does not touch Agent Substrate, so the rest of this page still applies. Prefer Helm, for the same reason that the install guide does: the CLI does not manage the Agent Substrate layer. + +## Uninstall Agent Substrate + +Agent Substrate is a separate installation in the `ate-system` namespace, and no kagent command removes it. + +1. Uninstall the Agent Substrate chart. + ```bash + helm uninstall substrate -n ate-system + ``` + +2. Uninstall the Agent Substrate CRDs chart, which deletes the `workerpools`, `sandboxconfigs`, and `csidriverconfigs` definitions. + ```bash + helm uninstall substrate-crds -n ate-system + ``` + +## Remove the identity material + +The identity material is the part most often left behind, and leaving it behind breaks the next installation rather than the current one. + +The install created certificate authority and JSON Web Token pools with the `kubectl ate` plugin instead of Helm, so no release owns them and no uninstall removes them. A later install that tries to create a pool that already exists fails with a message naming the secret. + +```console +Error: while uploading pool state to secret: secrets "service-dns-ca-pool" already exists +``` + +1. Delete the actor identity pools and the material derived from them. + ```bash + kubectl delete secret actor-id-jwt-pool actor-id-ca-pool actor-id-ca-certs -n ate-system + kubectl delete configmap ate-api-authentication -n ate-system + ``` + +2. Delete the certificate authority pools. + ```bash + kubectl delete secret service-dns-ca-pool pod-identity-ca-pool \ + -n podcertificate-controller-system + ``` + +3. Delete the Agent Substrate database volume, which a StatefulSet volume claim keeps alive after its release is gone. + ```bash + kubectl delete pvc data-postgres-0 -n ate-system + ``` + +> [!IMPORTANT] +> Deleting `data-postgres-0` matters even if you plan to reinstall immediately. Agent Substrate folds its schema changes into a single baseline migration before release, so a database that survives from an earlier version keeps that migration marked as applied and never picks up the new schema. The cluster then looks healthy and fails later, at the first checkpoint operation. + +## Remove the namespaces + +Deleting the namespaces removes anything that the preceding steps missed, including volumes left by optional components. + +```bash +kubectl delete namespace kagent ate-system podcertificate-controller-system +``` + +Confirm that nothing remains. + +```bash +kubectl get crd | grep -E 'kagent\.dev|ate\.dev' +kubectl get ns kagent ate-system podcertificate-controller-system +``` + +Both commands should report that they found nothing. diff --git a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md index 48fce19d..507ee412 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -37,11 +37,11 @@ A {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} selects its class through t ## Sandbox configuration -A **SandboxConfig** is a cluster-scoped resource that holds the material needed to start one sandbox runtime family. It carries the runtime assets that the node agent fetches, keyed by processor architecture, along with the pause image that holds the sandbox's namespaces as its root container. One SandboxConfig can be marked as the cluster default for its class, and a WorkerPool that names no configuration explicitly resolves to that default. +A **SandboxConfig** is a cluster-scoped resource that holds the material needed to start one sandbox runtime family. It carries the runtime assets that the node agent fetches, keyed by processor architecture, along with the pause image that holds the sandbox's namespaces as its root container. Each ActorTemplate names the configuration that it uses, and the name is required. Agent Substrate resolves no cluster default, so the configuration that a template names must exist before that template can be prepared. Defining these assets in a cluster resource lets one configuration pin a runtime version for many ActorTemplates at once, rather than each template carrying its own copy. -A default installation creates a single `gvisor-default` configuration, which looks like the following: +A default installation creates a single `gvisor-default` configuration, and kagent names exactly that configuration on every ActorTemplate that it generates. The configuration looks like the following: ```yaml apiVersion: ate.dev/v1alpha1 @@ -50,7 +50,6 @@ metadata: name: gvisor-default spec: sandboxClass: gvisor - default: true pauseImage: registry.k8s.io/pause:3.10.2@sha256: assets: amd64: @@ -65,8 +64,7 @@ spec: | Field | Description | | ----- | ----------- | -| `sandboxClass` | The sandbox runtime family that this configuration applies to, `gvisor` or `microvm`. A WorkerPool only draws on configurations whose class matches its own. | -| `default` | Whether this configuration is the cluster default for its class. Expect at most one default per class. | +| `sandboxClass` | The sandbox runtime family that this configuration applies to, `gvisor` or `microvm`. An ActorTemplate only uses configurations whose class matches its own, and preparation fails if the two disagree. | | `pauseImage` | The image for the root sandbox container, which holds the sandbox's namespaces and runs no workload code. It must be pinned to a digest, because the snapshot manifest records it, and changing the image invalidates the snapshots that were taken with it. | | `assets` | The files that the node agent fetches, keyed first by processor architecture and then by asset name. A `gvisor` class expects one `gvisor` asset, the release archive that the node agent extracts. A `microvm` class expects several, such as `cloud-hypervisor`, `kata-kernel`, and `kata-image`. | | `assets...sha256` | The lowercase hex digest of the file. The node agent verifies each download against it, and caches the result under a path that includes the digest, so changing the digest fetches the new asset instead of reusing the cached one. To read the configuration that your own cluster installed, including the pinned digests, run `kubectl get sandboxconfig gvisor-default -o yaml`.| diff --git a/docs-site/data/glossary.yaml b/docs-site/data/glossary.yaml index c74509cc..9202f5b4 100644 --- a/docs-site/data/glossary.yaml +++ b/docs-site/data/glossary.yaml @@ -34,7 +34,7 @@ AgentInstance: short: "A running, conversational pairing of a Harness and an AgentTemplate. Unlike the two, it is not a Kubernetes resource: kagent's gRPC API creates it and its database tracks it." Checkpoint: - short: "A durable pin on the snapshot that an AgentInstance most recently suspended to, and a record of how far its transcript had advanced. Not a copy of the state: it tags a snapshot so that Agent Substrate does not collect it, and a second AgentInstance can be forked from it." + short: "A durable pin on the snapshot that an AgentInstance most recently suspended to, and a record of how far its transcript had advanced. Not a new state: tagging copies the snapshot so that Agent Substrate does not collect it, and a second AgentInstance can be forked from it." AgentTemplate: short: "A Kubernetes custom resource defining what an agent does: its model, system prompt, tools, skills, and plugins. It runs only once a Harness accepts it." From bbceb21895b424a7bfd8ec87e6d47f4b7d475069 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Thu, 10 Sep 2026 16:26:02 -0500 Subject: [PATCH 56/70] review debug Signed-off-by: Rachael Graham --- docs-site/assets/css/custom.css | 14 ++++++++++++ .../1.x/get-started/your-first-agent.md | 2 +- .../1.x/get-started/your-first-mcp-tool.md | 2 +- .../content/kagent/1.x/operations/debug.md | 22 +++++++++++++------ .../1.x/operations/tune-agent-substrate.md | 2 +- .../model-providers/about-model-providers.md | 2 +- .../setup/model-providers/amazon-bedrock.md | 2 +- 7 files changed, 34 insertions(+), 12 deletions(-) diff --git a/docs-site/assets/css/custom.css b/docs-site/assets/css/custom.css index a1826742..30b0397e 100644 --- a/docs-site/assets/css/custom.css +++ b/docs-site/assets/css/custom.css @@ -481,3 +481,17 @@ html .glossary-term:hover, html .glossary-term:focus { text-decoration-color: var(--theme-primary, #0060cf); } + +/* Glossary tooltip: keep the definition at normal weight. + + extras' glossary.css sets font-weight on the tooltip's term (`> span strong`) + but never on the definition (`> span span`), so the definition inherits from + whatever surrounds the trigger. A term glossed inside a bold run — a bold + step lead-in, or a `**first mention**` — therefore renders its whole + definition bold and loses the term/definition contrast the markup intends. + + Same `html` prefix requirement as above: glossary.css loads after this file, + so a bare selector would lose the cascade at equal specificity. */ +html .glossary-term > span span { + font-weight: 400; +} diff --git a/docs-site/content/kagent/1.x/get-started/your-first-agent.md b/docs-site/content/kagent/1.x/get-started/your-first-agent.md index 7014bfb4..d92b0559 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-agent.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -152,7 +152,7 @@ The `invoke` command takes a few more options that are useful beyond a first con ## Clean up > [!IMPORTANT] -> Other guides build on the Harness, AgentTemplate, and AgentInstance that you created here, including [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}) and [Agent Substrate]({{< link path="examples/agent-substrate" >}}). Leave the resources in place unless you are finished with the kagent guides. +> Other guides build on the Harness, AgentTemplate, and AgentInstance that you created here, including [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}) and [Agent Substrate]({{< link path="examples/agent-substrate" >}}). Unless you are finished with the kagent guides, leave the resources in place. To remove the resources, follow these steps. diff --git a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md index b3651a2b..bb8cc0d4 100644 --- a/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -88,7 +88,7 @@ kagent records what it discovered on the server's status, so the tool names come When the two values differ, kagent is still compiling, or compilation failed. A binding that names a RemoteMCPServer that does not exist in the namespace fails at the `ResolvedRefs` condition with the reason `ReferenceResolutionFailed`. > [!WARNING] - > kagent resolves the server, but it does not check the tool names against the tools that the server actually serves. A misspelled tool name compiles into a ready revision, and the only symptom is an agent that never calls the tool that you expected. Check the spelling against the server's catalog when a bound tool appears to be missing. + > kagent resolves the server, but it does not check the tool names against the tools that the server actually serves. A misspelled tool name compiles into a ready revision, and the only symptom is an agent that never calls the tool that you expected. If a bound tool appears to be missing, check the spelling against the server's catalog. ## Create an AgentInstance that has the tool diff --git a/docs-site/content/kagent/1.x/operations/debug.md b/docs-site/content/kagent/1.x/operations/debug.md index 8924d97f..81ad4395 100644 --- a/docs-site/content/kagent/1.x/operations/debug.md +++ b/docs-site/content/kagent/1.x/operations/debug.md @@ -79,7 +79,7 @@ The same entry carries two revision fields that answer a different question. `de ## An AgentTemplate reports no conditions -An AgentTemplate that no Harness admits gets no `status.harnesses[]` entry at all, so the command in this page prints nothing. +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 object holds an `observedGeneration` and nothing else. @@ -119,7 +119,7 @@ metadata: ``` > [!NOTE] -> An empty `status.harnesses[]` and a genuinely broken template look nothing alike once you know the difference. No entry means admission never happened, so check the label first. An entry with a failing condition means admission succeeded and something later went wrong. +> 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 turn times out @@ -133,14 +133,16 @@ ERROR: Work through the causes in this order. -1. **Check that the {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} has ready Workers.** A pool with too few Workers produces exactly this error and logs no capacity message anywhere. [Tune Agent Substrate]({{< link path="operations/tune-agent-substrate" >}}) covers how to recognize and size it. +1. **Check that the {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} has ready Workers.** A pool with too few Workers produces exactly this error and logs no capacity message anywhere. To learn how to recognize this problem and size the pool, see [Tune Agent Substrate]({{< link path="operations/tune-agent-substrate" >}}). ```bash kubectl get workerpools -n kagent ``` 2. **Check the model provider.** A turn that reaches the model and waits on a slow or unreachable provider also times out. The agent's own logs name the provider error. -3. **Check the {{< gloss "Actor" >}}Actor{{< /gloss >}} state.** An Actor stuck in `RESUMING`, or sitting in `CRASHED`, never answers. [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) lists the states, and `GetSubstrateStatus` reports the current one for every Actor. +3. **Check the {{< gloss "Actor" >}}Actor{{< /gloss >}} state.** An Actor stuck in `RESUMING`, or sitting in `CRASHED`, never answers. + * To review the list of states, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume/#actor-lifecycle-operations" >}}). + * To get the current state for every actor, [call `GetSubstrateStatus`]({{< link path="operations/tune-agent-substrate#inspect-the-runtime" >}}). ## An edit to an AgentTemplate has no effect @@ -157,7 +159,11 @@ The second cause is deliberate. An {{< gloss "AgentInstance" >}}AgentInstance{{< ## Collect logs -Once the resource status is exhausted, the controller log is the next place to look, and it records every API call with its gRPC status code. +Once the resource status is exhausted, kagent offers two ways to gather evidence. Read the controller log to locate a single failing call, or collect a bug report to hand somebody else everything at once. + +### Read the controller log + +The controller records every API call with its gRPC status code. ```bash kubectl logs -n kagent deployment/kagent-controller @@ -169,14 +175,16 @@ A failing call appears as an `rpc completed` line whose `grpc_code` is not `OK`, {"time":"2026-09-09T19:23:47.112233381Z","level":"INFO","msg":"rpc completed","component":"grpc","grpc_method":"/lf.a2a.v1.A2AService/SendMessage","rpc_type":"unary","peer":"127.0.0.1:49588","grpc_code":"Internal","duration_ms":5033} ``` -Raise the controller's log level when the default does not say enough. +If the default log level does not have enough information, raise the controller's log level. ```yaml controller: loglevel: debug ``` -To gather everything at once, run `kagent bug-report`. The command writes the kagent resources in a namespace, the names of its secrets, and the logs of every pod into a timestamped directory. +### Collect a bug report + +`kagent bug-report` gathers the whole picture in one command. It writes the kagent resources in a namespace, the names of its secrets, and the logs of every pod into a timestamped directory. ```bash kagent bug-report -n kagent diff --git a/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md index d06689a3..f429ee06 100644 --- a/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md +++ b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md @@ -190,7 +190,7 @@ substrateWorkerPool: ``` > [!NOTE] -> The `ateomImage` field in the [Inspect the runtime](#inspect-the-runtime) response reports this same setting, which the WorkerPool resource calls `workerImage`. Compare the two names when you check which build a pool is running. +> The `ateomImage` field in the [Inspect the runtime](#inspect-the-runtime) response reports this same setting, which the WorkerPool resource calls `workerImage`. To check which build a pool is running, compare the two names. A cluster-scoped SandboxConfig named `gvisor-default` must also exist, because kagent names it directly rather than resolving a default. A missing one fails template preparation with `SandboxConfig "gvisor-default" not found`. diff --git a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md index 562bff17..5449a339 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md @@ -7,7 +7,7 @@ author: kagent.dev A `ModelConfig` is a Kubernetes custom resource that names one model at one provider, along with the credentials to reach it. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} references a {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}} by name in its `spec.modelConfig.name` field, and every agent compiled from that template calls the model that the ModelConfig names. -The kagent installation creates a `default-model-config` ModelConfig from the provider API key that you supply at install time, so a first agent needs no extra setup. Create additional ModelConfigs when you want to use a different provider, a different model, or a different set of credentials. +The kagent installation creates a `default-model-config` ModelConfig from the provider API key that you supply at install time, so a first agent needs no extra setup. To use a different provider, a different model, or a different set of credentials, create additional ModelConfigs. ## How a ModelConfig reaches an agent diff --git a/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md index ade87850..1cc57126 100644 --- a/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md +++ b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md @@ -7,7 +7,7 @@ author: kagent.dev Amazon Bedrock serves models from several families behind one AWS API. kagent reaches it two ways: the native `Bedrock` provider, which is the fuller integration, and Bedrock's OpenAI-compatible endpoint through the `OpenAI` provider. -Prefer the native provider. Use the OpenAI-compatible path when you need the OpenAI request format, or an inference profile that only that endpoint exposes. +Prefer the native provider. If you need the OpenAI request format, or an inference profile that only that endpoint exposes, use the OpenAI-compatible path. > [!NOTE] > Bedrock is the only provider that every runtime supports. A `codex` Harness accepts only OpenAI `gpt-*` model IDs, and both `codex` and `claude` accept no `bedrock` settings beyond `region`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). From ee29093883bcfa357132d366e1ee6e1f23d76aa2 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 11 Sep 2026 10:19:21 -0500 Subject: [PATCH 57/70] Prepare for initial PR to main website repo Signed-off-by: Rachael Graham --- docs-site/content/kagent/1.x/_index.md | 12 ++++++++++++ docs-site/hugo.yaml | 16 +++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/docs-site/content/kagent/1.x/_index.md b/docs-site/content/kagent/1.x/_index.md index 1f780c8f..53bc8677 100644 --- a/docs-site/content/kagent/1.x/_index.md +++ b/docs-site/content/kagent/1.x/_index.md @@ -4,6 +4,18 @@ linkTitle: "kagent 1.x (preview)" description: Preview the kagent 1.0 documentation, built on Agent Substrate. weight: 10 author: kagent.dev +# The 1.x docset is withheld from the published site until the 1.0 release is +# announced. `draft` keeps this section page out of a production `hugo` build and +# the cascade applies it to every descendant, so no 1.x page, list page, or +# llms.txt entry is generated. Authoring is unaffected: `make serve-docs` passes +# -D, so the section renders locally exactly as it will on release. +# +# To publish: delete both keys here, and restore the "1.x" entry in +# params.sections.kagent.versions in hugo.yaml, which is what puts the version +# back in the switcher. +draft: true +cascade: + draft: true --- kagent 1.0 moves the runtime from Kubernetes Deployments to [Agent Substrate](https://github.com/agent-substrate/substrate), introducing Harness, AgentTemplate, and AgentInstance as the new API surface. diff --git a/docs-site/hugo.yaml b/docs-site/hugo.yaml index 7b2114e2..bc96bbca 100644 --- a/docs-site/hugo.yaml +++ b/docs-site/hugo.yaml @@ -126,11 +126,17 @@ params: dropdown: "0.x (current)" linkVersion: "0.x" url: "/kagent/0.x" - - version: "1.x" - dropdown: "1.x (preview)" - linkVersion: "1.x" - url: "/kagent/1.x" - banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." + # The "1.x" entry is deliberately absent until the 1.0 release is + # announced. This list drives the version switcher independently of + # whether the pages exist, so leaving the entry here while the content + # is drafted publishes a "1.x (preview)" menu item pointing at a 404. + # Restore it alongside the draft keys in content/kagent/1.x/_index.md: + # + # - version: "1.x" + # dropdown: "1.x (preview)" + # linkVersion: "1.x" + # url: "/kagent/1.x" + # banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." # Top nav — mirrors kagent.dev. Docs is local; the marketing/blog sections stay # on the Next.js site, so those link out to absolute kagent.dev URLs. From eacee2479f83917c3ea0843f13c04abc1d94f631 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 11 Sep 2026 10:28:44 -0500 Subject: [PATCH 58/70] Uninstall testing updates Signed-off-by: Rachael Graham --- .../1.x/examples/documentation-agent.md | 3 ++- .../kagent/1.x/operations/uninstall.md | 22 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/docs-site/content/kagent/1.x/examples/documentation-agent.md b/docs-site/content/kagent/1.x/examples/documentation-agent.md index ed45d58f..84c733dc 100644 --- a/docs-site/content/kagent/1.x/examples/documentation-agent.md +++ b/docs-site/content/kagent/1.x/examples/documentation-agent.md @@ -303,9 +303,10 @@ Ask the agent something that the crawled documentation covers, and then somethin kubectl delete secret doc2vec-openai -n kagent ``` -3. Uninstall Qdrant, and stop the port-forward with `Ctrl+C`. +3. Uninstall Qdrant, and stop the port-forward with `Ctrl+C`. The chart's StatefulSet volume claim outlives the release, so delete the volume as well. ```bash helm uninstall qdrant -n kagent + kubectl delete pvc qdrant-storage-qdrant-0 -n kagent ``` ## Next steps diff --git a/docs-site/content/kagent/1.x/operations/uninstall.md b/docs-site/content/kagent/1.x/operations/uninstall.md index 68bcb554..d4ec04e1 100644 --- a/docs-site/content/kagent/1.x/operations/uninstall.md +++ b/docs-site/content/kagent/1.x/operations/uninstall.md @@ -22,9 +22,9 @@ Helm removes what its releases own, and the split matters because the material i | Removed by Helm | Left behind | | --------------- | ----------- | -| Every `kagent.dev` and `ate.dev` custom resource definition, and with them every Harness, AgentTemplate, WorkerPool, and SandboxConfig in the cluster | The certificate authority and JSON Web Token pools that the install created with `kubectl ate` | +| Every `kagent.dev` and `ate.dev` custom resource definition, and with them every Harness, AgentTemplate, WorkerPool, and SandboxConfig in the cluster | The actor identity pools that the install created in `ate-system` with `kubectl ate`, and the `ate-api-authentication` ConfigMap beside them | | kagent's bundled PostgreSQL volume, holding all conversation state | Agent Substrate's PostgreSQL volume, `data-postgres-0`, because a StatefulSet volume claim outlives its release | -| The object storage volume holding every Actor snapshot | The `kagent`, `ate-system`, and `podcertificate-controller-system` namespaces | +| The object storage volume holding every Actor snapshot, and the `podcertificate-controller-system` namespace with the service DNS and pod identity CA pools inside it | The `kagent` and `ate-system` namespaces | ## Uninstall kagent @@ -61,25 +61,21 @@ Agent Substrate is a separate installation in the `ate-system` namespace, and no The identity material is the part most often left behind, and leaving it behind breaks the next installation rather than the current one. -The install created certificate authority and JSON Web Token pools with the `kubectl ate` plugin instead of Helm, so no release owns them and no uninstall removes them. A later install that tries to create a pool that already exists fails with a message naming the secret. +The install created the actor identity pools with the `kubectl ate` plugin instead of Helm, so no release owns them and no uninstall removes them. A later install that tries to create a pool that already exists fails with a message naming the secret. ```console -Error: while uploading pool state to secret: secrets "service-dns-ca-pool" already exists +Error: while uploading pool state to secret: secrets "actor-id-jwt-pool" already exists ``` +The service DNS and pod identity CA pools need no such step. Because the install created them inside `podcertificate-controller-system`, a namespace that the Agent Substrate chart owns, `helm uninstall substrate` deletes that namespace and the pools along with it. + 1. Delete the actor identity pools and the material derived from them. ```bash kubectl delete secret actor-id-jwt-pool actor-id-ca-pool actor-id-ca-certs -n ate-system kubectl delete configmap ate-api-authentication -n ate-system ``` -2. Delete the certificate authority pools. - ```bash - kubectl delete secret service-dns-ca-pool pod-identity-ca-pool \ - -n podcertificate-controller-system - ``` - -3. Delete the Agent Substrate database volume, which a StatefulSet volume claim keeps alive after its release is gone. +2. Delete the Agent Substrate database volume, which a StatefulSet volume claim keeps alive after its release is gone. ```bash kubectl delete pvc data-postgres-0 -n ate-system ``` @@ -92,7 +88,7 @@ Error: while uploading pool state to secret: secrets "service-dns-ca-pool" alrea Deleting the namespaces removes anything that the preceding steps missed, including volumes left by optional components. ```bash -kubectl delete namespace kagent ate-system podcertificate-controller-system +kubectl delete namespace kagent ate-system ``` Confirm that nothing remains. @@ -102,4 +98,4 @@ kubectl get crd | grep -E 'kagent\.dev|ate\.dev' kubectl get ns kagent ate-system podcertificate-controller-system ``` -Both commands should report that they found nothing. +The first command prints nothing. The second reports that it found none of the three namespaces. From 31b8038f4ef69c077e28213131e87a0c25b276bb Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 11 Sep 2026 10:43:26 -0500 Subject: [PATCH 59/70] Update uninstall.md Signed-off-by: Rachael Graham --- .../kagent/1.x/operations/uninstall.md | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/docs-site/content/kagent/1.x/operations/uninstall.md b/docs-site/content/kagent/1.x/operations/uninstall.md index d4ec04e1..15c9c488 100644 --- a/docs-site/content/kagent/1.x/operations/uninstall.md +++ b/docs-site/content/kagent/1.x/operations/uninstall.md @@ -5,26 +5,31 @@ weight: 50 author: kagent.dev --- -A kagent installation has two layers, and removing it reverses the [install]({{< link path="setup/installation" >}}) in order: kagent first, then Agent Substrate underneath it. Helm removes most of each layer, but the identity material and some storage were never Helm's to begin with, so a complete uninstall ends with a manual pass. This page covers both. +Helm removes what its releases own, but does not uninstall the identity material and some storage that it does not own. -> [!CAUTION] -> Uninstalling deletes every kagent resource in every namespace, along with all agent conversation state and all stored snapshots. None of it can be recovered afterward. Back up anything you want to keep before you start. +Helm removes: -## Before you begin +- Every `kagent.dev` and `ate.dev` custom resource definition, and with them every Harness, AgentTemplate, WorkerPool, and SandboxConfig in the cluster +- kagent's bundled PostgreSQL volume, holding all conversation state +- The object storage volume holding every Actor snapshot +- The `podcertificate-controller-system` namespace, with the service DNS and pod identity CA pools inside it -- Confirm that you have administrative access to the cluster. -- Back up any Harness, AgentTemplate, and ModelConfig definitions that you want to keep. -- Confirm that nothing outside kagent depends on the agents that you are about to remove. +Helm leaves behind: -## What an uninstall removes +- The actor identity pools that the install created in `ate-system` with `kubectl ate`, and the `ate-api-authentication` ConfigMap beside them +- Agent Substrate's PostgreSQL volume, `data-postgres-0`, because a StatefulSet volume claim outlives its release +- The `kagent` and `ate-system` namespaces -Helm removes what its releases own, and the split matters because the material it leaves behind is exactly what blocks a later reinstall. +This guide includes both Helm steps to uninstall its owned components, and manual steps to remove separate material that can block a later reinstallation. + +## Before you begin -| Removed by Helm | Left behind | -| --------------- | ----------- | -| Every `kagent.dev` and `ate.dev` custom resource definition, and with them every Harness, AgentTemplate, WorkerPool, and SandboxConfig in the cluster | The actor identity pools that the install created in `ate-system` with `kubectl ate`, and the `ate-api-authentication` ConfigMap beside them | -| kagent's bundled PostgreSQL volume, holding all conversation state | Agent Substrate's PostgreSQL volume, `data-postgres-0`, because a StatefulSet volume claim outlives its release | -| The object storage volume holding every Actor snapshot, and the `podcertificate-controller-system` namespace with the service DNS and pod identity CA pools inside it | The `kagent` and `ate-system` namespaces | +1. Confirm that you have administrative access to the cluster. +2. Back up any Harness, AgentTemplate, and ModelConfig definitions that you want to keep. +3. Confirm that nothing outside kagent depends on the agents that you are removing. + +> [!CAUTION] +> Uninstalling deletes every kagent resource in every namespace, along with all agent conversation state and all stored snapshots. None of it can be recovered afterward. Back up anything you want to keep before you start. ## Uninstall kagent @@ -59,15 +64,13 @@ Agent Substrate is a separate installation in the `ate-system` namespace, and no ## Remove the identity material -The identity material is the part most often left behind, and leaving it behind breaks the next installation rather than the current one. - The install created the actor identity pools with the `kubectl ate` plugin instead of Helm, so no release owns them and no uninstall removes them. A later install that tries to create a pool that already exists fails with a message naming the secret. ```console Error: while uploading pool state to secret: secrets "actor-id-jwt-pool" already exists ``` -The service DNS and pod identity CA pools need no such step. Because the install created them inside `podcertificate-controller-system`, a namespace that the Agent Substrate chart owns, `helm uninstall substrate` deletes that namespace and the pools along with it. +The service DNS and pod identity CA pools do not need to be manually removed. Because the install created them inside `podcertificate-controller-system`, a namespace that the Agent Substrate chart owns, `helm uninstall substrate` deletes that namespace and the pools along with it. 1. Delete the actor identity pools and the material derived from them. ```bash From 34ece773f48e75ec0ca8997226bfa65ea55461f1 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 11 Sep 2026 12:09:56 -0500 Subject: [PATCH 60/70] review Signed-off-by: Rachael Graham --- .github/workflows/preview.yaml | 2 +- .github/workflows/update-ref-docs.yaml | 7 +- Makefile | 7 +- .../kagent-docs/versions/kagent-tools.md | 1 + .../assets/{ => kagent-docs}/versions/kmcp.md | 0 .../content/kagent/1.x/about/architecture.md | 8 +- .../kagent/1.x/agents/human-in-the-loop.md | 56 ++++++- .../operations/operational-considerations.md | 152 ++++++++++++++++++ .../content/kagent/1.x/reference/_index.md | 6 + .../content/kagent/1.x/reference/community.md | 15 ++ .../content/kagent/1.x/reference/versions.md | 51 ++++++ .../content/kagent/1.x/setup/installation.md | 3 +- .../kagent/1.x/skills-and-mcp/about-tools.md | 2 + .../kagent/1.x/substrate-runtime/identity.md | 7 +- .../content/kmcp/deploy/install-controller.md | 2 +- docs-site/content/kmcp/quickstart.md | 2 +- docs-site/hugo.preview.yaml | 29 ++++ 17 files changed, 335 insertions(+), 15 deletions(-) create mode 100644 docs-site/assets/kagent-docs/versions/kagent-tools.md rename docs-site/assets/{ => kagent-docs}/versions/kmcp.md (100%) create mode 100644 docs-site/content/kagent/1.x/operations/operational-considerations.md create mode 100644 docs-site/content/kagent/1.x/reference/_index.md create mode 100644 docs-site/content/kagent/1.x/reference/community.md create mode 100644 docs-site/content/kagent/1.x/reference/versions.md create mode 100644 docs-site/hugo.preview.yaml diff --git a/.github/workflows/preview.yaml b/.github/workflows/preview.yaml index 1776d1d0..28133701 100644 --- a/.github/workflows/preview.yaml +++ b/.github/workflows/preview.yaml @@ -50,7 +50,7 @@ jobs: # OpenNext Worker (which bundles public/ as static assets). HUGO=hugo uses # the Hugo installed above instead of the local hugo160 alias. - name: Build (Hugo docs + inject into /docs + Worker) - run: make build HUGO=hugo + run: make build HUGO=hugo HUGO_CONFIG=hugo.yaml,hugo.preview.yaml HUGO_FLAGS=-D # Derive a stable preview alias from the PR branch name. Cloudflare preview # aliases must be a valid subdomain label (lowercase alphanumerics and diff --git a/.github/workflows/update-ref-docs.yaml b/.github/workflows/update-ref-docs.yaml index 678b3b84..874bf014 100644 --- a/.github/workflows/update-ref-docs.yaml +++ b/.github/workflows/update-ref-docs.yaml @@ -22,8 +22,11 @@ concurrency: # generates against, is what 0.x actually ships. The 1.x rewrite tracks # v1alpha3 and gets its API/Helm reference hand-written for now (see the # kagent 1.0 docs scope: Phase 4, blocked on the v1alpha3 schema settling); -# point a similar job at docs-site/content/kagent/1.x/resources/ once that's -# ready to automate. +# point a similar job at docs-site/content/kagent/1.x/reference/ once that's +# ready to automate. Note the section is named reference/ in 1.x, not +# resources/ as in 0.x: 1.x pages link to reference/api-ref, and the provider +# pages use crd-ref-docs anchors (#modelconfigspec, #openaiconfig, ...), so +# keep that renderer's anchor naming when retargeting. jobs: generate-api-docs: runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index e0f08aa9..77c67988 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,13 @@ install: ## Install web + docs dependencies (npm) and Hugo modules # ── Docs (Hugo) ──────────────────────────────────────────────────────────── .PHONY: build-docs +# HUGO_CONFIG and HUGO_FLAGS let a preview build layer hugo.preview.yaml and pass +# -D without changing the production defaults. See docs-site/hugo.preview.yaml. +HUGO_CONFIG ?= hugo.yaml +HUGO_FLAGS ?= + build-docs: ## Build the Hugo docs site -> docs-site/public - cd $(DOCS_DIR) && $(HUGO) --config hugo.yaml $(if $(DOCS_BASEURL),--baseURL "$(DOCS_BASEURL)") --gc --minify + cd $(DOCS_DIR) && $(HUGO) --config $(HUGO_CONFIG) $(HUGO_FLAGS) $(if $(DOCS_BASEURL),--baseURL "$(DOCS_BASEURL)") --gc --minify .PHONY: inject-docs inject-docs: ## Copy built docs into public/docs (preserves tracked assets, e.g. versions/) diff --git a/docs-site/assets/kagent-docs/versions/kagent-tools.md b/docs-site/assets/kagent-docs/versions/kagent-tools.md new file mode 100644 index 00000000..7dff5b89 --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/kagent-tools.md @@ -0,0 +1 @@ +0.2.1 \ No newline at end of file diff --git a/docs-site/assets/versions/kmcp.md b/docs-site/assets/kagent-docs/versions/kmcp.md similarity index 100% rename from docs-site/assets/versions/kmcp.md rename to docs-site/assets/kagent-docs/versions/kmcp.md diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 03bf8b18..735f6b0e 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -11,10 +11,12 @@ The previous page defined the [core concepts]({{< link path="about/core-concepts kagent 1.0 splits authorization across two planes: -- The **Kubernetes plane** governs the {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit the resources, exactly as it would for any other Custom Resource Definition (CRD). +- The **Kubernetes plane** governs the {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit the resources with `kubectl`, exactly as it would for any other Custom Resource Definition (CRD). - The **kagent plane** governs any interactions involving {{< gloss "AgentInstance" >}}AgentInstances{{< /gloss >}}, such as creating, suspending, resuming, sharing, deleting, and holding a conversation with an AgentInstance. kagent's own gRPC authentication and authorization decide who can complete these interactions, independent of Kubernetes RBAC. -Someone with Kubernetes RBAC access to apply a Harness and AgentTemplate does not automatically have access to create or talk to AgentInstances that use them, and the reverse is also true. The following diagram shows where the boundary between the two planes falls. +Someone with Kubernetes RBAC access to apply a Harness and AgentTemplate does not automatically have access to create or talk to AgentInstances that use them. The planes are not mirror images, though. kagent's gRPC API also writes Harness and AgentTemplate resources, so a caller on the kagent plane reaches both. For more information on that second path, see [Identity]({{< link path="substrate-runtime/identity" >}}). + +The following diagram shows where the boundary between the two planes falls.

      ```mermaid @@ -61,7 +63,7 @@ flowchart TB class harness,template crd ``` -Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate, governed by Kubernetes RBAC. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. The ActorTemplate sits outside both planes in the diagram because that is where it sits in reality: it is a Substrate resource that the controller creates over gRPC, not a Kubernetes object, so no Kubernetes role grants access to it. +Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate with `kubectl`, governed by Kubernetes RBAC. The diagram shows this path because RBAC governs it, and `kagent apply` reaches the same two resources over gRPC instead. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. The ActorTemplate sits outside both planes in the diagram because that is where it sits in reality: it is a Substrate resource that the controller creates over gRPC, not a Kubernetes object, so no Kubernetes role grants access to it. The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an {{< gloss "Actor" >}}Actor{{< /gloss >}}. diff --git a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md index d677b9d2..dec64bf1 100644 --- a/docs-site/content/kagent/1.x/agents/human-in-the-loop.md +++ b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md @@ -8,7 +8,7 @@ author: kagent.dev An agent that only answers questions can run unattended. An agent that takes action often should not. The human in the loop (HITL) mechanism lets an agent stop mid-turn, return a question or a pending tool call to a person, and continue once that person answers. > [!IMPORTANT] -> HITL is negotiated by the **client**, per call, rather than configured on an {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}. There is no field to switch it on. A client that does not ask for the extension still gets the pause: the agent stops, and the task waits. What it loses is the ability to answer, because the request reaches it as bare text with no correlation `id`. This differs from kagent 0.x, where a `requireApproval` list on the `Agent` resource decided which tools paused. +> HITL has two halves, and a working setup needs both. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} decides which tool calls pause through `requireApproval` on a tool binding. The **client** decides whether it can answer a pause by negotiating the HITL extension on each call. A client that does not request the extension still gets the pause, as the agent stops and the task waits. That client cannot answer, because the request reaches it as bare text with no correlation `id`. ## How a pause works @@ -41,12 +41,58 @@ An agent pauses either to get permission before it acts or to ask a question. Ea | Request | Raised when | The client answers with | | ------- | ----------- | ----------------------- | -| `tool_approval_request` | The agent wants to call a tool that asked for confirmation before it runs. | `tool_approval_response` | +| `tool_approval_request` | The agent wants to call a tool from a binding that sets `requireApproval`. | `tool_approval_response` | | `ask_user_request` | The agent calls the built-in `ask_user` tool because it needs information only a person has. | `ask_user_response` | Both use the same pause and resume mechanism, so a client that handles one can handle the other with a different payload. -The runtime's tool-confirmation mechanism decides which tool calls raise an approval, rather than kagent configuration. kagent does not keep a list of tools that need approval. +The `kagent` and `codex` runtimes both raise `ask_user_request`. The `claude` runtime does not, because the upstream Claude Code tool that backed it was removed, so a `claude` agent pauses for tool approval only. + +## Require approval for a tool + +An agent pauses for a tool only when its binding asks for that. Set `requireApproval` on an `mcp` tool binding in the AgentTemplate, and the agent stops before each call to a tool that the binding exposes. + +```yaml +apiVersion: kagent.dev/v1alpha3 +kind: AgentTemplate +metadata: + name: cluster-operator + namespace: kagent + labels: + kagent.dev/harness: kagent +spec: + tools: + - mcp: + server: + kind: RemoteMCPServer + name: kagent-tool-server + tools: + - k8s_delete_resource + - k8s_patch_resource + requireApproval: true +``` + +| Field | Description | +| ----- | ----------- | +| `mcp.tools` | The names of the tools to bind. Omit the list, or leave it empty, to bind every tool that the server offers. | +| `mcp.requireApproval` | Pauses before each invocation of a tool that this binding exposes. The pause covers the tools in `mcp.tools`, or every tool on the server when `mcp.tools` is omitted or empty. Omit to run the bound tools without approval. | + +For the rest of the binding's fields, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). + +Approval belongs to the binding rather than to the tool name, so one server can supply both kinds of tool. Bind the tools that need a person in a binding that sets `requireApproval`, and bind the rest in a second binding that omits it. + +> [!NOTE] +> kagent 0.x named the tools that needed approval in a `requireApproval` list on the `Agent` resource, which matched tool names across every server. In 1.x, approval is a property of one binding, so the same tool name can pause for one server and run freely for another. + +Two limits apply to what a binding can express, and both depend on the runtime: + +| Runtime | Approval | Splitting one server across two bindings | +| ------- | -------- | ---------------------------------------- | +| `kagent` | Supported. | Supported. | +| `codex` | Supported. | Rejected, with `RemoteMCPServer "" is bound more than once`. | +| `claude` | Supported. | Rejected, with `RemoteMCPServer "" is bound more than once`. A binding whose tool selection kagent cannot verify against the server's discovered tools exposes the whole server and reports a warning. | + +Anything the binding does not cover runs without a pause. A built-in tool, such as file access, shell, or web search, and any MCP tool on a binding that omits `requireApproval`, is approved automatically. The sandbox is the boundary that contains those calls. For more information, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). ## Negotiate the extension @@ -121,6 +167,8 @@ An `ask_user_request` carries an `id` and a list of `questions`. The response ec A paused task waits. To resume, the client sends a message on the same task and context, carrying the response payload. kagent rejects a resume attempt on a task that is not waiting, with `task is not waiting for input`. +While the task waits, kagent pauses the {{< gloss "Actor" >}}Actor{{< /gloss >}} rather than suspending it. A pause keeps the running process in a full {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} on node-local storage, so a runtime that holds a live process across the wait, such as `codex` or `claude`, continues the same turn on resume. The {{< gloss "Worker" >}}Worker{{< /gloss >}} is released in the meantime, so a conversation that sits at `INPUT_REQUIRED` costs no pool capacity. For more information on the suspend that a finished turn uses instead, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}). + Because the {{< gloss "Transcript" >}}transcript{{< /gloss >}} only grows, the question and the answer both stay in the task history, so a later reader can see what was asked and what a person decided. ## Task states @@ -138,7 +186,7 @@ An agent that a parent binds as a tool can raise a pause of its own. The request ## Client support -Because the client negotiates HITL rather than the agent offering it, what a person can do with a pause depends on which client raised the turn. +The AgentTemplate decides that a turn pauses, but the client decides whether a person can answer it. What someone can do with a pause therefore depends on which client raised the turn. | Client | HITL | | ------ | ---- | diff --git a/docs-site/content/kagent/1.x/operations/operational-considerations.md b/docs-site/content/kagent/1.x/operations/operational-considerations.md new file mode 100644 index 00000000..b4ecd4e0 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/operational-considerations.md @@ -0,0 +1,152 @@ +--- +title: Operational considerations +description: Replace the evaluation defaults for the database, controller replicas, and the node pools that host Substrate Workers before you run kagent in production. +weight: 10 +author: kagent.dev +--- + +A default kagent installation is built for evaluation. It runs one controller replica against a bundled database, and places no constraints on the nodes that run agents. Production changes each of those. + +## Choose a database + +kagent stores conversations, {{< gloss "AgentInstance" >}}AgentInstances{{< /gloss >}}, and compiled {{< gloss "Revision" >}}revisions{{< /gloss >}} in PostgreSQL. A bundled instance ships with the chart so that an evaluation needs no external prerequisites, and production deployments supply their own. + +Two independent settings determine what runs and what the controller talks to: + +- `database.postgres.bundled.enabled` determines whether the chart deploys the bundled PostgreSQL pod and its PersistentVolumeClaim (PVC). This setting does not affect which database the controller connects to. +- `database.postgres.url` and `database.postgres.urlFile` determine what the controller connects to. When either is set, the controller uses it. When both are empty, the controller connects to the bundled instance. + +The controller resolves its connection in the order `urlFile`, then `url`, then the bundled connection string. Because the two settings are independent, a bundled pod can keep running while the controller points at an external database, which gives you a window to migrate data across. + +| `bundled.enabled` | `url` or `urlFile` | Bundled pod deployed | Controller connects to | +| ----------------- | ------------------ | -------------------- | ---------------------- | +| `true` | Omitted | Yes | The bundled instance | +| `false` | Set | No | The external instance | +| `true` | Set | Yes | The external instance | +| `false` | Omitted | No | Nothing. The chart fails to render. | + +The last row fails at template time with `No database connection configured`, rather than installing a controller that cannot start. + +### Use an external PostgreSQL instance + +For production, run PostgreSQL outside the cluster's lifecycle so that a kagent uninstall cannot take the data with it. + +1. Set the connection in your Helm values file. Mount the connection string from a Kubernetes Secret and reference the mount path with `urlFile` to keep credentials out of Helm values. + + ```yaml + database: + postgres: + urlFile: /var/secrets/db-url + vectorEnabled: true + bundled: + enabled: false + controller: + replicas: 3 + volumes: + - name: db-secret + secret: + secretName: my-postgres-url-secret + volumeMounts: + - name: db-secret + mountPath: /var/secrets + readOnly: true + ``` + +2. Apply the values to the kagent Helm release. + + ```bash + helm upgrade kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --namespace kagent \ + --values kagent.yaml + ``` + +Set `database.postgres.vectorEnabled: true` only when the instance has the `pgvector` extension installed. The setting enables the vector migration, and features that depend on it, such as [long-term memory]({{< link path="agents/agent-memory" >}}), fail without the extension. The bundled image does not include `pgvector`. + +Three further settings matter at production scale, and all three default to values suited to evaluation: + +| Setting | Description | +| ------- | ----------- | +| `database.postgres.pool` | Connection pool sizing, through `maxConns`, `minConns`, `maxConnIdleTime`, and `maxConnLifetime`. Leave the fields unset to keep the pgx library defaults. | +| `database.postgres.skipMigrations` | Set to `true` to stop the controller from running migrations at startup. The controller then verifies that the database is already migrated and fails if it is not. Apply the migrations from a pipeline before you install or upgrade. | +| `database.postgres.bundled.storageClassName` | The StorageClass for the bundled PVC. Leave it empty to use the cluster default. | + +## Run more than one controller replica + +Set `controller.replicas` above `1` so that a controller failure does not stop reconciliation. + +```yaml +controller: + replicas: 3 +``` + +Leader election keeps the replicas from conflicting. One replica holds a Kubernetes lease and performs reconciliation, garbage collection, and scheduled runs; the others stay ready and take over when the leader's lease expires. + +> [!NOTE] +> Leader election is always on, including at a single replica, because a rolling update briefly runs two controllers at once. The chart grants the lease permissions unconditionally and exposes no setting to turn election off. `LEADER_ELECT=false` remains available for local testing. + +PostgreSQL supports multiple controller replicas without further configuration. The bundled instance is still a single pod backed by one PVC, so an installation that runs several controllers for availability, against a bundled database, has only moved the single point of failure. + +## Reserve node pools for Workers + +{{< gloss "Worker" >}}Workers{{< /gloss >}} hold running {{< gloss "Actor" >}}Actors{{< /gloss >}}, and an Actor that loses its node without suspending first loses its conversation. Plan the node pools that run Workers around that. + +> [!WARNING] +> Turn node auto-upgrade off on every node pool that runs Workers, and do not use spot or preemptible nodes for them. An Actor that is still awake when its node goes away moves to `ACTOR_STATE_CRASHED`. That state is terminal. Agent Substrate refuses both `resume` and `suspend` on a crashed Actor, offers no recovery verb, and cannot start it from the {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} that the Actor still holds. Deleting the Actor and creating a new one is the only way out, and the conversation does not survive. + +A graceful pod deletion is safe. Kubernetes forwards `SIGTERM` into the Actor's containers, the Worker drains for up to 30 minutes inside a pod termination grace period of 3600 seconds, and an Actor that suspends inside that window keeps its state and stays resumable. Rolling a `workerImage` change through a pool therefore finishes in-flight turns rather than cutting them off. + +A reclaimed node is not a graceful deletion. Auto-upgrade is the case to plan for, because Google Kubernetes Engine (GKE) enables it by default and it fires on Google's maintenance schedule rather than yours. Disable it on every pool that runs Workers. + +```bash +gcloud container node-pools update "${NODE_POOL}" \ + --cluster "${CLUSTER_NAME}" --location "${CLUSTER_LOCATION}" \ + --no-enable-autoupgrade +``` + +Scaling a serving WorkerPool down removes pods without suspending the Actors on them, so treat a scale-down as the same class of event. For pool sizing and the rest of the Substrate runtime settings, see [Tune Agent Substrate]({{< link path="operations/tune-agent-substrate" >}}). + +## Understand when a configuration change reaches an agent + +kagent watches the Secrets and ConfigMaps that a {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} reference, such as the API keys and TLS certificates in a {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}}. An edit to one of them recompiles the pair into a new revision. + +A new revision does not reach the AgentInstances that are already running. An AgentInstance is pinned to the revision that it was created from and keeps that revision for life, so a rotated API key applies to AgentInstances created after the rotation. To move an existing conversation onto new configuration, create a new AgentInstance. + +This behavior differs from kagent 0.x, where an agent ran as a Deployment and a secret change restarted its pods. + +## Route agent traffic through a proxy + +When agents and MCP servers sit behind an API gateway or proxy, point kagent at the proxy endpoint so that agent-to-agent and agent-to-MCP traffic follows the same path as the rest of your cluster's egress. + +```yaml +proxy: + url: "http://proxy.kagent.svc.cluster.local:8080" +``` + +The controller rewrites internally built Kubernetes URLs to the proxy and sets the `x-kagent-host` header so that the proxy routes each request to the correct backend. The rewrite covers one agent invoking another as a tool, and an agent calling a RemoteMCPServer at an internal URL. An external URL, such as a RemoteMCPServer at `https://external.example.com`, is left alone. + +## Scrape controller metrics + +The controller serves a Prometheus-style `/metrics` endpoint, turned off by default. Enabling it provisions a dedicated metrics Service and the ClusterRoles that an authenticated scrape needs. + +```yaml +controller: + metrics: + enabled: true + bindAddress: ":8443" + secureServing: true +``` + +Bind the `-metrics-reader` ClusterRole to your Prometheus ServiceAccount to grant scrape access. Change the port through `bindAddress` rather than through `controller.env`, because the chart derives the Service `targetPort` and the pod `containerPort` from `bindAddress` at template time. Overriding `METRICS_BIND_ADDRESS` directly moves the listener and leaves the Service pointing at the old port. + +## Isolate what an agent can do + +kagent 0.x ran agents as Deployments and relied on a Kubernetes `securityContext` to constrain them. In 1.0, every agent runs as an Actor inside a gVisor sandbox, and the sandbox provides process, network, and filesystem isolation without per-agent security context configuration. + +For what the sandbox blocks, how to configure egress, and how to select a sandbox class, see [Sandboxing]({{< link path="substrate-runtime/sandboxing" >}}). + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="operations/tune-agent-substrate" >}}` title="Tune Agent Substrate" subtitle="Size the WorkerPool and configure snapshot storage." >}} + {{< card link=`{{< link path="operations/debug" >}}` title="Debug" subtitle="Work back from a symptom to the resource that caused it." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/reference/_index.md b/docs-site/content/kagent/1.x/reference/_index.md new file mode 100644 index 00000000..cd0eb894 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/_index.md @@ -0,0 +1,6 @@ +--- +title: Reference +description: Look up the API and Helm reference, the built-in tool catalog, version support, FAQs, release notes, and community links. +weight: 100 +author: kagent.dev +--- diff --git a/docs-site/content/kagent/1.x/reference/community.md b/docs-site/content/kagent/1.x/reference/community.md new file mode 100644 index 00000000..322d89fb --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/community.md @@ -0,0 +1,15 @@ +--- +title: Community and contributing +description: Connect with the kagent community, browse the source, and find out how to contribute. +weight: 80 +author: kagent.dev +--- + +kagent is developed in the open. Use the following links to follow the project, ask questions, and contribute. + +{{< cards >}} +{{< card link="https://github.com/kagent-dev/kagent" title="Official GitHub repository" subtitle="Access the source code and contribute to kagent development." >}} +{{< card link="https://github.com/kagent-dev/kagent/blob/main/CONTRIBUTING.md" title="Contribution guide" subtitle="Learn how to contribute to the kagent project." >}} +{{< card link="https://github.com/kagent-dev/kagent/blob/main/README.md#roadmap" title="Feature roadmap" subtitle="See what the project is planning for the future." >}} +{{< card link="https://discord.gg/Fu3k65f2k3" title="Join the Discord community" subtitle="Connect with other kagent users and developers." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/reference/versions.md b/docs-site/content/kagent/1.x/reference/versions.md new file mode 100644 index 00000000..037d2cf9 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/versions.md @@ -0,0 +1,51 @@ +--- +title: Version support +description: Review what a kagent release includes, which Kubernetes version it is tested against, and which upgrades are supported. +weight: 60 +author: kagent.dev +--- + +Only the latest kagent release is supported. The versions on this page apply to that release. + +## What a kagent release includes + +The kagent Helm chart pulls in {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} and two other components as subcharts, each on its own release cadence. Because a kagent release pins one version of each, the pinned versions are the combination that kagent is built and tested against. + +| Component | Version | What it provides | +| --------- | ------- | ---------------- | +| kagent | {{< reuse "kagent-docs/versions/kagent.md" >}} | The controller, the gRPC API, and the agent runtimes. | +| Agent Substrate | {{< reuse "kagent-docs/versions/agent-substrate.md" >}} | The {{< gloss "Actor" >}}Actor{{< /gloss >}} runtime that every agent runs on, including sandboxing, snapshots, and the {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}}. | +| kmcp | {{< reuse "kagent-docs/versions/kmcp.md" >}} | The MCP server toolkit and its controller. | +| kagent-tools | {{< reuse "kagent-docs/versions/kagent-tools.md" >}} | The bundled tool server that the built-in RemoteMCPServer points at. | + +> [!IMPORTANT] +> Do not upgrade Agent Substrate independently of kagent. Substrate folds schema changes into a single baseline migration before its own release, so an existing database keeps its recorded schema version and never applies the change. The cluster then looks healthy, agents answer normally, and every checkpoint operation fails at runtime against a table that was renamed. Install the substrate version that your kagent release pins. + +## Kubernetes versions + +kagent's CI tests one Kubernetes minor version at a time rather than a matrix, so there is a single tested version rather than a supported range. + +kagent's CI tests against Kubernetes {{< reuse "kagent-docs/versions/max-kube.md" >}} today. That version is sourced from `KIND_IMAGE_VERSION` in the [kagent Makefile](https://github.com/kagent-dev/kagent/blob/main/Makefile), which pins the [kindest/node](https://hub.docker.com/r/kindest/node) image that [CI](https://github.com/kagent-dev/kagent/blob/main/.github/workflows/ci.yaml) uses. + +Other Kubernetes versions are not exercised in CI and are not guaranteed to work. kagent's Kubernetes client libraries generally follow the [client-go version skew policy](https://github.com/kubernetes/client-go#compatibility-matrix). + +## Release support and compatibility + +kagent 1.0 is a deliberate clean break from the 0.10.x line, and the compatibility promises start rather than continue at 1.0. + +| Upgrade path | Supported | +| ------------ | --------- | +| 0.10.x to 1.0 in place | No. An existing 0.10.x database requires a new PostgreSQL database, because there is no migration bridge. | +| 1.0 back to 0.10.x | No. Downgrade across the 1.0 boundary is unsupported. | +| 1.0 forward to a later minor release | Yes. From 1.0 onward, migrations are append-only and each minor release retains compatibility with the previous release line. | + +Moving from 0.10.x therefore means standing up a new installation and recreating your resources on it, rather than running `helm upgrade`. For the procedure, see [Upgrade]({{< link path="reference/upgrade" >}}). + + diff --git a/docs-site/content/kagent/1.x/setup/installation.md b/docs-site/content/kagent/1.x/setup/installation.md index f3bafe15..45799ba3 100644 --- a/docs-site/content/kagent/1.x/setup/installation.md +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -167,7 +167,7 @@ Deploy the Agent Substrate control plane and data plane into the `ate-system` na ## Install kagent -The kagent chart connects the controller to Agent Substrate and creates a WorkerPool for agents to run on. A WorkerPool is platform capacity that you provision once, and every Harness references it. No Harness can run until a WorkerPool exists. +The kagent chart connects the controller to Agent Substrate and creates a WorkerPool for agents to run on. A WorkerPool is platform capacity that you provision once, and every Harness references it. No Harness can run until a WorkerPool exists. The values in the following steps are evaluation defaults, including a bundled PostgreSQL instance, one controller replica, and one Worker. For a production installation, add the production values from [Operational considerations]({{< link path="operations/operational-considerations" >}}) to the same command. > [!IMPORTANT] > Install kagent 1.0 with Helm. The `kagent install` command does not yet provision Agent Substrate and cannot produce a working 1.0 installation. @@ -269,4 +269,5 @@ The kagent chart connects the controller to Agent Substrate and creates a Worker {{< cards >}} {{< card link=`{{< link path="get-started/your-first-agent" >}}` title="Your first agent" subtitle="Apply a Harness and AgentTemplate, and talk to the AgentInstance they produce." >}} {{< card link=`{{< link path="setup/model-providers" >}}` title="Configure model providers" subtitle="Point kagent at OpenAI, Anthropic, Gemini, or a provider of your own." >}} + {{< card link=`{{< link path="operations/operational-considerations" >}}` title="Operational considerations" subtitle="Replace the evaluation defaults for the database, controller replicas, and Worker node pools." >}} {{< /cards >}} 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 3e367857..5c990304 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 @@ -25,6 +25,7 @@ tools: tools: - search_docs - fetch_page + requireApproval: true ``` | Field | Description | @@ -32,6 +33,7 @@ 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. | +| `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" >}}). | ## Agents as tools diff --git a/docs-site/content/kagent/1.x/substrate-runtime/identity.md b/docs-site/content/kagent/1.x/substrate-runtime/identity.md index 23574cee..324925d3 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/identity.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/identity.md @@ -13,7 +13,12 @@ A kagent installation authenticates three different kinds of caller, and each on ## The Kubernetes plane -Harness and AgentTemplate are Kubernetes custom resources, so Kubernetes role-based access control (RBAC) governs who can create, read, edit, or delete them. Nothing in kagent replaces or supplements that: a cluster's existing roles and bindings decide who authors an agent's runtime and behavior. +Harness and AgentTemplate are Kubernetes custom resources, so Kubernetes role-based access control (RBAC) governs who can create, read, edit, or delete them with `kubectl`. A cluster's existing roles and bindings decide who authors an agent's runtime and its behavior on that path. + +kagent's gRPC API reaches the same two resources by a second path. `kagent apply -f`, and the AgentTemplate and Harness services behind it, create, update, and delete these resources through the kagent controller. The controller writes them with its own service account rather than the caller's, so Kubernetes RBAC never evaluates the caller. The kagent plane authorizes this path instead. + +> [!WARNING] +> Because the open source build's authorizer permits every check, any caller that reaches the gRPC endpoint can author an agent's runtime and behavior, whatever their Kubernetes permissions are. Do not expose port `8083` outside the cluster. A Harness's `allowedAgentTemplates` selector adds a second, narrower control on top of RBAC. Whoever holds edit access on a Harness decides which AgentTemplates that Harness admits. In this way, RBAC governs who can write the resources, and the selector governs which pairs can run. For more information on the one-way match, see the [Harness core concept]({{< link path="about/core-concepts/#harness" >}}). diff --git a/docs-site/content/kmcp/deploy/install-controller.md b/docs-site/content/kmcp/deploy/install-controller.md index 5f32cc5c..31d074aa 100644 --- a/docs-site/content/kmcp/deploy/install-controller.md +++ b/docs-site/content/kmcp/deploy/install-controller.md @@ -42,7 +42,7 @@ The kmcp controller manages the lifecycle of MCP servers that are defined in an Example output: ```sh 🚀 Deploying KMCP controller to cluster... - No version specified, using latest: v{{< reuse "versions/kmcp.md" >}} + No version specified, using latest: v{{< reuse "kagent-docs/versions/kmcp.md" >}} Release "kmcp" does not exist. Installing it now. NAME: kmcp LAST DEPLOYED: Wed Jul 30 18:41:01 2025 diff --git a/docs-site/content/kmcp/quickstart.md b/docs-site/content/kmcp/quickstart.md index 441f4b3e..d6da5741 100644 --- a/docs-site/content/kmcp/quickstart.md +++ b/docs-site/content/kmcp/quickstart.md @@ -104,7 +104,7 @@ With your first FastMCP Python server up and running, you can now deploy it to a Example output: ```sh 🚀 Deploying KMCP controller to cluster... - No version specified, using latest: v{{< reuse "versions/kmcp.md" >}} + No version specified, using latest: v{{< reuse "kagent-docs/versions/kmcp.md" >}} Release "kmcp" does not exist. Installing it now. NAME: kmcp LAST DEPLOYED: Wed Jul 30 18:41:01 2025 diff --git a/docs-site/hugo.preview.yaml b/docs-site/hugo.preview.yaml new file mode 100644 index 00000000..653da486 --- /dev/null +++ b/docs-site/hugo.preview.yaml @@ -0,0 +1,29 @@ +# Preview/authoring overlay. Layered on top of hugo.yaml with +# `--config hugo.yaml,hugo.preview.yaml`, and never used by the production build. +# +# Restores the "1.x" versions entry that hugo.yaml deliberately omits while 1.x is +# withheld. That list does two jobs, and hiding 1.x from the published site breaks +# the second one: +# 1. It drives the version switcher, which is why the entry is absent in production. +# 2. The {{< version >}} shortcode iterates it and emits only on a linkVersion +# match, so with no 1.x entry every {{< version include-if="1.x" >}} renders +# EMPTY -- blanking the conref'd version numbers on setup/installation.md, +# agents/agent-memory.md, observability/tracing.md, +# operations/tune-agent-substrate.md, and reference/versions.md. No error, +# clean build, broken copy-paste commands. +# +# Delete this file at the 1.0 release, when the entry returns to hugo.yaml +# alongside dropping the draft keys in content/kagent/1.x/_index.md. +params: + sections: + kagent: + versions: + - version: "0.x" + dropdown: "0.x (current)" + linkVersion: "0.x" + url: "/kagent/0.x" + - version: "1.x" + dropdown: "1.x (preview)" + linkVersion: "1.x" + url: "/kagent/1.x" + banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." From 59eb1b802f88537ddf2532c8dfa9cae77135e623 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Fri, 11 Sep 2026 12:38:32 -0500 Subject: [PATCH 61/70] Phase 4 Signed-off-by: Rachael Graham --- Makefile | 5 +- .../kagent/1.x/agents/system-prompts.md | 12 ++--- .../operations/operational-considerations.md | 49 ++++++++++--------- .../content/kagent/1.x/reference/versions.md | 2 +- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 77c67988..d878e90b 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,9 @@ install: ## Install web + docs dependencies (npm) and Hugo modules # HUGO_CONFIG and HUGO_FLAGS let a preview build layer hugo.preview.yaml and pass # -D without changing the production defaults. See docs-site/hugo.preview.yaml. HUGO_CONFIG ?= hugo.yaml +# serve-docs layers the preview overlay by default: without it, local authoring +# renders every {{< version include-if="1.x" >}} conref empty. See docs-site/hugo.preview.yaml. +HUGO_CONFIG_PREVIEW ?= hugo.yaml,hugo.preview.yaml HUGO_FLAGS ?= build-docs: ## Build the Hugo docs site -> docs-site/public @@ -60,7 +63,7 @@ inject-docs: ## Copy built docs into public/docs (preserves tracked assets, e.g. # back but the stylesheets never do, and the preview degrades edit by edit # instead of failing outright. Rendering to memory removes the shared directory. serve-docs: ## Preview the docs alone at http://localhost:1313/docs/ - cd $(DOCS_DIR) && $(HUGO) server --config hugo.yaml -D --disableFastRender --renderToMemory + cd $(DOCS_DIR) && $(HUGO) server --config $(HUGO_CONFIG_PREVIEW) -D --disableFastRender --renderToMemory # ── Web (Next.js) ────────────────────────────────────────────────────────── .PHONY: serve-web diff --git a/docs-site/content/kagent/1.x/agents/system-prompts.md b/docs-site/content/kagent/1.x/agents/system-prompts.md index 079209b2..760b08bd 100644 --- a/docs-site/content/kagent/1.x/agents/system-prompts.md +++ b/docs-site/content/kagent/1.x/agents/system-prompts.md @@ -37,7 +37,7 @@ Write the value as a YAML block scalar, such as the `|-` in the example, so that ## Store the prompt in a ConfigMap -Use `systemPromptFrom` to keep the prompt outside the AgentTemplate, which lets several AgentTemplates share one prompt, or lets a prompt change without editing the agent. +Use `systemPromptFrom` to keep the prompt outside the AgentTemplate. Several AgentTemplates can then share one prompt, and a prompt can change without editing the agent. 1. Create a ConfigMap holding the prompt. ```yaml @@ -61,12 +61,12 @@ Use `systemPromptFrom` to keep the prompt outside the AgentTemplate, which lets key: kubernetes-assistant ``` -| Field | Description | -| ----- | ----------- | -| `systemPromptFrom.name` | The ConfigMap holding the prompt, in the AgentTemplate's namespace. | -| `systemPromptFrom.key` | The key within that ConfigMap. | + `systemPrompt` and `systemPromptFrom` are mutually exclusive, and an AgentTemplate that sets both is rejected. If you omit both fields, the revision compiles with no system prompt at all, and the agent runs on its harness's default behavior. -`systemPrompt` and `systemPromptFrom` are mutually exclusive, and an AgentTemplate that sets both is rejected. If you omit both fields, the revision compiles with no system prompt at all, and the agent runs on its harness's default behavior. + | Field | Description | + | ----- | ----------- | + | `systemPromptFrom.name` | The ConfigMap holding the prompt, in the AgentTemplate's namespace. | + | `systemPromptFrom.key` | The key within that ConfigMap. | > [!NOTE] > A prompt can come only from a ConfigMap. Earlier versions of kagent also accepted a Secret, through a `systemMessageFrom.type` field that v1alpha3 does not have. A system prompt is not a credential, so keep secrets out of it and pass them to the runtime as [Harness environment variables]({{< link path="agents/agent-harness" >}}) instead. diff --git a/docs-site/content/kagent/1.x/operations/operational-considerations.md b/docs-site/content/kagent/1.x/operations/operational-considerations.md index b4ecd4e0..92529d69 100644 --- a/docs-site/content/kagent/1.x/operations/operational-considerations.md +++ b/docs-site/content/kagent/1.x/operations/operational-considerations.md @@ -27,17 +27,23 @@ The controller resolves its connection in the order `urlFile`, then `url`, then The last row fails at template time with `No database connection configured`, rather than installing a controller that cannot start. +The bundled instance claims its PersistentVolumeClaim from the cluster's default StorageClass. Set `database.postgres.bundled.storageClassName` to choose a different one. + ### Use an external PostgreSQL instance -For production, run PostgreSQL outside the cluster's lifecycle so that a kagent uninstall cannot take the data with it. +For production, run PostgreSQL outside the cluster's lifecycle so that a kagent uninstall cannot delete the data. -1. Set the connection in your Helm values file. Mount the connection string from a Kubernetes Secret and reference the mount path with `urlFile` to keep credentials out of Helm values. +1. Set the connection in your Helm values file. To keep credentials out of Helm values, mount the connection string from a Kubernetes Secret and reference the mount path by using `urlFile`. ```yaml database: postgres: urlFile: /var/secrets/db-url vectorEnabled: true + skipMigrations: false + pool: + maxConns: 20 + minConns: 2 bundled: enabled: false controller: @@ -52,34 +58,33 @@ For production, run PostgreSQL outside the cluster's lifecycle so that a kagent readOnly: true ``` + | Setting | Description | + | ------- | ----------- | + | `database.postgres.url` or `database.postgres.urlFile` | The connection string, or the path to a file holding it. `urlFile` keeps the credentials out of Helm values. | + | `database.postgres.vectorEnabled` | Set to `true` only when the instance has the `pgvector` extension installed. The setting enables the vector migration, and features that depend on it, such as [long-term memory]({{< link path="agents/agent-memory" >}}), fail without the extension. The bundled image does not include `pgvector`. | + | `database.postgres.pool` | Connection pool sizing, through `maxConns`, `minConns`, `maxConnIdleTime`, and `maxConnLifetime`. Omit the fields to keep the pgx library defaults. | + | `database.postgres.skipMigrations` | Set to `true` to stop the controller from running migrations at startup. The controller then verifies that the database is already migrated and fails if it is not. Apply the migrations from a pipeline before you install or upgrade. | + 2. Apply the values to the kagent Helm release. ```bash - helm upgrade kagent oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + helm upgrade --install kagent \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ --namespace kagent \ --values kagent.yaml ``` -Set `database.postgres.vectorEnabled: true` only when the instance has the `pgvector` extension installed. The setting enables the vector migration, and features that depend on it, such as [long-term memory]({{< link path="agents/agent-memory" >}}), fail without the extension. The bundled image does not include `pgvector`. - -Three further settings matter at production scale, and all three default to values suited to evaluation: - -| Setting | Description | -| ------- | ----------- | -| `database.postgres.pool` | Connection pool sizing, through `maxConns`, `minConns`, `maxConnIdleTime`, and `maxConnLifetime`. Leave the fields unset to keep the pgx library defaults. | -| `database.postgres.skipMigrations` | Set to `true` to stop the controller from running migrations at startup. The controller then verifies that the database is already migrated and fails if it is not. Apply the migrations from a pipeline before you install or upgrade. | -| `database.postgres.bundled.storageClassName` | The StorageClass for the bundled PVC. Leave it empty to use the cluster default. | - -## Run more than one controller replica +## Run multiple controller replica -Set `controller.replicas` above `1` so that a controller failure does not stop reconciliation. +To ensure that a controller failure does not stop reconciliation, set `controller.replicas` to a number higher than `1`. ```yaml controller: replicas: 3 ``` -Leader election keeps the replicas from conflicting. One replica holds a Kubernetes lease and performs reconciliation, garbage collection, and scheduled runs; the others stay ready and take over when the leader's lease expires. +Leader election keeps the replicas from conflicting. One replica holds a Kubernetes lease and performs reconciliation, garbage collection, and scheduled runs; the other replicas stay ready and take over when the leader's lease expires. > [!NOTE] > Leader election is always on, including at a single replica, because a rolling update briefly runs two controllers at once. The chart grants the lease permissions unconditionally and exposes no setting to turn election off. `LEADER_ELECT=false` remains available for local testing. @@ -88,14 +93,14 @@ PostgreSQL supports multiple controller replicas without further configuration. ## Reserve node pools for Workers -{{< gloss "Worker" >}}Workers{{< /gloss >}} hold running {{< gloss "Actor" >}}Actors{{< /gloss >}}, and an Actor that loses its node without suspending first loses its conversation. Plan the node pools that run Workers around that. +{{< gloss "Worker" >}}Workers{{< /gloss >}} hold running {{< gloss "Actor" >}}Actors{{< /gloss >}}. An Actor that loses its node before it suspends loses its conversation, so the node pools that run Workers need stricter rules than the rest of the cluster. > [!WARNING] -> Turn node auto-upgrade off on every node pool that runs Workers, and do not use spot or preemptible nodes for them. An Actor that is still awake when its node goes away moves to `ACTOR_STATE_CRASHED`. That state is terminal. Agent Substrate refuses both `resume` and `suspend` on a crashed Actor, offers no recovery verb, and cannot start it from the {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} that the Actor still holds. Deleting the Actor and creating a new one is the only way out, and the conversation does not survive. +> Turn node auto-upgrade off on every node pool that runs Workers, and do not use spot or preemptible nodes for them. An Actor that is still awake when its node goes away moves to `ACTOR_STATE_CRASHED`. That state is terminal. Agent Substrate refuses both `resume` and `suspend` on a crashed Actor, offers no recovery verb, and cannot start it from the {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} that the Actor still holds. Deleting the Actor and creating a new one is the only available option, and the conversation does not survive. -A graceful pod deletion is safe. Kubernetes forwards `SIGTERM` into the Actor's containers, the Worker drains for up to 30 minutes inside a pod termination grace period of 3600 seconds, and an Actor that suspends inside that window keeps its state and stays resumable. Rolling a `workerImage` change through a pool therefore finishes in-flight turns rather than cutting them off. +A graceful pod deletion is safe. Kubernetes forwards `SIGTERM` into the Actor's containers, the Worker drains for up to 30 minutes inside a pod termination grace period of 3600 seconds, and an Actor that suspends inside that window keeps its state and stays resumable. Rolling a `workerImage` change through a pool therefore finishes any in-flight turns rather than cutting them off. -A reclaimed node is not a graceful deletion. Auto-upgrade is the case to plan for, because Google Kubernetes Engine (GKE) enables it by default and it fires on Google's maintenance schedule rather than yours. Disable it on every pool that runs Workers. +A reclaimed node is not a graceful deletion, and node auto-upgrade is the most likely way to hit one. Google Kubernetes Engine (GKE) enables auto-upgrade by default and runs it on Google's maintenance schedule, not yours. Disable it on every pool that runs Workers. ```bash gcloud container node-pools update "${NODE_POOL}" \ @@ -103,9 +108,9 @@ gcloud container node-pools update "${NODE_POOL}" \ --no-enable-autoupgrade ``` -Scaling a serving WorkerPool down removes pods without suspending the Actors on them, so treat a scale-down as the same class of event. For pool sizing and the rest of the Substrate runtime settings, see [Tune Agent Substrate]({{< link path="operations/tune-agent-substrate" >}}). +Scaling a serving WorkerPool down removes pods without suspending the Actors on them, so it strands conversations exactly as a reclaimed node does. For pool sizing and the rest of the Substrate runtime settings, see [Tune Agent Substrate]({{< link path="operations/tune-agent-substrate" >}}). -## Understand when a configuration change reaches an agent +## How configuration changes reach agents kagent watches the Secrets and ConfigMaps that a {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} reference, such as the API keys and TLS certificates in a {{< gloss "ModelConfig" >}}ModelConfig{{< /gloss >}}. An edit to one of them recompiles the pair into a new revision. diff --git a/docs-site/content/kagent/1.x/reference/versions.md b/docs-site/content/kagent/1.x/reference/versions.md index 037d2cf9..68752842 100644 --- a/docs-site/content/kagent/1.x/reference/versions.md +++ b/docs-site/content/kagent/1.x/reference/versions.md @@ -39,7 +39,7 @@ kagent 1.0 is a deliberate clean break from the 0.10.x line, and the compatibili | 1.0 back to 0.10.x | No. Downgrade across the 1.0 boundary is unsupported. | | 1.0 forward to a later minor release | Yes. From 1.0 onward, migrations are append-only and each minor release retains compatibility with the previous release line. | -Moving from 0.10.x therefore means standing up a new installation and recreating your resources on it, rather than running `helm upgrade`. For the procedure, see [Upgrade]({{< link path="reference/upgrade" >}}). +Moving from 0.10.x therefore means standing up a new installation and recreating your resources on it, rather than running `helm upgrade`. For the procedure, see [Upgrade]({{< link path="operations/upgrade" >}}). diff --git a/docs-site/content/kagent/1.x/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md index 7dd31d31..cb724339 100644 --- a/docs-site/content/kagent/1.x/agents/agent-memory.md +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -142,7 +142,7 @@ Add memory to a Harness that already exists. The examples in these steps use `my ``` > [!NOTE] -> Only the `kagent` runtime supports memory. The `spec.kagent` runtime block is the only runtimes that has settings, so a Harness that selects `codex`, `claude`, or `byo` has settings to configure memory. +> Only the `kagent` runtime supports memory. The `memory` block exists only under `spec.kagent`, so a Harness that selects `codex`, `claude`, or `byo` has no settings to configure memory. ## Verify that memory works diff --git a/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md index c77bda4f..9cb88f1b 100644 --- a/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md +++ b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md @@ -51,7 +51,7 @@ Read the current state of the runtime before you change it. Three values from th "namespace": "kagent", "name": "kagent-default", "replicas": 8, - "ateomImage": "ghcr.io/kagent-dev/substrate/ateom-gvisor:v0.0.26" + "ateomImage": "ghcr.io/kagent-dev/substrate/ateom-gvisor:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" } ], "actors": [ diff --git a/docs-site/content/kagent/1.x/reference/api-ref.md b/docs-site/content/kagent/1.x/reference/api-ref.md index a5c8412e..7de7842b 100644 --- a/docs-site/content/kagent/1.x/reference/api-ref.md +++ b/docs-site/content/kagent/1.x/reference/api-ref.md @@ -29,7 +29,7 @@ AgentTemplate defines portable agent behavior. | `kind` _string_ | `AgentTemplate` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[AgentTemplateSpec](#agenttemplatespec)_ | | | | | `status` _[AgentTemplateStatus](#agenttemplatestatus)_ | | | | @@ -58,7 +58,7 @@ _Appears in:_ | `desiredRevision` _string_ | | | MinLength: 1
      | | `latestSuccessfulRevision` _string_ | | | MinLength: 1
      | | `warnings` _string array_ | Warnings reports non-blocking compatibility decisions made while compiling
      this AgentTemplate for the Harness. | | MaxItems: 100
      | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | MaxItems: 4
      | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | MaxItems: 4
      | #### AgentTemplatePromptSource @@ -104,7 +104,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `modelConfig` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core)_ | ModelConfig is required by managed harnesses and optional for BYO harnesses. | | | +| `modelConfig` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core)_ | ModelConfig is required by managed harnesses and optional for BYO harnesses. | | | | `description` _string_ | | | | | `systemPrompt` _string_ | | | | | `systemPromptFrom` _[AgentTemplateConfigMapKeyReference](#agenttemplateconfigmapkeyreference)_ | SystemPromptFrom references prompt text in a same-namespace ConfigMap. | | | @@ -136,7 +136,7 @@ _Appears in:_ | --- | --- | --- | --- | | `name` _string_ | | | MinLength: 1
      | | `description` _string_ | Description tells the parent when to route work to this binding. | | MinLength: 1
      | -| `templateRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core)_ | | | | +| `templateRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core)_ | | | | | `isolation` _[AgentToolIsolation](#agenttoolisolation)_ | | Shared | Enum: [Shared Dedicated]
      | #### AgentToolIsolation @@ -170,7 +170,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `from` _[FromNamespaces](#fromnamespaces)_ | From indicates where references to this resource can originate.
      Possible values are:
      * All: References from all namespaces are allowed.
      * Same: Only references from the same namespace are allowed (default).
      * Selector: References from namespaces matching the selector are allowed. | Same | Enum: [All Same Selector]
      | -| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#labelselector-v1-meta)_ | Selector is a label selector for namespaces that are allowed to reference this resource.
      Only used when From is set to "Selector". | | | +| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#labelselector-v1-meta)_ | Selector is a label selector for namespaces that are allowed to reference this resource.
      Only used when From is set to "Selector". | | | #### AnthropicConfig @@ -266,7 +266,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `region` _string_ | AWS region where the Bedrock model is available (e.g., us-east-1, us-west-2) | | | -| `additionalModelRequestFields` _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#json-v1-apiextensions-k8s-io)_ | AdditionalModelRequestFields passes model-specific parameters to Bedrock's
      additionalModelRequestFields in the Converse API. Use this for provider-specific
      options that are not part of the standard InferenceConfiguration block, such as
      Claude extended thinking or top_k. Values are forwarded as-is to the API.
      Example: \{"top_k": 5, "thinking": \{"type": "enabled", "budget_tokens": 16000\}\} | | | +| `additionalModelRequestFields` _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#json-v1-apiextensions-k8s-io)_ | AdditionalModelRequestFields passes model-specific parameters to Bedrock's
      additionalModelRequestFields in the Converse API. Use this for provider-specific
      options that are not part of the standard InferenceConfiguration block, such as
      Claude extended thinking or top_k. Values are forwarded as-is to the API.
      Example: \{"top_k": 5, "thinking": \{"type": "enabled", "budget_tokens": 16000\}\} | | | | `promptCaching` _boolean_ | PromptCaching enables Bedrock prompt caching by appending a CachePoint
      block at the end of the Converse request's `system` content array and
      the end of the `toolConfig.tools` array. Bedrock will cache the prefix up to and
      including those cache points across requests in the same region for
      roughly 5 minutes after first use, billing the cached portion at a
      reduced rate on cache hits.

      Recommended for tool-using agents that make many Converse calls per
      task with a stable system prompt and tool set — the per-call input
      token count can drop by 70-90% on hit. Has no effect on models that
      don't support caching; the marker is ignored by Bedrock for those.

      See https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
      for the current list of supported models and minimum prefix sizes. | false | | | `cacheTTL` _string_ | CacheTTL controls how long Bedrock retains a cached prefix when
      PromptCaching is enabled. Only meaningful when PromptCaching is true.

      - "5m" (default): Bedrock's standard 5-minute sliding cache. Each cache
      hit refreshes the window. Supported by all prompt-caching models.
      - "1h": extended-TTL caching, useful for tasks whose Converse calls are
      spaced more than 5 minutes apart.

      NOTE: "1h" is NOT strictly better than "5m". Extended-TTL cache writes are
      billed at a higher per-token rate than 5-minute writes, and 1h is supported
      on a narrower set of models. Only choose "1h" when calls are spaced far
      enough apart that a 5-minute cache would expire between them; otherwise the
      higher write cost is wasted. See the AWS prompt-caching docs above. | 5m | Enum: [5m 1h]
      | | `guardrail` _[BedrockGuardrailConfig](#bedrockguardrailconfig)_ | | | | @@ -339,7 +339,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `endpoint` _string_ | Endpoint is the Foundry or Azure AI Services account endpoint
      (e.g., https://my-account.cognitiveservices.azure.com/).
      Mutually exclusive with EndpointFrom. | | | -| `endpointFrom` _[ConfigMapKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#configmapkeyselector-v1-core)_ | EndpointFrom resolves the Foundry endpoint from a ConfigMap key, such as
      one written by Azure Service Operator. Mutually exclusive with Endpoint.

      The selector's optional flag only controls how a missing key is handled: when
      set to true, the missing key is ignored while reading the ConfigMap, but a
      Foundry endpoint must always be supplied, so an unresolved endpointFrom still
      leaves the model unusable and the agent fails to start. | | | +| `endpointFrom` _[ConfigMapKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#configmapkeyselector-v1-core)_ | EndpointFrom resolves the Foundry endpoint from a ConfigMap key, such as
      one written by Azure Service Operator. Mutually exclusive with Endpoint.

      The selector's optional flag only controls how a missing key is handled: when
      set to true, the missing key is ignored while reading the ConfigMap, but a
      Foundry endpoint must always be supplied, so an unresolved endpointFrom still
      leaves the model unusable and the agent fails to start. | | | | `deployment` _string_ | Deployment is the Foundry model deployment name. | | | | `apiVersion` _string_ | APIVersion is the Foundry OpenAI-compatible data-plane API version.
      Ignored when APIFormat is Anthropic (the Messages surface is versioned via
      the anthropic-version header instead). | 2024-10-21 | | | `apiFormat` _[FoundryAPIFormat](#foundryapiformat)_ | APIFormat selects the Foundry API format: "OpenAI" (default, chat
      completions) or "Anthropic" (Claude models served over the Anthropic
      Messages API). | OpenAI | Enum: [OpenAI Anthropic]
      | @@ -427,7 +427,7 @@ Harness defines a reusable agent runtime and infrastructure policy. | `kind` _string_ | `Harness` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[HarnessSpec](#harnessspec)_ | | | | | `status` _[HarnessStatus](#harnessstatus)_ | | | | @@ -441,7 +441,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#labelselector-v1-meta)_ | Selector selects admitted AgentTemplates in the Harness namespace. | | | +| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#labelselector-v1-meta)_ | Selector selects admitted AgentTemplates in the Harness namespace. | | | #### HarnessCapabilities @@ -478,7 +478,7 @@ _Appears in:_ | --- | --- | --- | --- | | `name` _string_ | | | MinLength: 1
      | | `value` _string_ | Value is a literal value, including an empty string. | | | -| `credentialRef` _[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#secretkeyselector-v1-core)_ | CredentialRef references a key in a same-namespace Secret. | | | +| `credentialRef` _[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#secretkeyselector-v1-core)_ | CredentialRef references a key in a same-namespace Secret. | | | #### HarnessSnapshotPolicy @@ -520,7 +520,7 @@ _Appears in:_ | --- | --- | --- | --- | | `observedGeneration` _integer_ | ObservedGeneration is the latest Harness generation observed by the controller. | | | | `capabilities` _[HarnessCapabilities](#harnesscapabilities)_ | Capabilities is the single capability record for the selected runtime. | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions report adapter and dependency health. | | MaxItems: 8
      | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | Conditions report adapter and dependency health. | | MaxItems: 8
      | #### HarnessSubstratePolicy @@ -531,7 +531,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `workerPoolRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core)_ | WorkerPoolRef references a WorkerPool in the Harness namespace. | | | +| `workerPoolRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core)_ | WorkerPoolRef references a WorkerPool in the Harness namespace. | | | | `snapshotPolicy` _[HarnessSnapshotPolicy](#harnesssnapshotpolicy)_ | SnapshotPolicy configures runtime snapshot storage. | | | #### HarnessWorkload @@ -567,7 +567,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `modelConfigRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core)_ | ModelConfigRef references the embedding ModelConfig in the Harness namespace. | | | +| `modelConfigRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core)_ | ModelConfigRef references the embedding ModelConfig in the Harness namespace. | | | | `ttlDays` _integer_ | TTLDays controls how many days a stored memory entry remains valid. | | Minimum: 1
      | #### MCPTool @@ -589,7 +589,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `server` _[TypedLocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#typedlocalobjectreference-v1-core)_ | | | | +| `server` _[TypedLocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#typedlocalobjectreference-v1-core)_ | | | | | `tools` _string array_ | Tools optionally limits which server tools are exposed. An omitted or empty
      list exposes every tool. Harnesses that cannot enforce a partial selection
      may expose the whole server and report a warning. | | MaxItems: 50
      | | `requireApproval` _boolean_ | RequireApproval pauses before each invocation of a tool exposed by this
      binding. It applies to the selected tools, or to every server tool when
      Tools is omitted or empty. | | | @@ -603,7 +603,7 @@ ModelConfig is the Schema for the modelconfigs API. | `kind` _string_ | `ModelConfig` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[ModelConfigSpec](#modelconfigspec)_ | | | | | `status` _[ModelConfigStatus](#modelconfigstatus)_ | | | | @@ -643,7 +643,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | | | `observedGeneration` _integer_ | | | | | `secretHash` _string_ | The secret hash stores a hash of any secrets required by the model config (i.e. api key, tls cert) to ensure agents referencing this model config detect changes to these secrets and restart if necessary. | | | @@ -684,7 +684,7 @@ It represents a model provider configuration with automatic model discovery. | `kind` _string_ | `ModelProviderConfig` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[ModelProviderConfigSpec](#modelproviderconfigspec)_ | | | | | `status` _[ModelProviderConfigStatus](#modelproviderconfigstatus)_ | | | | @@ -711,10 +711,10 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `observedGeneration` _integer_ | ObservedGeneration reflects the generation of the most recently observed ModelProviderConfig spec | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions represent the latest available observations of the ModelProviderConfig's state | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | Conditions represent the latest available observations of the ModelProviderConfig's state | | | | `discoveredModels` _string array_ | DiscoveredModels is the cached list of model IDs available from this model provider | | | | `modelCount` _integer_ | ModelCount is the number of discovered models (for kubectl display) | | | -| `lastDiscoveryTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#time-v1-meta)_ | LastDiscoveryTime is the timestamp of the last successful model discovery | | | +| `lastDiscoveryTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#time-v1-meta)_ | LastDiscoveryTime is the timestamp of the last successful model discovery | | | | `secretHash` _string_ | SecretHash is a hash of the referenced secret data, used to detect secret changes | | | #### OllamaConfig @@ -806,7 +806,7 @@ RemoteMCPServer is the Schema for the RemoteMCPServers API. | `kind` _string_ | `RemoteMCPServer` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[RemoteMCPServerSpec](#remotemcpserverspec)_ | | | | | `status` _[RemoteMCPServerStatus](#remotemcpserverstatus)_ | | | | @@ -838,8 +838,8 @@ _Appears in:_ | `protocol` _[RemoteMCPServerProtocol](#remotemcpserverprotocol)_ | | STREAMABLE_HTTP | Enum: [SSE STREAMABLE_HTTP]
      | | `url` _string_ | | | MinLength: 1
      | | `headersFrom` _[ValueRef](#valueref) array_ | | | | -| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#duration-v1-meta)_ | | 30s | | -| `sseReadTimeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#duration-v1-meta)_ | | | | +| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#duration-v1-meta)_ | | 30s | | +| `sseReadTimeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#duration-v1-meta)_ | | | | | `terminateOnClose` _boolean_ | | true | | | `allowedNamespaces` _[AllowedNamespaces](#allowednamespaces)_ | AllowedNamespaces defines which namespaces are allowed to reference this RemoteMCPServer.
      This follows the Gateway API pattern for cross-namespace route attachments.
      If not specified, only Agents in the same namespace can reference this RemoteMCPServer.
      See: https://gateway-api.sigs.k8s.io/guides/multiple-ns/#cross-namespace-route-attachment

      A cross-namespace-permitting value (from: All or from: Selector) is
      mutually exclusive with spec.tls.caCertSecretRef (enforced by a spec-level
      XValidation rule): a pinned CA Secret is mounted onto the consuming agent's
      pod by bare name and Kubernetes resolves it in the agent's namespace, not
      this RemoteMCPServer's, so a CA-pinning RemoteMCPServer cannot be referenced
      cross-namespace. from: Same (the default) is always allowed. | | | | `tls` _[TLSConfig](#tlsconfig)_ | TLS configuration for the upstream MCP server connection.
      Use this for HTTPS upstreams that present a certificate the agent's
      system trust store does not include (corporate CA, self-signed cert
      on a test fixture, internal MCP gateway). Reuses the same TLSConfig
      type as ModelConfig.spec.tls — disableVerify turns off certificate
      validation entirely, caCertSecretRef + caCertSecretKey point at a
      PEM bundle Secret in the same namespace, and disableSystemCAs
      trusts only the named bundle.

      Note one asymmetry with ModelConfig: a spec-level XValidation rule
      on RemoteMCPServer rejects spec.tls when spec.url has the http://
      scheme (a TLS opinion contradicts a plaintext URL). ModelConfig has
      no equivalent rule, so a TLS block can sit alongside any baseUrl. | | | @@ -854,7 +854,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `observedGeneration` _integer_ | INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
      Important: Run "make" to regenerate code after modifying this file | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | | | `discoveredTools` _[MCPTool](#mcptool) array_ | | | | | `secretHash` _string_ | SecretHash stores a hash of the TLS Secret referenced by spec.tls so
      agents that consume this RemoteMCPServer can detect cert rotation and
      roll on the next reconcile. Empty when spec.tls.caCertSecretRef is unset. | | | diff --git a/docs-site/content/kagent/1.x/reference/versions.md b/docs-site/content/kagent/1.x/reference/versions.md index 68752842..22ebb10b 100644 --- a/docs-site/content/kagent/1.x/reference/versions.md +++ b/docs-site/content/kagent/1.x/reference/versions.md @@ -42,10 +42,8 @@ kagent 1.0 is a deliberate clean break from the 0.10.x line, and the compatibili Moving from 0.10.x therefore means standing up a new installation and recreating your resources on it, rather than running `helm upgrade`. For the procedure, see [Upgrade]({{< link path="operations/upgrade" >}}). diff --git a/docs-site/layouts/_shortcodes/gloss.html b/docs-site/layouts/_shortcodes/gloss.html index cb5dcec4..652029c8 100644 --- a/docs-site/layouts/_shortcodes/gloss.html +++ b/docs-site/layouts/_shortcodes/gloss.html @@ -10,9 +10,15 @@ rel="noopener" while doing so. An internal, root-relative link opens in place like every other link on the page. + Data lookup: the glossary reads hugo.Data, where upstream still reads + site.Data. Hugo deprecated .Site.Data in v0.156.0 and will remove it in + a later release. This file shadows upstream's, so an extras-side rename + never reaches this template — the override must carry the rename itself + or break when the removal lands. Re-sync when extras converts. + Everything else is byte-for-byte identical to upstream v0.2.0. */ -}} {{- $key := .Get 0 -}} -{{- $entry := index site.Data.glossary $key -}} +{{- $entry := index hugo.Data.glossary $key -}} {{- if $entry -}} {{ .Inner | default $key }}{{ $key }}{{ $entry.short }}{{- if $entry.link }}Learn more{{- end }} {{- else -}} diff --git a/docs-site/layouts/_shortcodes/glossary-list.html b/docs-site/layouts/_shortcodes/glossary-list.html index 45c254e7..0e902578 100644 --- a/docs-site/layouts/_shortcodes/glossary-list.html +++ b/docs-site/layouts/_shortcodes/glossary-list.html @@ -8,7 +8,7 @@ Sorted case-insensitively, so "gVisor" lands with the g's rather than last. Each
      carries an anchorized id, so a term is linkable. */ -}} {{- $terms := slice -}} -{{- range $key, $entry := site.Data.glossary -}} +{{- range $key, $entry := hugo.Data.glossary -}} {{- $terms = $terms | append (dict "key" $key "short" $entry.short "link" $entry.link "sortKey" (lower $key)) -}} {{- end -}}
      diff --git a/public/docs/versions/max-kube.md b/public/docs/versions/max-kube.md index 92443952..f71ef947 100644 --- a/public/docs/versions/max-kube.md +++ b/public/docs/versions/max-kube.md @@ -1 +1 @@ -1.31 \ No newline at end of file +1.35 \ No newline at end of file From 2284226c94194b7ac79e6803c0b666c7341cce5a Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 14 Sep 2026 12:42:38 -0500 Subject: [PATCH 66/70] BYO Signed-off-by: Rachael Graham --- .../content/kagent/1.x/about/architecture.md | 4 +- .../kagent/1.x/agents/bring-your-own-agent.md | 194 ++++++++++++++ .../content/kagent/1.x/examples/a2a-byo.md | 250 ++++++++++++++++++ .../kagent/1.x/substrate-runtime/identity.md | 2 +- 4 files changed, 447 insertions(+), 3 deletions(-) create mode 100644 docs-site/content/kagent/1.x/agents/bring-your-own-agent.md create mode 100644 docs-site/content/kagent/1.x/examples/a2a-byo.md diff --git a/docs-site/content/kagent/1.x/about/architecture.md b/docs-site/content/kagent/1.x/about/architecture.md index 735f6b0e..2b4f3cb5 100644 --- a/docs-site/content/kagent/1.x/about/architecture.md +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -14,7 +14,7 @@ kagent 1.0 splits authorization across two planes: - The **Kubernetes plane** governs the {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} custom resources. Kubernetes Role-Based Access Control (RBAC) decides who can create, read, or edit the resources with `kubectl`, exactly as it would for any other Custom Resource Definition (CRD). - The **kagent plane** governs any interactions involving {{< gloss "AgentInstance" >}}AgentInstances{{< /gloss >}}, such as creating, suspending, resuming, sharing, deleting, and holding a conversation with an AgentInstance. kagent's own gRPC authentication and authorization decide who can complete these interactions, independent of Kubernetes RBAC. -Someone with Kubernetes RBAC access to apply a Harness and AgentTemplate does not automatically have access to create or talk to AgentInstances that use them. The planes are not mirror images, though. kagent's gRPC API also writes Harness and AgentTemplate resources, so a caller on the kagent plane reaches both. For more information on that second path, see [Identity]({{< link path="substrate-runtime/identity" >}}). +Someone with Kubernetes RBAC access to apply a Harness and AgentTemplate does not automatically have access to create or talk to AgentInstances that use them. The planes are not mirror images, though. kagent's gRPC API also writes Harness and AgentTemplate resources, so a caller on the kagent plane reaches both. For more information on that second path, see [Identity]({{< link path="substrate-runtime/identity#the-kubernetes-plane" >}}). The following diagram shows where the boundary between the two planes falls.

      @@ -63,7 +63,7 @@ flowchart TB class harness,template crd ``` -Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate with `kubectl`, governed by Kubernetes RBAC. The diagram shows this path because RBAC governs it, and `kagent apply` reaches the same two resources over gRPC instead. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. The ActorTemplate sits outside both planes in the diagram because that is where it sits in reality: it is a Substrate resource that the controller creates over gRPC, not a Kubernetes object, so no Kubernetes role grants access to it. +Follow the **Kubernetes plane** first. An operator applies a Harness and an AgentTemplate with `kubectl`, governed by Kubernetes RBAC. The diagram shows this path because RBAC governs it, and kagent's gRPC API reaches the same two resources instead. The kagent controller watches for a valid pair with a matching `allowedAgentTemplates` selector, and compiles it into an {{< gloss "ActorTemplate" >}}ActorTemplate{{< /gloss >}} on Substrate. The ActorTemplate sits outside both planes in the diagram because that is where it sits in reality: it is a Substrate resource that the controller creates over gRPC, not a Kubernetes object, so no Kubernetes role grants access to it. The **kagent plane** starts once that ActorTemplate exists. A caller, who may or may not be the same person as the operator, calls `CreateAgentInstance` through kagent's gRPC API. This call is governed by kagent's own authentication and authorization, not by Kubernetes RBAC. kagent creates the AgentInstance from the newest ActorTemplate that compiled successfully, and that AgentInstance runs on an {{< gloss "Actor" >}}Actor{{< /gloss >}}. diff --git a/docs-site/content/kagent/1.x/agents/bring-your-own-agent.md b/docs-site/content/kagent/1.x/agents/bring-your-own-agent.md new file mode 100644 index 00000000..83a97e62 --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/bring-your-own-agent.md @@ -0,0 +1,194 @@ +--- +title: Bring your own agent +description: Run a container image of your own as a kagent agent by implementing the A2A service that the byo runtime expects. +weight: 20 +author: kagent.dev +--- + +The `byo` runtime runs a container image that you build, and treats what is inside it as opaque. kagent still compiles the {{< gloss "Harness" >}}Harness{{< /gloss >}} and {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} into a {{< gloss "Revision" >}}revision{{< /gloss >}}, schedules that revision onto {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}}, and routes conversations to it. What the image does with a message is yours to decide. Choose this runtime when you have an agent framework that kagent does not adapt, and you would rather bring the image than the integration. + +## What kagent runs and what your image runs + +The `byo` runtime divides the work at the {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) boundary. Everything on kagent's side of that boundary behaves in the same way as for the built-in runtimes, so a BYO agent is sandboxed, snapshotted, and addressed identically to one that kagent executes itself. + +kagent owns the lifecycle, the isolation, and the routing: + +- Compiles a Harness and an AgentTemplate into an immutable revision, and creates an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} from it. +- Wraps the {{< gloss "Actor" >}}Actor{{< /gloss >}} that the image runs in with a [gVisor sandbox]({{< link path="substrate-runtime/sandboxing#sandbox-classes" >}}). +- [Suspends and resumes]({{< link path="substrate-runtime/suspend-and-resume#suspension-between-turns" >}}) the Actor between turns, including its in-memory state. +- Routes every conversation through the A2A gateway, so callers address the AgentInstance rather than the Actor behind it. +- Delivers the compiled agent configuration and agent card to the container as environment variables. + +Your image owns the agent's behavior and the two endpoints that expose it: + +- An A2A service that accepts a message and returns a reply. +- A readiness endpoint that reports when the service can take traffic. +- Whatever the agent actually does: model calls, tool calls, and conversation state. + +Because Agent Substrate snapshots the whole Actor, an image that keeps conversation state in memory keeps it across a suspend. Your image does not need to persist anything to survive the gap between turns. + +## The A2A contract + +A `byo` image must meet four requirements to run as an agent. kagent enforces only `spec.workload.command` at apply time, and the rest surface as a failed invoke rather than as a validation error. The steps in the [Configure a byo Harness](#configure-a-byo-harness) and [Build the image](#build-the-image) sections later in this page show how to satisfy each requirement. + +| Requirement | Detail | +| ----------- | ------ | +| `spec.workload.command` is set on the Harness | A `byo` Harness must override the image entrypoint, because kagent does not infer it. | +| The container serves gRPC on port 80 | kagent builds the agent card with a single interface, `http://127.0.0.1:80` bound to gRPC, and that address is not configurable. The service is `lf.a2a.v1.A2AService`. | +| The container answers `GET /readyz` on port 8081 | Agent Substrate probes this path to decide when the Actor is ready, with a 30-second timeout. The probe is on a different port from the A2A service on purpose, so serve it independently. | +| The A2A service speaks gRPC, not JSON-RPC | The agent card fixes the protocol binding to gRPC. An image that serves A2A over JSON-RPC alone is never reached, whatever port it listens on. | + +> [!WARNING] +> **A `byo` Harness injects no `PORT` variable, and an image that listens elsewhere still reports `READY`.** Readiness is probed on port 8081, which succeeds no matter what the A2A service does, so nothing surfaces the mismatch until an invoke fails with `Connect: tunnel failed`. Either pin port 80 in the image, or set `PORT` in the Harness's `spec.env` as the examples on this page do. This gap is tracked as [kagent#2758](https://github.com/kagent-dev/kagent/issues/2758). + +## Opaque and configured agents + +kagent compiles an AgentTemplate for a `byo` Harness in the same way as for the `kagent` runtime, then hands the result to the container as environment variables. The two ways of using this runtime differ only in whether the image reads them. + +- **An opaque agent ignores the compiled configuration.** The AgentTemplate exists to give the agent an identity and a description, and the image decides everything else, including which model to call and which tools to offer. Every field on an opaque AgentTemplate is optional, `modelConfig` included. +- **A configured agent reads the compiled configuration.** The image honors the AgentTemplate's system prompt, ModelConfig, tool bindings, skills, and plugins, so an operator changes the agent's behavior by editing the AgentTemplate rather than by rebuilding the image. + +The `kagent` and `byo` runtimes compile through the same path, so a configured BYO agent accepts the same model providers and the same AgentTemplate features as the built-in runtime. For the provider matrix, see [Model provider support]({{< link path="agents/agent-harness#model-provider-support" >}}). For what an AgentTemplate can bind, see [Tool and skill support]({{< link path="agents/agent-harness#tool-and-skill-support" >}}). + +Both kinds of agent receive the same variables. + +| Variable | Contents | +| -------- | -------- | +| `KAGENT_CONFIG_JSON` | The compiled agent configuration: the resolved system prompt, the model and its settings, and every tool, skill, and plugin that the AgentTemplate binds. | +| `KAGENT_AGENT_CARD_JSON` | The agent card that kagent advertises for this agent, rendered as JSON. | +| `KAGENT_NAMESPACE` and `KAGENT_NAME` | The AgentTemplate's namespace and name, which kagent's own helpers use to scope sessions. | +| Anything in `spec.env` | Literal values and `credentialRef` lookups from the Harness, resolved before the Actor starts. | + +> [!NOTE] +> Agent Substrate accepts at most 32 environment variables on an Actor, and the compiled configuration counts toward that limit. A revision that exceeds it fails to compile rather than starting and misbehaving. + +## Configure a BYO Harness + +A `byo` Harness takes the same fields as any other, minus the runtime settings block. `spec.byo` is an empty object, because the runtime has nothing to configure. The image holds the behavior. + +```yaml +kubectl apply -f - </my-agent@sha256: + command: ["/my-agent"] + env: + - name: PORT + value: "80" + substrate: + workerPoolRef: + name: kagent-default + snapshotPolicy: + location: gs:///kagent/ + allowedAgentTemplates: + selector: + matchLabels: + kagent.dev/harness: my-byo-harness +EOF +``` + +{{< reuse "kagent-docs/snippets/review-table.md" >}} For the fields that every Harness shares, see [Configure a Harness]({{< link path="agents/agent-harness#configure-a-harness" >}}). + +| Field | Required | Description | +| ----- | -------- | ----------- | +| `byo` | Yes | Selects this runtime. The object is always empty, and naming a second runtime alongside it is rejected. | +| `workload.image` | Yes | Your image, pinned by `sha256` digest. A tag alone is rejected, because a revision must be reproducible. | +| `workload.command` | Yes | The entrypoint to run, up to 32 entries. Required for `byo` and optional for every other runtime. | +| `env` | No | Set `PORT` here unless the image pins port 80 itself. | + +An opaque agent's AgentTemplate carries only the label that the Harness selects on, plus a description for the agent card. + +```yaml +kubectl apply -f - <}}). + +## Build the image + +The A2A contract is a gRPC service and a readiness endpoint, so any language with a gRPC server can satisfy it. kagent ships helpers for two of them. To build and run a minimal image end to end before writing your own, see [Run your own agent image]({{< link path="examples/a2a-byo" >}}). + +> [!TIP] +> The Go helper produces smaller images, faster startup, and lower memory use than the Python one. Where both suit the agent that you are building, prefer Go. + +{{< tabs >}} +{{% tab name="Go" %}} +`github.com/kagent-dev/kagent/go/adk/pkg/app` serves the A2A gRPC service, the readiness endpoint on 8081, and the agent card, given any type that implements `a2asrv.AgentExecutor`. The helper is framework-agnostic, so the executor is the only part that you write. + +```go +application, err := app.New(app.AppConfig{ + AgentCard: a2atype.AgentCard{ + Name: "my-agent", + Version: "v1", + Capabilities: a2atype.AgentCapabilities{Streaming: true}, + }, + Port: "80", + AppName: "my-agent", + Logger: logger, +}, myExecutor{}) +if err != nil { + return err +} +return application.Run() +``` + +Setting `Port` to `80` keeps this image working without a `PORT` variable on the Harness. Omitting it falls back to the `PORT` environment variable and then to a default of `8080`, which kagent never dials. + +For a complete executor, see [`go/core/test/byoa2a/main.go`](https://github.com/kagent-dev/kagent/blob/main/go/core/test/byoa2a/main.go) in the kagent repository. +{{% /tab %}} +{{% tab name="Python" %}} +The `kagent-adk` package serves A2A over gRPC, defaulting its listener to `[::]:80` and its readiness endpoint to 8081. The default address matches what kagent dials, so a Python image needs no `PORT` variable on the Harness. + +```python +from kagent.adk import KAgentApp + +app = KAgentApp( + root_agent_factory=build_agent, + agent_card=card, + kagent_api_url=os.environ["KAGENT_URL"], + app_name="my-agent", +).build() +``` + +`KAgentApp` wraps a Google Agent Development Kit (ADK) agent rather than an arbitrary framework. Override the listener with the `KAGENT_A2A_GRPC_ADDRESS` environment variable, or the `a2a_grpc_address` argument. +{{% /tab %}} +{{% tab name="Any other language" %}} +Implement the contract directly: + +1. Serve `lf.a2a.v1.A2AService` over gRPC on port 80. Generate the stubs from the [A2A protocol](https://a2a-protocol.org) definitions. +2. Serve `GET /readyz` over HTTP on port 8081, returning `200`. +3. Read `KAGENT_CONFIG_JSON` if the agent should honor its AgentTemplate, or ignore it and run an opaque agent. +{{% /tab %}} +{{< /tabs >}} + +## Known limitations + +- **The A2A interface is fixed.** kagent advertises `http://127.0.0.1:80` over gRPC, and `spec.byo` takes no field to change the address, the port, or the protocol. An image that serves A2A over HTTP JSON-RPC alone cannot run on this runtime. +- **The `kagent-langgraph` and `kagent-crewai` adapters do not qualify yet.** Both build a FastAPI application with A2A JSON-RPC routes and no gRPC server, so neither satisfies the contract as shipped. Running LangGraph or CrewAI under `byo` currently means serving A2A over gRPC yourself. +- **Long-term memory is unavailable.** Memory is configured under `spec.kagent.memory` and wired only by the `kagent` runtime's compiler. A `byo` Harness has no equivalent setting. For what a BYO image would need to replace, see [Agent memory]({{< link path="agents/agent-memory" >}}). +- **A broken port mapping presents as a healthy agent.** Readiness passes on 8081 regardless of the A2A service, so the AgentInstance reports `READY` and every invoke fails. This is [kagent#2758](https://github.com/kagent-dev/kagent/issues/2758). + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="examples/a2a-byo" >}}` title="Run your own agent image" subtitle="Build the minimal BYO agent, run it on a byo Harness, and invoke it." >}} + {{< card link=`{{< link path="agents/agent-harness" >}}` title="Agent harness" subtitle="Compare the byo runtime against the three that kagent executes itself." >}} + {{< card link=`{{< link path="examples/a2a-agents" >}}` title="Call an agent over A2A" subtitle="Send messages to an AgentInstance with the same protocol that a BYO image serves." >}} + {{< card link=`{{< link path="substrate-runtime/suspend-and-resume" >}}` title="Suspend and resume" subtitle="Understand what Agent Substrate snapshots while your image is idle." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/examples/a2a-byo.md b/docs-site/content/kagent/1.x/examples/a2a-byo.md new file mode 100644 index 00000000..6fee9c88 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/a2a-byo.md @@ -0,0 +1,250 @@ +--- +title: Run your own agent image +description: Build a minimal BYO agent image, run it on a byo Harness, and invoke it the same way as any other kagent agent. +weight: 70 +author: kagent.dev +--- + +The `byo` runtime runs a container image that you build, so long as the image implements kagent's {{< gloss "A2A" >}}A2A{{< /gloss >}} (Agent-to-Agent) contract. This example takes the shortest path through that contract: build the minimal BYO agent that kagent tests itself against, run it on a {{< gloss "Harness" >}}Harness{{< /gloss >}}, and invoke it. + +The agent that you build here calls no model and binds no tools. It answers every message with a fixed string, which makes it a poor agent and a clear demonstration: everything that happens between `kagent invoke` and that reply is kagent's half of the contract. To review the contract and the configured agents that read their AgentTemplate instead of ignoring it, see [Bring your own agent]({{< link path="agents/bring-your-own-agent" >}}). + +## Before you begin + +1. [Install kagent]({{< link path="setup/installation#verify-the-installation" >}}), including the port-forward to the controller's gRPC API. + +2. [Create your first agent]({{< link path="get-started/your-first-agent" >}}) so that you have a Harness and AgentTemplate pair to model this one on, and a snapshot location to reuse. + +3. Install the following tools. + * [Docker](https://docs.docker.com/get-started/get-docker/) + * [git](https://git-scm.com/downloads) + +4. Export the container registry that your cluster can pull from. For example, a local kind cluster created with `make create-kind-cluster` runs one on `localhost:5001`. + ```bash + export DOCKER_REGISTRY=localhost:5001 + ``` + +5. Know which {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} and snapshot location your installation uses. The Harness that you created carries both. + ```bash + kubectl get harness my-first-harness -n kagent \ + -o custom-columns=WORKERPOOL:.spec.substrate.workerPoolRef.name,SNAPSHOT:.spec.substrate.snapshotPolicy.location + ``` + + Example output: + ```console + WORKERPOOL SNAPSHOT + kagent-default gs://your-bucket/kagent/ + ``` + +## Build the agent image + +kagent's own end-to-end suite runs an opaque BYO agent from `go/core/test/byoa2a/main.go`, and the repository has a make target that builds it. Building that image rather than writing one from scratch means starting from a version that is proven against the current contract. + +1. Clone the kagent repository and navigate to it. + ```bash + git clone https://github.com/kagent-dev/kagent.git + cd kagent + ``` + +2. Build the image and push it to your registry. The target builds `go/core/test/byoa2a/main.go` with the repository's Go Dockerfile, which produces a single binary at `/app`. + ```bash + make build-byo-a2a DOCKER_REGISTRY=$DOCKER_REGISTRY VERSION=byo-example + ``` + +3. Resolve the digest, and save the pinned reference. A Harness rejects an image that names only a tag, because a {{< gloss "Revision" >}}revision{{< /gloss >}} must be reproducible. + ```bash + export BYO_IMAGE=$DOCKER_REGISTRY/kagent-dev/kagent/byo-a2a@$(docker buildx imagetools inspect \ + $DOCKER_REGISTRY/kagent-dev/kagent/byo-a2a:byo-example \ + | awk '$1 == "Digest:" { print $2; exit }') + echo $BYO_IMAGE + ``` + + Example output: + ```console + localhost:5001/kagent-dev/kagent/byo-a2a@sha256:ea596db3dac8da570980143210efeb2b47bcfb0a3afc5aa0f325a6063c5cf009 + ``` + +## Create the Harness and the AgentTemplate + +A `byo` Harness carries two fields that the other runtimes do not need: an empty `byo` block to select the runtime, and `workload.command` to override the image entrypoint. The AgentTemplate stays almost empty, because this agent ignores everything that an AgentTemplate would configure. + +1. Create the Harness. The repository's Go Dockerfile puts the binary at `/app`, so `command` names that path. + ```yaml + kubectl apply -f - </kagent/ + allowedAgentTemplates: + selector: + matchLabels: + kagent.dev/harness: byo-example + EOF + ``` + + > [!NOTE] + > This Harness sets no `PORT` variable, because `byoa2a/main.go` pins `Port: "80"` in the image. An image that leaves the port to kagent listens on the wrong one and still reports `READY`. For that trap and its workaround, see [Bring your own agent]({{< link path="agents/bring-your-own-agent#the-a2a-contract" >}}). + +2. Create the AgentTemplate. The Harness's selector matches on the label, and `description` is the only other field that this agent needs. + ```yaml + kubectl apply -f - <}}AgentInstance{{< /gloss >}} is the conversation, the CLI reaches it through the controller's A2A service, and nothing in these commands names the runtime. + +1. Create an AgentInstance from the Harness and the AgentTemplate. + ```bash + kagent create agent-instance --harness byo-example --agent-template byo-example-agent + ``` + + The command returns only after the AgentInstance reaches `READY`. Example output: + ```console + +--------------------------------------+-------------------+-------------+-------+----------------------+ + | ID | AGENT TEMPLATE | HARNESS | STATE | CREATED | + +--------------------------------------+-------------------+-------------+-------+----------------------+ + | 01a08301-8cd0-72c8-818f-26c7490ce37d | byo-example-agent | byo-example | READY | 2026-09-14T14:22:07Z | + +--------------------------------------+-------------------+-------------+-------+----------------------+ + ``` + +2. Save the AgentInstance ID. + ```bash + export INSTANCE_ID=$(kagent get agent-instance -o json \ + | jq -r '[.agentInstances[] | select(.agentTemplate.name == "byo-example-agent")] | sort_by(.createdAt) | last | .id') + ``` + +3. Send it a message. + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "hello" + ``` + + Example output: + ```console + BYO agent response + ``` + + That string is hardcoded, so the reply itself proves nothing. Its path proves the contract: kagent compiled a revision, Agent Substrate started a sandboxed {{< gloss "Actor" >}}Actor{{< /gloss >}} from your image, the controller's A2A gateway routed the message to it, and your executor answered. + +4. Send another message to the same AgentInstance. The reply does not change, but the message reaches the same Actor. Agent Substrate suspended that Actor after the first turn and resumed it for this one. For that cycle, see [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume#suspension-between-turns" >}}). + ```bash + kagent invoke --agent-instance $INSTANCE_ID --task "hello again" + ``` + +## Change what the agent does + +The whole agent is one type with two methods. `Execute` receives a request and yields A2A events until the turn ends, and `Cancel` handles a caller stopping a task that is still running. + +```go +type executor struct{} + +func (executor) Execute(_ context.Context, request *a2asrv.ExecutorContext) iter.Seq2[a2atype.Event, error] { + return func(yield func(a2atype.Event, error) bool) { + if !yield(a2atype.NewSubmittedTask(request, request.Message), nil) { + return + } + message := a2atype.NewMessage(a2atype.MessageRoleAgent, a2atype.NewTextPart("BYO agent response")) + message.ContextID, message.TaskID = request.ContextID, request.TaskID + yield(a2atype.NewStatusUpdateEvent(request, a2atype.TaskStateCompleted, message), nil) + } +} + +func (executor) Cancel(context.Context, *a2asrv.ExecutorContext) iter.Seq2[a2atype.Event, error] { + return func(func(a2atype.Event, error) bool) {} +} +``` + +Two events make a complete turn. `NewSubmittedTask` acknowledges the message and opens the task, and a `TaskStateCompleted` status update carrying an agent message ends it. Between them, a real agent yields whatever its work produces. + +`app.New` serves the A2A gRPC service and the readiness endpoint on your behalf, and the `Port: "80"` line keeps the listener where kagent expects it. Both stay as they are in an agent of your own. + +To read the AgentTemplate rather than ignore it, parse the `KAGENT_CONFIG_JSON` variable that kagent sets on the container. For what that variable holds, see [Bring your own agent]({{< link path="agents/bring-your-own-agent#opaque-and-configured-agents" >}}). + +## Build and run your own agent + +An agent of your own takes the same path as the example image, with two differences: the build names your package, and the Harness moves to the image that it produces. + +1. Replace the body of `Execute` with the work that your agent does, and leave the rest of the file as-is. + +2. Build and push the image. The `build-byo-a2a` target names its package inline, so a package of your own means calling Docker directly. The Dockerfile takes the package as a build argument, relative to the `go` directory. + ```bash + docker build --build-arg BUILD_PACKAGE=core/test/myagent/main.go \ + -t $DOCKER_REGISTRY/kagent-dev/kagent/my-agent:v1 -f go/Dockerfile ./go + docker push $DOCKER_REGISTRY/kagent-dev/kagent/my-agent:v1 + ``` + + That Dockerfile copies `api`, `core`, `adk`, `harness`, and `pkg` from the kagent module, so it suits an agent written inside a checkout. An agent in a module of your own needs a Dockerfile of your own. kagent places no requirement on how the image is built, only on what it serves. + +3. Resolve the digest of the new image, as in [Build the agent image](#build-the-agent-image). A Harness rejects an image that names only a tag. + ```bash + export BYO_IMAGE=$DOCKER_REGISTRY/kagent-dev/kagent/my-agent@$(docker buildx imagetools inspect \ + $DOCKER_REGISTRY/kagent-dev/kagent/my-agent:v1 \ + | awk '$1 == "Digest:" { print $2; exit }') + ``` + +4. Point the Harness at the new image. kagent compiles a revision for the updated pair. + ```bash + kubectl patch harness byo-example -n kagent --type=merge \ + -p "{\"spec\":{\"workload\":{\"image\":\"$BYO_IMAGE\"}}}" + ``` + +5. Create an AgentInstance from the updated Harness, and invoke it as in [Invoke the agent](#invoke-the-agent). An AgentInstance pins the revision that it was created from, so the one from earlier keeps running the example image. + ```bash + kagent create agent-instance --harness byo-example --agent-template byo-example-agent + ``` + +## Clean up + +1. Delete the AgentInstance. Repeat for any AgentInstance that you created from an image of your own. + ```bash + kagent delete agent-instance $INSTANCE_ID + ``` + +2. Delete the AgentTemplate and the Harness. + ```bash + kubectl delete agenttemplate byo-example-agent -n kagent + kubectl delete harness byo-example -n kagent + ``` + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="agents/bring-your-own-agent" >}}` title="Bring your own agent" subtitle="Read the full A2A contract and the limits of the byo runtime." >}} + {{< card link=`{{< link path="examples/a2a-agents" >}}` title="Call an agent over A2A" subtitle="Talk to this AgentInstance with grpcurl instead of the CLI." >}} + {{< card link=`{{< link path="examples/agent-substrate" >}}` title="Agent Substrate" subtitle="Watch the Actor behind your image suspend, checkpoint, and fork." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/substrate-runtime/identity.md b/docs-site/content/kagent/1.x/substrate-runtime/identity.md index 324925d3..af417ce5 100644 --- a/docs-site/content/kagent/1.x/substrate-runtime/identity.md +++ b/docs-site/content/kagent/1.x/substrate-runtime/identity.md @@ -15,7 +15,7 @@ A kagent installation authenticates three different kinds of caller, and each on Harness and AgentTemplate are Kubernetes custom resources, so Kubernetes role-based access control (RBAC) governs who can create, read, edit, or delete them with `kubectl`. A cluster's existing roles and bindings decide who authors an agent's runtime and its behavior on that path. -kagent's gRPC API reaches the same two resources by a second path. `kagent apply -f`, and the AgentTemplate and Harness services behind it, create, update, and delete these resources through the kagent controller. The controller writes them with its own service account rather than the caller's, so Kubernetes RBAC never evaluates the caller. The kagent plane authorizes this path instead. +kagent's gRPC API reaches the same two resources by a second path. The AgentTemplate service creates, updates, and deletes AgentTemplates, and the Harness service creates and deletes Harnesses, both through the kagent controller. The `kagent apply -f` command calls the AgentTemplate service, and any client that reaches the gRPC endpoint can call either service. The controller writes these resources with its own service account rather than the caller's, so Kubernetes RBAC never evaluates the caller. The kagent plane authorizes this path instead. > [!WARNING] > Because the open source build's authorizer permits every check, any caller that reaches the gRPC endpoint can author an agent's runtime and behavior, whatever their Kubernetes permissions are. Do not expose port `8083` outside the cluster. From b767fe828a193992dc8cd4de8d409447cce608cc Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Mon, 14 Sep 2026 14:31:01 -0500 Subject: [PATCH 67/70] Upgrade from 0.x Signed-off-by: Rachael Graham --- .../content/kagent/1.x/about/core-concepts.md | 4 +- .../kagent/1.x/operations/upgrade-from-0x.md | 161 ++++++++++++++++++ docs-site/content/kagent/1.x/reference/faq.md | 2 +- .../content/kagent/1.x/reference/versions.md | 2 +- .../content/kagent/1.x/setup/installation.md | 3 + 5 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 docs-site/content/kagent/1.x/operations/upgrade-from-0x.md 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 f1294057..2947d27d 100644 --- a/docs-site/content/kagent/1.x/about/core-concepts.md +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -5,7 +5,9 @@ weight: 20 author: kagent.dev --- -kagent 1.0 replaces the Deployment-based `Agent` custom resource with a new model built around **Harness**, **AgentTemplate**, and **AgentInstance**, running on [Agent Substrate]({{< link path="about/agent-substrate" >}}) instead of the plain Kubernetes Deployments that the 0.x model uses. This page defines the vocabulary that the rest of the 1.0 model docs use. +## kagent 1.0 + +kagent 1.0 replaces the Deployment-based `Agent` custom resource with a new model built around **Harness**, **AgentTemplate**, and **AgentInstance**, running on [Agent Substrate]({{< link path="about/agent-substrate" >}}) instead of the plain Kubernetes Deployments that the 0.x model uses. This page defines the vocabulary that the rest of the 1.0 model docs use. If you already have a 0.x installation, see [Upgrade from 0.x]({{< link path="operations/upgrade-from-0x#recreate-your-resources" >}}), which maps each 0.x resource onto its 1.0 replacement. The new model separates what an agent can do from how it is allowed to run: diff --git a/docs-site/content/kagent/1.x/operations/upgrade-from-0x.md b/docs-site/content/kagent/1.x/operations/upgrade-from-0x.md new file mode 100644 index 00000000..76afe22a --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/upgrade-from-0x.md @@ -0,0 +1,161 @@ +--- +title: Upgrade from 0.x +description: Move an existing kagent 0.10.x installation to 1.0 by standing up a new installation and recreating your resources on it. +weight: 40 +author: kagent.dev +--- + +kagent 1.0 has no in-place upgrade path from the 0.10.x line. Moving to 1.0 means installing kagent fresh against a new database, and recreating your resources on it. When your installation runs 1.0, you can perform regular in-place upgrades for later minor releases. To review upgrade paths and versions, see [Version support]({{< link path="reference/versions#release-support-and-compatibility" >}}). + +## In-place upgrade blockers + +Three independent changes each rule out `helm upgrade`, so working around any one of them does not help. + +| Change | Consequence | +| ------ | ----------- | +| The database schema is a clean baseline | 1.0 replaces golang-migrate with goose and starts from a single baseline migration. An existing 0.10.x database has no bridge to it, and 1.0 refuses to run against one. | +| The custom resources serve one API version | The 1.0 CRDs serve `v1alpha3` alone and declare no conversion strategy, so objects stored as `v1alpha2` cannot be read through them. | +| The resource model is replaced | The `Agent` resource is gone. What it described is now split between an AgentTemplate and a {{< gloss "Harness" >}}Harness{{< /gloss >}}, and a conversation is an {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} created from that pair. For the model itself, see [Core concepts]({{< link path="about/core-concepts" >}}). | + +The two releases also cannot run side by side on one cluster. `modelconfigs.kagent.dev`, `modelproviderconfigs.kagent.dev`, and `remotemcpservers.kagent.dev` exist in both, and a CRD is cluster-scoped, so installing 1.0's CRDs replaces 0.10.x's. A second cluster keeps the old installation intact while you work. + +> [!WARNING] +> Downgrading from 1.0 back to 0.10.x is unsupported. Treat the cutover as one-way, and keep the 0.10.x installation running until you have verified the new one. + +## Before you begin + +1. Read the [kagent releases](https://github.com/kagent-dev/kagent/releases) for the breaking changes in the version that you are moving to, and [Version support]({{< link path="reference/versions#release-support-and-compatibility" >}}) for what 1.0 does and does not promise. + +2. Decide where you will install 1.0. A second cluster is the safer choice, because it leaves your 0.10.x installation untouched. Installing on the same cluster means uninstalling 0.10.x first, and that step is not reversible. + +3. Provision an empty PostgreSQL database for 1.0. It must be a new database rather than a new schema in the old one, and pointing 1.0 at a 0.10.x database fails at startup with a clear error. + ```console + source core uses an unsupported migration table. Use a new PostgreSQL database + ``` + +4. Back up your 0.10.x database. The backup is a restore point for the old installation rather than an input to the new one, because no procedure loads it into 1.0. + ```bash + pg_dump "postgres://:@:5432/" \ + --format=custom \ + --file=kagent-0.10-backup.dump + ``` + +## Export your 0.10.x resources + +Your Kubernetes resources do carry forward, so export them before anything replaces the CRDs. Conversation history does not carry forward. + +1. Export every kagent resource in your namespace. + ```bash + kubectl get agents,agentharnesses,sandboxagents,memories,toolservers,remotemcpservers,modelconfigs,modelproviderconfigs \ + -n kagent -o yaml > kagent-0.10-resources.yaml + ``` + +2. Note which Secrets your ModelConfigs reference. Secrets are ordinary Kubernetes resources that kagent does not own, so recreate them on the new cluster by whatever means you created them originally. + ```bash + kubectl get modelconfigs -n kagent \ + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.apiKeySecret}{"\n"}{end}' + ``` + +## Install kagent 1.0 + +Install 1.0 the same way as a first-time installation, with one addition: point it at the empty database that you provisioned. The full procedure covers Agent Substrate and the identity material that it needs before you install kagent 1.0. + +1. Follow all steps in the [1.0 installation guide]({{< link path="setup/installation" >}}). Set the following Helm values on the kagent install, rather than changing them afterward. + + | Value | Why | + | ----- | --- | + | `database.postgres.url` | Your new database's connection string. Setting it takes precedence over the bundled instance. Use `urlFile` instead to read the string from a file. | + | `database.postgres.bundled.enabled=false` | Turns off the bundled PostgreSQL instance. The bundled instance is for development and evaluation, and it is not suitable for production. | + | `database.postgres.vectorEnabled=true` | Applies the pgvector migrations, which [long-term memory]({{< link path="agents/agent-memory" >}}) depends on. Your database must have the pgvector extension installed. | + + The controller applies migrations at startup. To apply them from a pipeline instead, set `database.postgres.skipMigrations=true` and run `kagent db migrate up` yourself. The controller then verifies the schema and fails if it is not already current. For sizing and connection guidance on the database itself, see [Use an external PostgreSQL instance]({{< link path="operations/operational-considerations#use-an-external-postgresql-instance" >}}). + +2. Verify the schema before continuing. + ```bash + kagent db migrate status --db-url "postgres://:@:5432/" + ``` + +## Recreate your resources + +The export splits into three groups: resources that need only an `apiVersion` change, agents that need rewriting, and resources with no 1.0 equivalent. Work through them in that order, because an AgentTemplate refers to the ModelConfigs and RemoteMCPServers that the first group creates. + +### Resources that carry forward + +ModelConfig, ModelProviderConfig, and RemoteMCPServer have identical fields in `v1alpha2` and `v1alpha3`. + +1. Recreate the Secrets that your ModelConfigs name before you apply them, or the ModelConfigs resolve to nothing. + +2. Change the `apiVersion` and apply the resources unchanged. + ```bash + sed 's|^apiVersion: kagent.dev/v1alpha2$|apiVersion: kagent.dev/v1alpha3|' \ + kagent-0.10-resources.yaml > kagent-1.0-resources.yaml + ``` + +### Agents become an AgentTemplate and a Harness + +A 0.10.x `Agent` described both what the agent does and how it runs. In 1.0 these concepts are separated into two resources: an AgentTemplate holds the agent's behavior, and a Harness holds the runtime and infrastructure. One Harness serves many AgentTemplates, so expect fewer Harnesses than you had Agents. + +| 0.10.x `Agent` field | Equivalent field in 1.0 | +| -------------------- | -------------------- | +| `spec.description` | `AgentTemplate.spec.description` | +| `spec.declarative.systemMessage` | `AgentTemplate.spec.systemPrompt` | +| `spec.declarative.systemMessageFrom` | `AgentTemplate.spec.systemPromptFrom` | +| `spec.declarative.promptTemplate` | `AgentTemplate.spec.promptTemplate`, unchanged | +| `spec.declarative.modelConfig` | `AgentTemplate.spec.modelConfig`, now an object with a `name` rather than a bare string | +| `spec.declarative.tools` | `AgentTemplate.spec.tools`, reshaped. See the following note. | +| `spec.declarative.memory` | `Harness.spec.kagent.memory`, so memory is now a property of the runtime rather than of one agent | +| `spec.declarative.runtime` | `Harness.spec.workload.image`, through the runtime that the Harness selects | +| `spec.declarative.deployment` | `Harness.spec.workload` and `Harness.spec.substrate`. Agents no longer run as Deployments. | +| `spec.type`, `spec.byo` | The `byo` runtime on a Harness. See [Bring your own agent]({{< link path="agents/bring-your-own-agent" >}}). | +| `spec.declarative.a2aConfig` | Nothing. A2A is always on, and callers address an AgentInstance by ID. | +| `spec.iconUrl`, `spec.documentationUrl`, `spec.version`, `spec.provider` | Nothing. kagent builds the agent card from the AgentTemplate's name and description. | +| `spec.declarative.stream`, `executeCodeBlocks`, `shareTools`, `context` | Nothing. `v1alpha3` has no equivalent field. | + +> [!NOTE] +> Tool bindings changed shape. A 0.10.x tool set `type: McpServer` or `type: Agent` alongside a matching block. A 1.0 `ToolBinding` carries an `mcp` or `agent` block and no discriminator, so the block you set is the binding's kind. For what each binding does, see [About tools]({{< link path="skills-and-mcp/about-tools" >}}). + +Write one Harness for each distinct runtime and infrastructure combination that your agents need, then label each AgentTemplate so that a Harness admits it. A Harness admits nothing until its `allowedAgentTemplates.selector` matches, and an AgentTemplate has no field naming a Harness. For the full field reference, see [Agent harness]({{< link path="agents/agent-harness#configure-a-harness" >}}), and for a worked pair, see [Your first agent]({{< link path="get-started/your-first-agent#create-a-harness-and-an-agenttemplate" >}}). + +### Resources with no 1.0 equivalent + +Four resource kinds are removed rather than replaced, so plan for each one before you cut over. + +| Removed resource | What to do | +| ---------------- | ---------- | +| `AgentHarness` | No equivalent. It provisioned OpenClaw and Hermes coding-agent sandboxes with Slack and Telegram channels. 1.0's `Harness` shares part of the name and nothing else. | +| `Memory` | Configure memory on the Harness with `spec.kagent.memory` instead. See [Agent memory]({{< link path="agents/agent-memory#enable-memory" >}}). | +| `SandboxAgent` | No equivalent, and none is needed. Every 1.0 agent runs in a gVisor sandbox by default. | +| `ToolServer` | Use `RemoteMCPServer`, which 0.10.x already served alongside it. | + +## Verify the new installation + +Confirm that the resources resolved before you retire anything, because a Harness that is missing a dependency reports the reason on itself. + +1. Check that each Harness is ready. A Harness that is not ready most often names a WorkerPool that does not exist. + ```bash + kubectl get harness -n kagent + ``` + +2. Check that each AgentTemplate compiled against the Harness that admits it. `status.harnesses` carries one entry per admitting Harness, each ending in a `Ready` condition. An AgentTemplate has no status print column, so read the conditions rather than the table. + ```bash + kagent get agent-template -o json + ``` + +3. Create an AgentInstance from a migrated pair and send it a message. A reply confirms the whole path, from the compiled revision to the model credentials. + ```bash + kagent create agent-instance --harness --agent-template + ``` + +## Retire the 0.10.x installation + +Once the new installation answers correctly, remove the old one. Follow the 0.x procedure rather than the one in these docs: a 0.10.x installation has no Agent Substrate, no `ate.dev` resources, and no identity material to clean up. See [Uninstall kagent]({{< relref "/kagent/0.x/operations/uninstall" >}}#uninstall-with-helm) in the 0.x documentation. + +Keep the database backup after the uninstall for your own records. It is the only remaining copy of the 0.10.x conversation history, and nothing in 1.0 can read it. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="about/core-concepts" >}}` title="Core concepts" subtitle="Learn the Harness, AgentTemplate, and AgentInstance model that replaces the Agent resource." >}} + {{< card link=`{{< link path="reference/versions" >}}` title="Version support" subtitle="Check which upgrade paths kagent supports from 1.0 onward." >}} + {{< card link=`{{< link path="operations/operational-considerations" >}}` title="Operational considerations" subtitle="Replace the evaluation defaults before the new installation carries real traffic." >}} +{{< /cards >}} diff --git a/docs-site/content/kagent/1.x/reference/faq.md b/docs-site/content/kagent/1.x/reference/faq.md index ae4994f2..5e102ab7 100644 --- a/docs-site/content/kagent/1.x/reference/faq.md +++ b/docs-site/content/kagent/1.x/reference/faq.md @@ -34,7 +34,7 @@ Agent conversations are mostly idle, so Agent Substrate does not hold a pod open 1.0 changes how agents run and how you declare them. Agents no longer run as long-lived Deployments; each conversation runs as a sandboxed Actor on Agent Substrate that suspends between turns. The single 0.x `Agent` resource is replaced by the Harness and AgentTemplate pair, `ToolServer` is replaced by {{< gloss "RemoteMCPServer" >}}RemoteMCPServer{{< /gloss >}}, and the API group moves from `v1alpha2` to `v1alpha3`. -1.0 has no in-place upgrade path. An existing 0.10.x installation has no migration bridge to 1.0, so moving to 1.0 means standing up a new installation and recreating your resources on it. [Version support]({{< link path="reference/versions#release-support-and-compatibility" >}}) records which upgrade paths are supported, and the [release notes]({{< link path="reference/release-notes" >}}) list the breaking changes. +1.0 has no in-place upgrade path. An existing 0.10.x installation has no migration bridge to 1.0, so moving to 1.0 means standing up a new installation and recreating your resources on it. For the procedure, see [Upgrade from 0.x]({{< link path="operations/upgrade-from-0x" >}}). [Version support]({{< link path="reference/versions#release-support-and-compatibility" >}}) records which upgrade paths are supported, and the [release notes]({{< link path="reference/release-notes" >}}) list the breaking changes. ## How do I report a bug or request a feature? diff --git a/docs-site/content/kagent/1.x/reference/versions.md b/docs-site/content/kagent/1.x/reference/versions.md index 22ebb10b..6cad101d 100644 --- a/docs-site/content/kagent/1.x/reference/versions.md +++ b/docs-site/content/kagent/1.x/reference/versions.md @@ -39,7 +39,7 @@ kagent 1.0 is a deliberate clean break from the 0.10.x line, and the compatibili | 1.0 back to 0.10.x | No. Downgrade across the 1.0 boundary is unsupported. | | 1.0 forward to a later minor release | Yes. From 1.0 onward, migrations are append-only and each minor release retains compatibility with the previous release line. | -Moving from 0.10.x therefore means standing up a new installation and recreating your resources on it, rather than running `helm upgrade`. For the procedure, see [Upgrade]({{< link path="operations/upgrade" >}}). +Moving from 0.10.x therefore means standing up a new installation and recreating your resources on it, rather than running `helm upgrade`. For the procedure, see [Upgrade from 0.x]({{< link path="operations/upgrade-from-0x#in-place-upgrade-blockers" >}}). diff --git a/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md index 7d6c60b4..e41c4789 100644 --- a/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md +++ b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md @@ -99,6 +99,51 @@ spec: If you want to use one shared ServiceAccount for multiple agents, you can also set `controller.agentDeployment.serviceAccountName` in the [Helm chart configuration]({{< link path="resources/helm" >}}). +## Bedrock Guardrails + +You can apply [AWS Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) directly from the native Bedrock `ModelConfig` to enable content filtering, topic denial, and PII redaction. The guardrail applies on every request to the Converse and ConverseStream APIs. + +```yaml +spec: + provider: Bedrock + model: us.anthropic.claude-sonnet-4-20250514-v1:0 + bedrock: + region: us-east-1 + guardrail: + identifier: "abc123def456" + version: "1" + trace: "enabled" +``` + +| Field | Description | +|---|---| +| `bedrock.guardrail.identifier` | The guardrail ID or ARN. Required when the `guardrail` block is present. | +| `bedrock.guardrail.version` | The guardrail version to apply. Required when the `guardrail` block is present. | +| `bedrock.guardrail.trace` | Trace mode: `disabled` (default), `enabled`, or `enabled_full`. | + +Guardrail interventions apply before content returns to the caller so that blocked content does not leak to the stream. Interventions surface in the response content rather than as hard errors, allowing the agent loop to continue. + +## Request timeouts + +By default, the Bedrock client uses botocore's ~60 second read timeout, which can cause `ReadTimeoutError` on long completions. To override these values, use `bedrock.readTimeout` and `bedrock.connectTimeout`. + +```yaml +spec: + provider: Bedrock + model: us.anthropic.claude-sonnet-4-20250514-v1:0 + bedrock: + region: us-east-1 + readTimeout: 1800 + connectTimeout: 30 +``` + +| Field | Description | +|---|---| +| `bedrock.readTimeout` | Maximum seconds to wait for a response chunk. Minimum: 1. | +| `bedrock.connectTimeout` | Maximum seconds to wait for the initial connection. Minimum: 1. Optional. | + +Both fields are optional. When neither is set, botocore defaults apply and existing behavior is unchanged. + ## Option 2: OpenAI-compatible API You can also use Bedrock models via the [OpenAI Chat Completions API](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-chat-completions.html). This option is useful when you need compatibility with the OpenAI API format or when using Bedrock's inference profiles. diff --git a/docs-site/content/kagent/0.x/supported-providers/gemini.md b/docs-site/content/kagent/0.x/supported-providers/gemini.md index 7f0e93a3..7198950b 100644 --- a/docs-site/content/kagent/0.x/supported-providers/gemini.md +++ b/docs-site/content/kagent/0.x/supported-providers/gemini.md @@ -21,9 +21,7 @@ Make sure that your Google Cloud account has a project with the Gemini API enabl kubectl create secret generic kagent-gemini -n kagent --from-literal GOOGLE_API_KEY= ``` -3. Create a ModelConfig resource using the `Gemini` provider. - -You can find out the latest model names and capabilities on the [Gemini API docs](https://ai.google.dev/gemini-api/docs/models). Once you have chosen a model, replace the `model` field with the name such as `gemini-2.5-pro`. +3. Create a `ModelConfig` resource using the `Gemini` provider. You can find the latest model names and capabilities on the [Gemini API docs](https://ai.google.dev/gemini-api/docs/models). Replace the `model` field with your chosen model name, such as `gemini-2.5-pro`. ```yaml apiVersion: kagent.dev/v1alpha2 @@ -42,3 +40,17 @@ spec: 4. Apply the above resource to the cluster. Once the resource is applied, you can select the model from the Model dropdown in the UI when creating or updating agents. + +## Max output tokens + +Use `gemini.maxOutputTokens` to cap the number of tokens that the model can generate in a single response. + +```yaml +spec: + provider: Gemini + model: gemini-2.5-pro + gemini: + maxOutputTokens: 8192 +``` + +A per-request value set by the agent always takes precedence over this model-level default. diff --git a/docs-site/content/kagent/0.x/supported-providers/openai.md b/docs-site/content/kagent/0.x/supported-providers/openai.md index d695db4f..73ee021e 100644 --- a/docs-site/content/kagent/0.x/supported-providers/openai.md +++ b/docs-site/content/kagent/0.x/supported-providers/openai.md @@ -14,7 +14,7 @@ export OPENAI_API_KEY= kubectl create secret generic kagent-openai -n kagent --from-literal OPENAI_API_KEY=$OPENAI_API_KEY ``` -2. Create a ModelConfig resource that references the secret and key name: +2. Create a `ModelConfig` resource that references the secret and key name. For standard models such as GPT-4 and GPT-3.5, kagent automatically configures the appropriate model capabilities. ```yaml apiVersion: kagent.dev/v1alpha2 @@ -30,8 +30,51 @@ spec: openAI: {} ``` -For OpenAI's standard models like GPT-4 and GPT-3.5, kagent automatically configures the appropriate model capabilities. - -3. Apply the above resource to the cluster. +3. Apply the resource to the cluster. Once the resource is applied, you can select the model from the Model dropdown in the UI when creating or updating agents. + +## Reasoning effort + +For OpenAI reasoning models (o-series, GPT-5), you can control how many reasoning tokens the model generates before producing a response with the `openAI.reasoningEffort` field. Valid values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. + +For models that require reasoning to be explicitly disabled (such as some GPT-5 variants), set `reasoningEffort: none`. For standard models that do not support it, omit the field. + +```yaml +spec: + provider: OpenAI + model: o3 + openAI: + reasoningEffort: medium +``` + +## Max completion tokens + +For OpenAI reasoning models (o-series, GPT-5), use `openAI.maxCompletionTokens` to cap the total number of tokens the model can generate in a response, including both visible output tokens and reasoning tokens. + +> **Note**: Do not use `openAI.maxTokens` for reasoning models. OpenAI deprecated `max_tokens` for the Chat Completions API, and reasoning models reject it outright with a 400 error. Use `maxCompletionTokens` instead. + +```yaml +spec: + provider: OpenAI + model: o3 + openAI: + reasoningEffort: medium + maxCompletionTokens: 16000 +``` + +For standard (non-reasoning) models and OpenAI-compatible endpoints, `openAI.maxTokens` continues to work as before. The two fields are independent. + +## Responses API + +By default, kagent uses the [Chat Completions API](https://platform.openai.com/docs/api-reference/chat). To switch to the [OpenAI Responses API](https://platform.openai.com/docs/api-reference/responses) instead, set `openAI.apiFormat: responses` on the `ModelConfig`. This is also compatible with gateways such as AgentGateway that expose the Responses API. + +```yaml +spec: + provider: OpenAI + model: gpt-4o + openAI: + apiFormat: responses +``` + +Omit `apiFormat` (or set it to `chatCompletions`) to continue using Chat Completions. Native tool use and stateful Responses API chaining are not yet supported. From ac0dbdaafac0684ca53f1a3c52ac957bbba7ad88 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 15 Sep 2026 09:22:55 -0500 Subject: [PATCH 69/70] Hugo build fix Signed-off-by: Rachael Graham --- docs-site/hugo.preview.yaml | 34 +- docs-site/hugo.yaml | 114 +++++-- docs-site/layouts/_partials/navbar.html | 318 ------------------ docs-site/layouts/_partials/sidebar.html | 15 +- .../_partials/utils/section-segment.html | 210 ++++++++++++ 5 files changed, 320 insertions(+), 371 deletions(-) delete mode 100644 docs-site/layouts/_partials/navbar.html create mode 100644 docs-site/layouts/_partials/utils/section-segment.html diff --git a/docs-site/hugo.preview.yaml b/docs-site/hugo.preview.yaml index 653da486..fd594580 100644 --- a/docs-site/hugo.preview.yaml +++ b/docs-site/hugo.preview.yaml @@ -7,23 +7,25 @@ # 1. It drives the version switcher, which is why the entry is absent in production. # 2. The {{< version >}} shortcode iterates it and emits only on a linkVersion # match, so with no 1.x entry every {{< version include-if="1.x" >}} renders -# EMPTY -- blanking the conref'd version numbers on setup/installation.md, -# agents/agent-memory.md, observability/tracing.md, -# operations/tune-agent-substrate.md, and reference/versions.md. No error, -# clean build, broken copy-paste commands. +# EMPTY -- blanking the conref'd version numbers in assets/kagent-docs/versions/ +# wherever a page reuses them, including the component table on +# reference/versions.md. No error, clean build, broken copy-paste commands. +# +# Hugo REPLACES a list-valued param rather than merging it, so this restates the +# 0.x entry; an overlay holding 1.x alone would drop 0.x from the preview. # # Delete this file at the 1.0 release, when the entry returns to hugo.yaml # alongside dropping the draft keys in content/kagent/1.x/_index.md. params: - sections: - kagent: - versions: - - version: "0.x" - dropdown: "0.x (current)" - linkVersion: "0.x" - url: "/kagent/0.x" - - version: "1.x" - dropdown: "1.x (preview)" - linkVersion: "1.x" - url: "/kagent/1.x" - banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." + versions: + - version: "0.x" + dropdown: "0.x (current)" + linkVersion: "0.x" + url: "/kagent/0.x" + sections: ["kagent"] + - version: "1.x" + dropdown: "1.x (preview)" + linkVersion: "1.x" + url: "/kagent/1.x" + sections: ["kagent"] + banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." diff --git a/docs-site/hugo.yaml b/docs-site/hugo.yaml index c9f818af..b1a82ae4 100644 --- a/docs-site/hugo.yaml +++ b/docs-site/hugo.yaml @@ -70,6 +70,15 @@ markup: enableInlineShortcodes: true +# kmcp is registered under params.sections to scope the version dropdown (so +# kagent's 0.x/1.x never appear on kmcp pages) and to put both doc sets in the +# navbar section selector. It nests no version tree of its own, which is the +# shape docs-theme-extras warns about on every build. That registration is +# deliberate here, and the module documents allowlisting the warning as the way +# to say so. +ignoreLogs: + - extras-section-hollow + params: # Section registry, alphabetical. A section exists because it is a key here. # See docs-theme-extras USAGE.md, "Versions and sections". @@ -93,21 +102,88 @@ params: # falls through to a Material Icons ligature and renders as literal text, so a # typo here shows up on the page rather than failing the build. # - # Do NOT add params.versions to make something else work. These sections - # resolve through the theme's version-less path, and a single version entry - # moves the whole site onto the versioned path, where a section is only - # recognized directly above a version tree — of which this site has none. + # Registration only — a section's version list is NOT a sub-key here. The + # `sections..versions` shape this file used through docs-theme-extras + # v0.2.0 was removed in v0.2.2; every version now lives in the single + # top-level `versions` list below and names the sections it belongs to. See + # `versions` for why that single list is load-bearing, and the module's + # utils/resolve-section-versions.html for the removal rationale. sections: kagent: icon: icons/nav-kagent.svg kmcp: icon: icons/nav-kmcp.svg + # THE version list — docs-theme-extras reads this key and no other. Each entry + # names the sections it applies to, and an entry with no `sections` applies to + # every section. kagent is the only versioned doc set on this site, so its + # entries are tagged `[kagent]` and kmcp — the other product built into this + # same Hugo site — resolves to an empty list and renders no version dropdown. + # + # Tagging is what keeps this ONE list rather than two. Before v0.2.2 a section + # could carry its own `sections..versions`, and everything that reads + # site.Params.versions directly was blind to it: the `version` shortcode (so + # every {{< version include-if="1.x" >}} inside assets/kagent-docs/versions/*.md + # rendered EMPTY, blanking the version table on reference/versions.md with no + # error), flexsearch's visibleVersions, the version banner, and the noindex + # partial. A clean build with blank version numbers is the failure mode this + # single list prevents. + # + # 0.x is the frozen pre-1.0 doc set (moved verbatim from the former flat + # content/kagent/ tree); 1.x is the in-progress v1alpha3/Agent Substrate + # rewrite and carries an in-development banner until it's ready to become + # the default. + # + # Declaring versions at all moves section resolution off the theme's + # version-less positional path (utils/section-segment.html condition (c)) and + # onto the versioned path, where a section is recognized only directly above a + # version tree — condition (a) — or as its own landing page — condition (b). + # kagent satisfies (a): /docs/kagent/<0.x|1.x>/…. kmcp has no version tree, so + # it satisfies (a) nowhere and (b) only on its own landing page, /docs/kmcp/. + # Every kmcp page below that resolves to no section and falls back to a left + # nav rooted at site.Home — which is why layouts/_partials/sidebar.html carries + # a local override. Verify a kmcp sub-page's sidebar after any change here. + versions: + - version: "0.x" + dropdown: "0.x (current)" + linkVersion: "0.x" + url: "/kagent/0.x" + sections: ["kagent"] + # The "1.x" entry is deliberately absent until the 1.0 release is announced. + # This list drives the version switcher independently of whether the pages + # exist, so leaving the entry here while the content is drafted publishes a + # "1.x (preview)" menu item pointing at a 404. hugo.preview.yaml layers it + # back for local authoring; restore it here alongside dropping the draft keys + # in content/kagent/1.x/_index.md: + # + # - version: "1.x" + # dropdown: "1.x (preview)" + # linkVersion: "1.x" + # url: "/kagent/1.x" + # sections: ["kagent"] + # banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." + # Label on the section selector button. Without it the button falls back to # site.Title ("kagent docs"), which reads oddly above a menu offering kagent # and kmcp. Matches the "Docs" label the hand-rolled menu dropdown used. product: "Docs" + # The docs root segment, as it appears in every page's RelPermalink. It comes + # from the /docs/ path on baseURL, not from a content directory, but the theme + # cannot tell those apart: navbar.html finds the version segment by counting + # segments from the left, and it counts one for `folder` only when this is set + # AND the URL actually starts with it. Unset, the count is one short on this + # site — /docs/kagent/0.x/… yields "kagent" as the version, nothing matches, + # and the version dropdown silently does not render at all. + # + # `hugo server` keeps the path component of baseURL, so the prefix test holds + # locally as well as in production. + # + # This is NOT where the PDF link's product segment comes from, even though + # `folder` sits in that fallback chain — pdfDownload.product below is set + # explicitly and wins. + folder: docs + # Hide the visible "Last updated on " footer (imported OSS content # modules ship displayUpdatedDate=true; this overrides it). The git date still # feeds the sitemap for SEO. @@ -173,36 +249,6 @@ params: # Auto-render the light/dark toggle in the navbar displayToggle: true - # Per-section version lists, consumed by the local navbar.html override - # (layouts/_partials/navbar.html) and by docs-theme-extras' version-cards - # shortcode. Scoped under sections.kagent rather than the top-level - # `versions` key so kmcp — the other product built into this same Hugo - # site — never picks up kagent's version dropdown. See the navbar.html - # override's header comment for why that scoping is necessary here. - # - # 0.x is the frozen pre-1.0 doc set (moved verbatim from the former flat - # content/kagent/ tree); 1.x is the in-progress v1alpha3/Agent Substrate - # rewrite and carries an in-development banner until it's ready to become - # the default. - sections: - kagent: - versions: - - version: "0.x" - dropdown: "0.x (current)" - linkVersion: "0.x" - url: "/kagent/0.x" - # The "1.x" entry is deliberately absent until the 1.0 release is - # announced. This list drives the version switcher independently of - # whether the pages exist, so leaving the entry here while the content - # is drafted publishes a "1.x (preview)" menu item pointing at a 404. - # Restore it alongside the draft keys in content/kagent/1.x/_index.md: - # - # - version: "1.x" - # dropdown: "1.x (preview)" - # linkVersion: "1.x" - # url: "/kagent/1.x" - # banner: "This is preview documentation for the upcoming kagent 1.0 release. It is incomplete and may change without notice." - # Top nav — mirrors kagent.dev. Docs is local; the marketing/blog sections stay # on the Next.js site, so those link out to absolute kagent.dev URLs. menu: diff --git a/docs-site/layouts/_partials/navbar.html b/docs-site/layouts/_partials/navbar.html deleted file mode 100644 index bd13da2f..00000000 --- a/docs-site/layouts/_partials/navbar.html +++ /dev/null @@ -1,318 +0,0 @@ -{{- /* Custom navbar override: adds version dropdown from [[params.versions]] */ -}} -{{- $navWidth := "hx:max-w-[90rem]" -}} -{{- with .Site.Params.navbar.width -}} - {{ if eq . "normal" -}} - {{ $navWidth = "hx:max-w-screen-xl" -}} - {{ else if eq . "full" -}} - {{ $navWidth = "max-w-full" -}} - {{ end -}} -{{- end -}} - -{{- $page := . -}} -{{- $iconHeight := 24 -}} - -
      -
      - - -
      diff --git a/docs-site/layouts/_partials/sidebar.html b/docs-site/layouts/_partials/sidebar.html index 3c50bbdd..e278bb62 100644 --- a/docs-site/layouts/_partials/sidebar.html +++ b/docs-site/layouts/_partials/sidebar.html @@ -18,8 +18,8 @@ sidebar-children, data-sidebar-item, sidebar-mobile-panel) so the toggle JS and mobile drawer in docs-theme-extras keep working. - kagent (unlike kmcp) is also versioned (0.x, 1.x — see - sections.kagent.versions in hugo.yaml). .FirstSection alone would root the + kagent (unlike kmcp) is also versioned (0.x, 1.x — see the params.versions + entries tagged `sections: ["kagent"]` in hugo.yaml). .FirstSection alone would root the tree at the "kagent" product page, whose direct children are now the 0.x and 1.x version pages themselves — so BOTH versions' full trees would render side by side, and the version switcher (navbar.html) would have no @@ -43,9 +43,18 @@ {{- $navRoot := $context.FirstSection -}} {{- $suppress := false -}} + {{- /* Versions resolve through the module's utils/resolve-section-versions.html, + the one place that knows which entries in site.Params.versions apply to a + section. Reading site.Params.sections..versions directly — as this did + through docs-theme-extras v0.2.0 — stopped working in v0.2.2, when that + per-section list was removed in favour of tagging entries in the single + top-level list. The failure is silent: the lookup yields nothing, the + version branch never runs, and the sidebar roots at the product page, so + 0.x and 1.x render as one 197-item tree and the version switcher stops + affecting the nav. */ -}} {{- $sectionKey := $context.Section -}} {{- if and $sectionKey (isset $context.Site.Params.sections $sectionKey) -}} - {{- with (index $context.Site.Params.sections $sectionKey).versions -}} + {{- with partial "utils/resolve-section-versions.html" $sectionKey -}} {{- $segments := split (strings.Trim $context.RelPermalink "/") "/" -}} {{- $sectionIdx := -1 -}} {{- range $i, $seg := $segments -}} diff --git a/docs-site/layouts/_partials/utils/section-segment.html b/docs-site/layouts/_partials/utils/section-segment.html new file mode 100644 index 00000000..c58e72b9 --- /dev/null +++ b/docs-site/layouts/_partials/utils/section-segment.html @@ -0,0 +1,210 @@ +{{- /* + section-segment.html — detect an optional content-division path segment + (e.g. "kubernetes"/"standalone" for agentgateway, "envoy"/"agentgateway" + for kgateway) that a product opts into by registering keys under + site.Params.sections. + + Products nest their version trees directly under the product root + (///…). A product with more than one parallel + documentation section can instead nest version trees under a section + segment (//
      //…), matching how OSS sites lay + theirs out. Every file that parses Page.RelPermalink to find the version + segment needs to know whether a section segment is in the way; this + partial is the one place that answers "is there one, and where." + + A section registers by existing as a key under site.Params.sections, even + with no fields set (e.g. `[params.sections.kubernetes]` with nothing under + it). See docs-theme-extras USAGE.md, "Versions and sections", for the full + contract. (The table used to be able to carry a `.versions` override too; + that shape was removed in 0.2.2 — see utils/resolve-section-versions.html.) + + A consumer that IMPORTS a module which declares its own sections inherits + them, because Hugo deep-merges an imported module's params into the project's. + Decline that with stock Hugo config-merge control rather than anything in this + theme — `[params.sections]` with `_merge = "none"`. See docs-theme-extras + USAGE.md, "Versions and sections". + + Input: a Page (passed as `.`) + Output: dict: + segment string — the matched section string, or "" if none/not + configured + index int — the index of that segment within + split(trim(.RelPermalink, "/"), "/"), i.e. 0 for the + first path segment after the domain/baseURL. -1 if + no match. + + Products that don't set site.Params.sections get segment="" always, so + every caller's existing math is unchanged for them. +*/ -}} +{{- $page := . -}} +{{- $segment := "" -}} +{{- $index := -1 -}} +{{- if site.Params.sections -}} + {{- $parts := split (strings.Trim $page.RelPermalink "/") "/" -}} + + {{- /* Same shape fallback as utils/version-root.html, for a version segment + that matches no configured entry. */ -}} + {{- $versionShapeRE := `^(?:\d+\.\d+\.(?:x|\d+)|latest|main)$` -}} + {{- $known := slice -}} + {{- range site.Params.versions -}} + {{- with (.linkVersion | default .version) -}}{{- $known = $known | append . -}}{{- end -}} + {{- end -}} + + {{- /* VERSION-LESS SITES. A site can ship parallel doc sets with no version + axis at all — kagent's docs are `kagent` and `kmcp`, neither versioned. + Such a site has nothing for conditions (a) or (b) below to key off: no + version ever follows the section segment, so (a) never fires, and every + page below the section fails (b) because the section is not the last + segment. Without a third condition, registering sections on a + version-less site silently does nothing. + + The third condition is POSITIONAL, deliberately, and only applies when + the site declares NO versions whatsoever. A section on a version-less + site sits exactly one segment below the docs root, and $docsRootDepth is + how many URL segments precede that root: + + home / depth 0 → section at /
      / + home /docs/ depth 1 → section at /docs/
      / (kagent) + home /agentgateway/ depth 1 → section at //
      / + home /ja/ depth 1 → section at //
      / + + Reading it off site.Home.RelPermalink absorbs a baseURL subpath, a + per-product hub baseURL and a language prefix without this partial + having to know which one it is looking at. The `docs` alternative below + covers the OSS shape where the docs root is a content directory rather + than the baseURL (home is the MARKETING page at /, docs live at /docs/). + + Keeping it positional is what stops this from reintroducing the + match-anywhere bug documented below: on a version-less site + /docs/kagent/reference/kagent/ still resolves `kagent` only at index 1, + never at index 3. */ -}} + {{- $versionless := not site.Params.versions -}} + {{- $homeTrim := strings.Trim site.Home.RelPermalink "/" -}} + {{- $docsRootDepth := 0 -}} + {{- if $homeTrim -}} + {{- $docsRootDepth = len (split $homeTrim "/") -}} + {{- end -}} + + {{- range $i, $p := $parts -}} + {{- if and (eq $segment "") (isset site.Params.sections $p) -}} + {{- /* POSITION MATTERS. A registered key is only a SECTION where a section + can legitimately sit: immediately above a version tree. Matching the + key wherever it appears makes any ordinary content directory that + shares a section's name break that page. + + That is not hypothetical. solo-io/docs imports + github.com/kgateway-dev/kgateway.dev for content and therefore + inherits its `sections.envoy` key (Hugo deep-merges an imported + module's params). The hub also ships + content/en/kgateway/2.3.x/setup/customize/envoy/ — eight real pages. + Matching by name alone made version-root.html build + lookupPath="/envoy/2.3.x/", site.GetPage resolved nothing, and those + pages rendered with a COMPLETELY EMPTY left nav. No error, no + warning; it reads as a content problem. + + Two positions qualify: + + (a) the next segment is a version — /
      //… + (b) it is the LAST segment and no version precedes it — the + section landing page, //
      / + + (b) needs the "no version precedes it" half, or + /kgateway/2.3.x/setup/customize/envoy/ (the _index.md of that content + directory) reads as a section landing page and has its nav + suppressed — trading an empty nav for a missing one on the same + pages. A section sits ABOVE version trees, never below one. + + (c) the site declares NO versions and the key sits exactly one + segment below the docs root — see $docsRootDepth above. Gated + on version-less-ness so that no site with versions changes + behavior at all. */ -}} + {{- $next := "" -}} + {{- if lt (add $i 1) (len $parts) -}}{{- $next = index $parts (add $i 1) -}}{{- end -}} + {{- $nextIsVersion := or (in $known $next) (and $next (findRE $versionShapeRE $next)) -}} + + {{- $versionPrecedes := false -}} + {{- range $j, $q := $parts -}} + {{- if lt $j $i -}} + {{- if or (in $known $q) (findRE $versionShapeRE $q) -}} + {{- $versionPrecedes = true -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- $isLanding := and (eq $i (sub (len $parts) 1)) (not $versionPrecedes) -}} + + {{- /* (c). The `docs` alternative is index-guarded because $docsRootDepth + is derived from the home page and $parts from the page being + rendered — on a shallower URL than the home path the index would be + out of range and abort the build. */ -}} + {{- $atDocsRoot := eq $i $docsRootDepth -}} + {{- if and (not $atDocsRoot) (eq $i (add $docsRootDepth 1)) (lt $docsRootDepth (len $parts)) -}} + {{- if eq (index $parts $docsRootDepth) "docs" -}} + {{- $atDocsRoot = true -}} + {{- end -}} + {{- end -}} + + {{- /* A VERSION-LESS SITE USES (c) ALONE — it does not also get (a) and + (b), and that exclusivity is the fix for a real hole. + + (b) accepts "last segment, and no version precedes it". On a + VERSIONED site the second half carries the weight: almost every + content page sits under a version, so a trailing segment that + happens to share a section's name is rejected. Remove versions from + the site and nothing ever has a version before it — so (b) starts + accepting a registered name as a section at ANY depth, purely for + being last. + + Caught by the fixture's /docs/topics/alpha/, where `topics` is not a + section and `alpha` is: it resolved to section `alpha` at index 2 + and rendered the alpha tree on a page that belongs to neither doc + set. (a) is likewise vacuous here, since no segment can be a + version. So on a version-less site the positional test is the only + meaningful one, and making it the only one applied is both simpler + and tighter. */ -}} + {{- /* kagent project override — the ONLY change to this file. Upstream: + + {{- if $versionless -}} + {{- $accept = $atDocsRoot -}} + {{- else -}} + {{- $accept = or $nextIsVersion $isLanding -}} + {{- end -}} + + Upstream treats a site as EITHER version-less (positional test (c) + alone) or versioned ((a) or (b)). This site is both at once: kagent + nests 0.x and 1.x under /docs/kagent/, kmcp has no version axis at + all, and they share one Hugo build. Declaring kagent's versions -- + which is mandatory, since site.Params.versions is the only list the + module reads -- puts the whole site on the versioned branch, where + kmcp satisfies (a) nowhere and (b) only on /docs/kmcp/ itself. Every + kmcp page below that resolved to NO section, which drops kmcp and + kagent to one entry in utils/resolve-sections.html and so renders no + section selector: from any kmcp page there was no way back to the + kagent docs through the navbar. + + Folding (c) in ungated fixes that, and is safe for the reason + upstream's own header gives for keeping (c) positional: it accepts a + registered key at exactly one segment below the docs root and + nowhere else, so it cannot reintroduce the match-anywhere bug. The + `$versionless` gate exists to stop (b) over-matching on a site with + no versions; (c) has no such failure mode, and (a) still resolves + every kagent page identically -- /docs/kagent/0.x/... matches (a) at + index 1 and (c) at index 1. + + Retire this override if the module makes (c) unconditional, or if + kmcp ever nests a version tree of its own. */ -}} + {{- $accept := false -}} + {{- if $versionless -}} + {{- $accept = $atDocsRoot -}} + {{- else -}} + {{- $accept = or $nextIsVersion $isLanding $atDocsRoot -}} + {{- end -}} + + {{- if $accept -}} + {{- $segment = $p -}} + {{- $index = $i -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- return (dict "segment" $segment "index" $index) -}} From 60d94a71130dad7ce1b739622da25c74e81ba691 Mon Sep 17 00:00:00 2001 From: Rachael Graham Date: Tue, 15 Sep 2026 09:38:00 -0500 Subject: [PATCH 70/70] CLI generation Signed-off-by: Rachael Graham --- .github/workflows/update-ref-docs.yaml | 40 ++++- .../kagent-docs/versions/agent-substrate.md | 2 +- .../assets/kagent-docs/versions/kagent.md | 2 +- .../content/kagent/0.x/resources/api-ref.md | 122 ++++++++------- .../kagent/0.x/resources/cli/_index.md | 32 ++-- .../0.x/resources/cli/kagent-add-mcp.md | 8 +- .../0.x/resources/cli/kagent-bug-report.md | 8 +- .../kagent/0.x/resources/cli/kagent-build.md | 8 +- .../resources/cli/kagent-completion-bash.md | 8 +- .../resources/cli/kagent-completion-fish.md | 8 +- .../cli/kagent-completion-powershell.md | 8 +- .../resources/cli/kagent-completion-zsh.md | 8 +- .../0.x/resources/cli/kagent-completion.md | 16 +- .../0.x/resources/cli/kagent-dashboard.md | 8 +- .../resources/cli/kagent-db-migrate-down.md | 6 +- .../resources/cli/kagent-db-migrate-force.md | 6 +- .../resources/cli/kagent-db-migrate-goto.md | 6 +- .../resources/cli/kagent-db-migrate-status.md | 6 +- .../0.x/resources/cli/kagent-db-migrate-up.md | 6 +- .../cli/kagent-db-migrate-version.md | 6 +- .../0.x/resources/cli/kagent-db-migrate.md | 20 +-- .../kagent/0.x/resources/cli/kagent-db.md | 10 +- .../kagent/0.x/resources/cli/kagent-deploy.md | 8 +- .../0.x/resources/cli/kagent-get-agent.md | 8 +- .../0.x/resources/cli/kagent-get-session.md | 8 +- .../0.x/resources/cli/kagent-get-tool.md | 8 +- .../kagent/0.x/resources/cli/kagent-get.md | 14 +- .../kagent/0.x/resources/cli/kagent-init.md | 12 +- .../0.x/resources/cli/kagent-install.md | 8 +- .../kagent/0.x/resources/cli/kagent-invoke.md | 8 +- .../0.x/resources/cli/kagent-mcp-add-tool.md | 8 +- .../0.x/resources/cli/kagent-mcp-build.md | 8 +- .../cli/kagent-mcp-deploy-package.md | 8 +- .../0.x/resources/cli/kagent-mcp-deploy.md | 10 +- .../0.x/resources/cli/kagent-mcp-init-go.md | 8 +- .../0.x/resources/cli/kagent-mcp-init-java.md | 8 +- .../resources/cli/kagent-mcp-init-python.md | 8 +- .../cli/kagent-mcp-init-typescript.md | 8 +- .../0.x/resources/cli/kagent-mcp-init.md | 16 +- .../0.x/resources/cli/kagent-mcp-run.md | 8 +- .../resources/cli/kagent-mcp-secrets-sync.md | 8 +- .../0.x/resources/cli/kagent-mcp-secrets.md | 10 +- .../kagent/0.x/resources/cli/kagent-mcp.md | 20 +-- .../kagent/0.x/resources/cli/kagent-run.md | 8 +- .../0.x/resources/cli/kagent-uninstall.md | 8 +- .../0.x/resources/cli/kagent-version.md | 8 +- .../content/kagent/0.x/resources/helm.md | 142 ++++++++++++++---- .../kagent/1.x/reference/cli/_index.md | 21 +++ .../kagent/1.x/reference/cli/kagent-apply.md | 26 ++++ .../1.x/reference/cli/kagent-bug-report.md | 25 +++ .../reference}/cli/kagent-completion-bash.md | 15 +- .../reference}/cli/kagent-completion-fish.md | 15 +- .../cli/kagent-completion-powershell.md | 15 +- .../reference}/cli/kagent-completion-zsh.md | 15 +- .../1.x/reference/cli/kagent-completion.md | 32 ++++ .../cli/kagent-create-agent-instance.md | 28 ++++ .../kagent/1.x/reference/cli/kagent-create.md | 29 ++++ .../1.x/reference/cli/kagent-dashboard.md | 25 +++ .../reference/cli/kagent-db-migrate-down.md | 21 +++ .../reference/cli/kagent-db-migrate-goto.md | 21 +++ .../reference/cli/kagent-db-migrate-status.md | 22 +++ .../1.x/reference/cli/kagent-db-migrate-up.md | 21 +++ .../cli/kagent-db-migrate-version.md | 21 +++ .../1.x/reference/cli/kagent-db-migrate.md | 29 ++++ .../kagent/1.x/reference/cli/kagent-db.md | 22 +++ .../cli/kagent-delete-agent-instance.md | 25 +++ .../kagent/1.x/reference/cli/kagent-delete.md | 29 ++++ .../cli/kagent-get-agent-instance.md | 27 ++++ .../cli/kagent-get-agent-template.md | 27 ++++ .../kagent/1.x/reference/cli/kagent-get.md | 30 ++++ .../1.x/reference/cli/kagent-install.md | 26 ++++ .../kagent/1.x/reference/cli/kagent-invoke.md | 36 +++++ .../reference}/cli/kagent-mcp-add-tool.md | 15 +- .../reference}/cli/kagent-mcp-build.md | 15 +- .../cli/kagent-mcp-deploy-package.md | 15 +- .../reference}/cli/kagent-mcp-deploy.md | 17 +-- .../reference}/cli/kagent-mcp-init-go.md | 15 +- .../reference}/cli/kagent-mcp-init-java.md | 15 +- .../reference}/cli/kagent-mcp-init-python.md | 15 +- .../cli/kagent-mcp-init-typescript.md | 15 +- .../1.x/reference/cli/kagent-mcp-init.md | 41 +++++ .../reference}/cli/kagent-mcp-run.md | 15 +- .../reference}/cli/kagent-mcp-secrets-sync.md | 15 +- .../1.x/reference/cli/kagent-mcp-secrets.md | 28 ++++ .../kagent/1.x/reference/cli/kagent-mcp.md | 34 +++++ .../1.x/reference/cli/kagent-uninstall.md | 25 +++ .../1.x/reference/cli/kagent-version.md | 25 +++ .../resources/cli/kagent-db-migrate-down.md | 26 ---- .../resources/cli/kagent-db-migrate-force.md | 27 ---- .../resources/cli/kagent-db-migrate-goto.md | 27 ---- .../resources/cli/kagent-db-migrate-status.md | 23 --- .../resources/cli/kagent-db-migrate-up.md | 31 ---- .../cli/kagent-db-migrate-version.md | 25 --- .../kagent/resources/cli/kagent-db-migrate.md | 32 ---- .../content/kagent/resources/cli/kagent-db.md | 23 --- .../kagent/resources/cli/kagent-get-agent.md | 26 ---- .../resources/cli/kagent-get-session.md | 26 ---- .../kagent/resources/cli/kagent-get-tool.md | 26 ---- .../kagent/resources/cli/kagent-mcp-init.md | 42 ------ .../resources/cli/kagent-mcp-secrets.md | 29 ---- scripts/generate-cli-docs.py | 35 ++++- 101 files changed, 1157 insertions(+), 861 deletions(-) create mode 100644 docs-site/content/kagent/1.x/reference/cli/_index.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-apply.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-bug-report.md rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-completion-bash.md (64%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-completion-fish.md (58%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-completion-powershell.md (57%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-completion-zsh.md (65%) create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-completion.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-create-agent-instance.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-create.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-dashboard.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-down.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-goto.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-status.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-up.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-version.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-db.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-delete-agent-instance.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-delete.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-instance.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-template.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-get.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-install.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-invoke.md rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-add-tool.md (68%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-build.md (68%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-deploy-package.md (84%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-deploy.md (80%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-init-go.md (66%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-init-java.md (63%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-init-python.md (63%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-init-typescript.md (63%) create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init.md rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-run.md (74%) rename docs-site/content/kagent/{resources => 1.x/reference}/cli/kagent-mcp-secrets-sync.md (75%) create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-mcp.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-uninstall.md create mode 100644 docs-site/content/kagent/1.x/reference/cli/kagent-version.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate-down.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate-force.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate-goto.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate-status.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate-up.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate-version.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db-migrate.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-db.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-get-agent.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-get-session.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-get-tool.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-mcp-init.md delete mode 100644 docs-site/content/kagent/resources/cli/kagent-mcp-secrets.md diff --git a/.github/workflows/update-ref-docs.yaml b/.github/workflows/update-ref-docs.yaml index c9483865..96b31919 100644 --- a/.github/workflows/update-ref-docs.yaml +++ b/.github/workflows/update-ref-docs.yaml @@ -35,10 +35,33 @@ concurrency: # this retarget the job failed every night on the missing v1alpha2 directory. # # 0.x is FROZEN and is no longer generated here. Its committed pages -# (0.x/resources/api-ref.md and 0.x/resources/helm.md) describe v1alpha2 and -# the 0.5.x chart, neither of which main still contains, so regenerating them -# from main would overwrite correct frozen content with 1.0 values. Both are -# still linked from 0.x pages, so leave them in place rather than deleting. +# (0.x/resources/api-ref.md, 0.x/resources/helm.md and 0.x/resources/cli/) all +# describe kagent v0.10.1 -- the newest 0.x release -- so they document +# v1alpha2, the 0.10.1 chart and the v0.10.1 CLI, none of which main still +# contains. Regenerating them from main overwrites correct frozen content with +# 1.0 values. All are still linked from 0.x pages, so leave them in place rather +# than deleting. +# +# That is not hypothetical -- it happened to all three before this job was +# retargeted, in three different shapes, none of which failed a build: +# +# - cli/ gained the gRPC transport flags (--kagent-grpc-url and friends, +# kagent #2362) across 42 pages. Real flags, wrong release line. +# - helm.md LOST all ten agent subcharts and their values -- 258 documented +# keys where the 0.10.1 chart has 337. +# - api-ref.md kept the right API version (v1alpha2) and so looked clean, but +# carried topologySpreadConstraints (absent at v0.10.1), missed +# executeCodeBlocks (present at v0.10.1), and pinned every +# Kubernetes doc link to v1.31 from the old max-kube drift. +# +# All three were regenerated from the v0.10.1 tag on 2026-09-15. Regenerate from +# that TAG, never from main, if they ever need rebuilding. For the CLI pages: +# +# git -C kagent worktree add --detach /tmp/kagent-0x v0.10.1 +# (cd /tmp/kagent-0x/go && go build -o /tmp/kagent-cli-0x ./core/cli/cmd/kagent) +# python3 scripts/generate-cli-docs.py --binary /tmp/kagent-cli-0x \ +# --display-name kagent --out-dir docs-site/content/kagent/0.x/resources/cli \ +# --url-prefix /docs/kagent/0.x/resources/cli --weight 1 # # The section is named reference/ in 1.x, not resources/ as in 0.x, and the # provider pages link to crd-ref-docs anchors (#modelconfigspec, #openaiconfig, @@ -644,6 +667,12 @@ jobs: echo "kmcp CLI binary built and smoke-tested successfully" - name: Generate kagent CLI reference docs + # --weight 30 slots CLI docs into the 1.x reference section after + # api-ref (10) and helm (20). The generator's default of 1 would tie + # with nothing and sort CLI docs above the API reference, and kagent's + # reference section is the only one where that ordering is wrong -- + # kmcp's section deliberately leads with the CLI, so its step below + # keeps the default. run: | cd "$GITHUB_WORKSPACE/website" mkdir -p "$KAGENT_CLI_DIR" @@ -651,7 +680,8 @@ jobs: --binary /tmp/kagent-cli \ --display-name kagent \ --out-dir "$KAGENT_CLI_DIR" \ - --url-prefix "$KAGENT_CLI_URL_PREFIX" + --url-prefix "$KAGENT_CLI_URL_PREFIX" \ + --weight 30 - name: Generate kmcp CLI reference docs run: | diff --git a/docs-site/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md index e9d19937..9f60ea92 100644 --- a/docs-site/assets/kagent-docs/versions/agent-substrate.md +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -1 +1 @@ -{{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.26{{< /version >}} \ No newline at end of file +{{< version include-if="0.x" >}}0.0.9{{< /version >}}{{< version include-if="1.x" >}}0.0.26{{< /version >}} \ No newline at end of file diff --git a/docs-site/assets/kagent-docs/versions/kagent.md b/docs-site/assets/kagent-docs/versions/kagent.md index 68d3c797..3eb5ac91 100644 --- a/docs-site/assets/kagent-docs/versions/kagent.md +++ b/docs-site/assets/kagent-docs/versions/kagent.md @@ -1 +1 @@ -{{< version include-if="0.x" >}}0.9.9{{< /version >}}{{< version include-if="1.x" >}}1.0.0-beta0{{< /version >}} \ No newline at end of file +{{< version include-if="0.x" >}}0.10.1{{< /version >}}{{< version include-if="1.x" >}}1.0.0-beta0{{< /version >}} \ No newline at end of file diff --git a/docs-site/content/kagent/0.x/resources/api-ref.md b/docs-site/content/kagent/0.x/resources/api-ref.md index f4eb0bfd..ad2010e0 100644 --- a/docs-site/content/kagent/0.x/resources/api-ref.md +++ b/docs-site/content/kagent/0.x/resources/api-ref.md @@ -40,7 +40,7 @@ Agent is the Schema for the agents API. | `kind` _string_ | `Agent` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[AgentSpec](#agentspec)_ | | | | | `status` _[AgentStatus](#agentstatus)_ | | | | @@ -55,7 +55,7 @@ backend (OpenClaw or Hermes) running on Agent Substrate. | `kind` _string_ | `AgentHarness` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[AgentHarnessSpec](#agentharnessspec)_ | | | | | `status` _[AgentHarnessStatus](#agentharnessstatus)_ | | | | @@ -212,7 +212,7 @@ _Appears in:_ | `substrate` _[AgentHarnessSubstrateSpec](#agentharnesssubstratespec)_ | Substrate configures the Agent Substrate provisioning stack. Required. | | | | `description` _string_ | Description is a short human-readable summary shown in the UI (e.g. agents list). | | | | `image` _string_ | Image is the container image to run in the harness VM, if the backend
      supports per-resource images. Backend openclaw pins the image
      to the OpenClaw sandbox base when this field is empty; backend hermes pins
      to the Hermes sandbox base image when empty. | | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core) array_ | Env is a list of environment variables injected into the harness workload.
      Values use the Kubernetes EnvVar shape; ValueFrom references are
      resolved server-side where supported. | | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envvar-v1-core) array_ | Env is a list of environment variables injected into the harness workload.
      Values use the Kubernetes EnvVar shape; ValueFrom references are
      resolved server-side where supported. | | | | `modelConfigRef` _string_ | ModelConfigRef is the reference to the ModelConfig used to configure the harness.
      The controller registers the gateway provider and, after the harness is Ready,
      writes OpenClaw config inside the VM (~/.openclaw/openclaw.json) and starts the gateway. | | | | `channels` _[AgentHarnessChannel](#agentharnesschannel) array_ | Channels configures Telegram and Slack integrations for OpenClaw inside the harness VM. | | MaxItems: 1024
      | @@ -226,7 +226,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `observedGeneration` _integer_ | | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | | | `backendRef` _[AgentHarnessStatusRef](#agentharnessstatusref)_ | BackendRef points at the harness instance on the backend control
      plane, once Ensure has succeeded at least once. | | | | `connection` _[AgentHarnessConnection](#agentharnessconnection)_ | Connection is populated by the controller when the harness is ready. | | | @@ -348,7 +348,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `observedGeneration` _integer_ | | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | | #### AgentType @@ -384,7 +384,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `from` _[FromNamespaces](#fromnamespaces)_ | From indicates where references to this resource can originate.
      Possible values are:
      * All: References from all namespaces are allowed.
      * Same: Only references from the same namespace are allowed (default).
      * Selector: References from namespaces matching the selector are allowed. | Same | Enum: [All Same Selector]
      | -| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#labelselector-v1-meta)_ | Selector is a label selector for namespaces that are allowed to reference this resource.
      Only used when From is set to "Selector". | | | +| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#labelselector-v1-meta)_ | Selector is a label selector for namespaces that are allowed to reference this resource.
      Only used when From is set to "Selector". | | | #### AnthropicConfig @@ -468,7 +468,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `region` _string_ | AWS region where the Bedrock model is available (e.g., us-east-1, us-west-2) | | | -| `additionalModelRequestFields` _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#json-v1-apiextensions-k8s-io)_ | AdditionalModelRequestFields passes model-specific parameters to Bedrock's
      additionalModelRequestFields in the Converse API. Use this for provider-specific
      options that are not part of the standard InferenceConfiguration block, such as
      Claude extended thinking or top_k. Values are forwarded as-is to the API.
      Example: \{"top_k": 5, "thinking": \{"type": "enabled", "budget_tokens": 16000\}\} | | | +| `additionalModelRequestFields` _[JSON](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#json-v1-apiextensions-k8s-io)_ | AdditionalModelRequestFields passes model-specific parameters to Bedrock's
      additionalModelRequestFields in the Converse API. Use this for provider-specific
      options that are not part of the standard InferenceConfiguration block, such as
      Claude extended thinking or top_k. Values are forwarded as-is to the API.
      Example: \{"top_k": 5, "thinking": \{"type": "enabled", "budget_tokens": 16000\}\} | | | | `promptCaching` _boolean_ | PromptCaching enables Bedrock prompt caching by appending a CachePoint
      block at the end of the Converse request's `system` content array and
      the end of the `toolConfig.tools` array. Bedrock will cache the prefix up to and
      including those cache points across requests in the same region for
      roughly 5 minutes after first use, billing the cached portion at a
      reduced rate on cache hits.

      Recommended for tool-using agents that make many Converse calls per
      task with a stable system prompt and tool set — the per-call input
      token count can drop by 70-90% on hit. Has no effect on models that
      don't support caching; the marker is ignored by Bedrock for those.

      See https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
      for the current list of supported models and minimum prefix sizes. | false | | | `cacheTTL` _string_ | CacheTTL controls how long Bedrock retains a cached prefix when
      PromptCaching is enabled. Only meaningful when PromptCaching is true.

      - "5m" (default): Bedrock's standard 5-minute sliding cache. Each cache
      hit refreshes the window. Supported by all prompt-caching models.
      - "1h": extended-TTL caching, useful for tasks whose Converse calls are
      spaced more than 5 minutes apart.

      NOTE: "1h" is NOT strictly better than "5m". Extended-TTL cache writes are
      billed at a higher per-token rate than 5-minute writes, and 1h is supported
      on a narrower set of models. Only choose "1h" when calls are spaced far
      enough apart that a 5-minute cache would expire between them; otherwise the
      higher write cost is wasted. See the AWS prompt-caching docs above. | 5m | Enum: [5m 1h]
      | | `guardrail` _[BedrockGuardrailConfig](#bedrockguardrailconfig)_ | | | | @@ -498,25 +498,24 @@ _Appears in:_ | `args` _string array_ | Args are the arguments passed to the container entrypoint. | | | | `workingDir` _string_ | workingDir sets the container working directory. Defaults to the image WORKDIR when omitted. | | | | `replicas` _integer_ | Replicas is the number of desired agent pods. Defaults to 1. | | | -| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core) array_ | ImagePullSecrets are references to secrets in the agent's namespace
      used for pulling the agent container image. | | | -| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volume-v1-core) array_ | Volumes are additional volumes added to the agent pod. | | | -| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volumemount-v1-core) array_ | VolumeMounts are additional volume mounts added to the agent container. | | | +| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core) array_ | ImagePullSecrets are references to secrets in the agent's namespace
      used for pulling the agent container image. | | | +| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | Volumes are additional volumes added to the agent pod. | | | +| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | VolumeMounts are additional volume mounts added to the agent container. | | | | `labels` _object (keys:string, values:string)_ | Labels are additional labels added to the agent pods. | | | | `annotations` _object (keys:string, values:string)_ | Annotations are additional annotations added to the agent pods. | | | | `deploymentAnnotations` _object (keys:string, values:string)_ | DeploymentAnnotations are additional annotations added to the agent Deployment
      object itself. Unlike Annotations, which apply to the agent pods, these apply to
      the Deployment metadata. Keys set here take precedence over annotations inherited
      from the agent resource metadata. This has no effect when the agent runs with the
      Sandbox workload mode, as no Deployment is created in that mode. | | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core) array_ | Env are additional environment variables set on the agent container. | | | -| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envfromsource-v1-core) array_ | EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
      on the agent container. Values defined in Env with a duplicate key take precedence. | | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#pullpolicy-v1-core)_ | | | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#resourcerequirements-v1-core)_ | | | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#toleration-v1-core) array_ | Tolerations applied to the agent pods. | | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#affinity-v1-core)_ | | | | -| `topologySpreadConstraints` _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#topologyspreadconstraint-v1-core) array_ | TopologySpreadConstraints describes how a group of pods ought to spread across topology
      domains. All topologySpreadConstraints are ANDed. | | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envvar-v1-core) array_ | Env are additional environment variables set on the agent container. | | | +| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envfromsource-v1-core) array_ | EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
      on the agent container. Values defined in Env with a duplicate key take precedence. | | | +| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#pullpolicy-v1-core)_ | | | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#resourcerequirements-v1-core)_ | | | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#toleration-v1-core) array_ | Tolerations applied to the agent pods. | | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#affinity-v1-core)_ | | | | | `nodeSelector` _object (keys:string, values:string)_ | NodeSelector restricts the nodes the agent pods can be scheduled on. | | | -| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#securitycontext-v1-core)_ | | | | -| `podSecurityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#podsecuritycontext-v1-core)_ | | | | +| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#securitycontext-v1-core)_ | | | | +| `podSecurityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#podsecuritycontext-v1-core)_ | | | | | `serviceAccountName` _string_ | ServiceAccountName specifies the name of an existing ServiceAccount to use.
      If this field is set, the Agent controller will not create a ServiceAccount for the agent.
      This field is mutually exclusive with ServiceAccountConfig. | | | | `serviceAccountConfig` _[ServiceAccountConfig](#serviceaccountconfig)_ | ServiceAccountConfig configures the ServiceAccount created by the Agent controller.
      This field can only be used when ServiceAccountName is not set.
      If ServiceAccountName is not set, a default ServiceAccount (named after the agent)
      is created, and this config will be applied to it. | | | -| `extraContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#container-v1-core) array_ | ExtraContainers is a list of additional containers to run alongside the main agent container.
      Useful for sidecars such as token proxies, log shippers, or security agents. | | | +| `extraContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#container-v1-core) array_ | ExtraContainers is a list of additional containers to run alongside the main agent container.
      Useful for sidecars such as token proxies, log shippers, or security agents. | | | #### ContextCompressionConfig @@ -573,6 +572,7 @@ _Appears in:_ | `tools` _[Tool](#tool) array_ | | | MaxItems: 20
      | | `a2aConfig` _[A2AConfig](#a2aconfig)_ | A2AConfig instantiates an A2A server for this agent,
      served on the HTTP port of the kagent kubernetes
      controller (default 8083).
      The A2A server URL will be served at
      <kagent-controller-ip>:8083/api/a2a/<agent-namespace>/<agent-name>
      Read more about the A2A protocol here: https://github.com/a2aproject/A2A | | | | `deployment` _[DeclarativeDeploymentSpec](#declarativedeploymentspec)_ | | | | +| `executeCodeBlocks` _boolean_ | Allow code execution for python code blocks with this agent.
      If true, the agent will automatically execute python code blocks in the LLM responses.
      Code will be executed in a sandboxed environment.
      due to a bug in adk (https://github.com/google/adk-python/issues/3921 ), this field is ignored for now. | | | | `memory` _[MemorySpec](#memoryspec)_ | Memory configuration for the agent. | | | | `shareTools` _boolean_ | ShareTools enables the built-in share link tools for this agent.
      When true, the agent gains create_share_link, list_share_links, and delete_share_link tools
      that allow it to manage share tokens for the current session. | | | | `context` _[ContextConfig](#contextconfig)_ | Context configures context management for this agent.
      This includes event compaction (compression) and context caching. | | | @@ -586,25 +586,24 @@ _Appears in:_ | --- | --- | --- | --- | | `imageRegistry` _string_ | | | | | `replicas` _integer_ | Replicas is the number of desired agent pods. Defaults to 1. | | | -| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core) array_ | ImagePullSecrets are references to secrets in the agent's namespace
      used for pulling the agent container image. | | | -| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volume-v1-core) array_ | Volumes are additional volumes added to the agent pod. | | | -| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volumemount-v1-core) array_ | VolumeMounts are additional volume mounts added to the agent container. | | | +| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core) array_ | ImagePullSecrets are references to secrets in the agent's namespace
      used for pulling the agent container image. | | | +| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | Volumes are additional volumes added to the agent pod. | | | +| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | VolumeMounts are additional volume mounts added to the agent container. | | | | `labels` _object (keys:string, values:string)_ | Labels are additional labels added to the agent pods. | | | | `annotations` _object (keys:string, values:string)_ | Annotations are additional annotations added to the agent pods. | | | | `deploymentAnnotations` _object (keys:string, values:string)_ | DeploymentAnnotations are additional annotations added to the agent Deployment
      object itself. Unlike Annotations, which apply to the agent pods, these apply to
      the Deployment metadata. Keys set here take precedence over annotations inherited
      from the agent resource metadata. This has no effect when the agent runs with the
      Sandbox workload mode, as no Deployment is created in that mode. | | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core) array_ | Env are additional environment variables set on the agent container. | | | -| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envfromsource-v1-core) array_ | EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
      on the agent container. Values defined in Env with a duplicate key take precedence. | | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#pullpolicy-v1-core)_ | | | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#resourcerequirements-v1-core)_ | | | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#toleration-v1-core) array_ | Tolerations applied to the agent pods. | | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#affinity-v1-core)_ | | | | -| `topologySpreadConstraints` _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#topologyspreadconstraint-v1-core) array_ | TopologySpreadConstraints describes how a group of pods ought to spread across topology
      domains. All topologySpreadConstraints are ANDed. | | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envvar-v1-core) array_ | Env are additional environment variables set on the agent container. | | | +| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envfromsource-v1-core) array_ | EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
      on the agent container. Values defined in Env with a duplicate key take precedence. | | | +| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#pullpolicy-v1-core)_ | | | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#resourcerequirements-v1-core)_ | | | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#toleration-v1-core) array_ | Tolerations applied to the agent pods. | | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#affinity-v1-core)_ | | | | | `nodeSelector` _object (keys:string, values:string)_ | NodeSelector restricts the nodes the agent pods can be scheduled on. | | | -| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#securitycontext-v1-core)_ | | | | -| `podSecurityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#podsecuritycontext-v1-core)_ | | | | +| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#securitycontext-v1-core)_ | | | | +| `podSecurityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#podsecuritycontext-v1-core)_ | | | | | `serviceAccountName` _string_ | ServiceAccountName specifies the name of an existing ServiceAccount to use.
      If this field is set, the Agent controller will not create a ServiceAccount for the agent.
      This field is mutually exclusive with ServiceAccountConfig. | | | | `serviceAccountConfig` _[ServiceAccountConfig](#serviceaccountconfig)_ | ServiceAccountConfig configures the ServiceAccount created by the Agent controller.
      This field can only be used when ServiceAccountName is not set.
      If ServiceAccountName is not set, a default ServiceAccount (named after the agent)
      is created, and this config will be applied to it. | | | -| `extraContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#container-v1-core) array_ | ExtraContainers is a list of additional containers to run alongside the main agent container.
      Useful for sidecars such as token proxies, log shippers, or security agents. | | | +| `extraContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#container-v1-core) array_ | ExtraContainers is a list of additional containers to run alongside the main agent container.
      Useful for sidecars such as token proxies, log shippers, or security agents. | | | #### DeclarativeRuntime @@ -639,7 +638,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `endpoint` _string_ | Endpoint is the Foundry or Azure AI Services account endpoint
      (e.g., https://my-account.cognitiveservices.azure.com/).
      Mutually exclusive with EndpointFrom. | | | -| `endpointFrom` _[ConfigMapKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#configmapkeyselector-v1-core)_ | EndpointFrom resolves the Foundry endpoint from a ConfigMap key, such as
      one written by Azure Service Operator. Mutually exclusive with Endpoint.

      The selector's optional flag only controls how a missing key is handled: when
      set to true, the missing key is ignored while reading the ConfigMap, but a
      Foundry endpoint must always be supplied, so an unresolved endpointFrom still
      leaves the model unusable and the agent fails to start. | | | +| `endpointFrom` _[ConfigMapKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#configmapkeyselector-v1-core)_ | EndpointFrom resolves the Foundry endpoint from a ConfigMap key, such as
      one written by Azure Service Operator. Mutually exclusive with Endpoint.

      The selector's optional flag only controls how a missing key is handled: when
      set to true, the missing key is ignored while reading the ConfigMap, but a
      Foundry endpoint must always be supplied, so an unresolved endpointFrom still
      leaves the model unusable and the agent fails to start. | | | | `deployment` _string_ | Deployment is the Foundry model deployment name. | | | | `apiVersion` _string_ | APIVersion is the Foundry OpenAI-compatible data-plane API version. | 2024-10-21 | | @@ -765,7 +764,7 @@ ModelConfig is the Schema for the modelconfigs API. | `kind` _string_ | `ModelConfig` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[ModelConfigSpec](#modelconfigspec)_ | | | | | `status` _[ModelConfigStatus](#modelconfigstatus)_ | | | | @@ -805,7 +804,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | | | `observedGeneration` _integer_ | | | | | `secretHash` _string_ | The secret hash stores a hash of any secrets required by the model config (i.e. api key, tls cert) to ensure agents referencing this model config detect changes to these secrets and restart if necessary. | | | @@ -846,7 +845,7 @@ It represents a model provider configuration with automatic model discovery. | `kind` _string_ | `ModelProviderConfig` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[ModelProviderConfigSpec](#modelproviderconfigspec)_ | | | | | `status` _[ModelProviderConfigStatus](#modelproviderconfigstatus)_ | | | | @@ -873,10 +872,10 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `observedGeneration` _integer_ | ObservedGeneration reflects the generation of the most recently observed ModelProviderConfig spec | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | Conditions represent the latest available observations of the ModelProviderConfig's state | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | Conditions represent the latest available observations of the ModelProviderConfig's state | | | | `discoveredModels` _string array_ | DiscoveredModels is the cached list of model IDs available from this model provider | | | | `modelCount` _integer_ | ModelCount is the number of discovered models (for kubectl display) | | | -| `lastDiscoveryTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#time-v1-meta)_ | LastDiscoveryTime is the timestamp of the last successful model discovery | | | +| `lastDiscoveryTime` _[Time](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#time-v1-meta)_ | LastDiscoveryTime is the timestamp of the last successful model discovery | | | | `secretHash` _string_ | SecretHash is a hash of the referenced secret data, used to detect secret changes | | | #### NetworkConfig @@ -906,7 +905,7 @@ _Appears in:_ _Underlying type:_ _string_ -OpenAIAPIFormat selects the OpenAI HTTP API shape used by the Go ADK runtime. +OpenAIAPIFormat selects the OpenAI HTTP API shape used by the ADK runtime. _Validation:_ - Enum: [chatCompletions responses] @@ -994,7 +993,7 @@ RemoteMCPServer is the Schema for the RemoteMCPServers API. | `kind` _string_ | `RemoteMCPServer` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[RemoteMCPServerSpec](#remotemcpserverspec)_ | | | | | `status` _[RemoteMCPServerStatus](#remotemcpserverstatus)_ | | | | @@ -1026,8 +1025,8 @@ _Appears in:_ | `protocol` _[RemoteMCPServerProtocol](#remotemcpserverprotocol)_ | | STREAMABLE_HTTP | Enum: [SSE STREAMABLE_HTTP]
      | | `url` _string_ | | | MinLength: 1
      | | `headersFrom` _[ValueRef](#valueref) array_ | | | | -| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#duration-v1-meta)_ | | 30s | | -| `sseReadTimeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#duration-v1-meta)_ | | | | +| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#duration-v1-meta)_ | | 30s | | +| `sseReadTimeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#duration-v1-meta)_ | | | | | `terminateOnClose` _boolean_ | | true | | | `allowedNamespaces` _[AllowedNamespaces](#allowednamespaces)_ | AllowedNamespaces defines which namespaces are allowed to reference this RemoteMCPServer.
      This follows the Gateway API pattern for cross-namespace route attachments.
      If not specified, only Agents in the same namespace can reference this RemoteMCPServer.
      See: https://gateway-api.sigs.k8s.io/guides/multiple-ns/#cross-namespace-route-attachment

      A cross-namespace-permitting value (from: All or from: Selector) is
      mutually exclusive with spec.tls.caCertSecretRef (enforced by a spec-level
      XValidation rule): a pinned CA Secret is mounted onto the consuming agent's
      pod by bare name and Kubernetes resolves it in the agent's namespace, not
      this RemoteMCPServer's, so a CA-pinning RemoteMCPServer cannot be referenced
      cross-namespace. from: Same (the default) is always allowed. | | | | `tls` _[TLSConfig](#tlsconfig)_ | TLS configuration for the upstream MCP server connection.
      Use this for HTTPS upstreams that present a certificate the agent's
      system trust store does not include (corporate CA, self-signed cert
      on a test fixture, internal MCP gateway). Reuses the same TLSConfig
      type as ModelConfig.spec.tls — disableVerify turns off certificate
      validation entirely, caCertSecretRef + caCertSecretKey point at a
      PEM bundle Secret in the same namespace, and disableSystemCAs
      trusts only the named bundle.

      Note one asymmetry with ModelConfig: a spec-level XValidation rule
      on RemoteMCPServer rejects spec.tls when spec.url has the http://
      scheme (a TLS opinion contradicts a plaintext URL). ModelConfig has
      no equivalent rule, so a TLS block can sit alongside any baseUrl. | | | @@ -1042,7 +1041,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `observedGeneration` _integer_ | INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
      Important: Run "make" to regenerate code after modifying this file | | | -| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | | | | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | | | | | `discoveredTools` _[MCPTool](#mcptool) array_ | | | | | `secretHash` _string_ | SecretHash stores a hash of the TLS Secret referenced by spec.tls so
      agents that consume this RemoteMCPServer can detect cert rotation and
      roll on the next reconcile. Empty when spec.tls.caCertSecretRef is unset. | | | @@ -1086,7 +1085,7 @@ SandboxAgent declares an agent that runs in an isolated sandbox on Agent Substra | `kind` _string_ | `SandboxAgent` | | | | `kind` _string_ | Kind is a string value representing the REST resource this object represents.
      Servers may infer this from the endpoint the client submits requests to.
      Cannot be updated.
      In CamelCase.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | | | `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.
      Servers should convert recognized schemas to the latest internal value, and
      may reject unrecognized values.
      More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | | -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | | `spec` _[SandboxAgentSpec](#sandboxagentspec)_ | | | | | `status` _[AgentStatus](#agentstatus)_ | | | | @@ -1168,25 +1167,24 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `replicas` _integer_ | Replicas is the number of desired agent pods. Defaults to 1. | | | -| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core) array_ | ImagePullSecrets are references to secrets in the agent's namespace
      used for pulling the agent container image. | | | -| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volume-v1-core) array_ | Volumes are additional volumes added to the agent pod. | | | -| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volumemount-v1-core) array_ | VolumeMounts are additional volume mounts added to the agent container. | | | +| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core) array_ | ImagePullSecrets are references to secrets in the agent's namespace
      used for pulling the agent container image. | | | +| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volume-v1-core) array_ | Volumes are additional volumes added to the agent pod. | | | +| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#volumemount-v1-core) array_ | VolumeMounts are additional volume mounts added to the agent container. | | | | `labels` _object (keys:string, values:string)_ | Labels are additional labels added to the agent pods. | | | | `annotations` _object (keys:string, values:string)_ | Annotations are additional annotations added to the agent pods. | | | | `deploymentAnnotations` _object (keys:string, values:string)_ | DeploymentAnnotations are additional annotations added to the agent Deployment
      object itself. Unlike Annotations, which apply to the agent pods, these apply to
      the Deployment metadata. Keys set here take precedence over annotations inherited
      from the agent resource metadata. This has no effect when the agent runs with the
      Sandbox workload mode, as no Deployment is created in that mode. | | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core) array_ | Env are additional environment variables set on the agent container. | | | -| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envfromsource-v1-core) array_ | EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
      on the agent container. Values defined in Env with a duplicate key take precedence. | | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#pullpolicy-v1-core)_ | | | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#resourcerequirements-v1-core)_ | | | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#toleration-v1-core) array_ | Tolerations applied to the agent pods. | | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#affinity-v1-core)_ | | | | -| `topologySpreadConstraints` _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#topologyspreadconstraint-v1-core) array_ | TopologySpreadConstraints describes how a group of pods ought to spread across topology
      domains. All topologySpreadConstraints are ANDed. | | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envvar-v1-core) array_ | Env are additional environment variables set on the agent container. | | | +| `envFrom` _[EnvFromSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envfromsource-v1-core) array_ | EnvFrom are sources (ConfigMaps/Secrets) used to populate environment variables
      on the agent container. Values defined in Env with a duplicate key take precedence. | | | +| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#pullpolicy-v1-core)_ | | | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#resourcerequirements-v1-core)_ | | | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#toleration-v1-core) array_ | Tolerations applied to the agent pods. | | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#affinity-v1-core)_ | | | | | `nodeSelector` _object (keys:string, values:string)_ | NodeSelector restricts the nodes the agent pods can be scheduled on. | | | -| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#securitycontext-v1-core)_ | | | | -| `podSecurityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#podsecuritycontext-v1-core)_ | | | | +| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#securitycontext-v1-core)_ | | | | +| `podSecurityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#podsecuritycontext-v1-core)_ | | | | | `serviceAccountName` _string_ | ServiceAccountName specifies the name of an existing ServiceAccount to use.
      If this field is set, the Agent controller will not create a ServiceAccount for the agent.
      This field is mutually exclusive with ServiceAccountConfig. | | | | `serviceAccountConfig` _[ServiceAccountConfig](#serviceaccountconfig)_ | ServiceAccountConfig configures the ServiceAccount created by the Agent controller.
      This field can only be used when ServiceAccountName is not set.
      If ServiceAccountName is not set, a default ServiceAccount (named after the agent)
      is created, and this config will be applied to it. | | | -| `extraContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#container-v1-core) array_ | ExtraContainers is a list of additional containers to run alongside the main agent container.
      Useful for sidecars such as token proxies, log shippers, or security agents. | | | +| `extraContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#container-v1-core) array_ | ExtraContainers is a list of additional containers to run alongside the main agent container.
      Useful for sidecars such as token proxies, log shippers, or security agents. | | | #### SkillForAgent @@ -1198,8 +1196,8 @@ _Appears in:_ | --- | --- | --- | --- | | `insecureSkipVerify` _boolean_ | Fetch images insecurely from registries (allowing HTTP and skipping TLS verification).
      Meant for development and testing purposes only. | | | | `refs` _string array_ | The list of skill images to fetch. | | MaxItems: 20
      MinItems: 1
      | -| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core) array_ | ImagePullSecrets is a list of references to secrets in the same namespace to use for
      pulling skill images from private registries. Each referenced secret must be of type
      kubernetes.io/dockerconfigjson. The credentials from all secrets are merged and made
      available to the skills-init container at /.kagent/.docker/config.json; krane will
      use them automatically when pulling images. | | MaxItems: 20
      | -| `gitAuthSecretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#localobjectreference-v1-core)_ | Reference to a Secret containing git credentials.
      Applied to all gitRefs entries.
      The secret should contain a `token` key for HTTPS auth,
      or `ssh-privatekey` for SSH auth. | | | +| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core) array_ | ImagePullSecrets is a list of references to secrets in the same namespace to use for
      pulling skill images from private registries. Each referenced secret must be of type
      kubernetes.io/dockerconfigjson. The credentials from all secrets are merged and made
      available to the skills-init container at /.kagent/.docker/config.json; krane will
      use them automatically when pulling images. | | MaxItems: 20
      | +| `gitAuthSecretRef` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#localobjectreference-v1-core)_ | Reference to a Secret containing git credentials.
      Applied to all gitRefs entries.
      The secret should contain a `token` key for HTTPS auth,
      or `ssh-privatekey` for SSH auth. | | | | `gitRefs` _[GitRepo](#gitrepo) array_ | Git repositories to fetch skills from. | | MaxItems: 20
      MinItems: 1
      | | `s3Refs` _[S3SkillRef](#s3skillref) array_ | S3 object prefixes or archives to fetch skills from.
      Auth uses the AWS SDK default credential chain (typically static keys via
      skills.initContainer.env: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION). | | MaxItems: 20
      MinItems: 1
      | | `initContainer` _[SkillsInitContainer](#skillsinitcontainer)_ | Configuration for the skills-init init container. | | | @@ -1213,8 +1211,8 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#resourcerequirements-v1-core)_ | Resource requirements for the skills-init init container. | | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#envvar-v1-core) array_ | Additional environment variables for the skills-init init container. | | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#resourcerequirements-v1-core)_ | Resource requirements for the skills-init init container. | | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#envvar-v1-core) array_ | Additional environment variables for the skills-init init container. | | | #### TLSConfig diff --git a/docs-site/content/kagent/0.x/resources/cli/_index.md b/docs-site/content/kagent/0.x/resources/cli/_index.md index 10bdf865..6dfbcbfb 100644 --- a/docs-site/content/kagent/0.x/resources/cli/_index.md +++ b/docs-site/content/kagent/0.x/resources/cli/_index.md @@ -1,23 +1,23 @@ --- title: CLI docs -description: Complete reference docs for the kagent CLI commands +description: Review the reference docs for the kagent CLI commands. weight: 1 --- Review the kagent CLI commands and learn how to use them effectively. -- [`kagent add-mcp`]({{< link path="resources/cli/kagent-add-mcp/" >}}) - Add an MCP server entry to kagent.yaml -- [`kagent bug-report`]({{< link path="resources/cli/kagent-bug-report/" >}}) - Generate a bug report -- [`kagent build`]({{< link path="resources/cli/kagent-build/" >}}) - Build a Docker images for an agent project -- [`kagent completion`]({{< link path="resources/cli/kagent-completion/" >}}) - Generate the autocompletion script for the specified shell -- [`kagent dashboard`]({{< link path="resources/cli/kagent-dashboard/" >}}) - Open the kagent dashboard -- [`kagent db`]({{< link path="resources/cli/kagent-db/" >}}) - Database operations (migrations, inspection) -- [`kagent deploy`]({{< link path="resources/cli/kagent-deploy/" >}}) - Deploy an agent to Kubernetes -- [`kagent get`]({{< link path="resources/cli/kagent-get/" >}}) - Get a kagent resource -- [`kagent init`]({{< link path="resources/cli/kagent-init/" >}}) - Initialize a new agent project -- [`kagent install`]({{< link path="resources/cli/kagent-install/" >}}) - Install kagent -- [`kagent invoke`]({{< link path="resources/cli/kagent-invoke/" >}}) - Invoke a kagent agent -- [`kagent mcp`]({{< link path="resources/cli/kagent-mcp/" >}}) - MCP (Model Context Protocol) server management -- [`kagent run`]({{< link path="resources/cli/kagent-run/" >}}) - Run agent project locally with docker-compose and launch chat interface -- [`kagent uninstall`]({{< link path="resources/cli/kagent-uninstall/" >}}) - Uninstall kagent -- [`kagent version`]({{< link path="resources/cli/kagent-version/" >}}) - Print the kagent version +- [`kagent add-mcp`](/docs/kagent/0.x/resources/cli/kagent-add-mcp/) - Add an MCP server entry to kagent.yaml +- [`kagent bug-report`](/docs/kagent/0.x/resources/cli/kagent-bug-report/) - Generate a bug report +- [`kagent build`](/docs/kagent/0.x/resources/cli/kagent-build/) - Build a Docker images for an agent project +- [`kagent completion`](/docs/kagent/0.x/resources/cli/kagent-completion/) - Generate the autocompletion script for the specified shell +- [`kagent dashboard`](/docs/kagent/0.x/resources/cli/kagent-dashboard/) - Open the kagent dashboard +- [`kagent db`](/docs/kagent/0.x/resources/cli/kagent-db/) - Database operations (migrations, inspection) +- [`kagent deploy`](/docs/kagent/0.x/resources/cli/kagent-deploy/) - Deploy an agent to Kubernetes +- [`kagent get`](/docs/kagent/0.x/resources/cli/kagent-get/) - Get a kagent resource +- [`kagent init`](/docs/kagent/0.x/resources/cli/kagent-init/) - Initialize a new agent project +- [`kagent install`](/docs/kagent/0.x/resources/cli/kagent-install/) - Install kagent +- [`kagent invoke`](/docs/kagent/0.x/resources/cli/kagent-invoke/) - Invoke a kagent agent +- [`kagent mcp`](/docs/kagent/0.x/resources/cli/kagent-mcp/) - MCP (Model Context Protocol) server management +- [`kagent run`](/docs/kagent/0.x/resources/cli/kagent-run/) - Run agent project locally with docker-compose and launch chat interface +- [`kagent uninstall`](/docs/kagent/0.x/resources/cli/kagent-uninstall/) - Uninstall kagent +- [`kagent version`](/docs/kagent/0.x/resources/cli/kagent-version/) - Print the kagent version diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md b/docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md index 735bcfe9..b5621a24 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md @@ -1,6 +1,6 @@ --- title: kagent add-mcp -description: Add an MCP server entry to kagent.yaml +description: Add an MCP server entry to kagent.yaml. weight: 10 --- @@ -23,11 +23,7 @@ kagent add-mcp [name] [args...] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md b/docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md index d374c640..fd1dc09f 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md @@ -1,6 +1,6 @@ --- title: kagent bug-report -description: Generate a bug report +description: Generate a bug report. weight: 20 --- @@ -15,11 +15,7 @@ kagent bug-report [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-build.md b/docs-site/content/kagent/0.x/resources/cli/kagent-build.md index 36c1fc16..b4c343cb 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-build.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-build.md @@ -1,6 +1,6 @@ --- title: kagent build -description: Build a Docker images for an agent project +description: Build a Docker images for an agent project. weight: 30 --- @@ -24,11 +24,7 @@ kagent build [project-directory] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-bash.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-bash.md index 91f109cd..f8295a4b 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-bash.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-bash.md @@ -1,6 +1,6 @@ --- title: kagent completion bash -description: Generate the autocompletion script for bash +description: Generate the autocompletion script for bash. weight: 50 --- @@ -35,11 +35,7 @@ kagent completion bash **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-fish.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-fish.md index bda214e4..a29ab438 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-fish.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-fish.md @@ -1,6 +1,6 @@ --- title: kagent completion fish -description: Generate the autocompletion script for fish +description: Generate the autocompletion script for fish. weight: 60 --- @@ -26,11 +26,7 @@ kagent completion fish [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-powershell.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-powershell.md index 1ef996fd..8134a3b3 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-powershell.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-powershell.md @@ -1,6 +1,6 @@ --- title: kagent completion powershell -description: Generate the autocompletion script for powershell +description: Generate the autocompletion script for powershell. weight: 70 --- @@ -23,11 +23,7 @@ kagent completion powershell [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-zsh.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-zsh.md index c13d5513..5cc027ca 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-completion-zsh.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-zsh.md @@ -1,6 +1,6 @@ --- title: kagent completion zsh -description: Generate the autocompletion script for zsh +description: Generate the autocompletion script for zsh. weight: 80 --- @@ -37,11 +37,7 @@ kagent completion zsh [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-completion.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion.md index 3b20ee01..eb61ee8b 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-completion.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-completion.md @@ -1,6 +1,6 @@ --- title: kagent completion -description: Generate the autocompletion script for the specified shell +description: Generate the autocompletion script for the specified shell. weight: 40 --- @@ -12,21 +12,17 @@ kagent completion [command] ``` **Subcommands:** -- [`kagent completion bash`]({{< link path="resources/cli/kagent-completion-bash/" >}}) - Generate the autocompletion script for bash -- [`kagent completion fish`]({{< link path="resources/cli/kagent-completion-fish/" >}}) - Generate the autocompletion script for fish -- [`kagent completion powershell`]({{< link path="resources/cli/kagent-completion-powershell/" >}}) - Generate the autocompletion script for powershell -- [`kagent completion zsh`]({{< link path="resources/cli/kagent-completion-zsh/" >}}) - Generate the autocompletion script for zsh +- [`kagent completion bash`](/docs/kagent/0.x/resources/cli/kagent-completion-bash/) - Generate the autocompletion script for bash +- [`kagent completion fish`](/docs/kagent/0.x/resources/cli/kagent-completion-fish/) - Generate the autocompletion script for fish +- [`kagent completion powershell`](/docs/kagent/0.x/resources/cli/kagent-completion-powershell/) - Generate the autocompletion script for powershell +- [`kagent completion zsh`](/docs/kagent/0.x/resources/cli/kagent-completion-zsh/) - Generate the autocompletion script for zsh **Flags:** - `-h, --help` - help for completion **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md b/docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md index ecd1c723..3d3b1c98 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md @@ -1,6 +1,6 @@ --- title: kagent dashboard -description: Open the kagent dashboard +description: Open the kagent dashboard. weight: 90 --- @@ -15,11 +15,7 @@ kagent dashboard [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-down.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-down.md index 3ed29cce..0ad94d99 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-down.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-down.md @@ -1,6 +1,6 @@ --- title: kagent db migrate down -description: Roll back the N most-recent applied migrations for the selected source +description: Roll back the N most-recent applied migrations for the selected source. weight: 120 --- @@ -19,8 +19,4 @@ kagent db migrate down N [flags] **Global Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-force.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-force.md index b4cc6cdc..2b48b95f 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-force.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-force.md @@ -1,6 +1,6 @@ --- title: kagent db migrate force -description: Mark version V as applied without running its SQL +description: Mark version V as applied without running its SQL. weight: 130 --- @@ -20,8 +20,4 @@ kagent db migrate force V [flags] **Global Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-goto.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-goto.md index fbab53ce..d1318caf 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-goto.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-goto.md @@ -1,6 +1,6 @@ --- title: kagent db migrate goto -description: Move the selected source's schema to version V +description: Move the selected source's schema to version V. weight: 140 --- @@ -20,8 +20,4 @@ kagent db migrate goto V [flags] **Global Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-status.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-status.md index 92762ebc..26b1e270 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-status.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-status.md @@ -1,6 +1,6 @@ --- title: kagent db migrate status -description: Show how many migrations are applied vs pending across all sources +description: Show how many migrations are applied vs pending across all sources. weight: 150 --- @@ -16,8 +16,4 @@ kagent db migrate status [flags] **Global Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-up.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-up.md index feb5de31..da443958 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-up.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-up.md @@ -1,6 +1,6 @@ --- title: kagent db migrate up -description: Apply all pending migrations across every registered source +description: Apply all pending migrations across every registered source. weight: 160 --- @@ -24,8 +24,4 @@ kagent db migrate up [flags] **Global Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-version.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-version.md index 451bae2a..4e1d9a46 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-version.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-version.md @@ -1,6 +1,6 @@ --- title: kagent db migrate version -description: Print the highest applied migration version +description: Print the highest applied migration version. weight: 170 --- @@ -18,8 +18,4 @@ kagent db migrate version [flags] **Global Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate.md index ce2e545b..9c845747 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate.md @@ -1,6 +1,6 @@ --- title: kagent db migrate -description: Apply, roll back, and inspect database migrations +description: Apply, roll back, and inspect database migrations. weight: 110 --- @@ -13,20 +13,14 @@ kagent db migrate [command] ``` **Subcommands:** -- [`kagent db migrate down`]({{< link path="resources/cli/kagent-db-migrate-down/" >}}) - Roll back the N most-recent applied migrations for the selected source -- [`kagent db migrate force`]({{< link path="resources/cli/kagent-db-migrate-force/" >}}) - Mark version V as applied without running its SQL -- [`kagent db migrate goto`]({{< link path="resources/cli/kagent-db-migrate-goto/" >}}) - Move the selected source's schema to version V -- [`kagent db migrate status`]({{< link path="resources/cli/kagent-db-migrate-status/" >}}) - Show how many migrations are applied vs pending across all sources -- [`kagent db migrate up`]({{< link path="resources/cli/kagent-db-migrate-up/" >}}) - Apply all pending migrations across every registered source -- [`kagent db migrate version`]({{< link path="resources/cli/kagent-db-migrate-version/" >}}) - Print the highest applied migration version +- [`kagent db migrate down`](/docs/kagent/0.x/resources/cli/kagent-db-migrate-down/) - Roll back the N most-recent applied migrations for the selected source +- [`kagent db migrate force`](/docs/kagent/0.x/resources/cli/kagent-db-migrate-force/) - Mark version V as applied without running its SQL +- [`kagent db migrate goto`](/docs/kagent/0.x/resources/cli/kagent-db-migrate-goto/) - Move the selected source's schema to version V +- [`kagent db migrate status`](/docs/kagent/0.x/resources/cli/kagent-db-migrate-status/) - Show how many migrations are applied vs pending across all sources +- [`kagent db migrate up`](/docs/kagent/0.x/resources/cli/kagent-db-migrate-up/) - Apply all pending migrations across every registered source +- [`kagent db migrate version`](/docs/kagent/0.x/resources/cli/kagent-db-migrate-version/) - Print the highest applied migration version **Flags:** - `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) - `-h, --help` - help for migrate - `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. - -**Global Flags:** -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-db.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db.md index 9dbc0077..81578df0 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-db.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db.md @@ -1,6 +1,6 @@ --- title: kagent db -description: Database operations (migrations, inspection) +description: Database operations (migrations, inspection). weight: 100 --- @@ -11,13 +11,7 @@ kagent db [command] ``` **Subcommands:** -- [`kagent db migrate`]({{< link path="resources/cli/kagent-db-migrate/" >}}) - Apply, roll back, and inspect database migrations +- [`kagent db migrate`](/docs/kagent/0.x/resources/cli/kagent-db-migrate/) - Apply, roll back, and inspect database migrations **Flags:** - `-h, --help` - help for db - -**Global Flags:** -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md b/docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md index 7bd0a9bf..90ce44cf 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md @@ -1,6 +1,6 @@ --- title: kagent deploy -description: Deploy an agent to Kubernetes +description: Deploy an agent to Kubernetes. weight: 180 --- @@ -43,11 +43,7 @@ kagent deploy [project-directory] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-get-agent.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get-agent.md index b34d8c97..6c197909 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-get-agent.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-get-agent.md @@ -1,6 +1,6 @@ --- title: kagent get agent -description: Get an agent or list all agents +description: Get an agent or list all agents. weight: 200 --- @@ -15,11 +15,7 @@ kagent get agent [agent_name] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-get-session.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get-session.md index 59ea9e08..a39e27b4 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-get-session.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-get-session.md @@ -1,6 +1,6 @@ --- title: kagent get session -description: Get a session or list all sessions +description: Get a session or list all sessions. weight: 210 --- @@ -15,11 +15,7 @@ kagent get session [session_id] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-get-tool.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get-tool.md index f3246a15..947b91bf 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-get-tool.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-get-tool.md @@ -1,6 +1,6 @@ --- title: kagent get tool -description: Get tools +description: Get tools. weight: 220 --- @@ -15,11 +15,7 @@ kagent get tool [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-get.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get.md index 87f2b847..cfd4def0 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-get.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-get.md @@ -1,6 +1,6 @@ --- title: kagent get -description: Get a kagent resource +description: Get a kagent resource. weight: 190 --- @@ -12,20 +12,16 @@ kagent get [command] ``` **Subcommands:** -- [`kagent get agent`]({{< link path="resources/cli/kagent-get-agent/" >}}) - Get an agent or list all agents -- [`kagent get session`]({{< link path="resources/cli/kagent-get-session/" >}}) - Get a session or list all sessions -- [`kagent get tool`]({{< link path="resources/cli/kagent-get-tool/" >}}) - Get tools +- [`kagent get agent`](/docs/kagent/0.x/resources/cli/kagent-get-agent/) - Get an agent or list all agents +- [`kagent get session`](/docs/kagent/0.x/resources/cli/kagent-get-session/) - Get a session or list all sessions +- [`kagent get tool`](/docs/kagent/0.x/resources/cli/kagent-get-tool/) - Get tools **Flags:** - `-h, --help` - help for get **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-init.md b/docs-site/content/kagent/0.x/resources/cli/kagent-init.md index 38aa96d7..73539766 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-init.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-init.md @@ -1,6 +1,6 @@ --- title: kagent init -description: Initialize a new agent project +description: Initialize a new agent project. weight: 230 --- @@ -19,16 +19,12 @@ kagent init [framework] [language] [agent-name] [flags] - `--description string` - Description for the agent - `-h, --help` - help for init - `--instruction-file string` - Path to file containing custom instructions for the root agent -- `--model-name string` - Model name (e.g., gpt-4, claude-3-5-sonnet, gemini-2.5-flash) (default "gemini-2.5-flash") +- `--model-name string` - Model name (e.g., gpt-4, claude-3-5-sonnet, gemini-2.0-flash) (default "gemini-2.0-flash") - `--model-provider string` - Model provider (OpenAI, Anthropic, Gemini) (default "Gemini") **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) @@ -39,5 +35,5 @@ kagent init [framework] [language] [agent-name] [flags] ```bash kagent init adk python dice kagent init adk python dice --instruction-file instructions.md -kagent init adk python dice --model-provider Gemini --model-name gemini-2.5-flash +kagent init adk python dice --model-provider Gemini --model-name gemini-2.0-flash ``` diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-install.md b/docs-site/content/kagent/0.x/resources/cli/kagent-install.md index c306559d..43ba936a 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-install.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-install.md @@ -1,6 +1,6 @@ --- title: kagent install -description: Install kagent +description: Install kagent. weight: 240 --- @@ -16,11 +16,7 @@ kagent install [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md b/docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md index 6fcbaf95..e5dd3d24 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md @@ -1,6 +1,6 @@ --- title: kagent invoke -description: Invoke a kagent agent +description: Invoke a kagent agent. weight: 250 --- @@ -21,11 +21,7 @@ kagent invoke [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-add-tool.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-add-tool.md index a38a3ed5..0256a618 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-add-tool.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-add-tool.md @@ -1,6 +1,6 @@ --- title: kagent mcp add-tool -description: Add a new MCP tool to your project +description: Add a new MCP tool to your project. weight: 270 --- @@ -25,11 +25,7 @@ kagent mcp add-tool [tool-name] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-build.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-build.md index 57030dea..75d1bbf4 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-build.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-build.md @@ -1,6 +1,6 @@ --- title: kagent mcp build -description: Build MCP server as a Docker image +description: Build MCP server as a Docker image. weight: 280 --- @@ -24,11 +24,7 @@ kagent mcp build [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy-package.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy-package.md index 2b0bc10b..6e07b49d 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy-package.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy-package.md @@ -1,6 +1,6 @@ --- title: kagent mcp deploy package -description: Deploy an MCP server using a package manager (npx, uvx) +description: Deploy an MCP server using a package manager (npx, uvx). weight: 300 --- @@ -32,11 +32,7 @@ kagent mcp deploy package [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy.md index 3c3fb6e2..4157b247 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy.md @@ -1,6 +1,6 @@ --- title: kagent mcp deploy -description: Deploy MCP server to Kubernetes +description: Deploy MCP server to Kubernetes. weight: 290 --- @@ -28,7 +28,7 @@ kagent mcp deploy [command] ``` **Subcommands:** -- [`kagent mcp deploy package`]({{< link path="resources/cli/kagent-mcp-deploy-package/" >}}) - Deploy an MCP server using a package manager (npx, uvx) +- [`kagent mcp deploy package`](/docs/kagent/0.x/resources/cli/kagent-mcp-deploy-package/) - Deploy an MCP server using a package manager (npx, uvx) **Flags:** - `--args strings` - Command arguments @@ -48,11 +48,7 @@ kagent mcp deploy [command] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-go.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-go.md index 671a6d1d..e932c46e 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-go.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-go.md @@ -1,6 +1,6 @@ --- title: kagent mcp init go -description: Initialize a new Go MCP server project +description: Initialize a new Go MCP server project. weight: 320 --- @@ -25,11 +25,7 @@ kagent mcp init go [project-name] [flags] - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-java.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-java.md index c13c94ac..a731583c 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-java.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-java.md @@ -1,6 +1,6 @@ --- title: kagent mcp init java -description: Initialize a new Java MCP server project +description: Initialize a new Java MCP server project. weight: 330 --- @@ -22,11 +22,7 @@ kagent mcp init java [project-name] [flags] - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-python.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-python.md index b55d8816..3897fcee 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-python.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-python.md @@ -1,6 +1,6 @@ --- title: kagent mcp init python -description: Initialize a new Python MCP server project +description: Initialize a new Python MCP server project. weight: 340 --- @@ -22,11 +22,7 @@ kagent mcp init python [project-name] [flags] - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-typescript.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-typescript.md index 3cf9fb75..0e95e136 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-typescript.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-typescript.md @@ -1,6 +1,6 @@ --- title: kagent mcp init typescript -description: Initialize a new TypeScript MCP server project +description: Initialize a new TypeScript MCP server project. weight: 350 --- @@ -22,11 +22,7 @@ kagent mcp init typescript [project-name] [flags] - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init.md index a077285e..e8b18f3c 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init.md @@ -1,6 +1,6 @@ --- title: kagent mcp init -description: Initialize a new MCP server project +description: Initialize a new MCP server project. weight: 310 --- @@ -15,10 +15,10 @@ kagent mcp init [command] ``` **Subcommands:** -- [`kagent mcp init go`]({{< link path="resources/cli/kagent-mcp-init-go/" >}}) - Initialize a new Go MCP server project -- [`kagent mcp init java`]({{< link path="resources/cli/kagent-mcp-init-java/" >}}) - Initialize a new Java MCP server project -- [`kagent mcp init python`]({{< link path="resources/cli/kagent-mcp-init-python/" >}}) - Initialize a new Python MCP server project -- [`kagent mcp init typescript`]({{< link path="resources/cli/kagent-mcp-init-typescript/" >}}) - Initialize a new TypeScript MCP server project +- [`kagent mcp init go`](/docs/kagent/0.x/resources/cli/kagent-mcp-init-go/) - Initialize a new Go MCP server project +- [`kagent mcp init java`](/docs/kagent/0.x/resources/cli/kagent-mcp-init-java/) - Initialize a new Java MCP server project +- [`kagent mcp init python`](/docs/kagent/0.x/resources/cli/kagent-mcp-init-python/) - Initialize a new Python MCP server project +- [`kagent mcp init typescript`](/docs/kagent/0.x/resources/cli/kagent-mcp-init-typescript/) - Initialize a new TypeScript MCP server project **Flags:** - `--author string` - Author name for the project @@ -32,11 +32,7 @@ kagent mcp init [command] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-run.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-run.md index 6a53b768..f24be81e 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-run.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-run.md @@ -1,6 +1,6 @@ --- title: kagent mcp run -description: Run MCP server locally +description: Run MCP server locally. weight: 360 --- @@ -30,11 +30,7 @@ kagent mcp run [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets-sync.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets-sync.md index 032ed5a2..3ac9bb2e 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets-sync.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets-sync.md @@ -1,6 +1,6 @@ --- title: kagent mcp secrets sync -description: Sync secrets to a Kubernetes environment from a local .env file +description: Sync secrets to a Kubernetes environment from a local .env file. weight: 380 --- @@ -24,11 +24,7 @@ kagent mcp secrets sync [environment] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets.md index fa034cd4..da43e2ca 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets.md @@ -1,6 +1,6 @@ --- title: kagent mcp secrets -description: Manage project secrets +description: Manage project secrets. weight: 370 --- @@ -11,18 +11,14 @@ kagent mcp secrets [command] ``` **Subcommands:** -- [`kagent mcp secrets sync`]({{< link path="resources/cli/kagent-mcp-secrets-sync/" >}}) - Sync secrets to a Kubernetes environment from a local .env file +- [`kagent mcp secrets sync`](/docs/kagent/0.x/resources/cli/kagent-mcp-secrets-sync/) - Sync secrets to a Kubernetes environment from a local .env file **Flags:** - `-h, --help` - help for secrets **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md index c745ced9..78514bc1 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md @@ -1,6 +1,6 @@ --- title: kagent mcp -description: MCP (Model Context Protocol) server management +description: MCP (Model Context Protocol) server management. weight: 260 --- @@ -12,23 +12,19 @@ kagent mcp [command] ``` **Subcommands:** -- [`kagent mcp add-tool`]({{< link path="resources/cli/kagent-mcp-add-tool/" >}}) - Add a new MCP tool to your project -- [`kagent mcp build`]({{< link path="resources/cli/kagent-mcp-build/" >}}) - Build MCP server as a Docker image -- [`kagent mcp deploy`]({{< link path="resources/cli/kagent-mcp-deploy/" >}}) - Deploy MCP server to Kubernetes -- [`kagent mcp init`]({{< link path="resources/cli/kagent-mcp-init/" >}}) - Initialize a new MCP server project -- [`kagent mcp run`]({{< link path="resources/cli/kagent-mcp-run/" >}}) - Run MCP server locally -- [`kagent mcp secrets`]({{< link path="resources/cli/kagent-mcp-secrets/" >}}) - Manage project secrets +- [`kagent mcp add-tool`](/docs/kagent/0.x/resources/cli/kagent-mcp-add-tool/) - Add a new MCP tool to your project +- [`kagent mcp build`](/docs/kagent/0.x/resources/cli/kagent-mcp-build/) - Build MCP server as a Docker image +- [`kagent mcp deploy`](/docs/kagent/0.x/resources/cli/kagent-mcp-deploy/) - Deploy MCP server to Kubernetes +- [`kagent mcp init`](/docs/kagent/0.x/resources/cli/kagent-mcp-init/) - Initialize a new MCP server project +- [`kagent mcp run`](/docs/kagent/0.x/resources/cli/kagent-mcp-run/) - Run MCP server locally +- [`kagent mcp secrets`](/docs/kagent/0.x/resources/cli/kagent-mcp-secrets/) - Manage project secrets **Flags:** - `-h, --help` - help for mcp **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-run.md b/docs-site/content/kagent/0.x/resources/cli/kagent-run.md index 40797814..51aafd72 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-run.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-run.md @@ -1,6 +1,6 @@ --- title: kagent run -description: Run agent project locally with docker-compose and launch chat interface +description: Run agent project locally with docker-compose and launch chat interface. weight: 390 --- @@ -17,11 +17,7 @@ kagent run [project-directory] [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md b/docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md index 76073818..dcdcd671 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md @@ -1,6 +1,6 @@ --- title: kagent uninstall -description: Uninstall kagent +description: Uninstall kagent. weight: 400 --- @@ -15,11 +15,7 @@ kagent uninstall [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/cli/kagent-version.md b/docs-site/content/kagent/0.x/resources/cli/kagent-version.md index a1958d9b..feb68ddf 100644 --- a/docs-site/content/kagent/0.x/resources/cli/kagent-version.md +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-version.md @@ -1,6 +1,6 @@ --- title: kagent version -description: Print the kagent version +description: Print the kagent version. weight: 410 --- @@ -15,11 +15,7 @@ kagent version [flags] **Global Flags:** - `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--kagent-url string` - KAgent URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") - `--timeout duration` - Timeout (default 5m0s) diff --git a/docs-site/content/kagent/0.x/resources/helm.md b/docs-site/content/kagent/0.x/resources/helm.md index 85eadd2f..3b78bdfd 100644 --- a/docs-site/content/kagent/0.x/resources/helm.md +++ b/docs-site/content/kagent/0.x/resources/helm.md @@ -13,8 +13,17 @@ A Helm chart for kagent, built with Google ADK | Repository | Name | Version | |------------|------|---------| | `${SUBSTRATE_REPO}` | substrate | `${SUBSTRATE_VERSION}` | -| file://../tools/grafana-mcp | grafana-mcp | | -| file://../tools/querydoc | querydoc | | +| file://../agents/argo-rollouts | argo-rollouts-agent | 0.10.1 | +| file://../agents/cilium-debug | cilium-debug-agent | 0.10.1 | +| file://../agents/cilium-manager | cilium-manager-agent | 0.10.1 | +| file://../agents/cilium-policy | cilium-policy-agent | 0.10.1 | +| file://../agents/helm | helm-agent | 0.10.1 | +| file://../agents/istio | istio-agent | 0.10.1 | +| file://../agents/k8s | k8s-agent | 0.10.1 | +| file://../agents/kgateway | kgateway-agent | 0.10.1 | +| file://../agents/observability | observability-agent | 0.10.1 | +| file://../agents/promql | promql-agent | 0.10.1 | +| file://../tools/grafana-mcp | grafana-mcp | 0.10.1 | | https://oauth2-proxy.github.io/manifests | oauth2-proxy | ~10.7.0 | | oci://ghcr.io/kagent-dev/kmcp/helm | kmcp | `${KMCP_VERSION}` | | oci://ghcr.io/kagent-dev/tools/helm | kagent-tools | 0.2.1 | @@ -24,10 +33,48 @@ A Helm chart for kagent, built with Google ADK | Key | Type | Default | Description | |-----|------|---------|-------------| | annotations | object | `{}` | Additional annotations to add to all Kubernetes deployment resources | +| argo-rollouts-agent.enabled | bool | `true` | | +| argo-rollouts-agent.memory.enabled | bool | `false` | | +| argo-rollouts-agent.memory.modelConfigRef | string | `""` | | +| argo-rollouts-agent.memory.ttlDays | int | `15` | | +| argo-rollouts-agent.modelConfigRef | string | `""` | | +| argo-rollouts-agent.resources.limits.memory | string | `"256Mi"` | | +| argo-rollouts-agent.resources.requests.cpu | string | `"50m"` | | +| argo-rollouts-agent.resources.requests.memory | string | `"128Mi"` | | +| cilium-debug-agent.enabled | bool | `true` | | +| cilium-debug-agent.memory.enabled | bool | `false` | | +| cilium-debug-agent.memory.modelConfigRef | string | `""` | | +| cilium-debug-agent.memory.ttlDays | int | `15` | | +| cilium-debug-agent.modelConfigRef | string | `""` | | +| cilium-debug-agent.resources.limits.memory | string | `"256Mi"` | | +| cilium-debug-agent.resources.requests.cpu | string | `"50m"` | | +| cilium-debug-agent.resources.requests.memory | string | `"128Mi"` | | +| cilium-manager-agent.enabled | bool | `true` | | +| cilium-manager-agent.memory.enabled | bool | `false` | | +| cilium-manager-agent.memory.modelConfigRef | string | `""` | | +| cilium-manager-agent.memory.ttlDays | int | `15` | | +| cilium-manager-agent.modelConfigRef | string | `""` | | +| cilium-manager-agent.resources.limits.memory | string | `"256Mi"` | | +| cilium-manager-agent.resources.requests.cpu | string | `"50m"` | | +| cilium-manager-agent.resources.requests.memory | string | `"128Mi"` | | +| cilium-policy-agent.enabled | bool | `true` | | +| cilium-policy-agent.memory.enabled | bool | `false` | | +| cilium-policy-agent.memory.modelConfigRef | string | `""` | | +| cilium-policy-agent.memory.ttlDays | int | `15` | | +| cilium-policy-agent.modelConfigRef | string | `""` | | +| cilium-policy-agent.resources.limits.memory | string | `"256Mi"` | | +| cilium-policy-agent.resources.requests.cpu | string | `"50m"` | | +| cilium-policy-agent.resources.requests.memory | string | `"128Mi"` | | | controller.a2aBaseUrl | string | `http://-controller..svc:` | The base URL of the A2A Server endpoint, as advertised to clients. | | controller.a2aClientTimeout | string | "" (no timeout) | HTTP client timeout for A2A requests from the controller to agent pods. 0 (the default) means no timeout, which is correct for SSE-based streaming agents that can run for an arbitrarily long time. The previous implicit default was 3m (inherited from the a2a-go SDK), which caused `context deadline exceeded` errors for agents that take longer than 3 minutes to complete. Set a positive Go duration string (e.g. "30m", "1h") only if you need a hard upper bound on individual A2A calls. | -| controller.a2aGatewayUrl | string | `http://-controller..svc:` | Public gRPC URL advertised by AgentInstance Agent Cards. | | controller.affinity | object | `{}` | [Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) rules for the controller pod. | +| controller.agentDeployment | object | `{"host":"","nodeSelector":{},"podLabels":{},"serviceAccountName":""}` | Global deployment defaults applied to all agent pods. Per-agent settings in the Agent CRD take precedence over these defaults. | +| controller.agentDeployment.host | string | "" (controller falls back to "0.0.0.0"; "::" when ipv6.enabled) | Default host address for agent pods to bind to. Leave empty to use the controller's default fallback of "0.0.0.0". Automatically set to "::" when ipv6.enabled is true. Can be explicitly overridden here regardless of the ipv6 flag. | +| controller.agentDeployment.nodeSelector | object | {} (no default nodeSelector) | Default nodeSelector applied to all agent deployments. Useful when admission policies require a nodeSelector on every Deployment, since wizard-created Agents carry none. A per-agent nodeSelector in the Agent CRD takes precedence over these defaults. | +| controller.agentDeployment.podLabels | object | {} (no extra labels) | Default labels applied to all agent pod templates. Per-agent labels in the Agent CRD take precedence over these defaults. | +| controller.agentDeployment.serviceAccountName | string | "" (auto-create per-agent ServiceAccount) | Default ServiceAccount name for agent pods. When set, agent pods that don't specify an explicit serviceAccountName will use this ServiceAccount instead of creating a per-agent one. Useful for Workload Identity (GCP, AWS IRSA, Azure Workload Identity). Precedence: agent-level serviceAccountName > this default > auto-created SA. | +| controller.agentImage.pullPolicy | string | `""` | | +| controller.agentImage.pullSecret | string | `""` | Image pull secret name set on agent pods created by the controller | | controller.agentImage.registry | string | `""` | | | controller.agentImage.repository | string | `"kagent-dev/kagent/app"` | | | controller.agentImage.tag | string | `""` | | @@ -36,8 +83,7 @@ A Helm chart for kagent, built with Google ADK | controller.auth.userIdClaim | string | `""` | | | controller.env | list | `[]` | | | controller.envFrom | list | `[]` | | -| controller.goAgentImage | object | `{"registry":"","repository":"kagent-dev/kagent/golang-adk","tag":""}` | The image used for the Go (ADK) runtime agent. | -| controller.grpc | object | `{"bindAddress":":8084","maxMessageBytes":16777216,"reflection":false,"tlsCertFile":"","tlsKeyFile":""}` | Native gRPC application API settings. This port is internal unless a separate TLS-capable GRPCRoute or ingress is configured. | +| controller.goAgentImage | object | `{"pullPolicy":"","registry":"","repository":"kagent-dev/kagent/golang-adk","tag":""}` | The image used for the Go (ADK) runtime agent. | | controller.image.pullPolicy | string | `""` | | | controller.image.registry | string | `""` | | | controller.image.repository | string | `"kagent-dev/kagent/controller"` | | @@ -62,34 +108,38 @@ A Helm chart for kagent, built with Google ADK | controller.resources.requests.cpu | string | `"100m"` | | | controller.resources.requests.memory | string | `"128Mi"` | | | controller.service.annotations | object | `{}` | | -| controller.service.ports.grpc | int | `8084` | | | controller.service.ports.port | int | `8083` | | | controller.service.ports.targetPort | int | `8083` | | | controller.service.type | string | `"ClusterIP"` | | | controller.serviceAccount | object | `{"annotations":{}}` | ServiceAccount settings for the controller pod | | controller.serviceAccount.annotations | object | {} (no extra annotations) | Annotations to add to the controller ServiceAccount. Useful for GCP Workload Identity, AWS IRSA, or Azure Workload Identity. | -| controller.skillsInitImage | object | `{"registry":"","repository":"kagent-dev/kagent/skills-init","tag":""}` | The image used by the skills-init container to clone skills from Git and pull OCI skill images. | +| controller.skillsInitImage | object | `{"pullPolicy":"","registry":"","repository":"kagent-dev/kagent/skills-init","tag":""}` | The image used by the skills-init container to clone skills from Git and pull OCI skill images. | | controller.startupProbe | object | httpGet /health on port http, periodSeconds=15, initialDelaySeconds=15 | Custom startup probe for the controller container. Setting a value replaces the default probe entirely — include a handler (httpGet / exec / tcpSocket / grpc) when overriding. | | controller.streaming | string | `nil` | @deprecated Removed in 0.10.0. The A2A SDK now handles SSE buffering and timeouts internally. These values have no effect and will be removed in a future release. | | controller.substrate.ateApiEndpoint | string | `""` | | +| controller.substrate.ateApiInsecure | bool | `false` | | | controller.substrate.ateApiServer.namespace | string | `"ate-system"` | | | controller.substrate.ateApiServer.serviceAccount | string | `"ate-api-server"` | | +| controller.substrate.ateApiTokenAudience | string | `"api.ate-system.svc"` | | +| controller.substrate.ateApiTokenExpirationSeconds | int | `3600` | | +| controller.substrate.ateApiTokenFile | string | `"/var/run/secrets/tokens/ate-api/token"` | | | controller.substrate.atenetRouterURL | string | `""` | | | controller.substrate.defaultWorkerPool.name | string | `""` | | | controller.substrate.defaultWorkerPool.namespace | string | `""` | | | controller.substrate.enabled | bool | `false` | | | controller.tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| controller.toolRefreshInterval | string | `"60s"` | How often MCP tool-discovery controllers requeue to refresh the discovered-tool cache (RemoteMCPServer, MCPServer, labeled MCP Service). Default 60s. | | controller.topologySpreadConstraints | list | `[]` | [Topology spread constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#pod-topology-spread-constraints) for the controller pod. | | controller.volumeMounts | list | `[]` | | | controller.volumes | list | `[]` | | | controller.watchNamespaces | list | [] (watches all available namespaces) | Namespaces the controller should watch. If empty, the controller will watch ALL available namespaces. | -| database.postgres.bundled | object | `{"enabled":true,"image":{"name":"postgres","pullPolicy":"IfNotPresent","registry":"docker.io","repository":"library","tag":"18.3-alpine"},"podSecurityContext":{"fsGroup":999,"runAsGroup":999,"runAsNonRoot":true,"runAsUser":999,"seccompProfile":{"type":"RuntimeDefault"}},"resources":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"256Mi"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}},"storage":"500Mi","storageClassName":""}` | Bundled PostgreSQL instance — for development and evaluation only. Not suitable for production. Deployed when enabled is true and url/urlFile are not set. | +| database.postgres.bundled | object | `{"enabled":true,"image":{"name":"postgres","pullPolicy":"IfNotPresent","registry":"docker.io","repository":"library","tag":"18.6-alpine3.23"},"podSecurityContext":{"fsGroup":999,"runAsGroup":999,"runAsNonRoot":true,"runAsUser":999,"seccompProfile":{"type":"RuntimeDefault"}},"resources":{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"256Mi"}},"securityContext":{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}},"storage":"500Mi","storageClassName":""}` | Bundled PostgreSQL instance — for development and evaluation only. Not suitable for production. Deployed when enabled is true and url/urlFile are not set. | | database.postgres.bundled.enabled | bool | `true` | Set to false to disable the bundled database and provide your own via url or urlFile. | | database.postgres.bundled.image.name | string | `"postgres"` | Bundled PostgreSQL image name | | database.postgres.bundled.image.pullPolicy | string | `"IfNotPresent"` | Bundled PostgreSQL image pull policy | | database.postgres.bundled.image.registry | string | `"docker.io"` | Bundled PostgreSQL image registry | | database.postgres.bundled.image.repository | string | `"library"` | Bundled PostgreSQL image repository (org/namespace) | -| database.postgres.bundled.image.tag | string | `"18.3-alpine"` | Bundled PostgreSQL image tag | +| database.postgres.bundled.image.tag | string | `"18.6-alpine3.23"` | Bundled PostgreSQL image tag | | database.postgres.bundled.podSecurityContext | object | `{"fsGroup":999,"runAsGroup":999,"runAsNonRoot":true,"runAsUser":999,"seccompProfile":{"type":"RuntimeDefault"}}` | Pod-level security context for the bundled PostgreSQL deployment. | | database.postgres.bundled.resources | object | `{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"250m","memory":"256Mi"}}` | Resource requests/limits for the demo PostgreSQL container | | database.postgres.bundled.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]}}` | Container-level security context for the bundled PostgreSQL container. | @@ -110,9 +160,33 @@ A Helm chart for kagent, built with Google ADK | grafana-mcp.resources.limits.memory | string | `"512Mi"` | | | grafana-mcp.resources.requests.cpu | string | `"100m"` | | | grafana-mcp.resources.requests.memory | string | `"128Mi"` | | +| helm-agent.enabled | bool | `true` | | +| helm-agent.memory.enabled | bool | `false` | | +| helm-agent.memory.modelConfigRef | string | `""` | | +| helm-agent.memory.ttlDays | int | `15` | | +| helm-agent.modelConfigRef | string | `""` | | +| helm-agent.resources.limits.memory | string | `"256Mi"` | | +| helm-agent.resources.requests.cpu | string | `"50m"` | | +| helm-agent.resources.requests.memory | string | `"128Mi"` | | | imagePullPolicy | string | `"IfNotPresent"` | | | imagePullSecrets | list | `[]` | | | ipv6 | object | false | Enable IPv6/dual-stack support. When true, configures all components for dual-stack (IPv4+IPv6) networking: - nginx listens on both IPv4 and IPv6 (adds `listen [::]:8080`) - Next.js binds to `::` instead of `0.0.0.0` - Agent pods bind to `::` for dual-stack reachability Leave disabled on clusters where IPv6 is disabled at the kernel level. | +| istio-agent.enabled | bool | `true` | | +| istio-agent.memory.enabled | bool | `false` | | +| istio-agent.memory.modelConfigRef | string | `""` | | +| istio-agent.memory.ttlDays | int | `15` | | +| istio-agent.modelConfigRef | string | `""` | | +| istio-agent.resources.limits.memory | string | `"256Mi"` | | +| istio-agent.resources.requests.cpu | string | `"50m"` | | +| istio-agent.resources.requests.memory | string | `"128Mi"` | | +| k8s-agent.enabled | bool | `true` | | +| k8s-agent.memory.enabled | bool | `false` | | +| k8s-agent.memory.modelConfigRef | string | `""` | | +| k8s-agent.memory.ttlDays | int | `15` | | +| k8s-agent.modelConfigRef | string | `""` | | +| k8s-agent.resources.limits.memory | string | `"256Mi"` | | +| k8s-agent.resources.requests.cpu | string | `"50m"` | | +| k8s-agent.resources.requests.memory | string | `"128Mi"` | | | kagent-tools.enabled | bool | `true` | | | kagent-tools.nameOverride | string | `"tools"` | | | kagent-tools.nodeSelector | object | `{}` | Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | @@ -128,6 +202,14 @@ A Helm chart for kagent, built with Google ADK | kagent-tools.tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | | kagent-tools.tools.loglevel | string | `"debug"` | | | kagent-tools.tools.metrics.port | int | `8085` | | +| kgateway-agent.enabled | bool | `true` | | +| kgateway-agent.memory.enabled | bool | `false` | | +| kgateway-agent.memory.modelConfigRef | string | `""` | | +| kgateway-agent.memory.ttlDays | int | `15` | | +| kgateway-agent.modelConfigRef | string | `""` | | +| kgateway-agent.resources.limits.memory | string | `"256Mi"` | | +| kgateway-agent.resources.requests.cpu | string | `"50m"` | | +| kgateway-agent.resources.requests.memory | string | `"128Mi"` | | | kmcp.enabled | bool | `true` | | | kmcp.fullnameOverride | string | `""` | | | kmcp.nameOverride | string | `"kmcp"` | | @@ -156,12 +238,14 @@ A Helm chart for kagent, built with Google ADK | oauth2-proxy.extraArgs.skip-auth-route | string | `"^/(health|login)$"` | | | oauth2-proxy.extraArgs.skip-jwt-bearer-tokens | bool | `true` | | | oauth2-proxy.extraArgs.upstream | string | `"$(UPSTREAM_URL)"` | | -| oauth2-proxy.extraEnv[0].name | string | `"OIDC_ISSUER_URL"` | | -| oauth2-proxy.extraEnv[0].value | string | `""` | | -| oauth2-proxy.extraEnv[1].name | string | `"OIDC_REDIRECT_URL"` | | +| oauth2-proxy.extraEnv[0].name | string | `"KAGENT_OAUTH2_PROXY_SIGNIN_TEMPLATE_CHECKSUM"` | | +| oauth2-proxy.extraEnv[0].value | string | `"{{ include \"kagent.oauth2ProxySignInHTML\" . | sha256sum }}"` | | +| oauth2-proxy.extraEnv[1].name | string | `"OIDC_ISSUER_URL"` | | | oauth2-proxy.extraEnv[1].value | string | `""` | | -| oauth2-proxy.extraEnv[2].name | string | `"UPSTREAM_URL"` | | -| oauth2-proxy.extraEnv[2].value | string | `"http://kagent-ui:8080"` | | +| oauth2-proxy.extraEnv[2].name | string | `"OIDC_REDIRECT_URL"` | | +| oauth2-proxy.extraEnv[2].value | string | `""` | | +| oauth2-proxy.extraEnv[3].name | string | `"UPSTREAM_URL"` | | +| oauth2-proxy.extraEnv[3].value | string | `"http://kagent-ui:8080"` | | | oauth2-proxy.extraVolumeMounts[0].mountPath | string | `"/templates"` | | | oauth2-proxy.extraVolumeMounts[0].name | string | `"custom-templates"` | | | oauth2-proxy.extraVolumeMounts[0].readOnly | bool | `true` | | @@ -170,6 +254,14 @@ A Helm chart for kagent, built with Google ADK | oauth2-proxy.service.portNumber | int | `4180` | | | oauth2-proxy.service.type | string | `"ClusterIP"` | | | oauth2-proxy.sessionStorage.type | string | `"cookie"` | | +| observability-agent.enabled | bool | `true` | | +| observability-agent.memory.enabled | bool | `false` | | +| observability-agent.memory.modelConfigRef | string | `""` | | +| observability-agent.memory.ttlDays | int | `15` | | +| observability-agent.modelConfigRef | string | `""` | | +| observability-agent.resources.limits.memory | string | `"256Mi"` | | +| observability-agent.resources.requests.cpu | string | `"50m"` | | +| observability-agent.resources.requests.memory | string | `"128Mi"` | | | otel.logging.enabled | bool | `false` | | | otel.logging.exporter.otlp.endpoint | string | `""` | | | otel.logging.exporter.otlp.insecure | bool | `true` | | @@ -182,6 +274,14 @@ A Helm chart for kagent, built with Google ADK | podAnnotations | object | `{}` | | | podLabels | object | `{}` | Additional labels to add to all pod templates (merged into pod labels of the controller and UI Deployments; can be overridden per component). Useful for admission policies that require specific labels on pods. | | podSecurityContext | object | `{"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for all pods | +| promql-agent.enabled | bool | `true` | | +| promql-agent.memory.enabled | bool | `false` | | +| promql-agent.memory.modelConfigRef | string | `""` | | +| promql-agent.memory.ttlDays | int | `15` | | +| promql-agent.modelConfigRef | string | `""` | | +| promql-agent.resources.limits.memory | string | `"256Mi"` | | +| promql-agent.resources.requests.cpu | string | `"50m"` | | +| promql-agent.resources.requests.memory | string | `"128Mi"` | | | providers.annotations | object | `{}` | Annotations added to the metadata of the generated default ModelConfig (the one derived from `providers.default`). Omitted from the resource when empty. | | providers.anthropic.apiKeySecretKey | string | `"ANTHROPIC_API_KEY"` | | | providers.anthropic.apiKeySecretRef | string | `"kagent-anthropic"` | | @@ -198,7 +298,7 @@ A Helm chart for kagent, built with Google ADK | providers.default | string | `"openAI"` | | | providers.gemini.apiKeySecretKey | string | `"GOOGLE_API_KEY"` | | | providers.gemini.apiKeySecretRef | string | `"kagent-gemini"` | | -| providers.gemini.model | string | `"gemini-2.5-flash-lite"` | | +| providers.gemini.model | string | `"gemini-2.0-flash-lite"` | | | providers.gemini.provider | string | `"Gemini"` | | | providers.ollama.config.host | string | `"host.docker.internal:11434"` | | | providers.ollama.config.options.num_ctx | string | `"64000"` | | @@ -209,17 +309,6 @@ A Helm chart for kagent, built with Google ADK | providers.openAI.model | string | `"gpt-4.1-mini"` | | | providers.openAI.provider | string | `"OpenAI"` | | | proxy.url | string | `""` | | -| querydoc.enabled | bool | `true` | | -| querydoc.image.pullPolicy | string | `"IfNotPresent"` | | -| querydoc.image.registry | string | `"ghcr.io"` | | -| querydoc.image.repository | string | `"kagent-dev/doc2vec/mcp"` | | -| querydoc.image.tag | string | `"1.1.14"` | | -| querydoc.openai.apiKey | string | `""` | | -| querydoc.replicas | int | `1` | | -| querydoc.resources.limits.cpu | string | `"500m"` | | -| querydoc.resources.limits.memory | string | `"512Mi"` | | -| querydoc.resources.requests.cpu | string | `"100m"` | | -| querydoc.resources.requests.memory | string | `"128Mi"` | | | rbac.namespaces | list | `[]` | Namespaces in which to create Role and RoleBinding resources. If empty (default), the chart creates cluster-scoped ClusterRole and ClusterRoleBinding resources and the controller watches all namespaces. If set, the chart creates a Role + RoleBinding per listed namespace and the controller's WATCH_NAMESPACES is derived from this list (unless controller.watchNamespaces is set explicitly, which always takes precedence). | | registry | string | `"ghcr.io"` | | | securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"readOnlyRootFilesystem":true}` | Security context for all containers | @@ -231,7 +320,6 @@ A Helm chart for kagent, built with Google ADK | ui.affinity | object | `{}` | [Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) rules for the UI pod. | | ui.annotations | object | `{}` | Additional annotations to add to the UI Deployment metadata | | ui.auth.ssoRedirectPath | string | `"/oauth2/start"` | | -| ui.backendGrpcUrl | string | `""` | | | ui.backendInternalUrl | string | `""` | | | ui.env | object | `{}` | | | ui.externalUrl | string | "" (share tools return paths only) | Public-facing base URL of the UI (e.g. https://kagent.example.com). When set, the controller injects KAGENT_UI_URL into agent pods so that share link tools return full clickable URLs instead of relative paths. | diff --git a/docs-site/content/kagent/1.x/reference/cli/_index.md b/docs-site/content/kagent/1.x/reference/cli/_index.md new file mode 100644 index 00000000..399a0fcf --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/_index.md @@ -0,0 +1,21 @@ +--- +title: CLI docs +description: Review the reference docs for the kagent CLI commands. +weight: 30 +--- + +Review the kagent CLI commands and learn how to use them effectively. + +- [`kagent apply`](/docs/kagent/1.x/reference/cli/kagent-apply/) - Create or update an AgentTemplate +- [`kagent bug-report`](/docs/kagent/1.x/reference/cli/kagent-bug-report/) - Generate a bug report +- [`kagent completion`](/docs/kagent/1.x/reference/cli/kagent-completion/) - Generate the autocompletion script for the specified shell +- [`kagent create`](/docs/kagent/1.x/reference/cli/kagent-create/) - Create a kagent resource +- [`kagent dashboard`](/docs/kagent/1.x/reference/cli/kagent-dashboard/) - Open the kagent dashboard +- [`kagent db`](/docs/kagent/1.x/reference/cli/kagent-db/) - Database operations (migrations, inspection) +- [`kagent delete`](/docs/kagent/1.x/reference/cli/kagent-delete/) - Delete a kagent resource +- [`kagent get`](/docs/kagent/1.x/reference/cli/kagent-get/) - Get a kagent resource +- [`kagent install`](/docs/kagent/1.x/reference/cli/kagent-install/) - Install kagent +- [`kagent invoke`](/docs/kagent/1.x/reference/cli/kagent-invoke/) - Invoke an AgentInstance +- [`kagent mcp`](/docs/kagent/1.x/reference/cli/kagent-mcp/) - MCP (Model Context Protocol) server management +- [`kagent uninstall`](/docs/kagent/1.x/reference/cli/kagent-uninstall/) - Uninstall kagent +- [`kagent version`](/docs/kagent/1.x/reference/cli/kagent-version/) - Print the kagent version diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-apply.md b/docs-site/content/kagent/1.x/reference/cli/kagent-apply.md new file mode 100644 index 00000000..605ed5ab --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-apply.md @@ -0,0 +1,26 @@ +--- +title: kagent apply +description: Create or update an AgentTemplate. +weight: 10 +--- + +Create or update an AgentTemplate + +```bash +kagent apply -f FILE [flags] +``` + +**Flags:** +- `-f, --file string` - Path to AgentTemplate manifest +- `-h, --help` - help for apply + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-bug-report.md b/docs-site/content/kagent/1.x/reference/cli/kagent-bug-report.md new file mode 100644 index 00000000..33c32e40 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-bug-report.md @@ -0,0 +1,25 @@ +--- +title: kagent bug-report +description: Generate a bug report. +weight: 20 +--- + +Generate a bug report + +```bash +kagent bug-report [flags] +``` + +**Flags:** +- `-h, --help` - help for bug-report + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-completion-bash.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-bash.md similarity index 64% rename from docs-site/content/kagent/resources/cli/kagent-completion-bash.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-completion-bash.md index 91f109cd..753b2afb 100644 --- a/docs-site/content/kagent/resources/cli/kagent-completion-bash.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-bash.md @@ -1,7 +1,7 @@ --- title: kagent completion bash -description: Generate the autocompletion script for bash -weight: 50 +description: Generate the autocompletion script for bash. +weight: 40 --- Generate the autocompletion script for the bash shell. @@ -34,13 +34,12 @@ kagent completion bash - `--no-descriptions` - disable completion descriptions **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-completion-fish.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-fish.md similarity index 58% rename from docs-site/content/kagent/resources/cli/kagent-completion-fish.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-completion-fish.md index bda214e4..1ab372fb 100644 --- a/docs-site/content/kagent/resources/cli/kagent-completion-fish.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-fish.md @@ -1,7 +1,7 @@ --- title: kagent completion fish -description: Generate the autocompletion script for fish -weight: 60 +description: Generate the autocompletion script for fish. +weight: 50 --- Generate the autocompletion script for the fish shell. @@ -25,13 +25,12 @@ kagent completion fish [flags] - `--no-descriptions` - disable completion descriptions **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-completion-powershell.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-powershell.md similarity index 57% rename from docs-site/content/kagent/resources/cli/kagent-completion-powershell.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-completion-powershell.md index 1ef996fd..fdab5968 100644 --- a/docs-site/content/kagent/resources/cli/kagent-completion-powershell.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-powershell.md @@ -1,7 +1,7 @@ --- title: kagent completion powershell -description: Generate the autocompletion script for powershell -weight: 70 +description: Generate the autocompletion script for powershell. +weight: 60 --- Generate the autocompletion script for powershell. @@ -22,13 +22,12 @@ kagent completion powershell [flags] - `--no-descriptions` - disable completion descriptions **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-completion-zsh.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-zsh.md similarity index 65% rename from docs-site/content/kagent/resources/cli/kagent-completion-zsh.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-completion-zsh.md index c13d5513..390cf743 100644 --- a/docs-site/content/kagent/resources/cli/kagent-completion-zsh.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-zsh.md @@ -1,7 +1,7 @@ --- title: kagent completion zsh -description: Generate the autocompletion script for zsh -weight: 80 +description: Generate the autocompletion script for zsh. +weight: 70 --- Generate the autocompletion script for the zsh shell. @@ -36,13 +36,12 @@ kagent completion zsh [flags] - `--no-descriptions` - disable completion descriptions **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-completion.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion.md new file mode 100644 index 00000000..01592caf --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion.md @@ -0,0 +1,32 @@ +--- +title: kagent completion +description: Generate the autocompletion script for the specified shell. +weight: 30 +--- + +Generate the autocompletion script for kagent for the specified shell. +See each sub-command's help for details on how to use the generated script. + +```bash +kagent completion [command] +``` + +**Subcommands:** +- [`kagent completion bash`](/docs/kagent/1.x/reference/cli/kagent-completion-bash/) - Generate the autocompletion script for bash +- [`kagent completion fish`](/docs/kagent/1.x/reference/cli/kagent-completion-fish/) - Generate the autocompletion script for fish +- [`kagent completion powershell`](/docs/kagent/1.x/reference/cli/kagent-completion-powershell/) - Generate the autocompletion script for powershell +- [`kagent completion zsh`](/docs/kagent/1.x/reference/cli/kagent-completion-zsh/) - Generate the autocompletion script for zsh + +**Flags:** +- `-h, --help` - help for completion + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-create-agent-instance.md b/docs-site/content/kagent/1.x/reference/cli/kagent-create-agent-instance.md new file mode 100644 index 00000000..cc3217ff --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-create-agent-instance.md @@ -0,0 +1,28 @@ +--- +title: kagent create agent-instance +description: Create an AgentInstance. +weight: 90 +--- + +Create an AgentInstance + +```bash +kagent create agent-instance [flags] +``` + +**Flags:** +- `--agent-template string` - AgentTemplate name +- `--harness string` - Harness name +- `-h, --help` - help for agent-instance +- `--request-id string` - Idempotency key (generated when omitted) + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-create.md b/docs-site/content/kagent/1.x/reference/cli/kagent-create.md new file mode 100644 index 00000000..f4155beb --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-create.md @@ -0,0 +1,29 @@ +--- +title: kagent create +description: Create a kagent resource. +weight: 80 +--- + +Create a kagent resource + +```bash +kagent create [flags] +kagent create [command] +``` + +**Subcommands:** +- [`kagent create agent-instance`](/docs/kagent/1.x/reference/cli/kagent-create-agent-instance/) - Create an AgentInstance + +**Flags:** +- `-h, --help` - help for create + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-dashboard.md b/docs-site/content/kagent/1.x/reference/cli/kagent-dashboard.md new file mode 100644 index 00000000..c3a94c89 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-dashboard.md @@ -0,0 +1,25 @@ +--- +title: kagent dashboard +description: Open the kagent dashboard. +weight: 100 +--- + +Open the kagent dashboard + +```bash +kagent dashboard [flags] +``` + +**Flags:** +- `-h, --help` - help for dashboard + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-down.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-down.md new file mode 100644 index 00000000..c3ba9be6 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-down.md @@ -0,0 +1,21 @@ +--- +title: kagent db migrate down +description: Roll back the latest N migrations. +weight: 130 +--- + +Roll back the latest N migrations. A down migration can delete data. + +```bash +kagent db migrate down N [flags] +``` + +**Flags:** +- `-h, --help` - help for down + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--db-url string` - PostgreSQL connection URL +- `--server-name string` - TLS server name for KAgent endpoints +- `--source string` - Migration source for down, goto, or version +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-goto.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-goto.md new file mode 100644 index 00000000..c0617ac7 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-goto.md @@ -0,0 +1,21 @@ +--- +title: kagent db migrate goto +description: Move one source to version V. +weight: 140 +--- + +Move one source to version V. Version zero removes its schema. + +```bash +kagent db migrate goto V [flags] +``` + +**Flags:** +- `-h, --help` - help for goto + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--db-url string` - PostgreSQL connection URL +- `--server-name string` - TLS server name for KAgent endpoints +- `--source string` - Migration source for down, goto, or version +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-status.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-status.md new file mode 100644 index 00000000..22e4f815 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-status.md @@ -0,0 +1,22 @@ +--- +title: kagent db migrate status +description: Show migration status. +weight: 150 +--- + +Show migration status + +```bash +kagent db migrate status [flags] +``` + +**Flags:** +- `-h, --help` - help for status +- `--output string` - Output format: "text" or "json" (default "text") + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--db-url string` - PostgreSQL connection URL +- `--server-name string` - TLS server name for KAgent endpoints +- `--source string` - Migration source for down, goto, or version +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-up.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-up.md new file mode 100644 index 00000000..2ef613a4 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-up.md @@ -0,0 +1,21 @@ +--- +title: kagent db migrate up +description: Apply all pending migrations. +weight: 160 +--- + +Apply all pending migrations + +```bash +kagent db migrate up [flags] +``` + +**Flags:** +- `-h, --help` - help for up + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--db-url string` - PostgreSQL connection URL +- `--server-name string` - TLS server name for KAgent endpoints +- `--source string` - Migration source for down, goto, or version +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-version.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-version.md new file mode 100644 index 00000000..8eb2cf43 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate-version.md @@ -0,0 +1,21 @@ +--- +title: kagent db migrate version +description: Show the applied migration version. +weight: 170 +--- + +Show the applied migration version + +```bash +kagent db migrate version [flags] +``` + +**Flags:** +- `-h, --help` - help for version + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--db-url string` - PostgreSQL connection URL +- `--server-name string` - TLS server name for KAgent endpoints +- `--source string` - Migration source for down, goto, or version +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate.md new file mode 100644 index 00000000..883d083a --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db-migrate.md @@ -0,0 +1,29 @@ +--- +title: kagent db migrate +description: Apply, roll back, and inspect database migrations. +weight: 120 +--- + +Apply, roll back, and inspect database migrations. +The command reads POSTGRES_DATABASE_URL when --db-url is empty. + +```bash +kagent db migrate [command] +``` + +**Subcommands:** +- [`kagent db migrate down`](/docs/kagent/1.x/reference/cli/kagent-db-migrate-down/) - Roll back the latest N migrations +- [`kagent db migrate goto`](/docs/kagent/1.x/reference/cli/kagent-db-migrate-goto/) - Move one source to version V +- [`kagent db migrate status`](/docs/kagent/1.x/reference/cli/kagent-db-migrate-status/) - Show migration status +- [`kagent db migrate up`](/docs/kagent/1.x/reference/cli/kagent-db-migrate-up/) - Apply all pending migrations +- [`kagent db migrate version`](/docs/kagent/1.x/reference/cli/kagent-db-migrate-version/) - Show the applied migration version + +**Flags:** +- `--db-url string` - PostgreSQL connection URL +- `-h, --help` - help for migrate +- `--source string` - Migration source for down, goto, or version + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--server-name string` - TLS server name for KAgent endpoints +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-db.md b/docs-site/content/kagent/1.x/reference/cli/kagent-db.md new file mode 100644 index 00000000..5b202454 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-db.md @@ -0,0 +1,22 @@ +--- +title: kagent db +description: Database operations (migrations, inspection). +weight: 110 +--- + +Database operations (migrations, inspection) + +```bash +kagent db [command] +``` + +**Subcommands:** +- [`kagent db migrate`](/docs/kagent/1.x/reference/cli/kagent-db-migrate/) - Apply, roll back, and inspect database migrations + +**Flags:** +- `-h, --help` - help for db + +**Global Flags:** +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--server-name string` - TLS server name for KAgent endpoints +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-delete-agent-instance.md b/docs-site/content/kagent/1.x/reference/cli/kagent-delete-agent-instance.md new file mode 100644 index 00000000..dfaa87da --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-delete-agent-instance.md @@ -0,0 +1,25 @@ +--- +title: kagent delete agent-instance +description: Delete an AgentInstance. +weight: 190 +--- + +Delete an AgentInstance + +```bash +kagent delete agent-instance ID [flags] +``` + +**Flags:** +- `-h, --help` - help for agent-instance + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-delete.md b/docs-site/content/kagent/1.x/reference/cli/kagent-delete.md new file mode 100644 index 00000000..19432097 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-delete.md @@ -0,0 +1,29 @@ +--- +title: kagent delete +description: Delete a kagent resource. +weight: 180 +--- + +Delete a kagent resource + +```bash +kagent delete [flags] +kagent delete [command] +``` + +**Subcommands:** +- [`kagent delete agent-instance`](/docs/kagent/1.x/reference/cli/kagent-delete-agent-instance/) - Delete an AgentInstance + +**Flags:** +- `-h, --help` - help for delete + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-instance.md b/docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-instance.md new file mode 100644 index 00000000..5e4f22a6 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-instance.md @@ -0,0 +1,27 @@ +--- +title: kagent get agent-instance +description: Get an AgentInstance or list your AgentInstances. +weight: 210 +--- + +Get an AgentInstance or list your AgentInstances + +```bash +kagent get agent-instance [ID] [flags] +``` + +**Flags:** +- `-h, --help` - help for agent-instance +- `--page-size int32` - Number of AgentInstances to return (default 50, maximum 100) +- `--page-token string` - Token returned by the previous page + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-template.md b/docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-template.md new file mode 100644 index 00000000..96ff0dd5 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-get-agent-template.md @@ -0,0 +1,27 @@ +--- +title: kagent get agent-template +description: Get an AgentTemplate or list AgentTemplates. +weight: 220 +--- + +Get an AgentTemplate or list AgentTemplates + +```bash +kagent get agent-template [NAME] [flags] +``` + +**Flags:** +- `-h, --help` - help for agent-template +- `--page-size int` - Number of AgentTemplates per page (0 uses 100; maximum 100) +- `--page-token string` - Token returned by the previous page + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-get.md b/docs-site/content/kagent/1.x/reference/cli/kagent-get.md new file mode 100644 index 00000000..2a4d5023 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-get.md @@ -0,0 +1,30 @@ +--- +title: kagent get +description: Get a kagent resource. +weight: 200 +--- + +Get a kagent resource + +```bash +kagent get [flags] +kagent get [command] +``` + +**Subcommands:** +- [`kagent get agent-instance`](/docs/kagent/1.x/reference/cli/kagent-get-agent-instance/) - Get an AgentInstance or list your AgentInstances +- [`kagent get agent-template`](/docs/kagent/1.x/reference/cli/kagent-get-agent-template/) - Get an AgentTemplate or list AgentTemplates + +**Flags:** +- `-h, --help` - help for get + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-install.md b/docs-site/content/kagent/1.x/reference/cli/kagent-install.md new file mode 100644 index 00000000..e69d9735 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-install.md @@ -0,0 +1,26 @@ +--- +title: kagent install +description: Install kagent. +weight: 230 +--- + +Install kagent + +```bash +kagent install [flags] +``` + +**Flags:** +- `-h, --help` - help for install +- `--profile string` - Installation profile (minimal) + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-invoke.md b/docs-site/content/kagent/1.x/reference/cli/kagent-invoke.md new file mode 100644 index 00000000..3c435a2c --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-invoke.md @@ -0,0 +1,36 @@ +--- +title: kagent invoke +description: Invoke an AgentInstance. +weight: 240 +--- + +Invoke an existing AgentInstance through the A2A API. + +```bash +kagent invoke [flags] +``` + +**Flags:** +- `--agent-instance string` - AgentInstance ID +- `-f, --file string` - Read task text from a file or - for stdin +- `-h, --help` - help for invoke +- `-S, --stream` - Stream the response +- `-t, --task string` - Task text +- `--token string` - Model API key passed through as an A2A Bearer token + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output + +## Example + +```bash +kagent invoke --agent-instance 8bd650a8-9775-488f-8bc1-0d52bf7bdcab --task "Get all the pods" +``` diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-add-tool.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-add-tool.md similarity index 68% rename from docs-site/content/kagent/resources/cli/kagent-mcp-add-tool.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-add-tool.md index a38a3ed5..cc56b229 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-add-tool.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-add-tool.md @@ -1,7 +1,7 @@ --- title: kagent mcp add-tool -description: Add a new MCP tool to your project -weight: 270 +description: Add a new MCP tool to your project. +weight: 260 --- Generate a new MCP tool that will be automatically loaded by the server. @@ -24,15 +24,14 @@ kagent mcp add-tool [tool-name] [flags] - `--project-dir string` - Project directory (default: current directory) **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output ## Example diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-build.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-build.md similarity index 68% rename from docs-site/content/kagent/resources/cli/kagent-mcp-build.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-build.md index 57030dea..5a6fcc0a 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-build.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-build.md @@ -1,7 +1,7 @@ --- title: kagent mcp build -description: Build MCP server as a Docker image -weight: 280 +description: Build MCP server as a Docker image. +weight: 270 --- Build an MCP server from the current project. @@ -23,15 +23,14 @@ kagent mcp build [flags] - `-t, --tag string` - Docker image tag (alias for --output) **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output ## Example diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-deploy-package.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy-package.md similarity index 84% rename from docs-site/content/kagent/resources/cli/kagent-mcp-deploy-package.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy-package.md index 2b0bc10b..630c9015 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-deploy-package.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy-package.md @@ -1,7 +1,7 @@ --- title: kagent mcp deploy package -description: Deploy an MCP server using a package manager (npx, uvx) -weight: 300 +description: Deploy an MCP server using a package manager (npx, uvx). +weight: 290 --- Deploy an MCP server using a package manager to run Model Context Protocol servers. @@ -31,14 +31,13 @@ kagent mcp deploy package [flags] - `--transport string` - Transport type (stdio, http) **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output ## Example diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-deploy.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy.md similarity index 80% rename from docs-site/content/kagent/resources/cli/kagent-mcp-deploy.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy.md index 7e9957d9..16164e0a 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-deploy.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy.md @@ -1,7 +1,7 @@ --- title: kagent mcp deploy -description: Deploy MCP server to Kubernetes -weight: 290 +description: Deploy MCP server to Kubernetes. +weight: 280 --- Deploy an MCP server to Kubernetes by generating MCPServer CRDs. @@ -28,7 +28,7 @@ kagent mcp deploy [command] ``` **Subcommands:** -- [`kagent mcp deploy package`](/docs/kagent/resources/cli/kagent-mcp-deploy-package/) - Deploy an MCP server using a package manager (npx, uvx) +- [`kagent mcp deploy package`](/docs/kagent/1.x/reference/cli/kagent-mcp-deploy-package/) - Deploy an MCP server using a package manager (npx, uvx) **Flags:** - `--args strings` - Command arguments @@ -47,14 +47,13 @@ kagent mcp deploy [command] - `--transport string` - Transport type (stdio, http) **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output ## Example diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-init-go.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-go.md similarity index 66% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-go.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-go.md index 671a6d1d..84168df1 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-init-go.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-go.md @@ -1,7 +1,7 @@ --- title: kagent mcp init go -description: Initialize a new Go MCP server project -weight: 320 +description: Initialize a new Go MCP server project. +weight: 310 --- Initialize a new MCP server project using the mcp-go framework. @@ -20,19 +20,18 @@ kagent mcp init go [project-name] [flags] - `-h, --help` - help for go **Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") - `--author string` - Author name for the project -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") +- `--ca-file string` - CA certificate file for KAgent endpoints - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-init-java.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-java.md similarity index 63% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-java.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-java.md index c13c94ac..56aec77f 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-init-java.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-java.md @@ -1,7 +1,7 @@ --- title: kagent mcp init java -description: Initialize a new Java MCP server project -weight: 330 +description: Initialize a new Java MCP server project. +weight: 320 --- Initialize a new MCP server project using the Java MCP framework. @@ -17,19 +17,18 @@ kagent mcp init java [project-name] [flags] - `-h, --help` - help for java **Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") - `--author string` - Author name for the project -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") +- `--ca-file string` - CA certificate file for KAgent endpoints - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-init-python.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-python.md similarity index 63% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-python.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-python.md index b55d8816..346dfc62 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-init-python.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-python.md @@ -1,7 +1,7 @@ --- title: kagent mcp init python -description: Initialize a new Python MCP server project -weight: 340 +description: Initialize a new Python MCP server project. +weight: 330 --- Initialize a new MCP server project using the fastmcp-python framework. @@ -17,19 +17,18 @@ kagent mcp init python [project-name] [flags] - `-h, --help` - help for python **Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") - `--author string` - Author name for the project -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") +- `--ca-file string` - CA certificate file for KAgent endpoints - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-init-typescript.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-typescript.md similarity index 63% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-typescript.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-typescript.md index 3cf9fb75..66d93fc3 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-init-typescript.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-typescript.md @@ -1,7 +1,7 @@ --- title: kagent mcp init typescript -description: Initialize a new TypeScript MCP server project -weight: 350 +description: Initialize a new TypeScript MCP server project. +weight: 340 --- Initialize a new MCP server project using the TypeScript MCP framework. @@ -17,19 +17,18 @@ kagent mcp init typescript [project-name] [flags] - `-h, --help` - help for typescript **Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") - `--author string` - Author name for the project -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") +- `--ca-file string` - CA certificate file for KAgent endpoints - `--description string` - Description for the project - `--email string` - Author email for the project - `--force` - Overwrite existing directory -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `--namespace string` - Default namespace for project resources (default "default") - `--no-git` - Skip git initialization - `--non-interactive` - Run in non-interactive mode - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init.md new file mode 100644 index 00000000..9685df82 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init.md @@ -0,0 +1,41 @@ +--- +title: kagent mcp init +description: Initialize a new MCP server project. +weight: 300 +--- + +Initialize a new MCP server project with dynamic tool loading. + +This command provides subcommands to initialize a new MCP server project +using one of the supported frameworks. + +```bash +kagent mcp init [project-name] [flags] +kagent mcp init [command] +``` + +**Subcommands:** +- [`kagent mcp init go`](/docs/kagent/1.x/reference/cli/kagent-mcp-init-go/) - Initialize a new Go MCP server project +- [`kagent mcp init java`](/docs/kagent/1.x/reference/cli/kagent-mcp-init-java/) - Initialize a new Java MCP server project +- [`kagent mcp init python`](/docs/kagent/1.x/reference/cli/kagent-mcp-init-python/) - Initialize a new Python MCP server project +- [`kagent mcp init typescript`](/docs/kagent/1.x/reference/cli/kagent-mcp-init-typescript/) - Initialize a new TypeScript MCP server project + +**Flags:** +- `--author string` - Author name for the project +- `--description string` - Description for the project +- `--email string` - Author email for the project +- `--force` - Overwrite existing directory +- `-h, --help` - help for init +- `--namespace string` - Default namespace for project resources (default "default") +- `--no-git` - Skip git initialization +- `--non-interactive` - Run in non-interactive mode + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-run.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-run.md similarity index 74% rename from docs-site/content/kagent/resources/cli/kagent-mcp-run.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-run.md index 6a53b768..edb1fa14 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-run.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-run.md @@ -1,7 +1,7 @@ --- title: kagent mcp run -description: Run MCP server locally -weight: 360 +description: Run MCP server locally. +weight: 350 --- Run an MCP server locally using the Model Context Protocol inspector. @@ -29,15 +29,14 @@ kagent mcp run [flags] - `--transport string` - Transport mode (stdio or http) (default "stdio") **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output ## Example diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-secrets-sync.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets-sync.md similarity index 75% rename from docs-site/content/kagent/resources/cli/kagent-mcp-secrets-sync.md rename to docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets-sync.md index 032ed5a2..0e06b9b7 100644 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-secrets-sync.md +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets-sync.md @@ -1,7 +1,7 @@ --- title: kagent mcp secrets sync -description: Sync secrets to a Kubernetes environment from a local .env file -weight: 380 +description: Sync secrets to a Kubernetes environment from a local .env file. +weight: 370 --- Sync secrets from a local .env file to a Kubernetes secret. @@ -23,15 +23,14 @@ kagent mcp secrets sync [environment] [flags] - `-d, --project-dir string` - Project directory (default: current directory) **Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") - `-n, --namespace string` - Namespace (default "kagent") - `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints - `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") - `-v, --verbose` - Verbose output ## Example diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets.md new file mode 100644 index 00000000..86a91762 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets.md @@ -0,0 +1,28 @@ +--- +title: kagent mcp secrets +description: Manage project secrets. +weight: 360 +--- + +Manage secrets for MCP server projects. + +```bash +kagent mcp secrets [command] +``` + +**Subcommands:** +- [`kagent mcp secrets sync`](/docs/kagent/1.x/reference/cli/kagent-mcp-secrets-sync/) - Sync secrets to a Kubernetes environment from a local .env file + +**Flags:** +- `-h, --help` - help for secrets + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp.md new file mode 100644 index 00000000..1ba69154 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp.md @@ -0,0 +1,34 @@ +--- +title: kagent mcp +description: MCP (Model Context Protocol) server management. +weight: 250 +--- + +MCP server management commands for creating and managing +Model Context Protocol servers with dynamic tool loading. + +```bash +kagent mcp [command] +``` + +**Subcommands:** +- [`kagent mcp add-tool`](/docs/kagent/1.x/reference/cli/kagent-mcp-add-tool/) - Add a new MCP tool to your project +- [`kagent mcp build`](/docs/kagent/1.x/reference/cli/kagent-mcp-build/) - Build MCP server as a Docker image +- [`kagent mcp deploy`](/docs/kagent/1.x/reference/cli/kagent-mcp-deploy/) - Deploy MCP server to Kubernetes +- [`kagent mcp init`](/docs/kagent/1.x/reference/cli/kagent-mcp-init/) - Initialize a new MCP server project +- [`kagent mcp run`](/docs/kagent/1.x/reference/cli/kagent-mcp-run/) - Run MCP server locally +- [`kagent mcp secrets`](/docs/kagent/1.x/reference/cli/kagent-mcp-secrets/) - Manage project secrets + +**Flags:** +- `-h, --help` - help for mcp + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-uninstall.md b/docs-site/content/kagent/1.x/reference/cli/kagent-uninstall.md new file mode 100644 index 00000000..7983aa18 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-uninstall.md @@ -0,0 +1,25 @@ +--- +title: kagent uninstall +description: Uninstall kagent. +weight: 380 +--- + +Uninstall kagent + +```bash +kagent uninstall [flags] +``` + +**Flags:** +- `-h, --help` - help for uninstall + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-version.md b/docs-site/content/kagent/1.x/reference/cli/kagent-version.md new file mode 100644 index 00000000..f51ad1d2 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-version.md @@ -0,0 +1,25 @@ +--- +title: kagent version +description: Print the kagent version. +weight: 390 +--- + +Print the kagent version + +```bash +kagent version [flags] +``` + +**Flags:** +- `-h, --help` - help for version + +**Global Flags:** +- `--api-url string` - KAgent control-plane API URL (default "http://localhost:8083") +- `--ca-file string` - CA certificate file for KAgent endpoints +- `--gateway-url string` - KAgent A2A and MCP gateway URL (default "http://localhost:8083") +- `-n, --namespace string` - Namespace (default "kagent") +- `-o, --output-format string` - Output format (default "table") +- `--server-name string` - TLS server name for KAgent endpoints +- `--timeout duration` - Timeout (default 5m0s) +- `--user-id string` - Caller identity used to select the server-side data partition (default "admin@kagent.dev") +- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate-down.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate-down.md deleted file mode 100644 index 3ed29cce..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate-down.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: kagent db migrate down -description: Roll back the N most-recent applied migrations for the selected source -weight: 120 ---- - -Roll back the N most-recent applied migrations for the selected source. - -Down migrations can lose data by design — a rolled-back column loses -its contents. Refuses to run while the source's tracking table is -dirty; clear it with 'force' first. - -```bash -kagent db migrate down N [flags] -``` - -**Flags:** -- `-h, --help` - help for down - -**Global Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate-force.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate-force.md deleted file mode 100644 index b4cc6cdc..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate-force.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: kagent db migrate force -description: Mark version V as applied without running its SQL -weight: 130 ---- - -Used to reconcile the selected source's tracking table after manual -remediation, e.g. to clear a dirty flag left by a failed migration. -V=0 clears the version record entirely (the "no migrations applied" -state). Any other V must correspond to a shipped migration file in -the selected source — otherwise the tracking row would point at a -version the binary cannot apply or roll back to, wedging the DB. - -```bash -kagent db migrate force V [flags] -``` - -**Flags:** -- `-h, --help` - help for force - -**Global Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate-goto.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate-goto.md deleted file mode 100644 index fbab53ce..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate-goto.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: kagent db migrate goto -description: Move the selected source's schema to version V -weight: 140 ---- - -Move the selected source's schema to version V (forward or backward). -V=0 is the special "empty schema" target: every applied migration in -the source is rolled back. - -Refuses to run while the source's tracking table is dirty; clear it -with 'force' first. - -```bash -kagent db migrate goto V [flags] -``` - -**Flags:** -- `-h, --help` - help for goto - -**Global Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate-status.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate-status.md deleted file mode 100644 index 92762ebc..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate-status.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: kagent db migrate status -description: Show how many migrations are applied vs pending across all sources -weight: 150 ---- - -Show how many migrations are applied vs pending across all sources - -```bash -kagent db migrate status [flags] -``` - -**Flags:** -- `-h, --help` - help for status -- `--output string` - Output format: "text" (default) or "json" (default "text") - -**Global Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate-up.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate-up.md deleted file mode 100644 index feb5de31..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate-up.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: kagent db migrate up -description: Apply all pending migrations across every registered source -weight: 160 ---- - -Applies pending migrations for every registered source in -registration order, through the same orchestrator the server runs at -startup: per-source advisory locking, pre-run version snapshots, and -compensating rollback of earlier sources when a later one fails. - -Refuses to run while any source's tracking table is dirty; clear it -with 'force' first. - -The --source flag is intentionally not applicable to up; pass it only -on the per-source subcommands (down/goto/force). - -```bash -kagent db migrate up [flags] -``` - -**Flags:** -- `-h, --help` - help for up - -**Global Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate-version.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate-version.md deleted file mode 100644 index 451bae2a..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate-version.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: kagent db migrate version -description: Print the highest applied migration version -weight: 170 ---- - -Print the highest applied migration version. -For a single registered source the value is on one line; multi-source -binaries print one line per source. When multiple sources are -registered, --source filters to a single track. - -```bash -kagent db migrate version [flags] -``` - -**Flags:** -- `-h, --help` - help for version - -**Global Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. diff --git a/docs-site/content/kagent/resources/cli/kagent-db-migrate.md b/docs-site/content/kagent/resources/cli/kagent-db-migrate.md deleted file mode 100644 index 7d77c602..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db-migrate.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: kagent db migrate -description: Apply, roll back, and inspect database migrations -weight: 110 ---- - -Apply, roll back, and inspect database migrations independently -of server startup. Reads POSTGRES_DATABASE_URL from the environment when ---db-url is omitted. - -```bash -kagent db migrate [command] -``` - -**Subcommands:** -- [`kagent db migrate down`](/docs/kagent/resources/cli/kagent-db-migrate-down/) - Roll back the N most-recent applied migrations for the selected source -- [`kagent db migrate force`](/docs/kagent/resources/cli/kagent-db-migrate-force/) - Mark version V as applied without running its SQL -- [`kagent db migrate goto`](/docs/kagent/resources/cli/kagent-db-migrate-goto/) - Move the selected source's schema to version V -- [`kagent db migrate status`](/docs/kagent/resources/cli/kagent-db-migrate-status/) - Show how many migrations are applied vs pending across all sources -- [`kagent db migrate up`](/docs/kagent/resources/cli/kagent-db-migrate-up/) - Apply all pending migrations across every registered source -- [`kagent db migrate version`](/docs/kagent/resources/cli/kagent-db-migrate-version/) - Print the highest applied migration version - -**Flags:** -- `--db-url string` - PostgreSQL connection URL (defaults to value of POSTGRES_DATABASE_URL env var) -- `-h, --help` - help for migrate -- `--source string` - Migration source name for per-source ops (down/goto/force/version); inferred when only one source is registered. Not applicable to up or status — those aggregate across every registered source. - -**Global Flags:** -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") diff --git a/docs-site/content/kagent/resources/cli/kagent-db.md b/docs-site/content/kagent/resources/cli/kagent-db.md deleted file mode 100644 index 79da8488..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-db.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: kagent db -description: Database operations (migrations, inspection) -weight: 100 ---- - -Database operations (migrations, inspection) - -```bash -kagent db [command] -``` - -**Subcommands:** -- [`kagent db migrate`](/docs/kagent/resources/cli/kagent-db-migrate/) - Apply, roll back, and inspect database migrations - -**Flags:** -- `-h, --help` - help for db - -**Global Flags:** -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") diff --git a/docs-site/content/kagent/resources/cli/kagent-get-agent.md b/docs-site/content/kagent/resources/cli/kagent-get-agent.md deleted file mode 100644 index b34d8c97..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-get-agent.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: kagent get agent -description: Get an agent or list all agents -weight: 200 ---- - -Get an agent by name or list all agents - -```bash -kagent get agent [agent_name] [flags] -``` - -**Flags:** -- `-h, --help` - help for agent - -**Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") -- `-n, --namespace string` - Namespace (default "kagent") -- `-o, --output-format string` - Output format (default "table") -- `--timeout duration` - Timeout (default 5m0s) -- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-get-session.md b/docs-site/content/kagent/resources/cli/kagent-get-session.md deleted file mode 100644 index 59ea9e08..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-get-session.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: kagent get session -description: Get a session or list all sessions -weight: 210 ---- - -Get a session by ID or list all sessions - -```bash -kagent get session [session_id] [flags] -``` - -**Flags:** -- `-h, --help` - help for session - -**Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") -- `-n, --namespace string` - Namespace (default "kagent") -- `-o, --output-format string` - Output format (default "table") -- `--timeout duration` - Timeout (default 5m0s) -- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-get-tool.md b/docs-site/content/kagent/resources/cli/kagent-get-tool.md deleted file mode 100644 index f3246a15..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-get-tool.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: kagent get tool -description: Get tools -weight: 220 ---- - -List all available tools - -```bash -kagent get tool [flags] -``` - -**Flags:** -- `-h, --help` - help for tool - -**Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") -- `-n, --namespace string` - Namespace (default "kagent") -- `-o, --output-format string` - Output format (default "table") -- `--timeout duration` - Timeout (default 5m0s) -- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-init.md b/docs-site/content/kagent/resources/cli/kagent-mcp-init.md deleted file mode 100644 index 41f0a19a..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-init.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: kagent mcp init -description: Initialize a new MCP server project -weight: 310 ---- - -Initialize a new MCP server project with dynamic tool loading. - -This command provides subcommands to initialize a new MCP server project -using one of the supported frameworks. - -```bash -kagent mcp init [project-name] [flags] -kagent mcp init [command] -``` - -**Subcommands:** -- [`kagent mcp init go`](/docs/kagent/resources/cli/kagent-mcp-init-go/) - Initialize a new Go MCP server project -- [`kagent mcp init java`](/docs/kagent/resources/cli/kagent-mcp-init-java/) - Initialize a new Java MCP server project -- [`kagent mcp init python`](/docs/kagent/resources/cli/kagent-mcp-init-python/) - Initialize a new Python MCP server project -- [`kagent mcp init typescript`](/docs/kagent/resources/cli/kagent-mcp-init-typescript/) - Initialize a new TypeScript MCP server project - -**Flags:** -- `--author string` - Author name for the project -- `--description string` - Description for the project -- `--email string` - Author email for the project -- `--force` - Overwrite existing directory -- `-h, --help` - help for init -- `--namespace string` - Default namespace for project resources (default "default") -- `--no-git` - Skip git initialization -- `--non-interactive` - Run in non-interactive mode - -**Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") -- `-o, --output-format string` - Output format (default "table") -- `--timeout duration` - Timeout (default 5m0s) -- `-v, --verbose` - Verbose output diff --git a/docs-site/content/kagent/resources/cli/kagent-mcp-secrets.md b/docs-site/content/kagent/resources/cli/kagent-mcp-secrets.md deleted file mode 100644 index 7116fcb4..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-mcp-secrets.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: kagent mcp secrets -description: Manage project secrets -weight: 370 ---- - -Manage secrets for MCP server projects. - -```bash -kagent mcp secrets [command] -``` - -**Subcommands:** -- [`kagent mcp secrets sync`](/docs/kagent/resources/cli/kagent-mcp-secrets-sync/) - Sync secrets to a Kubernetes environment from a local .env file - -**Flags:** -- `-h, --help` - help for secrets - -**Global Flags:** -- `--config string` - config file (default is $HOME/.kagent/config.yaml) (default "$HOME/.kagent/config.yaml") -- `--kagent-grpc-ca-file string` - CA certificate file for KAgent gRPC -- `--kagent-grpc-server-name string` - TLS server name for KAgent gRPC -- `--kagent-grpc-tls` - Use TLS for KAgent gRPC -- `--kagent-grpc-url string` - KAgent gRPC target (default "localhost:8084") -- `--kagent-url string` - KAgent REST URL (default "http://localhost:8083") -- `-n, --namespace string` - Namespace (default "kagent") -- `-o, --output-format string` - Output format (default "table") -- `--timeout duration` - Timeout (default 5m0s) -- `-v, --verbose` - Verbose output diff --git a/scripts/generate-cli-docs.py b/scripts/generate-cli-docs.py index 47ed05e2..1bdc295c 100755 --- a/scripts/generate-cli-docs.py +++ b/scripts/generate-cli-docs.py @@ -285,6 +285,25 @@ def slugify(display_name: str, path: list[str]) -> str: return "-".join(parts) +def as_sentence(text: str) -> str: + """Terminate a Cobra Short string so it reads as a frontmatter description. + + Every description on these pages is a Cobra `Short`, which by convention is + an unterminated fragment ("Invoke an AgentInstance"). The site's frontmatter + descriptions are full sentences ending in a period, and they surface far + from the CLI -- search results, social cards, the section index -- where the + missing period reads as truncation rather than as convention. + + Only the terminator is added. A Short that is already imperative stays as + written, and one that is not is a wording fix in kagent or kmcp, not + something to paper over here. + """ + text = text.strip() + if not text or text[-1] in ".!?": + return text + return text + "." + + def render_flags(flags: list[tuple[str, str]]) -> str: if not flags: return "" @@ -342,7 +361,7 @@ def render_page(display_name: str, node: CommandNode, weight: int, description: # is not under this script's control; the first Cobra Short that # contains ": " (or a leading quote, #, etc.) would otherwise produce # invalid or silently misparsed YAML in an unattended nightly job. - frontmatter_data = {"title": title, "description": description, "weight": weight} + frontmatter_data = {"title": title, "description": as_sentence(description), "weight": weight} frontmatter = "---\n" + yaml.safe_dump(frontmatter_data, sort_keys=False, allow_unicode=True) + "---\n\n" return frontmatter + body @@ -365,6 +384,16 @@ def main() -> int: "correctly for one of those two forms." ), ) + parser.add_argument( + "--weight", + type=int, + default=1, + help=( + "Hugo weight for the section's _index.md, i.e. where CLI docs sit " + "among their siblings. Defaults to 1 (first). The per-page weights " + "below are independent of this and always start at 10." + ), + ) args = parser.parse_args() url_prefix = args.url_prefix.rstrip("/") @@ -400,8 +429,8 @@ def main() -> int: weight = 10 index_frontmatter_data = { "title": "CLI docs", - "description": f"Complete reference docs for the {args.display_name} CLI commands", - "weight": 1, + "description": f"Review the reference docs for the {args.display_name} CLI commands.", + "weight": args.weight, } index_lines = [ "---",