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 e5ae6db3..96b31919 100644 --- a/.github/workflows/update-ref-docs.yaml +++ b/.github/workflows/update-ref-docs.yaml @@ -13,10 +13,63 @@ 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/1.x/reference/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/1.x/reference/helm.md # Each page uses plain Hugo YAML frontmatter (no MDX `export const metadata`). +# +# It also refreshes the version conrefs under +# docs-site/assets/kagent-docs/versions/ (plus the second copy of the Kubernetes +# version at public/docs/versions/max-kube.md). Those steps run first, because +# the API reference is generated against the Kubernetes version they write. +# Conrefs and reference pages share ONE pull request on purpose: this repo +# already receives a dozen or so automated PRs a day, and splitting these would +# add another for a diff that is usually empty. When a conref does move, the PR +# title and body say so, because that case needs the guides re-tested rather +# than a routine review. +# +# Retargeted from 0.x to 1.x on 2026-09-11. This job generates from kagent +# main, so it can only ever be correct for the tree that main actually ships. +# main dropped go/api/v1alpha2 in kagent 7bf6a6cd (#2696) on 2026-09-04 and +# now ships v1alpha3, which is what 1.x documents. Between that removal and +# 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, 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, +# ...), so keep that renderer and its anchor naming. +# +# Frontmatter lives in the heredocs below, not in the generated pages: every +# run overwrites it. Descriptions follow the 1.x convention of an imperative +# verb and a full sentence. jobs: generate-api-docs: runs-on: ubuntu-latest @@ -27,12 +80,20 @@ 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/1.x/reference/api-ref.md KMCP_API_PAGE: docs-site/content/kmcp/reference/api-ref.md - HELM_PAGE: docs-site/content/kagent/resources/helm.md - KAGENT_CLI_DIR: docs-site/content/kagent/resources/cli + HELM_PAGE: docs-site/content/kagent/1.x/reference/helm.md + VERSIONS_DIR: website/docs-site/assets/kagent-docs/versions + # The second, easily-missed copy of the Kubernetes version. "Read max + # Kubernetes version" below feeds THIS file to crd-ref-docs as + # KUBE_VERSION, while the docs render the assets/ copy. Same fact, two + # committed files, so the conref step writes both. They had already + # drifted when this was wired up -- assets/ said 1.35 and public/ said + # 1.31, silently pinning every Kubernetes API link in api-ref.md to 1.31. + KUBE_VERSION_FILE: website/public/docs/versions/max-kube.md + KAGENT_CLI_DIR: docs-site/content/kagent/1.x/reference/cli KMCP_CLI_DIR: docs-site/content/kmcp/reference/cli - KAGENT_CLI_URL_PREFIX: /docs/kagent/resources/cli + KAGENT_CLI_URL_PREFIX: /docs/kagent/1.x/reference/cli KMCP_CLI_URL_PREFIX: /docs/kmcp/reference/cli steps: @@ -66,10 +127,221 @@ jobs: - name: Set kmcp commit SHA run: echo "KMCP_COMMIT=$(cd kmcp && git rev-parse --short HEAD)" >> $GITHUB_ENV + # --------------------------------------------------------------------- + # Version conrefs. + # + # These run BEFORE "Read max Kubernetes version" on purpose: that step + # feeds public/docs/versions/max-kube.md to crd-ref-docs as KUBE_VERSION, + # so correcting the conrefs first means the API reference is generated + # against the fresh value in the same run rather than a run later. + # + # Each value is read from the same place kagent's own build reads it, so + # the docs and the release artifact cannot disagree. helm/kagent/Chart.yaml + # is NOT a source: it is gitignored and generated from Chart-template.yaml + # by envsubst, so a checkout never carries a useful value. + # + # Deliberately not automated: kagent.md names the UPCOMING release while + # `git describe` on main yields a dev tag, so it stays editorial until 1.0 + # ships; and jaeger / loki / tempo / otel-collector are pinned nowhere in + # kagent, so the only source is "latest upstream", which would assert + # chart versions no guide was tested against. + # --------------------------------------------------------------------- + - name: Read versions from kagent + run: | + set -euo pipefail + + MAKEFILE="kagent/Makefile" + GOMOD="kagent/go/go.mod" + CHART_TEMPLATE="kagent/helm/kagent/Chart-template.yaml" + + for f in "$MAKEFILE" "$GOMOD" "$CHART_TEMPLATE"; do + if [ ! -f "$f" ]; then + echo "Error: expected $f in the kagent checkout" + exit 1 + fi + done + + # Field 5 of the replace directive: + # replace github.com/agent-substrate/substrate => github.com/kagent-dev/substrate v0.0.29 + SUBSTRATE_VERSION=$(awk '/github\.com\/kagent-dev\/substrate/ { print substr($5, 2) }' "$GOMOD" | head -1) + # Field 2 of the require line. + KMCP_VERSION=$(awk '/github\.com\/kagent-dev\/kmcp/ { print substr($2, 2) }' "$GOMOD" | head -1) + # kagent-tools carries a literal version in the template, not a ${VAR}. + KAGENT_TOOLS_VERSION=$(awk '/name: kagent-tools/{f=1} f&&/version:/{print $2; exit}' "$CHART_TEMPLATE") + # KIND_IMAGE_VERSION is a full x.y.z; the conref carries major.minor. + MAX_KUBE=$(sed -n 's/^KIND_IMAGE_VERSION[[:space:]]*?*=[[:space:]]*\([0-9]*\.[0-9]*\).*/\1/p' "$MAKEFILE" | head -1) + + # Fail loudly on an unexpected shape. An empty value would otherwise + # blank a conref and silently break every command that reuses it. + check() { + if ! printf '%s' "$2" | grep -Eq "$3"; then + echo "Error: $1 extracted as '$2', which does not match $3." + echo "The source file's shape likely changed in kagent. Fix the extraction here rather than editing the conref by hand." + exit 1 + fi + echo " $1 = $2" + } + + echo "Extracted from kagent ${KAGENT_COMMIT}:" + check SUBSTRATE_VERSION "$SUBSTRATE_VERSION" '^[0-9]+\.[0-9]+\.[0-9]+$' + check KMCP_VERSION "$KMCP_VERSION" '^[0-9]+\.[0-9]+\.[0-9]+$' + check KAGENT_TOOLS_VERSION "$KAGENT_TOOLS_VERSION" '^[0-9]+\.[0-9]+\.[0-9]+$' + check MAX_KUBE "$MAX_KUBE" '^[0-9]+\.[0-9]+$' + + { + echo "SUBSTRATE_VERSION=$SUBSTRATE_VERSION" + echo "KMCP_VERSION=$KMCP_VERSION" + echo "KAGENT_TOOLS_VERSION=$KAGENT_TOOLS_VERSION" + echo "MAX_KUBE=$MAX_KUBE" + } >> $GITHUB_ENV + + - name: Cross-check kmcp against its own latest release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + # versions/kmcp.md is reused by BOTH the kagent 1.x support matrix and + # the standalone kmcp install guides, which want subtly different + # things: what kagent bundles, versus what kmcp last released. The two + # agree today (both 0.3.0). This job writes the kagent-pinned value, + # because the guides that install kmcp inside kagent outnumber the + # standalone ones and must match the bundled chart. A divergence is + # surfaced here rather than silently resolved -- if it ever fires, the + # real fix is to split the conref by version the way + # versions/agent-substrate.md already does. + KMCP_LATEST=$(gh release view \ + --repo "${{ github.repository_owner }}/kmcp" \ + --json tagName -q .tagName 2>/dev/null | sed 's/^v//' || true) + + if [ -z "$KMCP_LATEST" ]; then + echo "Note: could not read kmcp's latest release; skipping the cross-check." + echo "KMCP_MISMATCH=" >> $GITHUB_ENV + exit 0 + fi + + if [ "$KMCP_LATEST" != "$KMCP_VERSION" ]; then + echo "::warning::kagent pins kmcp $KMCP_VERSION but kmcp's latest release is $KMCP_LATEST. Writing the pinned value; the standalone kmcp install guides may now understate." + echo "KMCP_MISMATCH=kagent pins \`$KMCP_VERSION\`, kmcp's latest release is \`$KMCP_LATEST\`. The pinned value was written. Consider splitting \`versions/kmcp.md\` by version." >> $GITHUB_ENV + else + echo "kmcp cross-check OK: pinned and latest release both $KMCP_VERSION" + echo "KMCP_MISMATCH=" >> $GITHUB_ENV + fi + + - name: Update version conrefs + run: | + set -euo pipefail + + if [ ! -d "$VERSIONS_DIR" ]; then + echo "Error: $VERSIONS_DIR not found in the docs checkout" + exit 1 + fi + + # These files carry NO trailing newline, and must not gain one: they + # render inline into shell commands like `--version {{< reuse ... >}} \`, + # where a newline would split the command. Always printf, never echo. + write_conref() { + local file="$1" value="$2" + if [ ! -f "$file" ]; then + echo "Error: expected conref $file" + exit 1 + fi + local before + before=$(cat "$file") + printf '%s' "$value" > "$file" + if [ "$before" != "$value" ]; then + echo " $(basename "$file"): $before -> $value" + else + echo " $(basename "$file"): unchanged ($value)" + fi + } + + echo "Plain-value conrefs:" + write_conref "$VERSIONS_DIR/kmcp.md" "$KMCP_VERSION" + write_conref "$VERSIONS_DIR/kagent-tools.md" "$KAGENT_TOOLS_VERSION" + write_conref "$VERSIONS_DIR/max-kube.md" "$MAX_KUBE" + write_conref "$KUBE_VERSION_FILE" "$MAX_KUBE" + + # agent-substrate.md is version-split and 0.x is FROZEN: + # {{< version include-if="0.x" >}}0.0.6{{< /version >}}{{< version include-if="1.x" >}}0.0.26{{< /version >}} + # Replace only the 1.x span. The 0.x value documents what kagent 0.9.x + # shipped against and must never be rewritten from main. + SUBSTRATE_CONREF="$VERSIONS_DIR/agent-substrate.md" + if [ ! -f "$SUBSTRATE_CONREF" ]; then + echo "Error: expected conref $SUBSTRATE_CONREF" + exit 1 + fi + + # Read, substitute, then printf the result back, rather than sed -i. + # Whether sed -i appends a trailing newline to a file that lacked one + # is unspecified by POSIX and varies between implementations; $( ) + # strips trailing newlines and printf '%s' writes none, so the byte + # layout is deterministic either way. + SUBSTRATE_BEFORE=$(cat "$SUBSTRATE_CONREF") + SUBSTRATE_AFTER=$(printf '%s' "$SUBSTRATE_BEFORE" \ + | sed -E "s|(include-if=\"1\.x\" >\}\})[^{]*(\{\{< /version >\}\})|\1${SUBSTRATE_VERSION}\2|") + printf '%s' "$SUBSTRATE_AFTER" > "$SUBSTRATE_CONREF" + + # Prove the surgery did what it claims: the 1.x span now holds the new + # value, and the 0.x span is byte-identical to what it was. -F because + # the needle is a literal containing regex metacharacters. + if ! printf '%s' "$SUBSTRATE_AFTER" | grep -qF "include-if=\"1.x\" >}}${SUBSTRATE_VERSION}{{< /version >}}"; then + echo "Error: the 1.x span of agent-substrate.md did not take the new value." + echo " before: $SUBSTRATE_BEFORE" + echo " after: $SUBSTRATE_AFTER" + exit 1 + fi + BEFORE_0X=$(printf '%s' "$SUBSTRATE_BEFORE" | sed -E 's|(\{\{< version include-if="1\.x").*||') + AFTER_0X=$(printf '%s' "$SUBSTRATE_AFTER" | sed -E 's|(\{\{< version include-if="1\.x").*||') + if [ "$BEFORE_0X" != "$AFTER_0X" ]; then + echo "Error: the frozen 0.x span of agent-substrate.md changed. Refusing to continue." + echo " before: $BEFORE_0X" + echo " after: $AFTER_0X" + exit 1 + fi + + echo "Version-split conref:" + if [ "$SUBSTRATE_BEFORE" != "$SUBSTRATE_AFTER" ]; then + echo " agent-substrate.md 1.x span -> $SUBSTRATE_VERSION (0.x span untouched)" + else + echo " agent-substrate.md: unchanged ($SUBSTRATE_VERSION)" + fi + + - name: Flag whether the conrefs moved + run: | + set -euo pipefail + cd website + # Drives the re-test callout in the PR body below. Most nights this is + # empty and the PR is a routine reference regeneration. + if git diff --quiet -- docs-site/assets/kagent-docs/versions public/docs/versions; then + echo "CONREFS_CHANGED=" >> $GITHUB_ENV + echo "CONREF_NOTE=" >> $GITHUB_ENV + echo "No conref changes this run; this is a routine reference regeneration." + else + echo "CONREFS_CHANGED=1" >> $GITHUB_ENV + echo "Conref changes in this run:" + git diff --stat -- docs-site/assets/kagent-docs/versions public/docs/versions + # Multi-line env value, so the PR body can carry a real callout. + { + echo "CONREF_NOTE< [!IMPORTANT]" + echo "> **A version conref moved in this run, so this is not a routine regeneration.**" + echo "> These values render into \`helm install --version\` lines that readers copy out of" + echo "> \`setup/installation.md\`, \`observability/tracing.md\`, and \`observability/audit-prompts.md\`." + echo "> Merging asserts the guides work against the versions below, so re-test the affected" + echo "> guides rather than merging on green CI alone." + echo "" + echo '```diff' + git diff -- docs-site/assets/kagent-docs/versions public/docs/versions | sed -n 's/^\([+-][^+-]\)/\1/p' + echo '```' + echo "CONREF_NOTE_EOF" + } >> $GITHUB_ENV + fi + - name: Verify API directory exists run: | - if [ ! -d "$GITHUB_WORKSPACE/kagent/go/api/v1alpha2" ]; then - echo "Error: API directory not found at $GITHUB_WORKSPACE/kagent/go/api/v1alpha2" + if [ ! -d "$GITHUB_WORKSPACE/kagent/go/api/v1alpha3" ]; then + echo "Error: API directory not found at $GITHUB_WORKSPACE/kagent/go/api/v1alpha3" ls -la "$GITHUB_WORKSPACE/kagent/go/api/" exit 1 fi @@ -102,7 +374,7 @@ jobs: # Generate API docs go run github.com/elastic/crd-ref-docs@v0.1.0 \ - --source-path="$GITHUB_WORKSPACE/kagent/go/api/v1alpha2/" \ + --source-path="$GITHUB_WORKSPACE/kagent/go/api/v1alpha3/" \ --renderer=markdown \ --output-path ./ \ --config=crd-ref-docs-config.yaml @@ -147,10 +419,9 @@ jobs: mkdir -p "$(dirname "$KAGENT_API_PAGE")" cat > "$KAGENT_API_PAGE" <<'EOF' --- - title: API Reference - linkTitle: API docs - description: kagent API reference documentation - weight: 1 + title: API reference + description: Look up every field in the kagent v1alpha3 custom resources, including AgentTemplate, Harness, ModelConfig, and RemoteMCPServer. + weight: 10 author: kagent.dev --- @@ -360,10 +631,9 @@ jobs: mkdir -p "$(dirname "$HELM_PAGE")" cat > "$HELM_PAGE" <<'EOF' --- - title: kagent - linkTitle: Helm Chart Configuration - description: kagent Helm chart configuration reference - weight: 2 + title: Helm reference + description: Look up the configurable values in the kagent Helm chart, including their defaults and types. + weight: 20 author: kagent.dev --- @@ -397,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" @@ -404,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: | @@ -426,14 +703,27 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} path: website - commit-message: "docs: Update kagent and kmcp API, Helm, and CLI reference docs" + commit-message: "docs: Update kagent 1.x and kmcp reference docs" signoff: true - title: "Update kagent and kmcp API, Helm, and CLI reference docs" + title: "Update kagent 1.x and kmcp reference docs${{ env.CONREFS_CHANGED && ' (version conrefs changed)' || '' }}" body: | - Automated API, kagent Helm chart, and CLI reference documentation update based on the latest commits: + Automated update of the kagent 1.x API and Helm references, the kmcp API reference, and the version conrefs, based on the latest commits: - **kagent**: [`${{ env.KAGENT_COMMIT }}`](https://github.com/${{ github.repository_owner }}/kagent/commit/${{ env.KAGENT_COMMIT }}) - **kmcp**: [`${{ env.KMCP_COMMIT }}`](https://github.com/${{ github.repository_owner }}/kmcp/commit/${{ env.KMCP_COMMIT }}) + ${{ env.CONREF_NOTE }} + + Version conrefs in this run, each read from the same place kagent's own build reads it: + + | Conref | Value | Source in kagent | + | ------ | ----- | ---------------- | + | `agent-substrate` (1.x span only) | `${{ env.SUBSTRATE_VERSION }}` | `go/go.mod` replace target | + | `kmcp` | `${{ env.KMCP_VERSION }}` | `go/go.mod` require | + | `kagent-tools` | `${{ env.KAGENT_TOOLS_VERSION }}` | `helm/kagent/Chart-template.yaml` | + | `max-kube` (both committed copies) | `${{ env.MAX_KUBE }}` | `Makefile` `KIND_IMAGE_VERSION` | + + Unchanged conref values are normal: most runs touch only the generated reference pages. + This PR was automatically generated by the [**Update Reference documentation** workflow](https://github.com/${{ github.repository_owner }}/website/actions/workflows/update-ref-docs.yaml). branch: api-gen-update delete-branch: true diff --git a/Makefile b/Makefile index 7ed431cf..d878e90b 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,16 @@ 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 +# 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 - 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/) @@ -47,8 +55,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_CONFIG_PREVIEW) -D --disableFastRender --renderToMemory # ── Web (Next.js) ────────────────────────────────────────────────────────── .PHONY: serve-web 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/assets/css/custom.css b/docs-site/assets/css/custom.css index 2680967b..30b0397e 100644 --- a/docs-site/assets/css/custom.css +++ b/docs-site/assets/css/custom.css @@ -434,3 +434,64 @@ 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;
+}
+
+/* ── 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);
+}
+
+/* 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/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/assets/kagent-docs/snippets/grpcurl-prerequisites.md b/docs-site/assets/kagent-docs/snippets/grpcurl-prerequisites.md
new file mode 100644
index 00000000..f636f2b0
--- /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 8083:8083
+   ```
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/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/assets/kagent-docs/versions/agent-substrate.md b/docs-site/assets/kagent-docs/versions/agent-substrate.md new file mode 100644 index 00000000..9f60ea92 --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/agent-substrate.md @@ -0,0 +1 @@ +{{< 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/jaeger.md b/docs-site/assets/kagent-docs/versions/jaeger.md new file mode 100644 index 00000000..34014745 --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/jaeger.md @@ -0,0 +1 @@ +4.4.7 \ No newline at end of file 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/kagent-docs/versions/kagent.md b/docs-site/assets/kagent-docs/versions/kagent.md new file mode 100644 index 00000000..3eb5ac91 --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/kagent.md @@ -0,0 +1 @@ +{{< 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/assets/kagent-docs/versions/kmcp.md b/docs-site/assets/kagent-docs/versions/kmcp.md new file mode 100644 index 00000000..9325c3cc --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/kmcp.md @@ -0,0 +1 @@ +0.3.0 \ No newline at end of file diff --git a/docs-site/assets/kagent-docs/versions/loki.md b/docs-site/assets/kagent-docs/versions/loki.md new file mode 100644 index 00000000..57f7599b --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/loki.md @@ -0,0 +1 @@ +6.24.0 \ No newline at end of file diff --git a/docs-site/assets/kagent-docs/versions/max-kube.md b/docs-site/assets/kagent-docs/versions/max-kube.md new file mode 100644 index 00000000..f71ef947 --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/max-kube.md @@ -0,0 +1 @@ +1.35 \ No newline at end of file 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/assets/kagent-docs/versions/tempo.md b/docs-site/assets/kagent-docs/versions/tempo.md new file mode 100644 index 00000000..71bd5d9e --- /dev/null +++ b/docs-site/assets/kagent-docs/versions/tempo.md @@ -0,0 +1 @@ +1.16.0 \ 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 1750564f..00000000 --- a/docs-site/assets/versions/agent-substrate.md +++ /dev/null @@ -1 +0,0 @@ -0.0.6 diff --git a/docs-site/assets/versions/jaeger.md b/docs-site/assets/versions/jaeger.md deleted file mode 100644 index c966188e..00000000 --- a/docs-site/assets/versions/jaeger.md +++ /dev/null @@ -1 +0,0 @@ -4.4.7 diff --git a/docs-site/assets/versions/kagent.md b/docs-site/assets/versions/kagent.md deleted file mode 100644 index 7e310bae..00000000 --- a/docs-site/assets/versions/kagent.md +++ /dev/null @@ -1 +0,0 @@ -0.9.9 diff --git a/docs-site/assets/versions/kmcp.md b/docs-site/assets/versions/kmcp.md deleted file mode 100644 index 0d91a54c..00000000 --- a/docs-site/assets/versions/kmcp.md +++ /dev/null @@ -1 +0,0 @@ -0.3.0 diff --git a/docs-site/assets/versions/loki.md b/docs-site/assets/versions/loki.md deleted file mode 100644 index 2496b04b..00000000 --- a/docs-site/assets/versions/loki.md +++ /dev/null @@ -1 +0,0 @@ -6.24.0 diff --git a/docs-site/assets/versions/max-kube.md b/docs-site/assets/versions/max-kube.md deleted file mode 100644 index f7613c2d..00000000 --- a/docs-site/assets/versions/max-kube.md +++ /dev/null @@ -1 +0,0 @@ -1.35 diff --git a/docs-site/assets/versions/tempo.md b/docs-site/assets/versions/tempo.md deleted file mode 100644 index 15b989e3..00000000 --- a/docs-site/assets/versions/tempo.md +++ /dev/null @@ -1 +0,0 @@ -1.16.0 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/0.x/concepts/_index.md b/docs-site/content/kagent/0.x/concepts/_index.md new file mode 100644 index 00000000..d195c405 --- /dev/null +++ b/docs-site/content/kagent/0.x/concepts/_index.md @@ -0,0 +1,10 @@ +--- +title: Core Concepts +description: Understand the fundamental concepts and architecture of kagent. +weight: 4 +author: kagent.dev +--- + +Learn about the AI agent and kagent concepts. + +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/concepts/agent-harness.md b/docs-site/content/kagent/0.x/concepts/agent-harness.md similarity index 86% rename from docs-site/content/kagent/concepts/agent-harness.md rename to docs-site/content/kagent/0.x/concepts/agent-harness.md index ab4455fe..bd07c01d 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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](/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]({{< 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/concepts/agent-memory.md b/docs-site/content/kagent/0.x/concepts/agent-memory.md similarity index 93% rename from docs-site/content/kagent/concepts/agent-memory.md rename to docs-site/content/kagent/0.x/concepts/agent-memory.md index 3e85e470..bace41e6 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< 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](/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]({{< 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/concepts/agent-substrate.md b/docs-site/content/kagent/0.x/concepts/agent-substrate.md similarity index 83% rename from docs-site/content/kagent/concepts/agent-substrate.md rename to docs-site/content/kagent/0.x/concepts/agent-substrate.md index f27c74f4..f7347be8 100644 --- a/docs-site/content/kagent/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]({{< 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 @@ -68,11 +68,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]({{< link path="concepts/agent-harness" >}}) for details. -See the [API reference](/docs/kagent/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](/docs/kagent/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/concepts/agents.md b/docs-site/content/kagent/0.x/concepts/agents.md similarity index 90% rename from docs-site/content/kagent/concepts/agents.md rename to docs-site/content/kagent/0.x/concepts/agents.md index b7ce79f0..bc4b8c88 100644 --- a/docs-site/content/kagent/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. To help you write good instructions, see the [system prompt tutorial](/docs/kagent/getting-started/system-prompts). +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. To help you write good instructions, see the [system prompt tutorial]({{< link path="getting-started/system-prompts" >}}). ### 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]({{< link path="examples/human-in-the-loop" >}}). ### Tool approval @@ -241,7 +241,7 @@ skills: value: us-west-2 ``` -You can combine S3 skills with OCI and Git skills in the same agent by specifying `refs`, `gitRefs`, and `s3Refs` together. For the full field reference, see [S3SkillRef](/docs/kagent/resources/api-ref/#s3skillref). +You can combine S3 skills with OCI and Git skills in the same agent by specifying `refs`, `gitRefs`, and `s3Refs` together. For the full field reference, see [S3SkillRef]({{< link path="resources/api-ref/#s3skillref" >}}). ### Best practices for skills @@ -255,7 +255,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]({{< link path="examples/skills" >}}). ## Runtime @@ -332,7 +332,7 @@ spec: 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]({{< link path="concepts/agent-memory" >}}). ## Context Management @@ -361,9 +361,31 @@ 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. All three runtimes are supported: **Go** (default), **Python**, and **BYO**. For Go and Python agents, session history is persisted to a local SQLite database in the agent's `durableDir` volume, so conversation state survives pod restarts and Deployment rollouts. BYO agents do not get local session storage automatically. 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. All three runtimes are supported: **Go** (default), **Python**, and **BYO**. For Go and Python agents, session history is persisted to a local SQLite database in the agent's `durableDir` volume, so conversation state survives pod restarts and Deployment rollouts. BYO agents do not get local session storage automatically. 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]({{< link path="examples/agent-substrate" >}}). + +## A2A AgentCard metadata + +When another agent or client discovers your agent over the [A2A protocol](https://google.github.io/A2A/specification/#5-agent-discovery-using-an-agent-card), it reads a machine-readable AgentCard from your agent's `/.well-known/agent.json` endpoint. You can enrich that card with optional metadata fields on the `Agent` spec. + +```yaml +spec: + iconUrl: https://example.com/icons/my-agent.png + documentationUrl: https://docs.example.com/my-agent/ + version: "1.0.0" + provider: + organization: My Organization + url: https://example.com +``` + +| Field | Description | +|-------|-------------| +| `iconUrl` | URL to an icon image representing the agent. Must be a valid URI. | +| `documentationUrl` | URL to human-readable documentation for the agent. Must be a valid URI. | +| `version` | Version string for the agent, such as `"1.0.0"`. | +| `provider.organization` | Name of the organization responsible for the agent. | +| `provider.url` | URL to the agent provider's website or documentation. Must be a valid URI. | ## A2A AgentCard metadata @@ -437,4 +459,4 @@ spec: 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]({{< link path="examples/agents-mcp" >}}) guide. diff --git a/docs-site/content/kagent/concepts/architecture.md b/docs-site/content/kagent/0.x/concepts/architecture.md similarity index 93% rename from docs-site/content/kagent/concepts/architecture.md rename to docs-site/content/kagent/0.x/concepts/architecture.md index e6dd9deb..7d40b4a5 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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/concepts/mcp-apps.md b/docs-site/content/kagent/0.x/concepts/mcp-apps.md similarity index 98% rename from docs-site/content/kagent/concepts/mcp-apps.md rename to docs-site/content/kagent/0.x/concepts/mcp-apps.md index f0cb1f61..1668554e 100644 --- a/docs-site/content/kagent/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]({{< link path="concepts/tools" >}}) diff --git a/docs-site/content/kagent/concepts/tools.md b/docs-site/content/kagent/0.x/concepts/tools.md similarity index 94% rename from docs-site/content/kagent/concepts/tools.md rename to docs-site/content/kagent/0.x/concepts/tools.md index c2bfdb73..0ea813fe 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< link path="concepts/mcp-apps" >}}) for details. ## HTTP Tools 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 98% rename from docs-site/content/kagent/examples/a2a-agents.md rename to docs-site/content/kagent/0.x/examples/a2a-agents.md index 08fb2670..b41fd043 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< link path="getting-started/first-agent" >}}) guide. ### kagent CLI diff --git a/docs-site/content/kagent/examples/a2a-byo.md b/docs-site/content/kagent/0.x/examples/a2a-byo.md similarity index 96% rename from docs-site/content/kagent/examples/a2a-byo.md rename to docs-site/content/kagent/0.x/examples/a2a-byo.md index 532a9892..0bfc740e 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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](/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]({{< 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/examples/agent-harness.md b/docs-site/content/kagent/0.x/examples/agent-harness.md similarity index 91% rename from docs-site/content/kagent/examples/agent-harness.md rename to docs-site/content/kagent/0.x/examples/agent-harness.md index 7272b3fe..98e27e10 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< 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](/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]({{< 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](/docs/kagent/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/examples/agent-substrate.md b/docs-site/content/kagent/0.x/examples/agent-substrate.md similarity index 86% rename from docs-site/content/kagent/examples/agent-substrate.md rename to docs-site/content/kagent/0.x/examples/agent-substrate.md index 312048d2..5cba795a 100644 --- a/docs-site/content/kagent/examples/agent-substrate.md +++ b/docs-site/content/kagent/0.x/examples/agent-substrate.md @@ -9,11 +9,11 @@ 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. -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]({{< link path="concepts/agent-substrate" >}}). This guide does not cover the `AgentHarness` path on substrate. ## Before you begin @@ -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. @@ -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]({{< 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/examples/agentgateway.md b/docs-site/content/kagent/0.x/examples/agentgateway.md similarity index 97% rename from docs-site/content/kagent/examples/agentgateway.md rename to docs-site/content/kagent/0.x/examples/agentgateway.md index 010a4554..801d69f6 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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/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 95% rename from docs-site/content/kagent/examples/crewai-byo.md rename to docs-site/content/kagent/0.x/examples/crewai-byo.md index 322ba174..5033e7d8 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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](/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]({{< link path="getting-started/first-agent" >}}) guide. ### kagent CLI diff --git a/docs-site/content/kagent/examples/discord-a2a.md b/docs-site/content/kagent/0.x/examples/discord-a2a.md similarity index 92% rename from docs-site/content/kagent/examples/discord-a2a.md rename to docs-site/content/kagent/0.x/examples/discord-a2a.md index 283c44ff..5dc298f3 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< 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/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 96% rename from docs-site/content/kagent/examples/langchain-byo.md rename to docs-site/content/kagent/0.x/examples/langchain-byo.md index 10d33c0e..1a898790 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< 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/examples/skills.md b/docs-site/content/kagent/0.x/examples/skills.md similarity index 97% rename from docs-site/content/kagent/examples/skills.md rename to docs-site/content/kagent/0.x/examples/skills.md index fd66647f..897cf325 100644 --- a/docs-site/content/kagent/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]({{< link path="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]({{< 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](/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]({{< 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/examples/slack-a2a.md b/docs-site/content/kagent/0.x/examples/slack-a2a.md similarity index 98% rename from docs-site/content/kagent/examples/slack-a2a.md rename to docs-site/content/kagent/0.x/examples/slack-a2a.md index 01ed5c7e..82b6f922 100644 --- a/docs-site/content/kagent/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]({{< 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/examples/telegram-bot.md b/docs-site/content/kagent/0.x/examples/telegram-bot.md similarity index 98% rename from docs-site/content/kagent/examples/telegram-bot.md rename to docs-site/content/kagent/0.x/examples/telegram-bot.md index dd3ecf81..c145d0f9 100644 --- a/docs-site/content/kagent/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]({{< 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/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 95% rename from docs-site/content/kagent/getting-started/first-agent.md rename to docs-site/content/kagent/0.x/getting-started/first-agent.md index 8083bfba..308cd9c4 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/concepts) +- Learn more about [Core Concepts]({{< link path="concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) 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 95% 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 index 40e4c890..1c6cd1eb 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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](/docs/kagent/concepts) +- Learn more about [Core Concepts]({{< link path="concepts" >}}) - Join our [Community](https://discord.gg/Fu3k65f2k3) 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 98% rename from docs-site/content/kagent/getting-started/local-development.md rename to docs-site/content/kagent/0.x/getting-started/local-development.md index 04a300f4..47c3e9cd 100644 --- a/docs-site/content/kagent/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]({{< link path="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]({{< 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/getting-started/quickstart.md b/docs-site/content/kagent/0.x/getting-started/quickstart.md similarity index 95% rename from docs-site/content/kagent/getting-started/quickstart.md rename to docs-site/content/kagent/0.x/getting-started/quickstart.md index de8cc6c0..9e548226 100644 --- a/docs-site/content/kagent/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 @@ -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]({{< 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](/docs/kagent/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/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 80% rename from docs-site/content/kagent/introduction/_index.md rename to docs-site/content/kagent/0.x/introduction/_index.md index 15a86baf..119de4c9 100644 --- a/docs-site/content/kagent/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]({{< link path="resources/community" >}}). 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 91% rename from docs-site/content/kagent/introduction/installation.md rename to docs-site/content/kagent/0.x/introduction/installation.md index 88c2bd33..e7d9f6e5 100644 --- a/docs-site/content/kagent/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, see the [Quick Start Guide](/docs/kagent/getting-started/quickstart). For enterprise offerings, see [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, see the [Quick Start Guide]({{< link path="getting-started/quickstart" >}}). For enterprise offerings, see [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](/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]({{< 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) @@ -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 @@ -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]({{< 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](/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]({{< 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](/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]({{< 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](/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]({{< link path="operations/operational-considerations/#database-configuration" >}}). ### Configure controller environment variables @@ -470,9 +470,9 @@ When unset, the `registry` and `pullPolicy` fields of `agentImage` and `goAgentI ## Uninstallation -Refer to the [Uninstall](/docs/kagent/operations/uninstall) guide. +Refer to the [Uninstall]({{< link path="operations/uninstall" >}}) guide. ## Next Steps -- [Create your first agent](/docs/kagent/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/introduction/what-is-kagent.md b/docs-site/content/kagent/0.x/introduction/what-is-kagent.md similarity index 95% rename from docs-site/content/kagent/introduction/what-is-kagent.md rename to docs-site/content/kagent/0.x/introduction/what-is-kagent.md index c17818c7..72dc0706 100644 --- a/docs-site/content/kagent/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]({{< 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](/docs/kagent/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 new file mode 100644 index 00000000..30a0b1be --- /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]({{< link path="" >}}) 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 98% rename from docs-site/content/kagent/observability/audit-prompts.md rename to docs-site/content/kagent/0.x/observability/audit-prompts.md index c4301fc3..9f48205b 100644 --- a/docs-site/content/kagent/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]({{< link path="introduction/installation" >}}) in your cluster. 2. Add the OpenTelemetry Helm repository. @@ -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 - <}}) +- [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/observability/tracing.md b/docs-site/content/kagent/0.x/observability/tracing.md similarity index 90% rename from docs-site/content/kagent/observability/tracing.md rename to docs-site/content/kagent/0.x/observability/tracing.md index 3792cec5..690673ec 100644 --- a/docs-site/content/kagent/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]({{< link path="introduction/installation" >}}). ## Install Jaeger @@ -44,7 +44,7 @@ Install a tracing tool, such as Jaeger. The following example installs Jaeger in --create-namespace \ --history-max 3 \ --values jaeger.yaml \ - --version {{< reuse "versions/jaeger.md" >}} + --version {{< reuse "kagent-docs/versions/jaeger.md" >}} ``` ## Upgrade kagent @@ -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]({{< 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](/docs/kagent/concepts) -- Try out some [Example](/docs/kagent/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](/docs/kagent/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/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 98% rename from docs-site/content/kagent/operations/operational-considerations.md rename to docs-site/content/kagent/0.x/operations/operational-considerations.md index 6ba9fec0..5c0b1fa4 100644 --- a/docs-site/content/kagent/operations/operational-considerations.md +++ b/docs-site/content/kagent/0.x/operations/operational-considerations.md @@ -52,7 +52,7 @@ controller: - **Database requirement**: PostgreSQL is the default database backend and supports multiple controller replicas. The bundled PostgreSQL instance is deployed automatically unless you configure an external PostgreSQL. - **Leader election**: Leader election uses Kubernetes leases and is handled automatically. - **Failover**: If the leader fails, another replica automatically becomes the leader. -- **Pod disruption budgets**: You can create a `PodDisruptionBudget` for the controller and UI Deployments via `controller.pdb.enabled: true` and `ui.pdb.enabled: true`. Both default to disabled because each component defaults to `replicas: 1`, and a `minAvailable: 1` budget on a single-replica Deployment blocks every voluntary eviction, which causes node drains and cluster upgrades to hang indefinitely. When enabled, the default budget uses `maxUnavailable: 1`, which is safe at any replica count. Raise `controller.replicas` and `ui.replicas` before switching to a `minAvailable`-based budget. For all available fields, see the [Helm reference](/docs/kagent/resources/helm/). +- **Pod disruption budgets**: You can create a `PodDisruptionBudget` for the controller and UI Deployments via `controller.pdb.enabled: true` and `ui.pdb.enabled: true`. Both default to disabled because each component defaults to `replicas: 1`, and a `minAvailable: 1` budget on a single-replica Deployment blocks every voluntary eviction, which causes node drains and cluster upgrades to hang indefinitely. When enabled, the default budget uses `maxUnavailable: 1`, which is safe at any replica count. Raise `controller.replicas` and `ui.replicas` before switching to a `minAvailable`-based budget. For all available fields, see the [Helm reference]({{< link path="resources/helm/" >}}). ## Database configuration @@ -90,7 +90,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]({{< link path="introduction/installation" >}}) or upgrade kagent. 1. Add the bundled database settings to your Helm values file for kagent. @@ -250,7 +250,7 @@ ui: proxySendTimeout: 7200s ``` -On OpenShift, also set the HAProxy route timeout via `ui.openshiftRoute.annotations`. For more information, see [Expose the UI outside the cluster](/docs/kagent/observability/launch-ui#expose-the-ui-outside-the-cluster). +On OpenShift, also set the HAProxy route timeout via `ui.openshiftRoute.annotations`. For more information, see [Expose the UI outside the cluster]({{< link path="observability/launch-ui#expose-the-ui-outside-the-cluster" >}}). ### A2A client timeout diff --git a/docs-site/content/kagent/operations/uninstall.md b/docs-site/content/kagent/0.x/operations/uninstall.md similarity index 93% rename from docs-site/content/kagent/operations/uninstall.md rename to docs-site/content/kagent/0.x/operations/uninstall.md index cca768ac..ecf6fb83 100644 --- a/docs-site/content/kagent/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]({{< link path="resources/cli/kagent-uninstall" >}}). ```bash kagent uninstall diff --git a/docs-site/content/kagent/operations/upgrade.md b/docs-site/content/kagent/0.x/operations/upgrade.md similarity index 83% rename from docs-site/content/kagent/operations/upgrade.md rename to docs-site/content/kagent/0.x/operations/upgrade.md index 747855f1..b95f57cb 100644 --- a/docs-site/content/kagent/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]({{< 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](/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]({{< link path="operations/operational-considerations#database-configuration" >}}). ```bash pg_dump "postgres://:@:5432/" \ @@ -28,7 +28,9 @@ 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]({{< link path="resources/release-notes#v09" >}}) for 0.9-specific upgrades related to database migrations and RBAC scope. + +5. **v0.10.0 and later (mirror registry operators)**: If you mirror kagent images and previously relied on `agentImage` alone, you must now also set `controller.goAgentImage` to point to your mirrored Go ADK image. In v0.10, the controller no longer derives the Go image location from the Python image path. If `controller.goAgentImage` is unset and you overrode `agentImage`, the controller will fall back to pulling `ghcr.io/kagent-dev/kagent/golang-adk` directly. The controller logs a startup warning when the two registries differ. For details, see [Private registry and image mirroring]({{< link path="introduction/installation#private-registry-and-image-mirroring" >}}). 5. **v0.10.0 and later (mirror registry operators)**: If you mirror kagent images and previously relied on `agentImage` alone, you must now also set `controller.goAgentImage` to point to your mirrored Go ADK image. In v0.10, the controller no longer derives the Go image location from the Python image path. If `controller.goAgentImage` is unset and you overrode `agentImage`, the controller will fall back to pulling `ghcr.io/kagent-dev/kagent/golang-adk` directly. The controller logs a startup warning when the two registries differ. For details, see [Private registry and image mirroring](/docs/kagent/introduction/installation#private-registry-and-image-mirroring). @@ -58,7 +60,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]({{< 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. @@ -103,7 +105,7 @@ When enabled, the controller does not run migrations at startup. Instead, it ver ### Apply migrations -Use `kagent db migrate up` to apply all pending migrations before starting or upgrading the controller. Set `POSTGRES_DATABASE_URL` to your database connection string (see [Database configuration](/docs/kagent/operations/operational-considerations#database-configuration)). +Use `kagent db migrate up` to apply all pending migrations before starting or upgrading the controller. Set `POSTGRES_DATABASE_URL` to your database connection string (see [Database configuration]({{< link path="operations/operational-considerations#database-configuration" >}})). ```bash export POSTGRES_DATABASE_URL="postgres://:@:5432/" @@ -206,7 +208,7 @@ The target is the highest migration sequence number present in the version that export ROLLBACK_MIGRATION_VERSION= ``` -4. Reset the core track. For the database connection string, see [Database configuration](/docs/kagent/operations/operational-considerations#database-configuration). +4. Reset the core track. For the database connection string, see [Database configuration]({{< link path="operations/operational-considerations#database-configuration" >}}). ```bash export POSTGRES_DATABASE_URL="postgres://:@:5432/" kagent db migrate goto $ROLLBACK_MIGRATION_VERSION --source core diff --git a/docs-site/content/kagent/resources/_index.md b/docs-site/content/kagent/0.x/resources/_index.md similarity index 75% rename from docs-site/content/kagent/resources/_index.md rename to docs-site/content/kagent/0.x/resources/_index.md index a1fb1b51..789e3b5c 100644 --- a/docs-site/content/kagent/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]({{< link path="getting-started/quickstart" >}}). diff --git a/docs-site/content/kagent/resources/api-ref.md b/docs-site/content/kagent/0.x/resources/api-ref.md similarity index 94% rename from docs-site/content/kagent/resources/api-ref.md rename to docs-site/content/kagent/0.x/resources/api-ref.md index f4eb0bfd..ad2010e0 100644 --- a/docs-site/content/kagent/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 new file mode 100644 index 00000000..6dfbcbfb --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/cli/_index.md @@ -0,0 +1,23 @@ +--- +title: CLI docs +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`](/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/resources/cli/kagent-add-mcp.md b/docs-site/content/kagent/0.x/resources/cli/kagent-add-mcp.md similarity index 75% 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 index 735bcfe9..b5621a24 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-bug-report.md b/docs-site/content/kagent/0.x/resources/cli/kagent-bug-report.md similarity index 56% 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 index d374c640..fd1dc09f 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-build.md b/docs-site/content/kagent/0.x/resources/cli/kagent-build.md similarity index 77% rename from docs-site/content/kagent/resources/cli/kagent-build.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-build.md index 36c1fc16..b4c343cb 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-completion-bash.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-bash.md similarity index 73% rename from docs-site/content/kagent/resources/cli/kagent-completion-bash.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-completion-bash.md index 91f109cd..f8295a4b 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-completion-fish.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-fish.md similarity index 68% rename from docs-site/content/kagent/resources/cli/kagent-completion-fish.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-completion-fish.md index bda214e4..a29ab438 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-completion-powershell.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-powershell.md similarity index 66% rename from docs-site/content/kagent/resources/cli/kagent-completion-powershell.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-completion-powershell.md index 1ef996fd..8134a3b3 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-completion-zsh.md b/docs-site/content/kagent/0.x/resources/cli/kagent-completion-zsh.md similarity index 73% rename from docs-site/content/kagent/resources/cli/kagent-completion-zsh.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-completion-zsh.md index c13d5513..5cc027ca 100644 --- a/docs-site/content/kagent/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 new file mode 100644 index 00000000..eb61ee8b --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-completion.md @@ -0,0 +1,29 @@ +--- +title: kagent completion +description: Generate the autocompletion script for the specified shell. +weight: 40 +--- + +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/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-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) +- `-v, --verbose` - Verbose output 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 56% rename from docs-site/content/kagent/resources/cli/kagent-dashboard.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-dashboard.md index ecd1c723..3d3b1c98 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-db-migrate-down.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-down.md similarity index 73% rename from docs-site/content/kagent/resources/cli/kagent-db-migrate-down.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-down.md index 3ed29cce..0ad94d99 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-db-migrate-force.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-force.md similarity index 72% rename from docs-site/content/kagent/resources/cli/kagent-db-migrate-force.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-force.md index b4cc6cdc..2b48b95f 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-db-migrate-goto.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-goto.md similarity index 69% rename from docs-site/content/kagent/resources/cli/kagent-db-migrate-goto.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-goto.md index fbab53ce..d1318caf 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-db-migrate-status.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-status.md similarity index 71% rename from docs-site/content/kagent/resources/cli/kagent-db-migrate-status.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-status.md index 92762ebc..26b1e270 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-db-migrate-up.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-up.md similarity index 78% rename from docs-site/content/kagent/resources/cli/kagent-db-migrate-up.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-up.md index feb5de31..da443958 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-db-migrate-version.md b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-version.md similarity index 68% rename from docs-site/content/kagent/resources/cli/kagent-db-migrate-version.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate-version.md index 451bae2a..4e1d9a46 100644 --- a/docs-site/content/kagent/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 new file mode 100644 index 00000000..9c845747 --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db-migrate.md @@ -0,0 +1,26 @@ +--- +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/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. 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 new file mode 100644 index 00000000..81578df0 --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-db.md @@ -0,0 +1,17 @@ +--- +title: kagent db +description: Database operations (migrations, inspection). +weight: 100 +--- + +Database operations (migrations, inspection) + +```bash +kagent db [command] +``` + +**Subcommands:** +- [`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 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 85% rename from docs-site/content/kagent/resources/cli/kagent-deploy.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-deploy.md index 7bd0a9bf..90ce44cf 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-get-agent.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get-agent.md similarity index 57% rename from docs-site/content/kagent/resources/cli/kagent-get-agent.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-get-agent.md index b34d8c97..6c197909 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-get-session.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get-session.md similarity index 57% rename from docs-site/content/kagent/resources/cli/kagent-get-session.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-get-session.md index 59ea9e08..a39e27b4 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-get-tool.md b/docs-site/content/kagent/0.x/resources/cli/kagent-get-tool.md similarity index 56% rename from docs-site/content/kagent/resources/cli/kagent-get-tool.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-get-tool.md index f3246a15..947b91bf 100644 --- a/docs-site/content/kagent/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 new file mode 100644 index 00000000..cfd4def0 --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-get.md @@ -0,0 +1,28 @@ +--- +title: kagent get +description: Get a kagent resource. +weight: 190 +--- + +Get a kagent resource + +```bash +kagent get [flags] +kagent get [command] +``` + +**Subcommands:** +- [`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-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) +- `-v, --verbose` - Verbose output 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 74% rename from docs-site/content/kagent/resources/cli/kagent-init.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-init.md index 38aa96d7..73539766 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-install.md b/docs-site/content/kagent/0.x/resources/cli/kagent-install.md similarity index 59% rename from docs-site/content/kagent/resources/cli/kagent-install.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-install.md index c306559d..43ba936a 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-invoke.md b/docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md similarity index 69% rename from docs-site/content/kagent/resources/cli/kagent-invoke.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-invoke.md index 6fcbaf95..e5dd3d24 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-add-tool.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-add-tool.md similarity index 76% rename from docs-site/content/kagent/resources/cli/kagent-mcp-add-tool.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-add-tool.md index a38a3ed5..0256a618 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-build.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-build.md similarity index 75% rename from docs-site/content/kagent/resources/cli/kagent-mcp-build.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-build.md index 57030dea..75d1bbf4 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-deploy-package.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy-package.md similarity index 88% rename from docs-site/content/kagent/resources/cli/kagent-mcp-deploy-package.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy-package.md index 2b0bc10b..6e07b49d 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-deploy.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy.md similarity index 84% rename from docs-site/content/kagent/resources/cli/kagent-mcp-deploy.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-deploy.md index 7e9957d9..4157b247 100644 --- a/docs-site/content/kagent/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`](/docs/kagent/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/resources/cli/kagent-mcp-init-go.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-go.md similarity index 74% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-go.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-go.md index 671a6d1d..e932c46e 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-init-java.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-java.md similarity index 71% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-java.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-java.md index c13c94ac..a731583c 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-init-python.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-python.md similarity index 72% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-python.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-python.md index b55d8816..3897fcee 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-init-typescript.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-typescript.md similarity index 72% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init-typescript.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init-typescript.md index 3cf9fb75..0e95e136 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-init.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init.md similarity index 53% rename from docs-site/content/kagent/resources/cli/kagent-mcp-init.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-init.md index 41f0a19a..e8b18f3c 100644 --- a/docs-site/content/kagent/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`](/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 +- [`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/resources/cli/kagent-mcp-run.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-run.md similarity index 80% rename from docs-site/content/kagent/resources/cli/kagent-mcp-run.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-run.md index 6a53b768..f24be81e 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-secrets-sync.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets-sync.md similarity index 81% rename from docs-site/content/kagent/resources/cli/kagent-mcp-secrets-sync.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets-sync.md index 032ed5a2..3ac9bb2e 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-mcp-secrets.md b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets.md similarity index 50% rename from docs-site/content/kagent/resources/cli/kagent-mcp-secrets.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-mcp-secrets.md index 7116fcb4..da43e2ca 100644 --- a/docs-site/content/kagent/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`](/docs/kagent/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 new file mode 100644 index 00000000..78514bc1 --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/cli/kagent-mcp.md @@ -0,0 +1,31 @@ +--- +title: kagent mcp +description: MCP (Model Context Protocol) server management. +weight: 260 +--- + +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/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-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) +- `-v, --verbose` - Verbose output 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 69% rename from docs-site/content/kagent/resources/cli/kagent-run.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-run.md index 40797814..51aafd72 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-uninstall.md b/docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md similarity index 56% rename from docs-site/content/kagent/resources/cli/kagent-uninstall.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-uninstall.md index 76073818..dcdcd671 100644 --- a/docs-site/content/kagent/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/resources/cli/kagent-version.md b/docs-site/content/kagent/0.x/resources/cli/kagent-version.md similarity index 56% rename from docs-site/content/kagent/resources/cli/kagent-version.md rename to docs-site/content/kagent/0.x/resources/cli/kagent-version.md index a1958d9b..feb68ddf 100644 --- a/docs-site/content/kagent/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/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 90% rename from docs-site/content/kagent/resources/faq.md rename to docs-site/content/kagent/0.x/resources/faq.md index 9d554b22..948151f8 100644 --- a/docs-site/content/kagent/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]({{< 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/helm.md b/docs-site/content/kagent/0.x/resources/helm.md new file mode 100644 index 00000000..3b78bdfd --- /dev/null +++ b/docs-site/content/kagent/0.x/resources/helm.md @@ -0,0 +1,372 @@ +--- +title: kagent +linkTitle: Helm Chart Configuration +description: kagent Helm chart configuration reference +weight: 2 +author: kagent.dev +--- + +A Helm chart for kagent, built with Google ADK + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| `${SUBSTRATE_REPO}` | substrate | `${SUBSTRATE_VERSION}` | +| 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 | + +## Values + +| 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.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 | `""` | | +| controller.annotations | object | `{}` | Additional annotations to add to the controller Deployment metadata | +| controller.auth.mode | string | `"unsecure"` | | +| controller.auth.userIdClaim | string | `""` | | +| controller.env | list | `[]` | | +| controller.envFrom | list | `[]` | | +| 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"` | | +| controller.image.tag | string | `""` | | +| controller.loglevel | string | `"info"` | | +| controller.mcpEgressPlaintext | bool | `false` | Rewrite RemoteMCPServer tool URLs and the controller's tool-discovery dial from `https://host[:port]` to `http://host:` so MCP traffic egresses in plaintext to a proxy that originates TLS upstream off by default. | +| controller.metrics | object | disabled | Prometheus-style /metrics endpoint for the controller manager. When enabled, provisions a dedicated metrics Service plus the ClusterRoles required for authenticated scrapes. Bind `-metrics-reader` to your Prometheus ServiceAccount to grant scrape access. Use `bindAddress` for any port change: the Service `targetPort` and the pod `containerPort` are derived from it at template time, so overriding `METRICS_BIND_ADDRESS` via `controller.env` shifts only the runtime listener and leaves the rendered Service pointing at the chart-time port. Setting `bindAddress: "0"` (or empty) is treated as a disable signal — equivalent to `enabled: false` — to keep faith with the controller binary's documented contract for `--metrics-bind-address`. | +| controller.nodeSelector | object | `{}` | Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| controller.pdb | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":1,"minAvailable":null,"unhealthyPodEvictionPolicy":""}` | [PodDisruptionBudget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for the controller pods. Disabled by default: `controller.replicas` is 1, and a `minAvailable: 1` budget on a single-replica Deployment blocks every voluntary eviction, so node drains and cluster upgrades hang indefinitely. Raise `controller.replicas` before switching to `minAvailable`. | +| controller.pdb.annotations | object | `{}` | Annotations for the controller PodDisruptionBudget. | +| controller.pdb.enabled | bool | `false` | Set to true to create the PodDisruptionBudget. | +| controller.pdb.labels | object | `{}` | Additional labels for the controller PodDisruptionBudget. | +| controller.pdb.maxUnavailable | int | `1` | Maximum number of pods that may be unavailable. Int or percentage string (e.g. `1` or `"50%"`). Mutually exclusive with `minAvailable`. | +| controller.pdb.minAvailable | string | unset (`maxUnavailable` is used instead) | Minimum number of pods that must remain available. Int or percentage string (e.g. `1` or `"50%"`). Mutually exclusive with `maxUnavailable`. | +| controller.pdb.unhealthyPodEvictionPolicy | string | "" (defer to the Kubernetes default) | `spec.unhealthyPodEvictionPolicy`, one of `IfHealthyBudget` (the Kubernetes default) or `AlwaysAllow`. `AlwaysAllow` lets unhealthy pods be evicted even when the budget is exhausted, which avoids drains wedging on a crash-looping pod. Requires Kubernetes >= 1.27. Omitted from the manifest when empty. | +| controller.podAnnotations | object | `{}` | | +| controller.podLabels | object | `{}` | Additional labels for the controller pod template, merged over the global `podLabels` (per-key; component keys win). Selector labels can never be overridden. | +| controller.readinessProbe | object | httpGet /health on port http, periodSeconds=30 | Custom readiness probe for the controller container. Setting a value replaces the default probe entirely — include a handler (httpGet / exec / tcpSocket / grpc) when overriding. | +| controller.replicas | int | `1` | | +| controller.resources.limits.cpu | int | `2` | | +| controller.resources.limits.memory | string | `"512Mi"` | | +| controller.resources.requests.cpu | string | `"100m"` | | +| controller.resources.requests.memory | string | `"128Mi"` | | +| controller.service.annotations | object | `{}` | | +| 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 | `{"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.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.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. | +| database.postgres.bundled.storage | string | `"500Mi"` | PersistentVolumeClaim size for demo PostgreSQL data | +| database.postgres.bundled.storageClassName | string | `""` | StorageClass for the PostgreSQL PVC. Defaults to the cluster default when empty. | +| database.postgres.pool | object | `{"maxConnIdleTime":"","maxConnLifetime":"","maxConns":null,"minConns":null}` | Optional pgxpool settings. Leave unset/null to keep pgx library defaults (MaxConns≈max(4,NumCPU), MinConns=0, MaxConnIdleTime=30m, MaxConnLifetime=1h). | +| database.postgres.sessionRetentionDays | int | `0` | Hard-delete idle sessions (and cascaded events/tasks/checkpoints/shares) after N days of no activity. Uses session.updated_at as a sliding idle clock (writes refresh it). 0 disables cleanup (default, existing installs unchanged). | +| database.postgres.skipMigrations | bool | `false` | Skip running database migrations at controller startup. The controller instead verifies the database is already migrated and fails if it is not. Migrations must be applied out-of-band (e.g. from a CI/CD pipeline) before install/upgrade. | +| database.postgres.url | string | `""` | External PostgreSQL connection string. Is always used if set regardless of the `.bundled.enabled` field. | +| database.postgres.urlFile | string | `""` | Path to a file containing the database URL. Takes precedence over url when set. Is always used if set regardless of the `.bundled.enabled` field. | +| database.postgres.vectorEnabled | bool | `false` | Enable the pgvector migration Required to use features that depend on database vector capability. (e.g. long-term memory) Set to true when using an external PostgreSQL that has the pgvector extension installed. | +| extraObjects | list | [] | Additional arbitrary Kubernetes manifests to deploy alongside the chart. Each list entry is rendered through `tpl`, so values may reference the release context (e.g. `{{ include "kagent.fullname" . }}`, `{{ .Release.Namespace }}`). Both map and multi-line string entries are supported. Use this to manage resources such as ExternalSecret, HTTPRoute, or NetworkPolicy within the same chart lifecycle without maintaining a separate chart. To use, replace the empty list below with your manifests, e.g.: extraObjects: - apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: '`{{ include "kagent.fullname" . }}`-openai' namespace: '`{{ .Release.Namespace }}`' spec: secretStoreRef: name: aws-secretsmanager kind: ClusterSecretStore target: name: kagent-openai data: - secretKey: OPENAI_API_KEY remoteRef: key: prod/kagent/openai property: api_key | +| fullnameOverride | string | `""` | | +| grafana-mcp.enabled | bool | `true` | | +| grafana-mcp.grafana.serviceAccountToken | string | `""` | | +| grafana-mcp.grafana.url | string | `"grafana.kagent:3000/api"` | | +| grafana-mcp.resources.limits.cpu | string | `"500m"` | | +| 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/). | +| kagent-tools.podSecurityContext.runAsNonRoot | bool | `true` | | +| kagent-tools.podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | | +| kagent-tools.replicaCount | int | `1` | | +| kagent-tools.resources.limits.memory | string | `"256Mi"` | | +| kagent-tools.resources.requests.cpu | string | `"50m"` | | +| kagent-tools.resources.requests.memory | string | `"128Mi"` | | +| kagent-tools.securityContext.allowPrivilegeEscalation | bool | `false` | | +| kagent-tools.securityContext.capabilities.drop[0] | string | `"ALL"` | | +| kagent-tools.securityContext.readOnlyRootFilesystem | bool | `true` | | +| 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"` | | +| kmcp.namespaceOverride | string | `""` | | +| labels | object | `{}` | Additional labels to add to all Kubernetes resources | +| nameOverride | string | `""` | | +| namespaceOverride | string | `.Release.Namespace` | Override the namespace | +| nodeSelector | object | `{}` | Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| oauth2-proxy.config.clientID | string | `""` | | +| oauth2-proxy.config.clientSecret | string | `""` | | +| oauth2-proxy.config.cookieSecret | string | `""` | | +| oauth2-proxy.config.existingSecret | string | `""` | | +| oauth2-proxy.enabled | bool | `false` | | +| oauth2-proxy.extraArgs.approval-prompt | string | `"auto"` | | +| oauth2-proxy.extraArgs.cookie-samesite | string | `"lax"` | | +| oauth2-proxy.extraArgs.cookie-secure | bool | `true` | | +| oauth2-proxy.extraArgs.custom-templates-dir | string | `"/templates"` | | +| oauth2-proxy.extraArgs.email-domain | string | `"*"` | | +| oauth2-proxy.extraArgs.oidc-issuer-url | string | `"$(OIDC_ISSUER_URL)"` | | +| oauth2-proxy.extraArgs.pass-authorization-header | bool | `true` | | +| oauth2-proxy.extraArgs.provider | string | `"oidc"` | | +| oauth2-proxy.extraArgs.redirect-url | string | `"$(OIDC_REDIRECT_URL)"` | | +| oauth2-proxy.extraArgs.scope | string | `"openid profile email groups"` | | +| oauth2-proxy.extraArgs.set-authorization-header | bool | `true` | | +| oauth2-proxy.extraArgs.skip-auth-regex | string | `"^/(login|_next/static|_next/image|login-bg\\.(jpg|png|webp)|logo-.*\\.png|favicon\\.ico|api/agentharnesses/.*/gateway).*$"` | | +| 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 | `"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 | `"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` | | +| oauth2-proxy.extraVolumes[0].configMap.name | string | `"kagent-oauth2-proxy-templates"` | | +| oauth2-proxy.extraVolumes[0].name | string | `"custom-templates"` | | +| 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` | | +| otel.logging.exporter.otlp.timeout | int | `15000` | | +| otel.tracing.enabled | bool | `false` | | +| otel.tracing.exporter.otlp.endpoint | string | `""` | | +| otel.tracing.exporter.otlp.insecure | bool | `true` | | +| otel.tracing.exporter.otlp.protocol | string | `"grpc"` | | +| otel.tracing.exporter.otlp.timeout | int | `15000` | | +| 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"` | | +| providers.anthropic.model | string | `"claude-haiku-4-5"` | | +| providers.anthropic.provider | string | `"Anthropic"` | | +| providers.azureOpenAI.apiKeySecretKey | string | `"AZUREOPENAI_API_KEY"` | | +| providers.azureOpenAI.apiKeySecretRef | string | `"kagent-azure-openai"` | | +| providers.azureOpenAI.config.apiVersion | string | `"2023-05-15"` | | +| providers.azureOpenAI.config.azureAdToken | string | `""` | | +| providers.azureOpenAI.config.azureDeployment | string | `""` | | +| providers.azureOpenAI.config.azureEndpoint | string | `""` | | +| providers.azureOpenAI.model | string | `"gpt-4.1-mini"` | | +| providers.azureOpenAI.provider | string | `"AzureOpenAI"` | | +| providers.default | string | `"openAI"` | | +| providers.gemini.apiKeySecretKey | string | `"GOOGLE_API_KEY"` | | +| providers.gemini.apiKeySecretRef | string | `"kagent-gemini"` | | +| 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"` | | +| providers.ollama.model | string | `"llama3.2"` | | +| providers.ollama.provider | string | `"Ollama"` | | +| providers.openAI.apiKeySecretKey | string | `"OPENAI_API_KEY"` | | +| providers.openAI.apiKeySecretRef | string | `"kagent-openai"` | | +| providers.openAI.model | string | `"gpt-4.1-mini"` | | +| providers.openAI.provider | string | `"OpenAI"` | | +| proxy.url | string | `""` | | +| 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 | +| substrate.enabled | bool | `false` | | +| substrateWorkerPool | object | `{"ateomImage":"","create":false,"labels":{},"name":"kagent-default","replicas":1,"sandboxClass":"gvisor","template":{}}` | Optional Agent Substrate WorkerPool installed by this chart. This is platform capacity and is not owned by individual AgentHarness resources. | +| tag | string | `""` | | +| tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| ui.additionalForwardedHeaders | list | `[]` | Additional request headers (beyond Authorization) the UI proxy will forward to the backend. Names are case-insensitive. Hop-by-hop headers (Connection, Transfer-Encoding, etc.) are silently dropped. | +| 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.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. | +| ui.httpRoute | object | `{"annotations":{},"enabled":false,"hostnames":[],"labels":{},"parentRefs":[],"rules":[]}` | Gateway API `HTTPRoute` for the UI. Requires the Gateway API CRDs (`gateway.networking.k8s.io/v1`) and an existing `Gateway` to attach to via `parentRefs`. Disabled by default; enable to front the UI with a Gateway API implementation (kgateway, Istio, Envoy Gateway, etc.) instead of the OpenShift Route or bundled oauth2-proxy. | +| ui.httpRoute.annotations | object | `{}` | Annotations to add to the `HTTPRoute`. | +| ui.httpRoute.hostnames | list | `[]` | Hostnames matched by the route. | +| ui.httpRoute.labels | object | `{}` | Extra labels to add to the `HTTPRoute` (merged with the chart labels). | +| ui.httpRoute.parentRefs | list | `[]` | Gateways this route attaches to. Required when `enabled` is `true`. | +| ui.httpRoute.rules | list | `[]` | Routing rules. When a rule omits `backendRefs`, it defaults to the UI `Service` on `ui.service.ports.port`. Each rule may also set `matches`, `filters`, and `timeouts`. | +| ui.image.pullPolicy | string | `""` | | +| ui.image.registry | string | `""` | | +| ui.image.repository | string | `"kagent-dev/kagent/ui"` | | +| ui.image.tag | string | `""` | | +| ui.nginx | object | `{"proxyReadTimeout":"1800s","proxySendTimeout":"1800s"}` | Nginx proxy timeout configuration for the UI sidecar (values are passed directly to the corresponding nginx directives, e.g. "1800s"). | +| ui.nginx.proxyReadTimeout | string | `"1800s"` | proxy_read_timeout: max time between two successive reads from the upstream. | +| ui.nginx.proxySendTimeout | string | `"1800s"` | proxy_send_timeout: max time between two successive writes to the upstream. | +| ui.nodeSelector | object | `{}` | Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| ui.openshiftRoute.annotations."haproxy.router.openshift.io/timeout" | string | `"120m"` | | +| ui.pdb | object | `{"annotations":{},"enabled":false,"labels":{},"maxUnavailable":1,"minAvailable":null,"unhealthyPodEvictionPolicy":""}` | [PodDisruptionBudget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) for the UI pods. Disabled by default: `ui.replicas` is 1, and a `minAvailable: 1` budget on a single-replica Deployment blocks every voluntary eviction, so node drains and cluster upgrades hang indefinitely. Raise `ui.replicas` before switching to `minAvailable`. | +| ui.pdb.annotations | object | `{}` | Annotations for the UI PodDisruptionBudget. | +| ui.pdb.enabled | bool | `false` | Set to true to create the PodDisruptionBudget. | +| ui.pdb.labels | object | `{}` | Additional labels for the UI PodDisruptionBudget. | +| ui.pdb.maxUnavailable | int | `1` | Maximum number of pods that may be unavailable. Int or percentage string (e.g. `1` or `"50%"`). Mutually exclusive with `minAvailable`. | +| ui.pdb.minAvailable | string | unset (`maxUnavailable` is used instead) | Minimum number of pods that must remain available. Int or percentage string (e.g. `1` or `"50%"`). Mutually exclusive with `maxUnavailable`. | +| ui.pdb.unhealthyPodEvictionPolicy | string | "" (defer to the Kubernetes default) | `spec.unhealthyPodEvictionPolicy`, one of `IfHealthyBudget` (the Kubernetes default) or `AlwaysAllow`. `AlwaysAllow` lets unhealthy pods be evicted even when the budget is exhausted, which avoids drains wedging on a crash-looping pod. Requires Kubernetes >= 1.27. Omitted from the manifest when empty. | +| ui.podAnnotations | object | `{}` | | +| ui.podLabels | object | `{}` | Additional labels for the UI pod template, merged over the global `podLabels` (per-key; component keys win). Selector labels can never be overridden. | +| ui.podSecurityContext | object | (uses global podSecurityContext) | Pod-level security context for the UI pod. Overrides the global podSecurityContext. | +| ui.publicBackendUrl | string | `"/api"` | | +| ui.readinessProbe | object | httpGet /health on port http, periodSeconds=30 | Custom readiness probe for the UI container. Override to adjust thresholds, use exec-based probes, or change the health path. | +| ui.replicas | int | `1` | | +| ui.resources.limits.cpu | string | `"1000m"` | | +| ui.resources.limits.memory | string | `"1Gi"` | | +| ui.resources.requests.cpu | string | `"100m"` | | +| ui.resources.requests.memory | string | `"256Mi"` | | +| ui.route | object | `{"enabled":true}` | Gates the OpenShift `Route` for the UI. Additionally conditional on the `route.openshift.io/v1` API being present, so it is a no-op off-OpenShift. Set to `false` to front the UI with your own Route/ingress or the bundled oauth2-proxy instead of the chart's edge-terminated Route. | +| ui.securityContext | object | (uses global securityContext) | Container-level security context for the UI container. Overrides the global securityContext. | +| ui.service.annotations | object | `{}` | | +| ui.service.ports.port | int | `8080` | | +| ui.service.ports.targetPort | int | `8080` | | +| ui.service.type | string | `"ClusterIP"` | | +| ui.serviceAccount | object | `{"annotations":{}}` | ServiceAccount settings for the UI pod | +| ui.serviceAccount.annotations | object | {} (no extra annotations) | Annotations to add to the UI ServiceAccount. Useful for GCP Workload Identity, AWS IRSA, or Azure Workload Identity. | +| ui.startupProbe | object | httpGet /health on port http, periodSeconds=1, initialDelaySeconds=1 | Custom startup probe for the UI container. Override to adjust thresholds, use exec-based probes, or change the health path. | +| ui.streamTimeoutSeconds | int | `1800` | Client-side chat stream inactivity timeout (seconds). The browser aborts a streaming response if no event is received within this window. Should be >= ui.nginx.proxyReadTimeout so nginx isn't the silent limit. Default 1800 (30m). | +| ui.tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| ui.topologySpreadConstraints | list | `[]` | [Topology spread constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#pod-topology-spread-constraints) for the UI pod. | +| ui.volumes | object | `{"nextjsCache":"100Mi","tmp":"50Mi"}` | EmptyDir volume sizes for Next.js UI workload (typically used when enabling readOnlyRootFilesystem) | +| ui.volumes.nextjsCache | string | `"100Mi"` | Size limit for Next.js build cache (.next/cache). Default 100Mi is sufficient for typical Next.js apps with moderate caching needs. | +| ui.volumes.tmp | string | `"50Mi"` | Size limit for temporary files (/tmp). Default 50Mi provides ample space for Next.js runtime temporary data. | diff --git a/docs-site/content/kagent/resources/release-notes.md b/docs-site/content/kagent/0.x/resources/release-notes.md similarity index 94% rename from docs-site/content/kagent/resources/release-notes.md rename to docs-site/content/kagent/0.x/resources/release-notes.md index 164d6dad..99fe1b32 100644 --- a/docs-site/content/kagent/resources/release-notes.md +++ b/docs-site/content/kagent/0.x/resources/release-notes.md @@ -19,7 +19,7 @@ Review this summary of significant changes from kagent version 0.9 to v0.10. The `querydoc` subchart and its bundled `doc2vec` image are removed in v0.10. If you had `querydoc` enabled, the `query_documentation` tool will no longer be available after upgrading, and any agent that references it will fail on reconciliation. -To continue using documentation search, deploy `doc2vec` separately and configure it as an external tool server. See [Documentation search example](/docs/kagent/examples/documentation/) for setup instructions. +To continue using documentation search, deploy `doc2vec` separately and configure it as an external tool server. See [Documentation search example]({{< link path="examples/documentation/" >}}) for setup instructions. ### What's included @@ -80,7 +80,7 @@ The default declarative agent runtime is now **Go**. Previously, new declarative Existing agents with an explicit `runtime: python` are unaffected. Agents that relied on the Python default will now use Go unless you add `runtime: python` to their spec. -For a full comparison, see [Agents — Runtime](/docs/kagent/concepts/agents#runtime). +For a full comparison, see [Agents — Runtime]({{< link path="concepts/agents#runtime" >}}). ### A2A AgentCard metadata @@ -104,7 +104,7 @@ spec: | `provider.organization` | Name of the organization responsible for the agent. | | `provider.url` | URL to the agent provider's website or documentation. | -For more information, see [Agents — A2A AgentCard metadata](/docs/kagent/concepts/agents#a2a-agentcard-metadata). +For more information, see [Agents — A2A AgentCard metadata]({{< link path="concepts/agents#a2a-agentcard-metadata" >}}). ### Configurable streaming timeouts @@ -126,7 +126,7 @@ ui: haproxy.router.openshift.io/timeout: 120m ``` -For tuning timeouts end-to-end for long-running agent sessions, see [Long-running connections](/docs/kagent/operations/operational-considerations#long-running-connections). +For tuning timeouts end-to-end for long-running agent sessions, see [Long-running connections]({{< link path="operations/operational-considerations#long-running-connections" >}}). ### Controller service annotations @@ -149,7 +149,7 @@ controller: a2aClientTimeout: "10m" # or "" for no timeout (default) ``` -For more information, see [Long-running connections](/docs/kagent/operations/operational-considerations#long-running-connections). +For more information, see [Long-running connections]({{< link path="operations/operational-considerations#long-running-connections" >}}). ### UI HTTPRoute @@ -168,7 +168,7 @@ ui: - kagent.example.com ``` -For all UI exposure options including LoadBalancer service and OpenShift Route, see [Expose the UI outside the cluster](/docs/kagent/observability/launch-ui#expose-the-ui-outside-the-cluster). +For all UI exposure options including LoadBalancer service and OpenShift Route, see [Expose the UI outside the cluster]({{< link path="observability/launch-ui#expose-the-ui-outside-the-cluster" >}}). ### Pod labels for controller and UI @@ -190,7 +190,7 @@ ui: This is useful for clusters with admission policies (such as OPA Gatekeeper or Kyverno) that require specific labels on every pod template. Note that selector labels always take precedence and cannot be overridden. -For more information, see [Customize Kubernetes resources](/docs/kagent/introduction/installation#customize-kubernetes-resources). +For more information, see [Customize Kubernetes resources]({{< link path="introduction/installation#customize-kubernetes-resources" >}}). ### Default nodeSelector for agent deployments @@ -205,7 +205,7 @@ controller: This is useful in clusters where admission policies (Gatekeeper, Kyverno) require a `nodeSelector` on every Deployment. Without this, agents created through the UI wizard carry no nodeSelector and fail admission. -For more information, see [Customize Kubernetes resources](/docs/kagent/introduction/installation#customize-kubernetes-resources). +For more information, see [Customize Kubernetes resources]({{< link path="introduction/installation#customize-kubernetes-resources" >}}). ### Configurable Go ADK agent image @@ -224,7 +224,7 @@ The `registry` and `pullPolicy` fields default to the global `image.registry` an > **Breaking change for mirror registry operators**: If you mirror kagent images and only set `agentImage`, you must now also set `controller.goAgentImage` to point to your mirrored Go ADK image. The controller logs a startup warning when the Go image registry differs from the main image registry, so that a misconfigured mirror is visible before a Go agent fails to pull. -For more information, see [Private registry and image mirroring](/docs/kagent/introduction/installation#private-registry-and-image-mirroring). +For more information, see [Private registry and image mirroring]({{< link path="introduction/installation#private-registry-and-image-mirroring" >}}). ### Max completion tokens for OpenAI @@ -241,7 +241,7 @@ spec: The existing `openAI.maxTokens` field is unchanged and continues to work for standard models and OpenAI-compatible endpoints. The two fields are independent: set `maxCompletionTokens` for reasoning models and `maxTokens` only for endpoints that still require `max_tokens`. -For more information, see [Max completion tokens](/docs/kagent/supported-providers/openai#max-completion-tokens). +For more information, see [Max completion tokens]({{< link path="supported-providers/openai#max-completion-tokens" >}}). ### ServiceAccount annotations @@ -259,7 +259,7 @@ ui: iam.gke.io/gcp-service-account: kagent-ui@my-project.iam.gserviceaccount.com ``` -For more information, see [Customize Kubernetes resources](/docs/kagent/introduction/installation#customize-kubernetes-resources). +For more information, see [Customize Kubernetes resources]({{< link path="introduction/installation#customize-kubernetes-resources" >}}). ### extraObjects @@ -285,7 +285,7 @@ extraObjects: key: anthropic-api-key ``` -For more information, see [Customize Kubernetes resources](/docs/kagent/introduction/installation#customize-kubernetes-resources). +For more information, see [Customize Kubernetes resources]({{< link path="introduction/installation#customize-kubernetes-resources" >}}). ### Deployment annotations @@ -303,7 +303,7 @@ ui: This is useful for tools that read Deployment annotations such as cluster autoscaler, Datadog, and Karpenter. -For more information, see [Customize Kubernetes resources](/docs/kagent/introduction/installation#customize-kubernetes-resources). +For more information, see [Customize Kubernetes resources]({{< link path="introduction/installation#customize-kubernetes-resources" >}}). ### nodeSelector for agent Helm charts @@ -332,13 +332,13 @@ When unset, `nodeSelector` is omitted entirely, so there is no change for existi kagent now includes an [ACP (Agent Client Protocol)](https://agentclientprotocol.com/) shim in the base images for agents running on substrate. The shim reuses the WebSocket connection from the substrate actor and translates it to stdio, enabling agents built with OpenClaw and Hermes to communicate over the substrate runtime without additional configuration. -For more information, see [Agent Substrate](/docs/kagent/concepts/agent-substrate). +For more information, see [Agent Substrate]({{< link path="concepts/agent-substrate" >}}). ### Substrate support for BYO and Python agents `SandboxAgent` now supports running BYO agents and Python runtime declarative agents on Agent Substrate, in addition to Go declarative agents. This means any `Agent` type can be run as a sandboxed substrate workload. -For setup details, see [Agent Substrate](/docs/kagent/concepts/agent-substrate). +For setup details, see [Agent Substrate]({{< link path="concepts/agent-substrate" >}}). ### Durable session state for sandbox agents @@ -348,7 +348,7 @@ Session metadata is mirrored to the PostgreSQL database to support session-listi You can override the session database endpoint with the `KAGENT_SESSION_DB_URL` environment variable. -For more information, see [Agent Substrate — Declarative agents](/docs/kagent/concepts/agent-substrate#declarative-agents). +For more information, see [Agent Substrate — Declarative agents]({{< link path="concepts/agent-substrate#declarative-agents" >}}). ### Chat session sharing @@ -392,7 +392,7 @@ Set `POSTGRES_DATABASE_URL` or pass `--db-url` to provide the database connectio A new `database.postgres.skipMigrations` Helm value (default: `false`) prevents the controller from running migrations at startup. When enabled, the controller verifies the schema is already fully migrated and exits with an error if it is not. Apply migrations out-of-band before installing or upgrading when this option is set. -For details and usage examples, see [Run migrations out-of-band](/docs/kagent/operations/upgrade#run-migrations-out-of-band). +For details and usage examples, see [Run migrations out-of-band]({{< link path="operations/upgrade#run-migrations-out-of-band" >}}). ### maxOutputTokens for Gemini and Vertex AI @@ -418,7 +418,7 @@ spec: A per-request value set by the agent always takes precedence over the model-level default. -For more information, see [Gemini](/docs/kagent/supported-providers/gemini#max-output-tokens) and [Vertex AI](/docs/kagent/supported-providers/google-vertexai). +For more information, see [Gemini]({{< link path="supported-providers/gemini#max-output-tokens" >}}) and [Vertex AI]({{< link path="supported-providers/google-vertexai" >}}). ### AWS Bedrock Guardrails @@ -444,7 +444,7 @@ spec: 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. -For more information, see [Amazon Bedrock — Bedrock Guardrails](/docs/kagent/supported-providers/amazon-bedrock#bedrock-guardrails). +For more information, see [Amazon Bedrock — Bedrock Guardrails]({{< link path="supported-providers/amazon-bedrock#bedrock-guardrails" >}}). ### envFrom for agent deployments @@ -463,7 +463,7 @@ spec: name: my-agent-secrets ``` -For more information, see [Agents — Deployment configuration](/docs/kagent/concepts/agents#deployment-configuration). +For more information, see [Agents — Deployment configuration]({{< link path="concepts/agents#deployment-configuration" >}}). ### Disable default ModelConfig @@ -475,7 +475,7 @@ providers: null When `providers` is unset or null, neither the `modelconfig` nor the `modelconfig-secret` templates are rendered. Existing installs that define `providers` are unaffected. -For more information, see [Disable the default ModelConfig](/docs/kagent/introduction/installation#disable-the-default-modelconfig). +For more information, see [Disable the default ModelConfig]({{< link path="introduction/installation#disable-the-default-modelconfig" >}}). ### Azure AI Foundry @@ -507,7 +507,7 @@ To authenticate with an API key, create a Kubernetes Secret with the key stored Memory embeddings are supported and use 768-dimensional vectors. Anthropic (Claude) models on Foundry are not yet supported. -For more information, see [Azure AI Foundry](/docs/kagent/supported-providers/azure-ai-foundry). +For more information, see [Azure AI Foundry]({{< link path="supported-providers/azure-ai-foundry" >}}). ### OpenAI Responses API @@ -523,7 +523,7 @@ spec: Omit `apiFormat` (or set it to `chatCompletions`) to continue using Chat Completions, which remains the default. Native tool use and stateful Responses API chaining are not yet supported. -For more information, see [OpenAI — Responses API](/docs/kagent/supported-providers/openai#responses-api). +For more information, see [OpenAI — Responses API]({{< link path="supported-providers/openai#responses-api" >}}). ### Per-call session isolation for Agent tools @@ -541,7 +541,7 @@ spec: The default (`isolateSessions: false`) preserves the existing behavior where calls to the same sub-agent share a session for stateful continuity. -For more information, see [Agents — Per-call session isolation](/docs/kagent/concepts/agents#per-call-session-isolation). +For more information, see [Agents — Per-call session isolation]({{< link path="concepts/agents#per-call-session-isolation" >}}). ### Affinity and topologySpreadConstraints @@ -573,7 +573,7 @@ ui: Both fields accept standard Kubernetes scheduling objects. When unset, no affinity or spread constraints are applied and existing behavior is unchanged. -For more information, see [Installing kagent — Affinity and topology spread constraints](/docs/kagent/introduction/installation#affinity-and-topology-spread-constraints). +For more information, see [Installing kagent — Affinity and topology spread constraints]({{< link path="introduction/installation#affinity-and-topology-spread-constraints" >}}). ### S3 skills @@ -613,7 +613,7 @@ spec: tools: [] ``` -For the full field reference, see [S3SkillRef](/docs/kagent/resources/api-ref/#s3skillref) in the API reference. +For the full field reference, see [S3SkillRef]({{< link path="resources/api-ref/#s3skillref" >}}) in the API reference. ### File upload in agent chat @@ -676,7 +676,7 @@ ui: To use `minAvailable` instead, set `maxUnavailable: null` and specify `minAvailable`. Note that `minAvailable` and `maxUnavailable` are mutually exclusive — the Helm chart fails at template time if both are set. -For all available fields, see the [Helm reference](/docs/kagent/resources/helm/). +For all available fields, see the [Helm reference]({{< link path="resources/helm/" >}}). ### Additional changes in v0.10 @@ -760,7 +760,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]({{< 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:** @@ -903,7 +903,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]({{< link path="examples/human-in-the-loop" >}}) and the [blog post](https://kagent.dev/blog/human-in-the-loop-kagent). ### Agent Memory @@ -913,7 +913,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]({{< link path="concepts/agent-memory" >}}). ### Go ADK Runtime @@ -930,7 +930,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]({{< link path="concepts/agents#runtime" >}}) and the [blog post](https://kagent.dev/blog/go-vs-python-runtime). ### Agents as MCP Servers @@ -945,7 +945,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]({{< link path="concepts/agents#git-based-skills" >}}). ### Go Workspace Restructure @@ -963,13 +963,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]({{< 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](/docs/kagent/concepts/agents#context-management). +For more information, see [Agents]({{< link path="concepts/agents#context-management" >}}). ### AWS Bedrock Support @@ -996,7 +996,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]({{< 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`. @@ -1050,7 +1050,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]({{< link path="getting-started/local-development" >}}) guide. ### Discovery label @@ -1398,7 +1398,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]({{< link path="examples/a2a-byo" >}}) guide. ```yaml apiVersion: kagent.dev/v1alpha2 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 92% rename from docs-site/content/kagent/resources/versions.md rename to docs-site/content/kagent/0.x/resources/versions.md index f40549bc..3e304b05 100644 --- a/docs-site/content/kagent/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. 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 81% rename from docs-site/content/kagent/supported-providers/amazon-bedrock.md rename to docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md index c73c8c42..b94182ac 100644 --- a/docs-site/content/kagent/supported-providers/amazon-bedrock.md +++ b/docs-site/content/kagent/0.x/supported-providers/amazon-bedrock.md @@ -97,7 +97,52 @@ 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]({{< 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. ## Bedrock Guardrails 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 99% 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 index 2f8edd63..b5c90041 100644 --- a/docs-site/content/kagent/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]({{< link path="concepts/agent-memory" >}}). ## Troubleshooting 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 91% rename from docs-site/content/kagent/supported-providers/azure-openai.md rename to docs-site/content/kagent/0.x/supported-providers/azure-openai.md index ff10dc02..dfc02b0e 100644 --- a/docs-site/content/kagent/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]({{< 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/supported-providers/byo-agentgateway.md b/docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md similarity index 94% rename from docs-site/content/kagent/supported-providers/byo-agentgateway.md rename to docs-site/content/kagent/0.x/supported-providers/byo-agentgateway.md index 4c0095cc..86c331b2 100644 --- a/docs-site/content/kagent/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/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..53bc8677 --- /dev/null +++ b/docs-site/content/kagent/1.x/_index.md @@ -0,0 +1,23 @@ +--- +title: kagent 1.0 (preview) +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. + +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/about/_index.md b/docs-site/content/kagent/1.x/about/_index.md new file mode 100644 index 00000000..e2c087a0 --- /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: 20 +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..f5cf26fc --- /dev/null +++ b/docs-site/content/kagent/1.x/about/agent-substrate.md @@ -0,0 +1,56 @@ +--- +title: Agent Substrate architecture +description: See how Agent Substrate runs, suspends, and resumes the Actors behind every AgentInstance. +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 {{< 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. + +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 + +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. + +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 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. + +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 + +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. +

+ +{{< 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. + +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. +- A **{{< gloss "Tag" >}}Tag{{< /gloss >}}** 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. + +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. 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..2b4f3cb5 --- /dev/null +++ b/docs-site/content/kagent/1.x/about/architecture.md @@ -0,0 +1,76 @@ +--- +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 +--- + +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. + +## Two authorization planes + +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#the-kubernetes-plane" >}}). + +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"] + operator --> harness + operator --> template + harness --> controller + template --> controller + 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"] + instance["AgentInstance"] + actor["Actor (Substrate)"] + caller -->|A2A conversation| gateway + caller -->|CreateAgentInstance| instance + gateway -->|routes to| actor + instance -->|runs on| actor + end + + actortemplate -->|instantiated as| instance + %% 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 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 >}}. + +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 + +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. 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..2947d27d --- /dev/null +++ b/docs-site/content/kagent/1.x/about/core-concepts.md @@ -0,0 +1,113 @@ +--- +title: Core concepts +description: Learn the Harness, AgentTemplate, AgentInstance, and Actor model that kagent 1.0 is built on. +weight: 20 +author: kagent.dev +--- + +## 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: + +- 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. 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 + 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 + actortemplate -->|instantiated as| instance + instance -->|runs on| actor + + classDef crd stroke:#a78bfa,stroke-width:2px + 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. + +## 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. 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. + +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] +> 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. + +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: + +- **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 {{< 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. + +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, 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 pair into an `ActorTemplate`, a Substrate resource that holds everything Substrate needs to start an Actor. + +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 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. + +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. + +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 + +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** (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. + +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. 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..cf333e00 --- /dev/null +++ b/docs-site/content/kagent/1.x/about/what-is-kagent.md @@ -0,0 +1,76 @@ +--- +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 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. + +## 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: + +- 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 that those two resources produce, backed by an **Actor** on Agent Substrate. + +[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. + +## 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. + +## 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, 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'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." >}} +{{< 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, with control plane traces carrying the Actor that they belong to." >}} +{{< feature-card title="Postgres storage" desc="AgentInstances, conversations, and compiled revisions persist in PostgreSQL with reviewable migrations. Start on the bundled instance, then point kagent at your own database." >}} +{{< /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 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. + +## 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/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..95aaec04 --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/agent-harness.md @@ -0,0 +1,150 @@ +--- +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 +--- + +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 + +The following configuration is for a complete Harness resource. 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 +``` + +{{< reuse "kagent-docs/snippets/review-table.md" >}} For more information, see the [API reference]({{< link path="reference/api-ref#harness" >}}). + +| 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 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 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. | + +## Choose a runtime + +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. 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. + +### 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. 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" >}}). + +## Model provider support + +The runtime that a Harness selects decides which ModelConfig its AgentTemplates can use. + +| Provider | `kagent` | `byo` | `codex` | `claude` | +| -------- | :------: | :---: | :-----: | :------: | +| `OpenAI` | ✅ | ✅ | ✅ | ❌ | +| `Anthropic` | ✅ | ✅ | ❌ | ✅ | +| `Bedrock` | ✅ | ✅ | ✅ | ✅ | +| `AnthropicVertexAI` | ❌ | ❌ | ❌ | ✅ | +| `GeminiVertexAI` | ❌ | ❌ | ❌ | ❌ | +| `AzureOpenAI` | ✅ | ✅ | ❌ | ❌ | +| `Gemini` | ✅ | ✅ | ❌ | ❌ | +| `Ollama` | ✅ | ✅ | ❌ | ❌ | +| `SAPAICore` | ✅ | ✅ | ❌ | ❌ | +| `Foundry` | ✅ | ✅ | ❌ | ❌ | + +Some supported combinations 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 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" >}}). + +## 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 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` 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" >}}). + +## Check that a Harness is ready + +The `READY` column reports whether a Harness's dependencies resolved. +```bash +kubectl get 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 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 + +{{< 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/agents/agent-memory.md b/docs-site/content/kagent/1.x/agents/agent-memory.md new file mode 100644 index 00000000..cb724339 --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/agent-memory.md @@ -0,0 +1,257 @@ +--- +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 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. + +## 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. 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 + +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, 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. + +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. 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. | + | `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. 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 + kubectl port-forward -n kagent svc/kagent-controller 8083:8083 + ``` + +2. List the memories that an agent stores for one user. + ```bash + grpcurl -plaintext -d '{ + "agent_name": "kagent__NS__my_first_agent_my_first_harness", + "user_id": "admin@kagent.dev" + }' 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. + +3. Delete the memories for an agent and user. + ```bash + grpcurl -plaintext -d '{ + "agent_name": "kagent__NS__my_first_agent_my_first_harness", + "user_id": "admin@kagent.dev" + }' 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. + +## Memory lifetime + +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 >}} + {{< 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/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/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..dec64bf1 --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/human-in-the-loop.md @@ -0,0 +1,202 @@ +--- +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 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 + +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 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 `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 + +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-id: ' \ + -d '{ + "message": { + "messageId": "msg-1", + "role": "ROLE_USER", + "parts": [{"text": "Delete the obsolete pod in the production namespace."}] + } + }' 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. + +| 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`. + +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 + +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 + +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 | +| ------ | ---- | +| Your own A2A client | Full. Request the extension URI and handle the four payload types. | +| 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 + +{{< 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 >}} 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..760b08bd --- /dev/null +++ b/docs-site/content/kagent/1.x/agents/system-prompts.md @@ -0,0 +1,169 @@ +--- +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 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, 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: |- + 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. +``` + +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. Several AgentTemplates can then share one prompt, and a prompt can 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 both inline prompts or prompts set in 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 +``` + +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 {{< 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. + +| 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. 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 + - name: house-style + alias: style +``` + +> [!NOTE] +> A prompt template can reach only the supported values and the ConfigMaps that `dataSources` names. Templates cannot read arbitrary Kubernetes objects. + +## Troubleshooting + +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. + +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")]}' +``` + +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 | +| ------- | ----- | +| `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/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/a2a-agents.md b/docs-site/content/kagent/1.x/examples/a2a-agents.md new file mode 100644 index 00000000..347d4a15 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/a2a-agents.md @@ -0,0 +1,268 @@ +--- +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. 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. + +## About the kagent A2A service + +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 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 `8083` outside the cluster. For what the open source build does guarantee, see [Identity]({{< link path="substrate-runtime/identity" >}}). + +### A2A methods + +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. + +| Method | What it does | +| ------ | ------------ | +| `GetExtendedAgentCard` | Returns the agent card describing the instance. | +| `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. | + +## Before you begin + +{{< reuse "kagent-docs/snippets/grpcurl-prerequisites.md" >}} + +## Read the agent card + +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 + grpcurl -plaintext \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + localhost:8083 lf.a2a.v1.A2AService/GetExtendedAgentCard + ``` + + Example output: + ```json + { + "name": "my_first_agent", + "description": "My first kagent agent", + "supportedInterfaces": [ + { + "url": "http://kagent-controller.kagent.svc:8083", + "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 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. 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 + +`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 + grpcurl -plaintext \ + -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:8083 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": [ ] + } + } + ``` + 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's `id` so that you can read the task again later. + ```bash + export TASK_ID= + ``` + +## 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. + +1. Send a message on the streaming method. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"message":{"messageId":"'"$(uuidgen)"'","role":"ROLE_USER","parts":[{"text":"Count from 1 to 3."}]}}' \ + 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: + ```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. + +1. Read the task by ID. + ```bash + grpcurl -plaintext \ + -H "x-kagent-agent-instance-id: $INSTANCE_ID" \ + -d '{"id":"'"$TASK_ID"'"}' \ + 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. + ```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 + +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. + +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-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: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: + ```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-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:8083 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 + +* This example creates no Kubernetes resources, so you have nothing to delete. +* 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 + +{{< 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 >}} 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/examples/agent-delegation.md b/docs-site/content/kagent/1.x/examples/agent-delegation.md new file mode 100644 index 00000000..29b5d31e --- /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. For the two modes and the rules that a `Shared` tree must satisfy, 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/agent-substrate.md b/docs-site/content/kagent/1.x/examples/agent-substrate.md new file mode 100644 index 00000000..2dcd2c68 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/agent-substrate.md @@ -0,0 +1,204 @@ +--- +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 that continues the conversation. +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. 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 + +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. + +{{< reuse "kagent-docs/snippets/grpcurl-prerequisites.md" >}} + +## Watch the Actor suspend between turns + +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 `` 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 11m + ``` + +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. 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 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 {{< 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 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 '{"agentInstanceId":"'"$INSTANCE_ID"'","requestId":"'"$(uuidgen)"'"}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/CreateCheckpoint + ``` + + Example output: + ```json + { + "checkpoint": { + "id": "0198c3e2-8a41-7d05-b6c2-1f4e9a7b3c58", + "agentInstanceId": "0198c3d7-4f2a-7b61-9c3e-5d8f7a2b4e10", + "headTaskId": "0198c3d9-b7e3-7a24-8f10-6c2d5e8a1b47", + "historySequence": "4", + "state": "CHECKPOINT_STATE_READY", + "createdAt": "2026-08-31T15:12:44Z" + } + } + ``` + + > [!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= + ``` + +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 '{"agentInstanceId":"'"$INSTANCE_ID"'","page":{"limit":50}}' \ + localhost:8083 kagent.api.v1alpha1.CheckpointService/ListCheckpoints + ``` + +Underneath, the checkpoint attaches a {{< gloss "Tag" >}}Tag{{< /gloss >}} 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 tags --atespace kagent`. + +## 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 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. + +> [!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 '{"checkpointId":"'"$CHECKPOINT_ID"'","requestId":"'"$(uuidgen)"'"}' \ + localhost:8083 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", + "harness": { + "namespace": "kagent", + "name": "my-first-harness" + }, + "agentTemplate": { + "namespace": "kagent", + "name": "my-first-agent" + }, + "state": "AGENT_INSTANCE_STATE_READY", + "contextId": "ce5a10b8-7789-4ba7-8395-e60a339de763" + } + } + ``` + + 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 "What did I ask you first?" + ``` + + 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 + 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 {{< 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. + +## Clean up + +1. Delete the checkpoint. Deleting removes the Tag and releases the pin, and Agent Substrate can collect the snapshot whenever no tag names it. + ```bash + grpcurl -plaintext \ + -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. + ```bash + kagent delete agent-instance $FORK_ID + ``` + +## 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/examples/agents-via-mcp.md b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md new file mode 100644 index 00000000..3d6742a6 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/agents-via-mcp.md @@ -0,0 +1,590 @@ +--- +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. + +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 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 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. 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" >}}). + +## 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. [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. Port-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" %}} + 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 + ``` + + 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. + ```json + { + "mcpServers": { + "kagent": { + "url": "http://localhost:8083/mcp" + } + } + } + ``` + + Continue with the steps in [Use agents from Claude Code or Cursor](#use-agents-from-claude-code-or-cursor). + {{% /tab %}} + {{% tab name="curl" %}} + 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' \ + -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"}}} + ``` + + Continue with the steps in [Use agents from curl](#use-agents-from-curl). + {{% /tab %}} + {{< /tabs >}} + +## Use agents from Claude Code or Cursor + +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. + +### 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 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] +> 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 + +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 and it answers from the conversation it inherited, because a fork continues from the checkpoint rather than starting fresh. + +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). + +## 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": {} + } + }' + ``` + + 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) + ``` + +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' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": { + "name": "invoke_agent_instance", + "arguments": { + "agent_instance_id": "'"$INSTANCE_ID"'", + "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 + { + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "task_id": "01a06d0d-5fcf-7b07-aae3-1f470a8ee157", + "context_id": "ce5a10b8-7789-4ba7-8395-e60a339de763", + "state": "TASK_STATE_COMPLETED", + "text": "4" + } + ``` + +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": { + "agent_instance_id": "'"$INSTANCE_ID"'", + "message": "Multiply that by 10." + } + } + }' + ``` + Example output: + ```json + { + "agent_instance_id": "01a068e3-aeb6-7abc-8d6f-5ba9becd3143", + "task_id": "01a06d0d-6864-79f1-a4cb-8547f77638ba", + "context_id": "ce5a10b8-7789-4ba7-8395-e60a339de763", + "state": "TASK_STATE_COMPLETED", + "text": "40" + } + ``` + +### 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, 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 + 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": { + "agent_instance_id": "'"$INSTANCE_ID"'", + "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-04T15:35:25.722159606Z", + "lastUpdatedAt": "2026-09-04T15:35:25.722159606Z", + "ttlMs": null, + "pollIntervalMs": 1000, + "resultType": "task" + } + ``` + +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' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 4, + "method": "tasks/get", + "params": { + "taskId": "'"$TASK_ID"'", + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { "io.modelcontextprotocol/tasks": {} } + } + } + } + }' + ``` + +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). + +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", + "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] +> `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 + +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. + +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 + } + } + } + } + } + ``` + + 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. + +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' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 5, + "method": "tasks/update", + "params": { + "taskId": "'"$TASK_ID"'", + "inputResponses": { + "'"$INPUT_REQUEST_ID"'": { + "action": "accept", + "content": { "response": "PostgreSQL" } + } + }, + "_meta": { + "io.modelcontextprotocol/clientCapabilities": { + "extensions": { "io.modelcontextprotocol/tasks": {} } + } + } + } + }' + ``` + + The reply confirms only that the update was accepted, and carries no agent output. Example output: + ```json + { "resultType": "complete" } + ``` + +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", + "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 + +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`. + +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": { + "agent_instance_id": "'"$INSTANCE_ID"'", + "request_id": "my-first-checkpoint" + } + } + }' + ``` + + The result identifies the checkpoint and the turn it pinned. Example output: + ```json + { + "checkpoint": { + "id": "01a06d19-540a-7040-befb-ec4499c96ff2", + "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" + } + } + ``` + +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' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 7, + "method": "tools/call", + "params": { + "name": "list_agent_instance_checkpoints", + "arguments": { + "agent_instance_id": "'"$INSTANCE_ID"'" + } + } + }' + ``` + + The result is a `checkpoints` array of the same records, oldest first. Example output: + ```json + { + "checkpoints": [ + { + "id": "01a0690f-5548-7935-b7ca-70919fc9c221", + "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", + "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" + } + ] + } + ``` + +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' \ + -H 'Accept: application/json, text/event-stream' \ + -d '{ + "jsonrpc": "2.0", + "id": 8, + "method": "tools/call", + "params": { + "name": "fork_agent_instance", + "arguments": { + "checkpoint_id": "'"$CHECKPOINT_ID"'", + "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": "01a06d19-7eec-797b-87b8-7397a96b1544", + "harness": "my-first-harness", + "agent_template": "my-first-agent", + "state": "AGENT_INSTANCE_STATE_READY" + } + } + ``` + +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 + { + "agent_instance_id": "01a06d19-7eec-797b-87b8-7397a96b1544", + "task_id": "01a06d19-80e7-7554-8288-377eda9e861b", + "context_id": "ce5a10b8-7789-4ba7-8395-e60a339de763", + "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" >}}). + +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 + ``` + +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 8083:8083 + ``` + +3. Delete the checkpoint that you created. + ```bash + grpcurl -plaintext \ + -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. + +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. 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 | +| ---- | ------------------ | ------------ | +| `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 + +{{< cards >}} + {{< 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 >}} 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..84c733dc --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/documentation-agent.md @@ -0,0 +1,318 @@ +--- +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`. 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 + +{{< 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 >}} 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..513254f0 --- /dev/null +++ b/docs-site/content/kagent/1.x/examples/skills.md @@ -0,0 +1,400 @@ +--- +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`. + +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. + +### 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" >}}) 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 + +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, 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 + +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 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 and save the pinned reference. An `oci` source must be pinned to a digest, and a tag alone is rejected. + ```bash + export SKILL_OCI="$SKILL_REPO@$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' "$SKILL_REPO:1.0.0")" + echo "$SKILL_OCI" + ``` + + Example output: + ```console + ghcr.io/example-org/release-notes@sha256:3091b917d23de93c40e38a574aea1e5615989ca4d7b38f79431c87e04adfa58a + ``` + +## 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 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's ID to an environment variable. + ```bash + 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 + +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?" + ``` + +## 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. + +2. Build and push the skill under a new tag and read the new digest. + ```bash + 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")" + ``` + +3. Update `skills[].source.oci` on the AgentTemplate with the new digest, which compiles a new revision. + +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 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 + 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" . + 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. + ```bash + kubectl apply -f - < [!IMPORTANT] + > A package enables only the skills that you list. If you omit `plugins[].skills`, or leave it empty, the agent gets none of them, and kagent accepts that rather than reporting an error. For why an explicit list is the safer default, see [Skills]({{< link path="skills-and-mcp/skills" >}}). + +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?" + ``` + + 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. + +## 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 + kubectl get agenttemplate -n kagent \ + -o jsonpath='{range .status.harnesses[0].conditions[?(@.type=="Ready")]}{.status} {.reason} {.message}{end}' + ``` + + Example output: + ```console + False ActorTemplatePending waiting for the ActorTemplate golden snapshot + ``` + + > [!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: + ```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 + +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 + +{{< 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/get-started/_index.md b/docs-site/content/kagent/1.x/get-started/_index.md new file mode 100644 index 00000000..91326661 --- /dev/null +++ b/docs-site/content/kagent/1.x/get-started/_index.md @@ -0,0 +1,6 @@ +--- +title: Get started +description: Install kagent and create your first agent. +weight: 10 +author: kagent.dev +--- \ 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 new file mode 100644 index 00000000..d92b0559 --- /dev/null +++ b/docs-site/content/kagent/1.x/get-started/your-first-agent.md @@ -0,0 +1,179 @@ +--- +title: Your first agent +description: Create and communicate with your first agent by using the kagent project. +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. 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. 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] +> 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 + +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 + metadata: + name: my-first-harness + namespace: kagent + spec: + kagent: {} + workload: + # 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. + +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 + metadata: + 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. + ``` + +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 + ``` + + Example output: + ```console + +----------------+------------------+-------+----------------------+ + | NAME | HARNESS | READY | CREATED | + +----------------+------------------+-------+----------------------+ + | my-first-agent | my-first-harness | TRUE | 2026-08-31T15:01:44Z | + +----------------+------------------+-------+----------------------+ + ``` + + 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 + ``` + + 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. + ```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 | + +--------------------------------------+----------------+------------------+-------+----------------------+ + ``` + + 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 + +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?" + ``` + + The agent's reply prints as text. + ```console + 4 + ``` + +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?" + ``` + + ```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 + +> [!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" >}}). Unless you are finished with the kagent guides, leave the resources in place. + +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 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. + ```bash + kubectl delete agenttemplate my-first-agent -n kagent + kubectl delete harness my-first-harness -n kagent + ``` + +## 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." >}} + {{< 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/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..24b5b611 --- /dev/null +++ b/docs-site/content/kagent/1.x/get-started/your-first-mcp-tool.md @@ -0,0 +1,197 @@ +--- +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 {{< 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 + +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, 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" >}}). + +1. List the {{< gloss "RemoteMCPServer" >}}RemoteMCPServers{{< /gloss >}} in the `kagent` namespace. + ```bash + kubectl get remotemcpserver -n kagent + ``` + + 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 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] + > 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 - <}}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}' + ``` + + Example output: + ```console + my-first-harness 7c1f9a2b4e8d3f60a5b7c9e1d2f4a6b8c0d2e4f68a9b1c3d5e7f9a1b3c5d7e9f 7c1f9a2b4e8d3f60a5b7c9e1d2f4a6b8c0d2e4f68a9b1c3d5e7f9a1b3c5d7e9f + ``` + + 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. If a bound tool appears to be missing, check the spelling against the server's catalog. + +## 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 {{< 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." + ``` + +## 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" >}}) 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 >}} 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..7f96bd52 --- /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 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/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..8d19d531 --- /dev/null +++ b/docs-site/content/kagent/1.x/observability/audit-prompts.md @@ -0,0 +1,387 @@ +--- +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. + +### 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. + +| 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`. 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 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. + +- **`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 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" >}}). + +## 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 a collector and a logging backend + +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 + helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts + helm repo update + ``` + +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 \ + --version {{< reuse "kagent-docs/versions/loki.md" >}} \ + --namespace telemetry \ + --create-namespace \ + --values - < otel-collector-audit.yaml <}} \ + --values otel-collector-audit.yaml + ``` + +6. Verify that the collector is running. + ```bash + kubectl get pods -n telemetry -l app.kubernetes.io/name=opentelemetry-collector + ``` + Example output: + ```console + NAME READY STATUS RESTARTS AGE + opentelemetry-collector-audit-xxxxxxxxx-xxxxx 1/1 Running 0 30s + ``` + +## Turn on audit logging + +Add the audit variables to the Harness that your agents run on. The runtime then audits every AgentTemplate that the Harness admits. Auditing therefore applies to an entire Harness, not to a single agent. + +1. Add the three environment variables to the Harness. Keep the rest of its configuration unchanged. + ```yaml + kubectl apply -f - <@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. 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. 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=200 \ + | grep -B 5 -A 4 "EventName: gen_ai" + ``` + Example output: + ```console + 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: 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 + ``` + +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` 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", + "data": { + "resultType": "streams", + "result": [ + { + "stream": { + "service_name": "my_first_agent_my_first_harness", + "service_namespace": "kagent", + "scope_name": "gcp.vertex.agent", + "trace_id": "3d34d2f1b74f30a5cce0d5ed8571e928", + "span_id": "12671255711f5511", + "flags": "1" + }, + "values": [ + [ + "1788463578483244930", + "{\"content\":{\"parts\":[{\"text\":\"What is 2+2?\"}],\"role\":\"user\"}}" + ], + [ + "1788463578483063303", + "{\"content\":\"You are a concise, helpful assistant. ...\"}" + ] + ] + } + ] + } + } + ``` + +## Refine audit queries + +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. 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"} | 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 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"} | 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 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 + +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..cf2f984d --- /dev/null +++ b/docs-site/content/kagent/1.x/observability/tracing.md @@ -0,0 +1,218 @@ +--- +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. 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`. + +> [!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 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 | +| ---- | ------------------ | +| `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)` | 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 + +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 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 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=`. + +## 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/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..81ad4395 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/debug.md @@ -0,0 +1,200 @@ +--- +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 any command that ranges over that array 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] +> 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 + +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. 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. + * 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 + +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, 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 +``` + +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} +``` + +If the default log level does not have enough information, raise the controller's log level. + +```yaml +controller: + loglevel: debug +``` + +### 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 +``` + +> [!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/operational-considerations.md b/docs-site/content/kagent/1.x/operations/operational-considerations.md new file mode 100644 index 00000000..92529d69 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/operational-considerations.md @@ -0,0 +1,157 @@ +--- +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. + +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 delete the data. + +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: + replicas: 3 + volumes: + - name: db-secret + secret: + secretName: my-postgres-url-secret + volumeMounts: + - name: db-secret + mountPath: /var/secrets + 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 --install kagent \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ + --namespace kagent \ + --values kagent.yaml + ``` + +## Run multiple controller replica + +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 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. + +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 >}}. 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 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 any in-flight turns rather than cutting them off. + +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}" \ + --cluster "${CLUSTER_NAME}" --location "${CLUSTER_LOCATION}" \ + --no-enable-autoupgrade +``` + +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" >}}). + +## 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. + +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/operations/tune-agent-substrate.md b/docs-site/content/kagent/1.x/operations/tune-agent-substrate.md new file mode 100644 index 00000000..9cb88f1b --- /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:v{{< reuse "kagent-docs/versions/agent-substrate.md" >}}" + } + ], + "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 {{< gloss "Tag" >}}Tag{{< /gloss >}} 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`. 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`. + +```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..15c9c488 --- /dev/null +++ b/docs-site/content/kagent/1.x/operations/uninstall.md @@ -0,0 +1,104 @@ +--- +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 +--- + +Helm removes what its releases own, but does not uninstall the identity material and some storage that it does not own. + +Helm removes: + +- 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 + +Helm leaves behind: + +- 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 + +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 + +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 + +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 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 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 + 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 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 +``` + +Confirm that nothing remains. + +```bash +kubectl get crd | grep -E 'kagent\.dev|ate\.dev' +kubectl get ns kagent ate-system podcertificate-controller-system +``` + +The first command prints nothing. The second reports that it found none of the three namespaces. 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/_index.md b/docs-site/content/kagent/1.x/reference/_index.md new file mode 100644 index 00000000..0019d898 --- /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, the glossary, and community links. +weight: 100 +author: kagent.dev +--- diff --git a/docs-site/content/kagent/1.x/reference/api-ref.md b/docs-site/content/kagent/1.x/reference/api-ref.md new file mode 100644 index 00000000..7de7842b --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/api-ref.md @@ -0,0 +1,995 @@ +--- +title: API reference +description: Look up every field in the kagent v1alpha3 custom resources, including AgentTemplate, Harness, ModelConfig, and RemoteMCPServer. +weight: 10 +author: kagent.dev +--- + +## Packages +- [kagent.dev/v1alpha3](#kagentdevv1alpha3) + +## kagent.dev/v1alpha3 + +Package v1alpha3 contains API Schema definitions for the kagent.dev v1alpha3 API group. + +### Resource Types +- [AgentTemplate](#agenttemplate) +- [Harness](#harness) +- [ModelConfig](#modelconfig) +- [ModelProviderConfig](#modelproviderconfig) +- [RemoteMCPServer](#remotemcpserver) + +#### AgentTemplate + +AgentTemplate defines portable agent behavior. + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `kagent.dev/v1alpha3` | | | +| `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.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[AgentTemplateSpec](#agenttemplatespec)_ | | | | +| `status` _[AgentTemplateStatus](#agenttemplatestatus)_ | | | | + +#### AgentTemplateConfigMapKeyReference + +AgentTemplateConfigMapKeyReference identifies a key in a same-namespace ConfigMap. + +_Appears in:_ +- [AgentTemplateSpec](#agenttemplatespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | | | MinLength: 1
| +| `key` _string_ | | | MinLength: 1
| + +#### AgentTemplateHarnessStatus + +AgentTemplateHarnessStatus reports runtime revision state for one admitting Harness. + +_Appears in:_ +- [AgentTemplateStatus](#agenttemplatestatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `harness` _string_ | Harness names a same-namespace Harness whose admission selector matches
this AgentTemplate. | | MinLength: 1
| +| `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.35/#condition-v1-meta) array_ | | | MaxItems: 4
| + +#### AgentTemplatePromptSource + +AgentTemplatePromptSource makes a same-namespace ConfigMap available to a prompt template. + +_Appears in:_ +- [AgentTemplatePromptTemplateSpec](#agenttemplateprompttemplatespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | | | MinLength: 1
| +| `alias` _string_ | Alias is the name used by include. The ConfigMap name is used when omitted. | | MinLength: 1
| + +#### AgentTemplatePromptTemplateSpec + +AgentTemplatePromptTemplateSpec enables Go template rendering and ConfigMap includes. + +_Appears in:_ +- [AgentTemplateSpec](#agenttemplatespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `dataSources` _[AgentTemplatePromptSource](#agenttemplatepromptsource) array_ | DataSources are same-namespace ConfigMaps available to include("source/key"). | | MaxItems: 20
| + +#### AgentTemplateSkill + +AgentTemplateSkill identifies one standalone skill and its immutable source. + +_Appears in:_ +- [AgentTemplateSpec](#agenttemplatespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | | | MinLength: 1
| +| `source` _[ArtifactSource](#artifactsource)_ | | | | + +#### AgentTemplateSpec + +AgentTemplateSpec defines portable agent behavior. + +_Appears in:_ +- [AgentTemplate](#agenttemplate) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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. | | | +| `promptTemplate` _[AgentTemplatePromptTemplateSpec](#agenttemplateprompttemplatespec)_ | | | | +| `tools` _[ToolBinding](#toolbinding) array_ | | | MaxItems: 50
| +| `skills` _[AgentTemplateSkill](#agenttemplateskill) array_ | | | MaxItems: 50
| +| `plugins` _[PluginBundle](#pluginbundle) array_ | | | MaxItems: 20
| + +#### AgentTemplateStatus + +AgentTemplateStatus is the controller-observed state for each admitting Harness. + +_Appears in:_ +- [AgentTemplate](#agenttemplate) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `observedGeneration` _integer_ | | | | +| `harnesses` _[AgentTemplateHarnessStatus](#agenttemplateharnessstatus) array_ | Harnesses has at most one entry for each admitting Harness. | | | + +#### AgentToolBinding + +AgentToolBinding exposes another same-namespace AgentTemplate as a logical tool. + +_Appears in:_ +- [ToolBinding](#toolbinding) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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.35/#localobjectreference-v1-core)_ | | | | +| `isolation` _[AgentToolIsolation](#agenttoolisolation)_ | | Shared | Enum: [Shared Dedicated]
| + +#### AgentToolIsolation + +_Underlying type:_ _string_ + +AgentToolIsolation controls whether a referenced template shares its parent's runtime boundary. + +_Validation:_ +- Enum: [Shared Dedicated] + +_Appears in:_ +- [AgentToolBinding](#agenttoolbinding) + +| Field | Description | +| --- | --- | +| `Shared` | | +| `Dedicated` | | + +#### AllowedNamespaces + +AllowedNamespaces defines which namespaces are allowed to reference this resource. +This mechanism provides a bidirectional handshake for cross-namespace references, +following the pattern used by Gateway API for cross-namespace route attachments. + +By default (when not specified), only references from the same namespace are allowed. + +_Appears in:_ +- [RemoteMCPServerSpec](#remotemcpserverspec) + +| 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.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 + +AnthropicConfig contains Anthropic-specific configuration options + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `baseUrl` _string_ | Base URL for the Anthropic API (overrides default) | | | +| `maxTokens` _integer_ | Maximum tokens to generate | | | +| `temperature` _string_ | Temperature for sampling | | | +| `topP` _string_ | Top-p sampling parameter | | | +| `topK` _integer_ | Top-k sampling parameter | | | + +#### AnthropicVertexAIConfig + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `projectID` _string_ | The project ID | | | +| `location` _string_ | The project location | | | +| `temperature` _string_ | Temperature | | | +| `topP` _string_ | Top-p sampling parameter | | | +| `topK` _string_ | Top-k sampling parameter | | | +| `stopSequences` _string array_ | Stop sequences | | | +| `maxTokens` _integer_ | Maximum tokens to generate | | | + +#### ArtifactSource + +ArtifactSource selects exactly one immutable artifact. + +_Appears in:_ +- [AgentTemplateSkill](#agenttemplateskill) +- [PluginBundle](#pluginbundle) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `oci` _string_ | OCI is a digest-pinned image reference. | | Pattern: `^[^[:space:]@]+@sha256:[0-9a-f]\{64\}$`
| +| `git` _[GitArtifact](#gitartifact)_ | | | | +| `bucket` _[BucketArtifact](#bucketartifact)_ | | | | +| `path` _string_ | Path selects a directory within the immutable artifact. | | MaxLength: 1024
| + +#### AzureOpenAIConfig + +AzureOpenAIConfig contains Azure OpenAI-specific configuration options + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `azureEndpoint` _string_ | Endpoint for the Azure OpenAI API | | | +| `apiVersion` _string_ | API version for the Azure OpenAI API | | | +| `azureDeployment` _string_ | Deployment name for the Azure OpenAI API | | | +| `azureAdToken` _string_ | Azure AD token for authentication | | | +| `temperature` _string_ | Temperature for sampling | | | +| `maxTokens` _integer_ | Maximum tokens to generate | | | +| `topP` _string_ | Top-p sampling parameter | | | + +#### BYOHarness + +BYOHarness selects an image that implements kagent's private A2A contract. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +#### BaseVertexAIConfig + +_Appears in:_ +- [AnthropicVertexAIConfig](#anthropicvertexaiconfig) +- [GeminiVertexAIConfig](#geminivertexaiconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `projectID` _string_ | The project ID | | | +| `location` _string_ | The project location | | | +| `temperature` _string_ | Temperature | | | +| `topP` _string_ | Top-p sampling parameter | | | +| `topK` _string_ | Top-k sampling parameter | | | +| `stopSequences` _string array_ | Stop sequences | | | + +#### BedrockConfig + +BedrockConfig contains AWS Bedrock-specific configuration options. + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| 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.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)_ | | | | +| `readTimeout` _integer_ | ReadTimeout is the Bedrock HTTP client read timeout in seconds, applied by
both the Python and Go ADK runtimes. Raise this for agents that make long
Converse calls (large tool-augmented turns, extended reasoning). On the
Python ADK it overrides botocore's ~60s read timeout, which otherwise
aborts long completions with a ReadTimeoutError; on the Go ADK it bounds
the whole Converse request (default 30m). When unset, each runtime's
default is used. | | Minimum: 1
| +| `connectTimeout` _integer_ | ConnectTimeout is the Bedrock HTTP client connection-establishment timeout
in seconds, applied by both the Python and Go ADK runtimes. It bounds
connection setup only, not the response read. When unset, each runtime's
default is used (Python ADK: botocore; Go ADK: net dialer). | | Minimum: 1
| + +#### BedrockGuardrailConfig + +_Appears in:_ +- [BedrockConfig](#bedrockconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `identifier` _string_ | Identifier is the guardrail ID or full ARN. AWS accepts either a bare
guardrail ID or an arn:aws:bedrock:...:guardrail/... ARN, so the value is
only length-bounded here (AWS caps guardrailIdentifier at 2048 chars). | | MaxLength: 2048
MinLength: 1
| +| `version` _string_ | Version is the guardrail version: a numeric version (e.g. "1") or "DRAFT". | | MaxLength: 8
MinLength: 1
| +| `trace` _string_ | | disabled | Enum: [disabled enabled enabled_full]
| + +#### BucketArtifact + +BucketArtifact selects the supported object-store provider. + +_Appears in:_ +- [ArtifactSource](#artifactsource) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `s3` _[S3Object](#s3object)_ | | | | + +#### ClaudeHarness + +ClaudeHarness selects the Claude runtime adapter. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +#### CodexHarness + +CodexHarness selects the Codex runtime adapter. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +#### FoundryAPIFormat + +_Underlying type:_ _string_ + +FoundryAPIFormat selects the Foundry API format for a Foundry ModelConfig. + +_Appears in:_ +- [FoundryConfig](#foundryconfig) + +| Field | Description | +| --- | --- | +| `OpenAI` | | +| `Anthropic` | | + +#### FoundryConfig + +FoundryConfig contains Azure AI Foundry-specific configuration options. + +Authentication is implicit and mirrors the other cloud providers: if +spec.apiKeySecret is set the API key is used; if it is absent, the Foundry +runtime falls back to DefaultAzureCredential (which resolves to Azure +Workload Identity in-cluster, or the az CLI in local development). There is +no auth-type selector. + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| 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.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]
| + +#### FromNamespaces + +_Underlying type:_ _string_ + +FromNamespaces specifies namespace from which references to this resource are allowed. +This follows the same pattern as Gateway API's cross-namespace route attachment. +See: https://gateway-api.sigs.k8s.io/guides/multiple-ns/#cross-namespace-route-attachment + +_Validation:_ +- Enum: [All Same Selector] + +_Appears in:_ +- [AllowedNamespaces](#allowednamespaces) + +| Field | Description | +| --- | --- | +| `All` | NamespacesFromAll allows references from all namespaces.
| +| `Same` | NamespacesFromSame only allows references from the same namespace as the target resource (default).
| +| `Selector` | NamespacesFromSelector allows references from namespaces matching the selector.
| + +#### GDCHServiceAccountConfig + +GDCHServiceAccountConfig holds GDCH-specific token exchange parameters. + +_Appears in:_ +- [TokenExchangeConfig](#tokenexchangeconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `audience` _string_ | Audience is the token exchange audience URL (the GDC inference gateway base URL) | | | + +#### GeminiConfig + +GeminiConfig contains Gemini (AI Studio, API-key) specific configuration options + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `maxOutputTokens` _integer_ | Maximum output tokens to generate for a single response | | Minimum: 1
| + +#### GeminiVertexAIConfig + +GeminiVertexAIConfig contains Gemini Vertex AI-specific configuration options + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `projectID` _string_ | The project ID | | | +| `location` _string_ | The project location | | | +| `temperature` _string_ | Temperature | | | +| `topP` _string_ | Top-p sampling parameter | | | +| `topK` _string_ | Top-k sampling parameter | | | +| `stopSequences` _string array_ | Stop sequences | | | +| `maxOutputTokens` _integer_ | Maximum output tokens | | Minimum: 1
| +| `candidateCount` _integer_ | Candidate count | | | +| `responseMimeType` _string_ | Response mime type | | | + +#### GitArtifact + +GitArtifact identifies immutable content at a full Git commit ID. + +_Appears in:_ +- [ArtifactSource](#artifactsource) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `url` _string_ | | | MinLength: 1
Pattern: `^https?://[^[:space:]]+$`
| +| `commit` _string_ | | | Pattern: `^([0-9a-fA-F]\{40\}\|[0-9a-fA-F]\{64\})$`
| + +#### Harness + +Harness defines a reusable agent runtime and infrastructure policy. + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `kagent.dev/v1alpha3` | | | +| `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.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[HarnessSpec](#harnessspec)_ | | | | +| `status` _[HarnessStatus](#harnessstatus)_ | | | | + +#### HarnessAgentTemplateAdmission + +HarnessAgentTemplateAdmission selects AgentTemplates that this Harness admits. +An omitted admission accepts no AgentTemplates. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `selector` _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#labelselector-v1-meta)_ | Selector selects admitted AgentTemplates in the Harness namespace. | | | + +#### HarnessCapabilities + +HarnessCapabilities records behavior proven for a pinned adapter and runtime. +It is populated by the controller and is not user-authored configuration. + +_Appears in:_ +- [HarnessStatus](#harnessstatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `version` _string_ | Version identifies the controller capability catalog entry. | | MinLength: 1
| +| `nativeAgentTools` _boolean_ | | | | +| `maxNativeAgentDepth` _integer_ | | | Minimum: 0
| +| `dedicatedAgentTools` _boolean_ | | | | +| `mcpInjection` _boolean_ | | | | +| `streaming` _boolean_ | | | | +| `interruption` _boolean_ | | | | +| `inputRequired` _boolean_ | | | | +| `approvals` _boolean_ | | | | +| `inputModalities` _string array_ | | | MaxItems: 16
| +| `outputModalities` _string array_ | | | MaxItems: 16
| +| `resume` _boolean_ | | | | +| `checkpoint` _boolean_ | | | | + +#### HarnessEnvVar + +HarnessEnvVar configures one runtime environment variable. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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.35/#secretkeyselector-v1-core)_ | CredentialRef references a key in a same-namespace Secret. | | | + +#### HarnessSnapshotPolicy + +HarnessSnapshotPolicy configures storage for Substrate snapshots. + +_Appears in:_ +- [HarnessSubstratePolicy](#harnesssubstratepolicy) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `location` _string_ | Location is the snapshot storage location used by Substrate. | | Pattern: `^[^[:space:]]+$`
| + +#### HarnessSpec + +HarnessSpec defines a reusable runtime and its infrastructure policy. + +_Appears in:_ +- [Harness](#harness) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `kagent` _[KagentHarness](#kagentharness)_ | | | | +| `codex` _[CodexHarness](#codexharness)_ | | | | +| `claude` _[ClaudeHarness](#claudeharness)_ | | | | +| `byo` _[BYOHarness](#byoharness)_ | | | | +| `workload` _[HarnessWorkload](#harnessworkload)_ | | | | +| `env` _[HarnessEnvVar](#harnessenvvar) array_ | | | MaxItems: 100
| +| `substrate` _[HarnessSubstratePolicy](#harnesssubstratepolicy)_ | | | | +| `allowedAgentTemplates` _[HarnessAgentTemplateAdmission](#harnessagenttemplateadmission)_ | AllowedAgentTemplates selects AgentTemplates this Harness admits.
When omitted, the Harness admits none. | | | + +#### HarnessStatus + +HarnessStatus reports controller-derived capabilities and current health. + +_Appears in:_ +- [Harness](#harness) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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.35/#condition-v1-meta) array_ | Conditions report adapter and dependency health. | | MaxItems: 8
| + +#### HarnessSubstratePolicy + +HarnessSubstratePolicy contains the Substrate policy shared by all runtime variants. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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 + +HarnessWorkload identifies the immutable runtime image used by a Harness. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `image` _string_ | Image is an OCI image reference pinned by sha256 digest. | | Pattern: `^[^[:space:]@]+@sha256:[a-f0-9]\{64\}$`
| +| `command` _string array_ | Command overrides the image entrypoint when set. | | MaxItems: 32
| +| `args` _string array_ | Args overrides the image command arguments when set. | | MaxItems: 64
| + +#### KagentHarness + +KagentHarness configures the kagent runtime adapter. + +_Appears in:_ +- [HarnessSpec](#harnessspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `memory` _[KagentHarnessMemory](#kagentharnessmemory)_ | Memory enables long-term memory for agents using this Harness. | | | + +#### KagentHarnessMemory + +KagentHarnessMemory configures kagent's long-term memory service. + +_Appears in:_ +- [KagentHarness](#kagentharness) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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 + +_Appears in:_ +- [RemoteMCPServerStatus](#remotemcpserverstatus) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | | | | +| `description` _string_ | | | | + +#### MCPToolBinding + +MCPToolBinding binds tools from a same-namespace MCP server. + +_Appears in:_ +- [ToolBinding](#toolbinding) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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. | | | + +#### ModelConfig + +ModelConfig is the Schema for the modelconfigs API. + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `kagent.dev/v1alpha3` | | | +| `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.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[ModelConfigSpec](#modelconfigspec)_ | | | | +| `status` _[ModelConfigStatus](#modelconfigstatus)_ | | | | + +#### ModelConfigSpec + +ModelConfigSpec defines the desired state of ModelConfig. + +_Appears in:_ +- [ModelConfig](#modelconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `model` _string_ | | | | +| `apiKeySecret` _string_ | The name of the secret that contains the API key. Must be a reference to the name of a secret in the same namespace as the referencing ModelConfig.
For the SAPAICore provider, the secret must contain two keys: "client_id" and "client_secret"
(the OAuth2 client credentials for SAP AI Core). The apiKeySecretKey field is not used for SAPAICore. | | | +| `apiKeySecretKey` _string_ | The key in the secret that contains the API key.
Not used for the SAPAICore provider (which always reads "client_id" and "client_secret" from the secret). | | | +| `apiKeyPassthrough` _boolean_ | APIKeyPassthrough enables forwarding the Bearer token from incoming A2A requests
directly to the LLM provider as the API key. This is useful for organizations
with federated identity that want to avoid separate secret management.
Mutually exclusive with apiKeySecret. | | | +| `defaultHeaders` _object (keys:string, values:string)_ | | | | +| `provider` _[ModelProvider](#modelprovider)_ | The provider of the model | OpenAI | Enum: [Anthropic OpenAI AzureOpenAI Ollama Gemini GeminiVertexAI AnthropicVertexAI Bedrock SAPAICore Foundry]
| +| `openAI` _[OpenAIConfig](#openaiconfig)_ | OpenAI-specific configuration | | | +| `anthropic` _[AnthropicConfig](#anthropicconfig)_ | Anthropic-specific configuration | | | +| `azureOpenAI` _[AzureOpenAIConfig](#azureopenaiconfig)_ | Azure OpenAI-specific configuration | | | +| `ollama` _[OllamaConfig](#ollamaconfig)_ | Ollama-specific configuration | | | +| `gemini` _[GeminiConfig](#geminiconfig)_ | Gemini-specific configuration | | | +| `geminiVertexAI` _[GeminiVertexAIConfig](#geminivertexaiconfig)_ | Gemini Vertex AI-specific configuration | | | +| `anthropicVertexAI` _[AnthropicVertexAIConfig](#anthropicvertexaiconfig)_ | Anthropic-specific configuration | | | +| `bedrock` _[BedrockConfig](#bedrockconfig)_ | AWS Bedrock-specific configuration | | | +| `sapAICore` _[SAPAICoreConfig](#sapaicoreconfig)_ | SAP AI Core-specific configuration | | | +| `foundry` _[FoundryConfig](#foundryconfig)_ | Azure AI Foundry-specific configuration | | | +| `tls` _[TLSConfig](#tlsconfig)_ | TLS configuration for provider connections.
Enables agents to connect to internal LiteLLM gateways or other providers
that use self-signed certificates or custom certificate authorities. | | | + +#### ModelConfigStatus + +ModelConfigStatus defines the observed state of ModelConfig. + +_Appears in:_ +- [ModelConfig](#modelconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `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. | | | + +#### ModelProvider + +_Underlying type:_ _string_ + +ModelProvider represents the model provider type + +_Validation:_ +- Enum: [Anthropic OpenAI AzureOpenAI Ollama Gemini GeminiVertexAI AnthropicVertexAI Bedrock SAPAICore Foundry] + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) +- [ModelProviderConfigSpec](#modelproviderconfigspec) + +| Field | Description | +| --- | --- | +| `Anthropic` | | +| `AzureOpenAI` | | +| `OpenAI` | | +| `Ollama` | | +| `Gemini` | | +| `GeminiVertexAI` | | +| `AnthropicVertexAI` | | +| `Bedrock` | | +| `SAPAICore` | | +| `Foundry` | | + +#### ModelProviderConfig + +ModelProviderConfig is the Schema for the modelproviderconfigs API. +It represents a model provider configuration with automatic model discovery. + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `kagent.dev/v1alpha3` | | | +| `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.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[ModelProviderConfigSpec](#modelproviderconfigspec)_ | | | | +| `status` _[ModelProviderConfigStatus](#modelproviderconfigstatus)_ | | | | + +#### ModelProviderConfigSpec + +ModelProviderConfigSpec defines the desired state of ModelProviderConfig. + +_Appears in:_ +- [ModelProviderConfig](#modelproviderconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[ModelProvider](#modelprovider)_ | Type is the model provider type (OpenAI, Anthropic, etc.) | | Enum: [Anthropic OpenAI AzureOpenAI Ollama Gemini GeminiVertexAI AnthropicVertexAI Bedrock SAPAICore Foundry]
| +| `endpoint` _string_ | Endpoint is the API endpoint URL for the provider.
If not specified, the default endpoint for the provider type will be used. | | Pattern: `^https?://.*`
| +| `secretRef` _[SecretReference](#secretreference)_ | SecretRef references the Kubernetes Secret containing the API key.
Optional for providers that don't require authentication (e.g., local Ollama). | | | + +#### ModelProviderConfigStatus + +ModelProviderConfigStatus defines the observed state of ModelProviderConfig. + +_Appears in:_ +- [ModelProviderConfig](#modelproviderconfig) + +| 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.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.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 + +OllamaConfig contains Ollama-specific configuration options + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `host` _string_ | Host for the Ollama API | | | +| `options` _object (keys:string, values:string)_ | Options for the Ollama API | | | + +#### OpenAIAPIFormat + +_Underlying type:_ _string_ + +OpenAIAPIFormat selects the OpenAI HTTP API shape used by the ADK runtime. + +_Validation:_ +- Enum: [chatCompletions responses] + +_Appears in:_ +- [OpenAIConfig](#openaiconfig) + +| Field | Description | +| --- | --- | +| `chatCompletions` | | +| `responses` | | + +#### OpenAIConfig + +OpenAIConfig contains OpenAI-specific configuration options + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `baseUrl` _string_ | Base URL for the OpenAI API (overrides default) | | | +| `organization` _string_ | Organization ID for the OpenAI API | | | +| `temperature` _string_ | Temperature for sampling | | | +| `maxTokens` _integer_ | Maximum tokens to generate. Sent as the OpenAI `max_tokens` request
parameter, which is deprecated and rejected by reasoning models
(GPT-5 / o-series). For those models set maxCompletionTokens instead.
Mutually exclusive with maxCompletionTokens. | | Minimum: 1
| +| `maxCompletionTokens` _integer_ | Maximum completion tokens to generate. Sent as the OpenAI
`max_completion_tokens` request parameter (an upper bound on visible
output plus reasoning tokens). This is the parameter reasoning models
(GPT-5 / o-series) require in place of the deprecated maxTokens.
Mutually exclusive with maxTokens. | | Minimum: 1
| +| `topP` _string_ | Top-p sampling parameter | | | +| `frequencyPenalty` _string_ | Frequency penalty | | | +| `presencePenalty` _string_ | Presence penalty | | | +| `seed` _integer_ | Seed value | | | +| `n` _integer_ | N value | | | +| `timeout` _integer_ | Timeout | | | +| `reasoningEffort` _[OpenAIReasoningEffort](#openaireasoningeffort)_ | Reasoning effort | | Enum: [none minimal low medium high xhigh]
| +| `apiFormat` _[OpenAIAPIFormat](#openaiapiformat)_ | APIFormat selects which OpenAI HTTP API the runtime uses for this model.
chatCompletions (default) posts to /v1/chat/completions.
responses posts to /v1/responses. Use responses for OpenAI-compatible
gateways or models that require the Responses API. | chatCompletions | Enum: [chatCompletions responses]
| +| `tokenExchange` _[TokenExchangeConfig](#tokenexchangeconfig)_ | TokenExchange configures dynamic bearer token acquisition via credential exchange.
Requires apiKeySecret (used as the service account secret) and is mutually exclusive with apiKeyPassthrough. | | | + +#### OpenAIReasoningEffort + +_Underlying type:_ _string_ + +OpenAIReasoningEffort represents how many reasoning tokens the model generates before producing a response. +Supported values vary by model. Set to "none" to disable reasoning; some models (e.g. gpt-5.6-terra) +require this to use function tools via the Chat Completions API. + +_Validation:_ +- Enum: [none minimal low medium high xhigh] + +_Appears in:_ +- [OpenAIConfig](#openaiconfig) + +#### PluginBundle + +PluginBundle selects Agent Skills from one immutable Agent Plugins package. + +_Appears in:_ +- [AgentTemplateSpec](#agenttemplatespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `source` _[ArtifactSource](#artifactsource)_ | | | | +| `skills` _string array_ | An empty selection enables nothing. | | MaxItems: 50
| + +#### RemoteMCPServer + +RemoteMCPServer is the Schema for the RemoteMCPServers API. + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `apiVersion` _string_ | `kagent.dev/v1alpha3` | | | +| `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.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | | +| `spec` _[RemoteMCPServerSpec](#remotemcpserverspec)_ | | | | +| `status` _[RemoteMCPServerStatus](#remotemcpserverstatus)_ | | | | + +#### RemoteMCPServerProtocol + +_Underlying type:_ _string_ + +_Validation:_ +- Enum: [SSE STREAMABLE_HTTP] + +_Appears in:_ +- [RemoteMCPServerSpec](#remotemcpserverspec) + +| Field | Description | +| --- | --- | +| `SSE` | | +| `STREAMABLE_HTTP` | | + +#### RemoteMCPServerSpec + +RemoteMCPServerSpec defines the desired state of RemoteMCPServer. + +_Appears in:_ +- [RemoteMCPServer](#remotemcpserver) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `description` _string_ | | | | +| `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.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. | | | + +#### RemoteMCPServerStatus + +RemoteMCPServerStatus defines the observed state of RemoteMCPServer. + +_Appears in:_ +- [RemoteMCPServer](#remotemcpserver) + +| 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.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. | | | + +#### S3Object + +S3Object identifies one immutable S3 object version. + +_Appears in:_ +- [BucketArtifact](#bucketartifact) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `endpoint` _string_ | Endpoint is the HTTP(S) endpoint of an AWS or S3-compatible service. | | Pattern: `^https?://[^[:space:]]+$`
| +| `bucket` _string_ | | | MinLength: 1
| +| `key` _string_ | | | MinLength: 1
| +| `versionId` _string_ | | | MinLength: 1
| +| `region` _string_ | Region is used for request signing when required by the service. | | | + +#### SAPAICoreConfig + +SAPAICoreConfig contains SAP AI Core-specific configuration options. + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `baseUrl` _string_ | Base URL for the SAP AI Core API (e.g., https://api.ai.prod.eu-central-1.aws.ml.hana.ondemand.com) | | | +| `resourceGroup` _string_ | Resource group in SAP AI Core | default | | +| `authUrl` _string_ | OAuth2 token endpoint URL (e.g., https://tenant.authentication.eu10.hana.ondemand.com) | | | + +#### SecretReference + +SecretReference references a Kubernetes Secret that must contain exactly one data key +holding the API key or credential. + +_Appears in:_ +- [ModelProviderConfigSpec](#modelproviderconfigspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | Name is the name of the secret in the same namespace as the ModelProviderConfig. | | | + +#### TLSConfig + +TLSConfig contains TLS/SSL configuration options for outbound HTTPS +connections from the agent (model provider, RemoteMCPServer). The +XValidation rules below apply at admission to every CRD field that +uses TLSConfig, so callers don't need to re-declare them per spec. + +_Appears in:_ +- [ModelConfigSpec](#modelconfigspec) +- [RemoteMCPServerSpec](#remotemcpserverspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `disableVerify` _boolean_ | DisableVerify disables SSL certificate verification entirely.
When false (default), SSL certificates are verified.
When true, SSL certificate verification is disabled.
WARNING: This should ONLY be used in development/testing environments.
Production deployments MUST use proper certificates. | false | | +| `caCertSecretRef` _string_ | CACertSecretRef is a reference to a Kubernetes Secret containing
CA certificate(s) in PEM format. The Secret must be in the same
namespace as the resource referencing it (ModelConfig,
RemoteMCPServer, or any future consumer of TLSConfig).
When set, the certificate will be used to verify the upstream's
SSL certificate. | | | +| `caCertSecretKey` _string_ | CACertSecretKey is the key within the Secret that contains the
CA certificate data (PEM-encoded). Required when CACertSecretRef
is set — admission rejects ref-without-key regardless of
DisableVerify (see the TLSConfig-level XValidation rules). | | | +| `disableSystemCAs` _boolean_ | DisableSystemCAs disables the use of system CA certificates.
When false (default), system CA certificates are used for verification (safe behavior).
When true, only the custom CA from CACertSecretRef is trusted.
This allows strict security policies where only corporate CAs should be trusted. | false | | + +#### TokenExchangeConfig + +TokenExchangeConfig configures dynamic bearer token acquisition before model calls. + +_Appears in:_ +- [OpenAIConfig](#openaiconfig) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[TokenExchangeType](#tokenexchangetype)_ | | | Enum: [GDCHServiceAccount]
| +| `gdchServiceAccount` _[GDCHServiceAccountConfig](#gdchserviceaccountconfig)_ | | | | + +#### TokenExchangeType + +_Underlying type:_ _string_ + +TokenExchangeType identifies the token exchange mechanism + +_Validation:_ +- Enum: [GDCHServiceAccount] + +_Appears in:_ +- [TokenExchangeConfig](#tokenexchangeconfig) + +| Field | Description | +| --- | --- | +| `GDCHServiceAccount` | | + +#### ToolBinding + +ToolBinding selects exactly one MCP or AgentTemplate-backed tool source. + +_Appears in:_ +- [AgentTemplateSpec](#agenttemplatespec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `mcp` _[MCPToolBinding](#mcptoolbinding)_ | | | | +| `agent` _[AgentToolBinding](#agenttoolbinding)_ | | | | + +#### ValueRef + +ValueRef represents a configuration value + +_Appears in:_ +- [RemoteMCPServerSpec](#remotemcpserverspec) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `name` _string_ | | | | +| `value` _string_ | | | | +| `valueFrom` _[ValueSource](#valuesource)_ | | | | + +#### ValueSource + +ValueSource defines a source for configuration values from a Secret or ConfigMap + +_Appears in:_ +- [ValueRef](#valueref) + +| Field | Description | Default | Validation | +| --- | --- | --- | --- | +| `type` _[ValueSourceType](#valuesourcetype)_ | | | Enum: [ConfigMap Secret]
| +| `name` _string_ | The name of the ConfigMap or Secret. | | MaxLength: 253
| +| `key` _string_ | The key of the ConfigMap or Secret. | | MaxLength: 253
| + +#### ValueSourceType + +_Underlying type:_ _string_ + +_Appears in:_ +- [ValueSource](#valuesource) + +| Field | Description | +| --- | --- | +| `ConfigMap` | | +| `Secret` | | 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/1.x/reference/cli/kagent-completion-bash.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-bash.md new file mode 100644 index 00000000..753b2afb --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-bash.md @@ -0,0 +1,45 @@ +--- +title: kagent completion bash +description: Generate the autocompletion script for bash. +weight: 40 +--- + +Generate the autocompletion script for the bash shell. + +This script depends on the 'bash-completion' package. +If it is not installed already, you can install it via your OS's package manager. + +To load completions in your current shell session: + + source <(kagent completion bash) + +To load completions for every new session, execute once: + +\#### Linux: + + kagent completion bash > /etc/bash_completion.d/kagent + +\#### macOS: + + kagent completion bash > $(brew --prefix)/etc/bash_completion.d/kagent + +You will need to start a new shell for this setup to take effect. + +```bash +kagent completion bash +``` + +**Flags:** +- `-h, --help` - help for bash +- `--no-descriptions` - disable completion descriptions + +**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-completion-fish.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-fish.md new file mode 100644 index 00000000..1ab372fb --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-fish.md @@ -0,0 +1,36 @@ +--- +title: kagent completion fish +description: Generate the autocompletion script for fish. +weight: 50 +--- + +Generate the autocompletion script for the fish shell. + +To load completions in your current shell session: + + kagent completion fish | source + +To load completions for every new session, execute once: + + kagent completion fish > ~/.config/fish/completions/kagent.fish + +You will need to start a new shell for this setup to take effect. + +```bash +kagent completion fish [flags] +``` + +**Flags:** +- `-h, --help` - help for fish +- `--no-descriptions` - disable completion descriptions + +**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-completion-powershell.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-powershell.md new file mode 100644 index 00000000..fdab5968 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-powershell.md @@ -0,0 +1,33 @@ +--- +title: kagent completion powershell +description: Generate the autocompletion script for powershell. +weight: 60 +--- + +Generate the autocompletion script for powershell. + +To load completions in your current shell session: + + kagent completion powershell | Out-String | Invoke-Expression + +To load completions for every new session, add the output of the above command +to your powershell profile. + +```bash +kagent completion powershell [flags] +``` + +**Flags:** +- `-h, --help` - help for powershell +- `--no-descriptions` - disable completion descriptions + +**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-completion-zsh.md b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-zsh.md new file mode 100644 index 00000000..390cf743 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-completion-zsh.md @@ -0,0 +1,47 @@ +--- +title: kagent completion zsh +description: Generate the autocompletion script for zsh. +weight: 70 +--- + +Generate the autocompletion script for the zsh shell. + +If shell completion is not already enabled in your environment you will need +to enable it. You can execute the following once: + + echo "autoload -U compinit; compinit" >> ~/.zshrc + +To load completions in your current shell session: + + source <(kagent completion zsh) + +To load completions for every new session, execute once: + +\#### Linux: + + kagent completion zsh > "${fpath[1]}/_kagent" + +\#### macOS: + + kagent completion zsh > $(brew --prefix)/share/zsh/site-functions/_kagent + +You will need to start a new shell for this setup to take effect. + +```bash +kagent completion zsh [flags] +``` + +**Flags:** +- `-h, --help` - help for zsh +- `--no-descriptions` - disable completion descriptions + +**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-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/1.x/reference/cli/kagent-mcp-add-tool.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-add-tool.md new file mode 100644 index 00000000..cc56b229 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-add-tool.md @@ -0,0 +1,43 @@ +--- +title: kagent mcp add-tool +description: Add a new MCP tool to your project. +weight: 260 +--- + +Generate a new MCP tool that will be automatically loaded by the server. + +This command creates a new tool file in src/tools/ with a generic template. +The tool will be automatically discovered and loaded when the server starts. + +Each tool is a Python file containing a function decorated with @mcp.tool(). +The function should use the @mcp.tool() decorator from FastMCP. + +```bash +kagent mcp add-tool [tool-name] [flags] +``` + +**Flags:** +- `-d, --description string` - Tool description +- `-f, --force` - Overwrite existing tool file +- `-h, --help` - help for add-tool +- `-i, --interactive` - Interactive tool creation +- `--project-dir string` - Project directory (default: current directory) + +**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 mcp add-tool weather +kagent mcp add-tool database --description "Database operations tool" +kagent mcp add-tool weather --force # Overwrite existing tool +``` diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-build.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-build.md new file mode 100644 index 00000000..5a6fcc0a --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-build.md @@ -0,0 +1,41 @@ +--- +title: kagent mcp build +description: Build MCP server as a Docker image. +weight: 270 +--- + +Build an MCP server from the current project. + +This command will detect the project type and build the appropriate +MCP server Docker image. + +```bash +kagent mcp build [flags] +``` + +**Flags:** +- `-h, --help` - help for build +- `--kind-load` - Load image into kind cluster (requires kind) +- `--kind-load-cluster string` - Name of the kind cluster to load image into (default: current cluster) +- `--platform string` - Target platform (e.g., linux/amd64,linux/arm64) +- `-d, --project-dir string` - Build directory (default: current directory) +- `--push` - Push Docker image to registry +- `-t, --tag string` - Docker image tag (alias for --output) + +**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 mcp build # Build Docker image from current directory +kagent mcp build --project-dir ./my-project # Build Docker image from specific directory +``` diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy-package.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy-package.md new file mode 100644 index 00000000..630c9015 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy-package.md @@ -0,0 +1,52 @@ +--- +title: kagent mcp deploy package +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. + +This subcommand creates an MCPServer Custom Resource Definition (CRD) that runs +an MCP server using npx (for npm packages) or uvx (for Python packages). + +The deployment name, manager, and args are required. The package manager must be either 'npx' or 'uvx'. + +```bash +kagent mcp deploy package [flags] +``` + +**Flags:** +- `--args strings` - Arguments to pass to the package manager (e.g., package names) (required) +- `--deployment-name string` - Name for the deployment (required) +- `--dry-run` - Generate manifest without applying to cluster +- `--env strings` - Environment variables (KEY=VALUE) +- `-h, --help` - help for package +- `--image string` - Docker image to deploy (overrides default) +- `--manager string` - Package manager to use (npx or uvx) (required) +- `-n, --namespace string` - Kubernetes namespace +- `--no-inspector` - Do not start the MCP inspector after deployment (default true) +- `--output string` - Output file for the generated YAML +- `--port int` - Container port (default: 3000) +- `--secrets strings` - List of Kubernetes secret names to mount +- `--transport string` - Transport type (stdio, http) + +**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 + +## Example + +```bash +kagent mcp deploy package --deployment-name github-server --manager npx --args @modelcontextprotocol/server-github # Deploy GitHub MCP server +kagent mcp deploy package --deployment-name github-server --manager npx --args @modelcontextprotocol/server-github --dry-run # Print YAML without deploying +kagent mcp deploy package --deployment-name my-server --manager npx --args my-package --env "KEY1=value1,KEY2=value2" # Set environment variables +kagent mcp deploy package --deployment-name github-server --manager npx --args @modelcontextprotocol/server-github --secrets secret1,secret2 # Mount Kubernetes secrets +kagent mcp deploy package --deployment-name my-server --manager npx --args my-package --no-inspector # Deploy without starting inspector +kagent mcp deploy package --deployment-name my-server --manager uvx --args mcp-server-git # Use UV and write managed tools and installables to /tmp directories +``` diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy.md new file mode 100644 index 00000000..16164e0a --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-deploy.md @@ -0,0 +1,71 @@ +--- +title: kagent mcp deploy +description: Deploy MCP server to Kubernetes. +weight: 280 +--- + +Deploy an MCP server to Kubernetes by generating MCPServer CRDs. + +This command generates MCPServer Custom Resource Definitions (CRDs) based on: +- Project configuration from manifest.yaml +- Docker image built with 'kagent mcp build --docker' +- Deployment configuration options + +The generated MCPServer will include: +- Docker image reference from the build +- Transport configuration (stdio/http) +- Port and command configuration +- Environment variables and secrets + +The command can also apply Kubernetes secret YAML files to the cluster before deploying the MCPServer. +The secrets will be referenced in the MCPServer CRD for mounting as volumes to the MCP server container. +Secret namespace will be overridden with the deployment namespace to avoid the need for reference grants +to enable cross-namespace references. + +```bash +kagent mcp deploy [flags] +kagent mcp deploy [command] +``` + +**Subcommands:** +- [`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 +- `--command string` - Command to run (overrides project config) +- `--dry-run` - Generate manifest without applying to cluster +- `--env strings` - Environment variables (KEY=VALUE) +- `--environment string` - Target environment for deployment (e.g., staging, production) (default "staging") +- `-f, --file string` - Path to manifest.yaml file (default: current directory) +- `--force` - Force deployment even if validation fails +- `-h, --help` - help for deploy +- `--image string` - Docker image to deploy (overrides build image) +- `-n, --namespace string` - Kubernetes namespace (default "default") +- `--no-inspector` - Do not start the MCP inspector after deployment (default true) +- `--output string` - Output file for the generated YAML +- `--port int` - Container port (default: from project config) +- `--transport string` - Transport type (stdio, http) + +**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 + +## Example + +```bash +kagent mcp deploy # Deploy with project name to cluster +kagent mcp deploy my-server # Deploy with custom name +kagent mcp deploy --namespace staging # Deploy to staging namespace +kagent mcp deploy --dry-run # Generate manifest without applying to cluster +kagent mcp deploy --image custom:tag # Use custom image +kagent mcp deploy --transport http # Use HTTP transport +kagent mcp deploy --output deploy.yaml # Save to file +kagent mcp deploy --file /path/to/manifest.yaml # Use custom manifest.yaml file +kagent mcp deploy --environment staging # Target environment for deployment (e.g., staging, production) +``` diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-go.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-go.md new file mode 100644 index 00000000..84168df1 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-go.md @@ -0,0 +1,37 @@ +--- +title: kagent mcp init go +description: Initialize a new Go MCP server project. +weight: 310 +--- + +Initialize a new MCP server project using the mcp-go framework. + +This command will create a new directory with a basic mcp-go project structure, +including a go.mod file, a main.go file, and an example tool. + +You must provide a valid Go module name for the project. + +```bash +kagent mcp init go [project-name] [flags] +``` + +**Flags:** +- `--go-module-name string` - The Go module name for the project (e.g., github.com/my-org/my-project) +- `-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 +- `--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 +- `--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-java.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-java.md new file mode 100644 index 00000000..56aec77f --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-java.md @@ -0,0 +1,34 @@ +--- +title: kagent mcp init java +description: Initialize a new Java MCP server project. +weight: 320 +--- + +Initialize a new MCP server project using the Java MCP framework. + +This command will create a new directory with a basic Java MCP project structure, +including a pom.xml file, a Main.java file, and an example tool. + +```bash +kagent mcp init java [project-name] [flags] +``` + +**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 +- `--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 +- `--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-python.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-python.md new file mode 100644 index 00000000..346dfc62 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-python.md @@ -0,0 +1,34 @@ +--- +title: kagent mcp init python +description: Initialize a new Python MCP server project. +weight: 330 +--- + +Initialize a new MCP server project using the fastmcp-python framework. + +This command will create a new directory with a basic fastmcp-python project structure, +including a pyproject.toml file, a main.py file, and an example tool. + +```bash +kagent mcp init python [project-name] [flags] +``` + +**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 +- `--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 +- `--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-typescript.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-typescript.md new file mode 100644 index 00000000..66d93fc3 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-init-typescript.md @@ -0,0 +1,34 @@ +--- +title: kagent mcp init typescript +description: Initialize a new TypeScript MCP server project. +weight: 340 +--- + +Initialize a new MCP server project using the TypeScript MCP framework. + +This command will create a new directory with a basic TypeScript MCP project structure, +including a package.json file, a tsconfig.json file, and an example tool. + +```bash +kagent mcp init typescript [project-name] [flags] +``` + +**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 +- `--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 +- `--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/1.x/reference/cli/kagent-mcp-run.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-run.md new file mode 100644 index 00000000..edb1fa14 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-run.md @@ -0,0 +1,48 @@ +--- +title: kagent mcp run +description: Run MCP server locally. +weight: 350 +--- + +Run an MCP server locally using the Model Context Protocol inspector. + +By default, this command will: +1. Load the manifest.yaml configuration from the project directory +2. Determine the framework type and create the appropriate mcp inspector configuration +3. Launch the MCP inspector and select STDIO as the transport type, the server will start when you click "Connect" + +If you want to run the server directly without the inspector, use the --no-inspector flag. +This will execute the server directly using the appropriate framework command. + +Supported frameworks: +- fastmcp-python: Requires uv to be installed +- mcp-go: Requires Go to be installed + +```bash +kagent mcp run [flags] +``` + +**Flags:** +- `-h, --help` - help for run +- `--no-inspector` - Run the server directly without launching the MCP inspector +- `-d, --project-dir string` - Project directory to use (default: current directory) +- `--transport string` - Transport mode (stdio or http) (default "stdio") + +**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 run mcp --project-dir ./my-project # Run with inspector (default) +kagent run mcp --no-inspector # Run server directly without inspector +kagent run mcp --transport http # Run with HTTP transport +``` diff --git a/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets-sync.md b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets-sync.md new file mode 100644 index 00000000..0e06b9b7 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/cli/kagent-mcp-secrets-sync.md @@ -0,0 +1,50 @@ +--- +title: kagent mcp secrets sync +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. + +This command reads a .env file and the project's manifest.yaml file to determine +the correct secret name and namespace for the specified environment. It then +creates or updates the Kubernetes secret directly in the cluster. + +The command will look for a ".env" file in the project root by default. + +```bash +kagent mcp secrets sync [environment] [flags] +``` + +**Flags:** +- `--dry-run` - Output the generated secret YAML instead of applying it +- `--from-file string` - Source .env file to sync from (default ".env") +- `-h, --help` - help for sync +- `-d, --project-dir string` - Project directory (default: current directory) + +**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 +# Sync secrets to the "staging" environment defined in manifest.yaml +kagent mcp secrets sync staging + +# Sync secrets from a custom .env file +kagent mcp secrets sync staging --from-file .env.staging + +# Sync secrets from a specific project directory +kagent mcp secrets sync staging --project-dir ./my-project + +# Perform a dry run to see the generated secret without applying it +kagent mcp secrets sync production --dry-run +``` 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/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/faq.md b/docs-site/content/kagent/1.x/reference/faq.md new file mode 100644 index 00000000..5e102ab7 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/faq.md @@ -0,0 +1,45 @@ +--- +title: Frequently asked questions +linkTitle: FAQs +description: Find answers to common questions about kagent, its core resources, and what changed in the 1.0 release. +weight: 50 +author: kagent.dev +--- + +## How do I get started with kagent? + +Install kagent first, with a {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} provisioned, by following [Install kagent]({{< link path="setup/installation" >}}). Then work through [Your first agent]({{< link path="get-started/your-first-agent" >}}), which applies a Harness and an AgentTemplate and holds a conversation with the AgentInstance that they produce. Those two resources and that conversation are the model that the rest of these docs assume. [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool" >}}) then gives that agent a tool. + +## What makes kagent different from other agent frameworks? + +kagent is declarative and Kubernetes-native. You author an agent's runtime and behavior as custom resources and let the controller reconcile them, rather than writing code that drives a model through each step. Those resources are then governed by the same role-based access control (RBAC), GitOps, and observability as your other workloads. [What is kagent?]({{< link path="about/what-is-kagent" >}}) covers the platform in full. + +## What is the difference between a Harness and an AgentTemplate? + +A {{< gloss "Harness" >}}Harness{{< /gloss >}} defines how an agent is allowed to run: its runtime, workload image, {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}}, snapshot storage, and which templates it accepts. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} defines what an agent does: its model, system prompt, tools, skills, and plugins. Separating the two lets a platform team own the runtime while an application team owns the behavior. Neither resource runs anything on its own, because an agent exists only once a Harness accepts a template. For the full definition of each resource and the fields that it carries, see [Core concepts]({{< link path="about/core-concepts#harness" >}}). + +## Is a Harness the same as 0.x's AgentHarness? + +No. The two share part of a name and nothing else. 0.x's `AgentHarness` provisions OpenClaw or Hermes coding-agent sandboxes, while 1.0's `Harness` governs how any agent is allowed to run. Read `Harness` as a new resource rather than a renamed one. + +## What is an AgentInstance? + +An {{< gloss "AgentInstance" >}}AgentInstance{{< /gloss >}} is one running conversation between a Harness and an AgentTemplate. Unlike those two, it is not a Kubernetes custom resource: kagent's gRPC API creates it, kagent's database tracks it, and an {{< gloss "Actor" >}}Actor{{< /gloss >}} on {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} runs it. One template can back many concurrent instances, each with its own {{< gloss "Transcript" >}}transcript{{< /gloss >}}. + +## How does suspend and resume work? + +Agent conversations are mostly idle, so Agent Substrate does not hold a pod open between turns. When a turn ends, it writes the Actor's memory and filesystem to a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}} and releases the {{< gloss "Worker" >}}Worker{{< /gloss >}} that was hosting it. The next message restores that snapshot onto whichever Worker is free, and the conversation continues where it stopped. [Suspend and resume]({{< link path="substrate-runtime/suspend-and-resume" >}}) covers the lifecycle, what a snapshot captures, and how {{< gloss "Checkpoint" >}}checkpoints{{< /gloss >}} pin one. + +## How is 1.0 different from 0.x? + +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. 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? + +Open an issue on the [kagent GitHub repository](https://github.com/kagent-dev/kagent/issues). For a bug, include your kagent version, the resources that reproduce it, and the controller logs. [Debug]({{< link path="operations/debug#collect-logs" >}}) covers how to collect those. + +## How do I contribute to kagent? + +Start with the [contribution guide](https://github.com/kagent-dev/kagent/blob/main/CONTRIBUTING.md), then open a pull request. [Community and contributing]({{< link path="reference/community" >}}) collects the repository, the roadmap, and the project's Discord. diff --git a/docs-site/content/kagent/1.x/reference/glossary.md b/docs-site/content/kagent/1.x/reference/glossary.md new file mode 100644 index 00000000..c1148257 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/glossary.md @@ -0,0 +1,10 @@ +--- +title: Glossary +description: Look up the kagent and Agent Substrate terms that the rest of the documentation uses. +weight: 90 +author: kagent.dev +--- + +kagent 1.0 introduces vocabulary that the rest of these docs use without re-explaining: the resources you author, the runtime objects that the controller compiles them into, and the Agent Substrate primitives that run them. + +{{< glossary-list >}} diff --git a/docs-site/content/kagent/resources/helm.md b/docs-site/content/kagent/1.x/reference/helm.md similarity index 84% rename from docs-site/content/kagent/resources/helm.md rename to docs-site/content/kagent/1.x/reference/helm.md index 85eadd2f..b8750188 100644 --- a/docs-site/content/kagent/resources/helm.md +++ b/docs-site/content/kagent/1.x/reference/helm.md @@ -1,8 +1,7 @@ --- -title: kagent -linkTitle: Helm Chart Configuration -description: kagent Helm chart configuration reference -weight: 2 +title: Helm reference +description: Look up the configurable values in the kagent Helm chart, including their defaults and types. +weight: 20 author: kagent.dev --- @@ -13,8 +12,7 @@ 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://../tools/grafana-mcp | grafana-mcp | 0.10.0-rc1 | | 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,20 +22,16 @@ A Helm chart for kagent, built with Google ADK | Key | Type | Default | Description | |-----|------|---------|-------------| | annotations | object | `{}` | Additional annotations to add to all Kubernetes deployment resources | -| 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.agentImage.registry | string | `""` | | -| controller.agentImage.repository | string | `"kagent-dev/kagent/app"` | | -| controller.agentImage.tag | string | `""` | | +| controller.agentImage | object | `{"registry":"","repository":"kagent-dev/kagent/golang-adk","tag":""}` | The image used for declarative agents. | | controller.annotations | object | `{}` | Additional annotations to add to the controller Deployment metadata | | controller.auth.mode | string | `"unsecure"` | | | 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.grpc | object | `{"maxMessageBytes":16777216,"reflection":false,"tlsCertFile":"","tlsKeyFile":""}` | gRPC application API settings. Native gRPC, gRPC-Web, MCP, and health share the controller service port. | | controller.image.pullPolicy | string | `""` | | | controller.image.registry | string | `""` | | | controller.image.repository | string | `"kagent-dev/kagent/controller"` | | @@ -62,18 +56,14 @@ 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.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.ateApiServer.namespace | string | `"ate-system"` | | -| controller.substrate.ateApiServer.serviceAccount | string | `"ate-api-server"` | | | controller.substrate.atenetRouterURL | string | `""` | | | controller.substrate.defaultWorkerPool.name | string | `""` | | | controller.substrate.defaultWorkerPool.namespace | string | `""` | | @@ -83,20 +73,23 @@ A Helm chart for kagent, built with Google ADK | 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 | `{"affinity":{},"enabled":true,"image":{"name":"postgres","pullPolicy":"IfNotPresent","registry":"docker.io","repository":"library","tag":"18.6-alpine3.23"},"nodeSelector":{},"podLabels":{},"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":"","tolerations":[]}` | 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.affinity | object | `{}` | [Affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) rules for the bundled PostgreSQL pod. | | 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.nodeSelector | object | `{}` | Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | +| database.postgres.bundled.podLabels | object | `{}` | Additional labels for the bundled PostgreSQL pod template, merged over the global `podLabels` (per-key; component keys win). Selector labels can never be overridden. | | 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. | | database.postgres.bundled.storage | string | `"500Mi"` | PersistentVolumeClaim size for demo PostgreSQL data | | database.postgres.bundled.storageClassName | string | `""` | StorageClass for the PostgreSQL PVC. Defaults to the cluster default when empty. | +| database.postgres.bundled.tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | | database.postgres.pool | object | `{"maxConnIdleTime":"","maxConnLifetime":"","maxConns":null,"minConns":null}` | Optional pgxpool settings. Leave unset/null to keep pgx library defaults (MaxConns≈max(4,NumCPU), MinConns=0, MaxConnIdleTime=30m, MaxConnLifetime=1h). | -| database.postgres.sessionRetentionDays | int | `0` | Hard-delete idle sessions (and cascaded events/tasks/checkpoints/shares) after N days of no activity. Uses session.updated_at as a sliding idle clock (writes refresh it). 0 disables cleanup (default, existing installs unchanged). | | database.postgres.skipMigrations | bool | `false` | Skip running database migrations at controller startup. The controller instead verifies the database is already migrated and fails if it is not. Migrations must be applied out-of-band (e.g. from a CI/CD pipeline) before install/upgrade. | | database.postgres.url | string | `""` | External PostgreSQL connection string. Is always used if set regardless of the `.bundled.enabled` field. | | database.postgres.urlFile | string | `""` | Path to a file containing the database URL. Takes precedence over url when set. Is always used if set regardless of the `.bundled.enabled` field. | @@ -152,16 +145,18 @@ A Helm chart for kagent, built with Google ADK | oauth2-proxy.extraArgs.redirect-url | string | `"$(OIDC_REDIRECT_URL)"` | | | oauth2-proxy.extraArgs.scope | string | `"openid profile email groups"` | | | oauth2-proxy.extraArgs.set-authorization-header | bool | `true` | | -| oauth2-proxy.extraArgs.skip-auth-regex | string | `"^/(login|_next/static|_next/image|login-bg\\.(jpg|png|webp)|logo-.*\\.png|favicon\\.ico|api/agentharnesses/.*/gateway).*$"` | | +| oauth2-proxy.extraArgs.skip-auth-regex | string | `"^/(login|assets/|env-config\\.js|logo-.*\\.png|favicon\\.ico).*$"` | | | 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` | | @@ -209,31 +204,18 @@ 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 | | substrate.enabled | bool | `false` | | -| substrateWorkerPool | object | `{"ateomImage":"","create":false,"labels":{},"name":"kagent-default","replicas":1,"sandboxClass":"gvisor","template":{}}` | Optional Agent Substrate WorkerPool installed by this chart. This is platform capacity and is not owned by individual AgentHarness resources. | +| substrateWorkerPool | object | `{"create":false,"labels":{},"name":"kagent-default","replicas":1,"sandboxClass":"gvisor","template":{},"workerImage":""}` | Optional Agent Substrate WorkerPool installed by this chart. This is platform capacity and is not owned by individual agents. | | tag | string | `""` | | | tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | -| ui.additionalForwardedHeaders | list | `[]` | Additional request headers (beyond Authorization) the UI proxy will forward to the backend. Names are case-insensitive. Hop-by-hop headers (Connection, Transfer-Encoding, etc.) are silently dropped. | +| ui.additionalForwardedHeaders | list | `[]` | Identity headers the UI's nginx proxy will forward to the backend on /api/ and /a2a/. Names are case-insensitive. Authorization is always forwarded; the auth-proxy identity headers (x-auth-request-*, x-forwarded-user, x-forwarded-email, x-forwarded-groups, x-forwarded-preferred-username) are stripped from client requests unless listed here, so a caller cannot spoof an identity the backend trusts. Headers outside that set are forwarded by nginx as normal. | | 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.env | list | `[]` | Extra environment variables for the UI container: a list of `{name, value}` entries, spliced into its `env:` verbatim. An installed app extension's own settings go here, named `EXTENSION_*`; the container's startup script copies those onto `window.environmentVariables` for the browser to read. | | 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. | | ui.httpRoute | object | `{"annotations":{},"enabled":false,"hostnames":[],"labels":{},"parentRefs":[],"rules":[]}` | Gateway API `HTTPRoute` for the UI. Requires the Gateway API CRDs (`gateway.networking.k8s.io/v1`) and an existing `Gateway` to attach to via `parentRefs`. Disabled by default; enable to front the UI with a Gateway API implementation (kgateway, Istio, Envoy Gateway, etc.) instead of the OpenShift Route or bundled oauth2-proxy. | | ui.httpRoute.annotations | object | `{}` | Annotations to add to the `HTTPRoute`. | @@ -260,7 +242,7 @@ A Helm chart for kagent, built with Google ADK | ui.podAnnotations | object | `{}` | | | ui.podLabels | object | `{}` | Additional labels for the UI pod template, merged over the global `podLabels` (per-key; component keys win). Selector labels can never be overridden. | | ui.podSecurityContext | object | (uses global podSecurityContext) | Pod-level security context for the UI pod. Overrides the global podSecurityContext. | -| ui.publicBackendUrl | string | `"/api"` | | +| ui.publicBackendUrl | string | `"/api"` | Base URL the browser calls the controller API on. Reaches the browser at runtime as the `apiBaseUrl` key of /config.json, which the app fetches on startup — it is deliberately not baked into the bundle, so changing it here takes effect on pod restart rather than requiring an image rebuild. The default is a path on the UI's own hostname, which nginx proxies to the controller; set an absolute URL only if the browser must reach the API somewhere other than the UI origin. | | ui.readinessProbe | object | httpGet /health on port http, periodSeconds=30 | Custom readiness probe for the UI container. Override to adjust thresholds, use exec-based probes, or change the health path. | | ui.replicas | int | `1` | | | ui.resources.limits.cpu | string | `"1000m"` | | @@ -279,6 +261,5 @@ A Helm chart for kagent, built with Google ADK | ui.streamTimeoutSeconds | int | `1800` | Client-side chat stream inactivity timeout (seconds). The browser aborts a streaming response if no event is received within this window. Should be >= ui.nginx.proxyReadTimeout so nginx isn't the silent limit. Default 1800 (30m). | | ui.tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). | | ui.topologySpreadConstraints | list | `[]` | [Topology spread constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#pod-topology-spread-constraints) for the UI pod. | -| ui.volumes | object | `{"nextjsCache":"100Mi","tmp":"50Mi"}` | EmptyDir volume sizes for Next.js UI workload (typically used when enabling readOnlyRootFilesystem) | -| ui.volumes.nextjsCache | string | `"100Mi"` | Size limit for Next.js build cache (.next/cache). Default 100Mi is sufficient for typical Next.js apps with moderate caching needs. | -| ui.volumes.tmp | string | `"50Mi"` | Size limit for temporary files (/tmp). Default 50Mi provides ample space for Next.js runtime temporary data. | +| ui.volumes | object | `{"tmp":"50Mi"}` | EmptyDir volume sizes for the UI workload (typically used when enabling readOnlyRootFilesystem) | +| ui.volumes.tmp | string | `"50Mi"` | Size limit for temporary files (/tmp). Holds the nginx temp directories and the generated config.json. Default 50Mi is ample for both. | diff --git a/docs-site/content/kagent/1.x/reference/tools-ecosystem.md b/docs-site/content/kagent/1.x/reference/tools-ecosystem.md new file mode 100644 index 00000000..aabfe976 --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/tools-ecosystem.md @@ -0,0 +1,308 @@ +--- +title: Tools ecosystem +description: Look up the MCP servers that a kagent installation ships with, the tools that each one serves, and the community servers that you can add. +weight: 40 +author: kagent.dev +--- + +A kagent installation ships with two {{< gloss "Model Context Protocol" >}}Model Context Protocol{{< /gloss >}} (MCP) servers already registered, and you can register more of your own. This page is the catalog: what is installed, what each server serves, and how to narrow the set. For the schema that binds a server to an agent, see [About tools]({{< link path="skills-and-mcp/about-tools#mcp-tools" >}}). + +## Servers that a kagent installation registers + +Both servers arrive as subcharts of the kagent chart, and each one creates its own {{< gloss "RemoteMCPServer" >}}RemoteMCPServer{{< /gloss >}} in the kagent namespace. Neither is bound to an agent for you, so an agent reaches a server's tools only through a {{< gloss "Tool binding" >}}tool binding{{< /gloss >}} that you add to its {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}}. + +| RemoteMCPServer | Helm value | Serves | +| --------------- | ---------- | ------ | +| [`kagent-tool-server`](#kagent-tool-server) | `kagent-tools.enabled` | 124 tools for Kubernetes, Helm, Istio, Cilium, Argo Rollouts, Prometheus, and Kubescape. | +| [`kagent-grafana-mcp`](#kagent-grafana-mcp) | `grafana-mcp.enabled` | Grafana's own MCP server, for dashboards, data sources, alerts, Loki logs, and incidents. | + +The kagent release pins the `kagent-tool-server` version, which is currently {{< reuse "kagent-docs/versions/kagent-tools.md" >}}. For the full set of pinned component versions, see [Version support]({{< link path="reference/versions#what-a-kagent-release-includes" >}}). + +## Read the tools that a server serves + +The controller connects to each RemoteMCPServer, asks it what it serves, and records the answer in `status.discoveredTools`. That status reports the server that your cluster actually runs, so it is more reliable than any list on this page. + +```sh +kubectl get remotemcpserver kagent-tool-server -n kagent \ + -o jsonpath='{range .status.discoveredTools[*]}{.name}{"\t"}{.description}{"\n"}{end}' +``` + +[Your first MCP tool]({{< link path="get-started/your-first-mcp-tool#bind-the-tool-to-your-agenttemplate" >}}) runs the same command as the first step of binding one of these tools to an agent. + +> [!NOTE] +> `status.discoveredTools` stays empty until the controller completes a discovery pass, and `status.observedGeneration` tells you whether the recorded set matches the current spec. A server whose `Accepted` condition is not `True` has not been reached at all. + +## kagent-tool-server + +One Go binary serves every tool in this section, grouped into eight providers. A provider's tools shell out to the matching command line tool inside the server's own container, so the Kubernetes, Helm, Istio, and Cilium providers act on your cluster with the server's ServiceAccount rather than with the caller's credentials. + +Tools marked `*` perform write operations, and `--read-only` skips them at registration. The following sections list each provider's tools by the name that an agent sees. + +### Kubernetes + +Agents use the Kubernetes provider the most, and it covers both inspection and modification of any resource that `kubectl` can reach. + +| Tool | Description | +| ---- | ----------- | +| `k8s_get_resources` | Get Kubernetes resources using kubectl. | +| `k8s_describe_resource` | Describe a Kubernetes resource in detail. | +| `k8s_get_resource_yaml` | Get the YAML representation of a Kubernetes resource. | +| `k8s_get_pod_logs` | Get logs from a Kubernetes pod. | +| `k8s_get_events` | Get events from a Kubernetes namespace. | +| `k8s_get_available_api_resources` | Get available Kubernetes API resources. | +| `k8s_get_cluster_configuration` | Get cluster configuration details. | +| `k8s_generate_resource` | Generate a Kubernetes resource YAML from a description. | +| `k8s_apply_manifest` * | Apply a YAML manifest to the Kubernetes cluster. | +| `k8s_create_resource` * | Create a Kubernetes resource from YAML content. | +| `k8s_create_resource_from_url` * | Create a Kubernetes resource from a URL that points to a YAML manifest. | +| `k8s_patch_resource` * | Patch a Kubernetes resource using a strategic merge patch. | +| `k8s_patch_status` * | Patch the status of a Kubernetes resource. | +| `k8s_delete_resource` * | Delete a Kubernetes resource. | +| `k8s_scale` * | Scale a Kubernetes deployment. | +| `k8s_rollout` * | Perform rollout operations on Kubernetes resources, including history, pause, restart, resume, status, and undo. | +| `k8s_label_resource` * | Add or update labels on a Kubernetes resource. | +| `k8s_remove_label` * | Remove a label from a Kubernetes resource. | +| `k8s_annotate_resource` * | Add or update annotations on a Kubernetes resource. | +| `k8s_remove_annotation` * | Remove an annotation from a Kubernetes resource. | +| `k8s_execute_command` * | Execute a command in a Kubernetes pod. | +| `k8s_check_service_connectivity` * | Check connectivity to a service using a temporary curl pod. | + +### Helm + +The Helm provider manages releases and chart repositories with the Helm configuration inside the server's container, so a repository that one tool adds is available to the others. + +| Tool | Description | +| ---- | ----------- | +| `helm_list_releases` | List Helm releases in a namespace. | +| `helm_get_release` | Get extended information about a Helm release. | +| `helm_repo_update` | Update information about available charts locally from chart repositories. | +| `helm_upgrade` * | Upgrade or install a Helm release. | +| `helm_uninstall` * | Uninstall a Helm release. | +| `helm_repo_add` * | Add a Helm repository. | + +### Istio + +Istio's tools wrap `istioctl`, and most of them read mesh state rather than change it. Waypoint management is the exception, as generating a waypoint resource and applying it are separate tools. + +| Tool | Description | +| ---- | ----------- | +| `istio_proxy_status` | Get Envoy proxy status for pods, which retrieves the last sent and acknowledged xDS sync from Istiod to each Envoy in the mesh. | +| `istio_proxy_config` | Get the proxy configuration for a single pod. | +| `istio_analyze_cluster_configuration` | Analyze Istio cluster configuration for issues. | +| `istio_version` | Get Istio version information. | +| `istio_remote_clusters` | List remote clusters that are registered with Istio. | +| `istio_generate_manifest` | Generate an Istio manifest for a given profile. | +| `istio_list_waypoints` | List all waypoints in the mesh. | +| `istio_generate_waypoint` | Generate a waypoint resource YAML. | +| `istio_waypoint_status` | Get the status of a waypoint resource. | +| `istio_ztunnel_config` | Get the ztunnel configuration for a namespace. | +| `istio_install_istio` * | Install Istio with a specified configuration profile. | +| `istio_apply_waypoint` * | Apply a waypoint resource to the cluster. | +| `istio_delete_waypoint` * | Delete a waypoint resource from the cluster. | + +### Argo Rollouts + +Argo Rollouts tools cover progressive delivery. A rollout tool fails confusingly when the controller or one of its plugins is missing, so four of the eight tools verify the installation instead of acting on a rollout. + +| Tool | Description | +| ---- | ----------- | +| `argo_rollouts_list` | List rollouts or experiments. | +| `argo_verify_argo_rollouts_controller_install` | Verify that the Argo Rollouts controller is installed and running. | +| `argo_verify_kubectl_plugin_install` | Verify that the kubectl Argo Rollouts plugin is installed. | +| `argo_check_plugin_logs` | Check the logs of the Argo Rollouts Gateway API plugin. | +| `argo_promote_rollout` * | Promote a paused rollout to the next step. | +| `argo_pause_rollout` * | Pause a rollout. | +| `argo_set_rollout_image` * | Set the image of a rollout. | +| `argo_verify_gateway_plugin` * | Verify the installation status of the Argo Rollouts Gateway API plugin. | + +### Cilium + +Cilium is the largest provider, with 58 tools ranging from installation to individual BPF maps. An agent that can see every tool spends its context on tool descriptions, so bind only the handful that an agent needs rather than the whole provider. + +| Tool | Description | +| ---- | ----------- | +| `cilium_status_and_version` | Get the status and version of the Cilium installation. | +| `cilium_get_daemon_status` | Get the status of the Cilium daemon for the cluster. | +| `cilium_show_features_status` | Show Cilium features status. | +| `cilium_show_configuration_options` | Show Cilium configuration options. | +| `cilium_request_debugging_information` | Request debugging information for the cluster. | +| `cilium_get_endpoints_list` | Get the list of all endpoints in the cluster. | +| `cilium_get_endpoint_details` | List the details of an endpoint in the cluster. | +| `cilium_get_endpoint_logs` | Get the logs of an endpoint in the cluster. | +| `cilium_get_endpoint_health` | Get the health of an endpoint in the cluster. | +| `cilium_list_identities` | List all identities in the cluster. | +| `cilium_get_identity_details` | Get the details of an identity in the cluster. | +| `cilium_list_services` | List services for the cluster. | +| `cilium_get_service_information` | Get information about a service in the cluster. | +| `cilium_validate_cilium_network_policies` | Validate Cilium network policies for the cluster. | +| `cilium_display_policy_node_information` | Display policy node information for the cluster. | +| `cilium_display_selectors` | Display selectors for the cluster. | +| `cilium_list_local_redirect_policies` | List local redirect policies for the cluster. | +| `cilium_show_cluster_mesh_status` | Show cluster mesh status. | +| `cilium_list_bgp_peers` | List BGP peers. | +| `cilium_list_bgp_routes` | List BGP routes. | +| `cilium_list_cluster_nodes` | List cluster nodes for the cluster. | +| `cilium_list_node_ids` | List node IDs for the cluster. | +| `cilium_list_ip_addresses` | List the IP addresses for the cluster. | +| `cilium_show_ip_cache_information` | Show the IP cache information for the cluster. | +| `cilium_show_dns_names` | Show the DNS names for the cluster. | +| `cilium_fqdn_cache` | Manage the FQDN cache for the cluster. | +| `cilium_display_encryption_state` | Display the encryption state for the cluster. | +| `cilium_list_envoy_config` | List the Envoy configuration for a resource in the cluster. | +| `cilium_show_load_information` | Show load information for the cluster. | +| `cilium_list_metrics` | List metrics for the cluster. | +| `cilium_list_bpf_maps` | List BPF maps for the cluster. | +| `cilium_get_bpf_map` | Get a BPF map for the cluster. | +| `cilium_list_bpf_map_events` | List BPF map events for the cluster. | +| `cilium_list_xdp_cidr_filters` | List XDP CIDR filters for the cluster. | +| `cilium_get_kv_store_key` | Get a key from the kvstore for the cluster. | +| `cilium_list_pcap_recorders` | List PCAP recorders for the cluster. | +| `cilium_get_pcap_recorder` | Get a PCAP recorder for the cluster. | +| `cilium_install_cilium` * | Install Cilium on the cluster. | +| `cilium_upgrade_cilium` * | Upgrade Cilium on the cluster. | +| `cilium_uninstall_cilium` * | Uninstall Cilium from the cluster. | +| `cilium_toggle_configuration_option` * | Toggle a Cilium configuration option. | +| `cilium_toggle_hubble` * | Enable or disable Hubble. | +| `cilium_toggle_cluster_mesh` * | Enable or disable cluster mesh. | +| `cilium_connect_to_remote_cluster` * | Connect to a remote cluster for cluster mesh. | +| `cilium_disconnect_remote_cluster` * | Disconnect from a remote cluster. | +| `cilium_manage_endpoint_labels` * | Add or delete the labels of an endpoint in the cluster. | +| `cilium_manage_endpoint_config` * | Manage the configuration of an endpoint in the cluster. | +| `cilium_disconnect_endpoint` * | Disconnect an endpoint from the network. | +| `cilium_update_service` * | Update a service in the cluster. | +| `cilium_delete_service` * | Delete a service from the cluster. | +| `cilium_delete_policy_rules` * | Delete policy rules for the cluster. | +| `cilium_update_xdp_cidr_filters` * | Update XDP CIDR filters for the cluster. | +| `cilium_delete_xdp_cidr_filters` * | Delete XDP CIDR filters for the cluster. | +| `cilium_set_kv_store_key` * | Set a key in the kvstore for the cluster. | +| `cilium_delete_key_from_kv_store` * | Delete a key from the kvstore for the cluster. | +| `cilium_flush_ipsec_state` * | Flush the IPsec state for the cluster. | +| `cilium_update_pcap_recorder` * | Update a PCAP recorder for the cluster. | +| `cilium_delete_pcap_recorder` * | Delete a PCAP recorder for the cluster. | + +### Prometheus + +The Prometheus provider queries a Prometheus server directly. Each tool takes the server's URL as an argument and defaults to `http://localhost:9090`, which does not resolve from inside the tool server's container, so have the agent pass the in-cluster address. + +| Tool | Description | +| ---- | ----------- | +| `prometheus_query_tool` | Execute a PromQL query against Prometheus. | +| `prometheus_query_range_tool` | Execute a PromQL range query against Prometheus. | +| `prometheus_label_names_tool` | Get all available labels from Prometheus. | +| `prometheus_targets_tool` | Get all Prometheus targets and their status. | +| `prometheus_promql_tool` | Generate a PromQL query. | + +### Kubescape + +Kubescape's tools read scan results that the Kubescape operator has already produced, so they return nothing useful until that operator is installed and has completed a scan. Start with `kubescape_check_health`, which reports whether the rest of the provider can work. + +| Tool | Description | +| ---- | ----------- | +| `kubescape_check_health` | Check whether the Kubescape operator is installed and operational, by verifying the namespace, operator pods, storage pods, CRDs, and scan data availability. | +| `kubescape_list_vulnerability_manifests` | List vulnerability manifests from the Kubescape operator, at image or workload level. | +| `kubescape_list_vulnerabilities` | List all CVEs in a specific vulnerability manifest, with a severity summary. | +| `kubescape_get_vulnerability_details` | Get details about a specific CVE in a vulnerability manifest, including affected packages and fix information. | +| `kubescape_list_configuration_scans` | List configuration security scan results, which show the workloads that have been scanned for misconfigurations. | +| `kubescape_get_configuration_scan` | Get configuration security scan results for a specific workload, including failed controls and remediation guidance. | +| `kubescape_list_application_profiles` | List the ApplicationProfiles that capture the runtime behavior of workloads. | +| `kubescape_get_application_profile` | Get the runtime behavior profile for a specific workload, including the processes that run and the files that are accessed. | +| `kubescape_list_network_neighborhoods` | List the NetworkNeighborhoods that record the observed network communication patterns of workloads. | +| `kubescape_get_network_neighborhood` | Get the observed ingress and egress connections for a specific workload. | + +### Utilities + +Two tools sit outside any product. `shell` runs an arbitrary command in the server's container with the server's ServiceAccount, so treat it as the widest permission that this server grants. + +| Tool | Description | +| ---- | ----------- | +| `datetime_get_current_time` | Return the current date and time in ISO 8601 format. | +| `shell` * | Execute shell commands. | + +## Narrow what kagent-tool-server serves + +Serving all 124 tools costs an agent context on every turn, and it grants the server broad authority over your cluster. Two independent settings narrow it, and each one acts at a different layer. + +```yaml +kagent-tools: + tools: + enabledTools: + - k8s + - helm + args: + - "--read-only" + rbac: + readOnly: true + additionalRules: + - apiGroups: ["networking.istio.io"] + resources: ["virtualservices", "destinationrules", "gateways"] + verbs: ["get", "list", "watch"] +``` + +| Field | Description | +| ----- | ----------- | +| `tools.enabledTools` | The providers to register, from `k8s`, `helm`, `istio`, `cilium`, `argo`, `prometheus`, `kubescape`, and `utils`. Omit or leave empty to register every provider. | +| `tools.args` | Extra command line arguments for the server. Add `--read-only` here to skip the write tools that this page marks with `*`. | +| `rbac.readOnly` | Binds the server's ServiceAccount to a read-only ClusterRole of `get`, `list`, and `watch` instead of `cluster-admin`. Defaults to `false`. | +| `rbac.allowSecrets` | Applies only where `rbac.readOnly` is `true`, and grants the read-only ClusterRole read access to Secrets. Defaults to `false`. | +| `rbac.additionalRules` | Applies only where `rbac.readOnly` is `true`. Extra rules to append to the read-only ClusterRole, for the CRDs that the Istio, Cilium, and Argo providers read. | + +> [!IMPORTANT] +> `--read-only` and `rbac.readOnly` are separate controls, and setting only one leaves a gap. `--read-only` stops the write tools from being registered, so an agent cannot call them. `rbac.readOnly` removes the cluster permissions that back them. Set only the flag, and the ServiceAccount keeps `cluster-admin`, which anything else in the container can still use. Set only the RBAC value, and the write tools stay in the catalog and fail at call time with permission errors that the agent then tries to work around. + +Because the settings are per-installation, they change what every agent sees. To give one agent a smaller set while leaving the server intact, list the tools on the tool binding instead, as described in [About tools]({{< link path="skills-and-mcp/about-tools#mcp-tools" >}}). + +> [!WARNING] +> A tool binding's tool list does not narrow anything on the Claude {{< gloss "Harness" >}}Harness{{< /gloss >}}. The compiler exposes the whole server instead, and names the tools that you selected in a warning on the AgentTemplate's `status.harnesses[].warnings`. The kagent and Codex harnesses both honor the list. Where an agent runs on the Claude harness and must not reach a tool, narrow the server with `tools.enabledTools` or `--read-only` rather than with the binding. + +## kagent-grafana-mcp + +The `kagent-grafana-mcp` server runs [mcp-grafana](https://github.com/grafana/mcp-grafana), Grafana's own MCP server. The kagent chart packages it as a subchart. Its tools fall into four groups: + +- Grafana dashboards, data sources, and alert rules. +- PromQL queries against Grafana's Prometheus data sources. +- LogQL queries against Loki. +- Grafana incidents and on-call schedules. + +Set the Grafana instance that the server queries, along with its credentials, at install time. + +```yaml +grafana-mcp: + enabled: true + grafana: + url: "grafana.kagent:3000/api" + serviceAccountToken: "" +``` + +| Field | Description | +| ----- | ----------- | +| `grafana.url` | The Grafana API endpoint that the server queries. Defaults to `grafana.kagent:3000/api`, which matches the Grafana instance in `contrib/addons/grafana.yaml`. | +| `grafana.serviceAccountToken` | A Grafana service account token. Empty by default, so the server starts and answers discovery while every tool call fails until you supply a token. | +| `grafana.secretRef` | The name of an existing Secret that holds `GRAFANA_SERVICE_ACCOUNT_TOKEN`. Use this instead of `serviceAccountToken` to keep the token out of your Helm values. | + +> [!NOTE] +> Upstream publishes no tag other than `latest`, so this subchart tracks the `mcp/grafana:latest` image on Docker Hub. A kagent release therefore does not pin which tools this server serves, and the set can change without a kagent upgrade. Read `status.discoveredTools` on `kagent-grafana-mcp` for the tools that your installation has, rather than relying on a published list. + +## Community and contributed servers + +kagent's repository carries example servers in [contrib/tools](https://github.com/kagent-dev/kagent/tree/main/contrib/tools). Each one is a starting point rather than a supported component, and their manifests were written against different kagent API versions, so check the `apiVersion` before you apply one. + +| Server | Ready to apply | Description | +| ------ | -------------- | ----------- | +| [k8sgpt](https://github.com/kagent-dev/kagent/tree/main/contrib/tools/k8sgpt-mcp-server) | Yes | K8sGPT integration, for diagnosing cluster problems. Declares `RemoteMCPServer` on `kagent.dev/v1alpha3`. | +| [server-everything](https://github.com/kagent-dev/kagent/tree/main/contrib/tools/server-everything) | Yes | The MCP reference server, useful for testing a binding end to end. Declares `RemoteMCPServer` on `kagent.dev/v1alpha3`. | +| [GitHub MCP Server](https://github.com/kagent-dev/kagent/tree/main/contrib/tools/github-mcp-server) | No | Tools for issues, pull requests, repositories, and actions. Its chart still declares the removed `ToolServer` kind. | +| [mcp-grafana](https://github.com/kagent-dev/kagent/tree/main/contrib/tools/mcp-grafana) | No | Superseded by the `grafana-mcp` subchart that a kagent installation already registers. Its chart still declares the removed `ToolServer` kind. | +| [context7](https://github.com/kagent-dev/kagent/blob/main/contrib/tools/context7.mcp.yaml) | No | Documentation lookup over stdio. Both the `ToolServer` kind and the stdio transport were removed. | + +To register any other MCP server, write a RemoteMCPServer that points at its URL. [Your first MCP tool]({{< link path="get-started/your-first-mcp-tool#bind-your-own-mcp-server" >}}) works through a complete example. + +> [!NOTE] +> A RemoteMCPServer takes a URL, so kagent connects only to servers that speak streamable HTTP or Server-Sent Events (SSE). To reach a server that runs over stdio, wrap it in a deployment that exposes an HTTP endpoint. [kmcp](/docs/kmcp/) builds and runs such servers. + +## Next steps + +{{< cards >}} + {{< card link=`{{< link path="skills-and-mcp/about-tools#mcp-tools" >}}` title="About tools" subtitle="Bind a server's tools to an AgentTemplate, and read the rules that a binding must satisfy." >}} + {{< card link=`{{< link path="agents/human-in-the-loop#require-approval-for-a-tool" >}}` title="Human in the loop" subtitle="Pause an agent for a person's approval before a tool runs." >}} + {{< card link=`{{< link path="skills-and-mcp/skills" >}}` title="Skills" subtitle="Give your agent reusable instructions instead of another tool." >}} +{{< /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..6cad101d --- /dev/null +++ b/docs-site/content/kagent/1.x/reference/versions.md @@ -0,0 +1,49 @@ +--- +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 from 0.x]({{< link path="operations/upgrade-from-0x#in-place-upgrade-blockers" >}}). + + 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..cd851cf4 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/installation.md @@ -0,0 +1,276 @@ +--- +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. Install Agent Substrate first, because the kagent controller connects to it at startup. + +> [!NOTE] +> These steps install kagent 1.0 fresh. kagent 1.0 has no in-place upgrade from the 0.10.x version line, and installing its custom resource definitions replaces the ones that a 0.10.x installation uses. To move an existing installation, start with [Upgrade from 0.x]({{< link path="operations/upgrade-from-0x#in-place-upgrade-blockers" >}}). + +## Before you begin + +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. + ```bash + curl -fsSL -o kubectl-ate \ + "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 + ``` + +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" + ``` + +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](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=- < [!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 %}} + {{< /tabs >}} + +## Install Agent Substrate + +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 "kagent-docs/versions/agent-substrate.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 create the identity material in the following steps. + ```bash + helm upgrade --install substrate \ + oci://ghcr.io/kagent-dev/substrate/helm/substrate \ + --version {{< reuse "kagent-docs/versions/agent-substrate.md" >}} \ + --namespace ate-system + ``` + +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 \ + --secret-namespace=podcertificate-controller-system + kubectl ate admin make-ca-pool --ca-id=1 \ + --name=pod-identity-ca-pool \ + --secret-namespace=podcertificate-controller-system + ``` + +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 \ + --secret-namespace=ate-system + kubectl ate admin make-ca-pool --ca-id=1 \ + --name=actor-id-ca-pool \ + --secret-namespace=ate-system + ``` + +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 \ + | 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}" + ``` + +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 + 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 + ' + ``` + +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 "kagent-docs/versions/agent-substrate.md" >}} \ + --namespace ate-system --reuse-values --wait --timeout 10m + ``` + +8. 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 2/2 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. 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. + +1. Install the kagent CRDs. + ```bash + helm upgrade --install kagent-crds \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ + --namespace kagent --create-namespace --wait + ``` + +2. Install kagent with the Agent Substrate integration enabled. + ```bash + helm upgrade --install kagent \ + oci://ghcr.io/kagent-dev/kagent/helm/kagent \ + --version {{< reuse "kagent-docs/versions/kagent.md" >}} \ + --namespace kagent --create-namespace --timeout 10m \ + -f - <}}" + EOF + ``` + > [!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 + ``` + +> [!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 indicates 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-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. + ```bash + kubectl get workerpools -n kagent + ``` + Example output: + ```console + 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. + {{< tabs >}} + {{% tab name="Port-forward for local testing" %}} + 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 8083:8083 + ``` + {{% /tab %}} + {{% tab name="Cloud Provider LoadBalancer" %}} + 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']}" + ``` + {{% /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/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/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..5449a339 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/about-model-providers.md @@ -0,0 +1,59 @@ +--- +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. To use a different provider, a different model, or a different set of credentials, create additional ModelConfigs. + +## 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, 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 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 + +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 + +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..1cc57126 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/amazon-bedrock.md @@ -0,0 +1,126 @@ +--- +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. 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" >}}). + +> [!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..3958d33c --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/anthropic.md @@ -0,0 +1,77 @@ +--- +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. + +> [!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 + +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..78f1f0d7 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/azure-ai-foundry.md @@ -0,0 +1,141 @@ +--- +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 must 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 +``` + +## 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 | +| ------- | ----- | +| 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..773bbdb4 --- /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..6209ffc2 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/google-vertexai.md @@ -0,0 +1,86 @@ +--- +title: Google Vertex AI +description: Configure kagent to use Claude models through Google Cloud Vertex AI on a Claude harness. +weight: 20 +author: kagent.dev +--- + +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. + +| Provider | Harness runtime | Supported | +| -------- | --------------- | --------- | +| `AnthropicVertexAI` | `claude` | Yes | +| `AnthropicVertexAI` | `kagent` or `byo` | No | +| `GeminiVertexAI` | any | No | + +For the full provider matrix across all four runtimes, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). + +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. + +## Claude models on a Claude harness + +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 + ``` + +2. Create a `ModelConfig` that uses the `AnthropicVertexAI` provider. + ```yaml + kubectl apply -f - <}}). + +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 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 + +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 + +{{< 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..c26d1fb5 --- /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 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 + +{{< 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..93c725c4 --- /dev/null +++ b/docs-site/content/kagent/1.x/setup/model-providers/openai.md @@ -0,0 +1,88 @@ +--- +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. + +> [!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 + +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. For the full list of configurations that this affects, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}). + +## 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..10ace7aa --- /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 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 \ + --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 >}} 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..da14a380 --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/_index.md @@ -0,0 +1,6 @@ +--- +title: Skills and MCP +description: Give an agent capabilities through skills and Model Context Protocol tools. +weight: 50 +author: kagent.dev +--- \ No newline at end of file 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..beebb4b4 --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/about-tools.md @@ -0,0 +1,87 @@ +--- +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 **{{< 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. + +Both kinds resolve within the AgentTemplate's own namespace, so a binding cannot reach a server or a template in another namespace. + +## MCP tools + +An `mcp` binding names a server, and optionally the tools to take from it. On the kagent and Codex harnesses, listing tools narrows the binding to those tools. Omitting the list, or leaving it empty, exposes every tool that the server offers. + +```yaml +tools: + - mcp: + server: + kind: RemoteMCPServer + name: my-mcp-server + tools: + - search_docs + - fetch_page + requireApproval: true +``` + +| 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` | Optional. The names of the tools to bind, up to 50. Duplicates are collapsed. An omitted or empty list exposes every tool on the server, and so does any list on the Claude harness. | +| `mcp.requireApproval` | Optional. Pauses the agent for a person's approval before each call to a tool that this binding exposes. Omit to run the bound tools without approval. For more information, see [Human in the loop]({{< link path="agents/human-in-the-loop#require-approval-for-a-tool" >}}). | + +> [!WARNING] +> **The Claude {{< gloss "Harness" >}}Harness{{< /gloss >}} ignores `mcp.tools` and exposes the whole server.** Claude's MCP configuration has no per-tool allowlist, so kagent cannot narrow a server there. The compiler records the tools that you selected in a warning on the AgentTemplate's `status.harnesses[].warnings` and then admits the {{< gloss "Revision" >}}revision{{< /gloss >}} anyway, so the agent becomes ready with every tool that the server serves. Read the warning after you bind a server: +> +> ```sh +> kubectl get agenttemplate -n \ +> -o jsonpath='{range .status.harnesses[*]}{.harness}{": "}{.warnings}{"\n"}{end}' +> ``` +> +> Where an agent on the Claude harness must not reach a tool, narrow the server rather than the binding. Set `requireApproval: true`, which does apply on this harness and pauses every call to the server, or give the agent its own RemoteMCPServer that serves only the tools you intend. For the bundled tool server, see the installation-level settings that drop providers and write tools in [Tools ecosystem]({{< link path="reference/tools-ecosystem#narrow-what-kagent-tool-server-serves" >}}). + +## 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 {{< 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. +- **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 must 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 new file mode 100644 index 00000000..41ed0f4d --- /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 **{{< 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 + +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, 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. + +| 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` | 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. + +- 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 new file mode 100644 index 00000000..f02668a8 --- /dev/null +++ b/docs-site/content/kagent/1.x/skills-and-mcp/skills.md @@ -0,0 +1,71 @@ +--- +title: Skills +description: Package instructions and supporting files as skills, and attach them to an AgentTemplate. +weight: 20 +author: kagent.dev +--- + +A **{{< gloss "Skill" >}}skill{{< /gloss >}}** packages a piece of know-how that an agent can pick up: a set of instructions, together with whatever scripts or reference files those instructions depend on. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} attaches skills by naming where each one comes from, and kagent fetches them and places them where the agent runtime can find them. + +## About + +A skill is a directory whose root holds a `SKILL.md` file. That file carries front matter naming the skill and describing what it is for, followed by the instructions themselves. + +The description makes a skill usable. When an agent starts, the runtime reads the front matter of every skill that is attached to it, and offers those skills to the model as tools that it can call. The model chooses a skill from its description, in the same way that it chooses any other tool. This means that a description that states plainly when to use the skill matters more than the length of the instructions behind it. + +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 {{< gloss "Plugin package" >}}plugin package{{< /gloss >}}. + +```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` | 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` | The directory to select inside the artifact, when the content is not at its root. The path must be relative, and it cannot climb out of the artifact with `..` segments. | + +### Plugin allowlist + +Attaching a plugin package does not enable any of the skills that it carries. Only the names listed in `plugins[].skills` are enabled. + +> [!IMPORTANT] +> An empty skills list enables nothing. Adding a plugin package and omitting its `skills` list gives the agent no skills from that package, which is the safe default rather than an error. Listing skills explicitly also means that a package gaining new skills in a later version does not silently grant them to your agent. + +{{< reuse "kagent-docs/snippets/artifact-sources.md" >}} + +## Naming rules + +Skill names are checked before anything is fetched, and two rules apply across every skill on an AgentTemplate. + +- A name must be a single path component. A name containing a slash, or a name of `.` or `..`, is rejected. +- Names must be unique across the whole AgentTemplate. Because standalone skills and plugin skills are mounted into the same place, a standalone skill cannot reuse the name of an enabled plugin skill, and two plugin packages cannot both contribute the same name. + +Plugin package names must also be unique. Two entries in `plugins` whose manifests declare the same name are rejected. Unlike skill names, kagent checks this as each package is fetched, because the name comes from the package's `plugin.json` manifest rather than from your AgentTemplate. 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/identity.md b/docs-site/content/kagent/1.x/substrate-runtime/identity.md new file mode 100644 index 00000000..af417ce5 --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/identity.md @@ -0,0 +1,58 @@ +--- +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 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. 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. + +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. 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..507ee412 --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/sandboxing.md @@ -0,0 +1,96 @@ +--- +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 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 + 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 + +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 {{< 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 {{< gloss "ActorTemplate" >}}ActorTemplates{{< /gloss >}} 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. 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, and kagent names exactly that configuration on every ActorTemplate that it generates. The configuration looks like the following: + +```yaml +apiVersion: ate.dev/v1alpha1 +kind: SandboxConfig +metadata: + name: gvisor-default +spec: + sandboxClass: gvisor + 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`. 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`.| + +## 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 {{< 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 + +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. +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 provides 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. 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..49a67437 --- /dev/null +++ b/docs-site/content/kagent/1.x/substrate-runtime/suspend-and-resume.md @@ -0,0 +1,88 @@ +--- +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" >}}) 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 + +{{< 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 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). +

+ +{{< 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] +> 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 + +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. + +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 {{< 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. + +> [!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. + +- **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. + +```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. + +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 {{< 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 as suspended, and the first message addressed to the AgentInstance resumes it. + +## Resuming on demand + +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 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 Agent Substrate {{< gloss "Tag" >}}Tag{{< /gloss >}} 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 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/content/kagent/_index.md b/docs-site/content/kagent/_index.md index 57f56871..7133ff0e 100644 --- a/docs-site/content/kagent/_index.md +++ b/docs-site/content/kagent/_index.md @@ -1,8 +1,9 @@ --- 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 # PDF export. This one page opting into `book` is the whole opt-in: the format # stitches this page plus its entire .Pages subtree into one print document, so # the manual is scoped to this section by where the opt-in lives. kmcp is a @@ -19,32 +20,6 @@ author: kagent.dev outputs: ["html", "rss", "markdown", "llms", "book"] --- -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/content/kagent/concepts/_index.md b/docs-site/content/kagent/concepts/_index.md deleted file mode 100644 index 0f67b0a6..00000000 --- a/docs-site/content/kagent/concepts/_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Core Concepts -description: Understand the fundamental concepts and architecture of kagent. -weight: 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. diff --git a/docs-site/content/kagent/resources/cli/_index.md b/docs-site/content/kagent/resources/cli/_index.md deleted file mode 100644 index a50c883e..00000000 --- a/docs-site/content/kagent/resources/cli/_index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: CLI docs -description: Complete reference docs for the kagent CLI commands -weight: 1 ---- - -Review the kagent CLI commands and learn how to use them effectively. - -- [`kagent add-mcp`](/docs/kagent/resources/cli/kagent-add-mcp/) - Add an MCP server entry to kagent.yaml -- [`kagent bug-report`](/docs/kagent/resources/cli/kagent-bug-report/) - Generate a bug report -- [`kagent build`](/docs/kagent/resources/cli/kagent-build/) - Build a Docker images for an agent project -- [`kagent completion`](/docs/kagent/resources/cli/kagent-completion/) - Generate the autocompletion script for the specified shell -- [`kagent dashboard`](/docs/kagent/resources/cli/kagent-dashboard/) - Open the kagent dashboard -- [`kagent db`](/docs/kagent/resources/cli/kagent-db/) - Database operations (migrations, inspection) -- [`kagent deploy`](/docs/kagent/resources/cli/kagent-deploy/) - Deploy an agent to Kubernetes -- [`kagent get`](/docs/kagent/resources/cli/kagent-get/) - Get a kagent resource -- [`kagent init`](/docs/kagent/resources/cli/kagent-init/) - Initialize a new agent project -- [`kagent install`](/docs/kagent/resources/cli/kagent-install/) - Install kagent -- [`kagent invoke`](/docs/kagent/resources/cli/kagent-invoke/) - Invoke a kagent agent -- [`kagent mcp`](/docs/kagent/resources/cli/kagent-mcp/) - MCP (Model Context Protocol) server management -- [`kagent run`](/docs/kagent/resources/cli/kagent-run/) - Run agent project locally with docker-compose and launch chat interface -- [`kagent uninstall`](/docs/kagent/resources/cli/kagent-uninstall/) - Uninstall kagent -- [`kagent version`](/docs/kagent/resources/cli/kagent-version/) - Print the kagent version diff --git a/docs-site/content/kagent/resources/cli/kagent-completion.md b/docs-site/content/kagent/resources/cli/kagent-completion.md deleted file mode 100644 index e75b4a93..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-completion.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: kagent completion -description: Generate the autocompletion script for the specified shell -weight: 40 ---- - -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/resources/cli/kagent-completion-bash/) - Generate the autocompletion script for bash -- [`kagent completion fish`](/docs/kagent/resources/cli/kagent-completion-fish/) - Generate the autocompletion script for fish -- [`kagent completion powershell`](/docs/kagent/resources/cli/kagent-completion-powershell/) - Generate the autocompletion script for powershell -- [`kagent completion zsh`](/docs/kagent/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") -- `-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-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.md b/docs-site/content/kagent/resources/cli/kagent-get.md deleted file mode 100644 index f978e018..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-get.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: kagent get -description: Get a kagent resource -weight: 190 ---- - -Get a kagent resource - -```bash -kagent get [flags] -kagent get [command] -``` - -**Subcommands:** -- [`kagent get agent`](/docs/kagent/resources/cli/kagent-get-agent/) - Get an agent or list all agents -- [`kagent get session`](/docs/kagent/resources/cli/kagent-get-session/) - Get a session or list all sessions -- [`kagent get tool`](/docs/kagent/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") -- `-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.md b/docs-site/content/kagent/resources/cli/kagent-mcp.md deleted file mode 100644 index 4d50afda..00000000 --- a/docs-site/content/kagent/resources/cli/kagent-mcp.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: kagent mcp -description: MCP (Model Context Protocol) server management -weight: 260 ---- - -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/resources/cli/kagent-mcp-add-tool/) - Add a new MCP tool to your project -- [`kagent mcp build`](/docs/kagent/resources/cli/kagent-mcp-build/) - Build MCP server as a Docker image -- [`kagent mcp deploy`](/docs/kagent/resources/cli/kagent-mcp-deploy/) - Deploy MCP server to Kubernetes -- [`kagent mcp init`](/docs/kagent/resources/cli/kagent-mcp-init/) - Initialize a new MCP server project -- [`kagent mcp run`](/docs/kagent/resources/cli/kagent-mcp-run/) - Run MCP server locally -- [`kagent mcp secrets`](/docs/kagent/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") -- `-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/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/data/glossary.yaml b/docs-site/data/glossary.yaml new file mode 100644 index 00000000..17fea4c6 --- /dev/null +++ b/docs-site/data/glossary.yaml @@ -0,0 +1,127 @@ +# 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. +# +# Most entries carry a `link` as well as a `short`, which renders a "Learn more" +# link in the tooltip and on the glossary page. Upstream's shortcode hardcodes +# target="_blank" on that link, which strands a reader in a new tab for an +# ordinary cross-reference, so `layouts/_shortcodes/gloss.html` overrides it to +# open a new tab only for an absolute http(s) destination. That override is the +# reason these links can point inside the docset at all. +# +# Links are root-relative and hardcode the 1.x segment. That is safe because +# {{< gloss >}} is used in 1.x content only, and nowhere in 0.x or kmcp. Check +# with: grep -rl "{{< gloss " content/ | grep -v 1.x +# +# `Revision` and `Transcript` carry no `link` on purpose: no page in 1.x defines +# either term, so there is nowhere to send the reader. Add the link when a page +# claims them. + +Actor: + short: "The sandboxed unit of compute, provided by Agent Substrate, that runs an AgentInstance's conversation loop. Every AgentInstance is backed by one." + link: "/docs/kagent/1.x/about/core-concepts/#actor" + +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." + link: "/docs/kagent/1.x/about/agent-substrate/#atespaces" + +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." + link: "/docs/kagent/1.x/about/agent-substrate/" + +ActorTemplate: + short: "The compiled, immutable definition that the kagent controller produces from a Harness and AgentTemplate pair. Every Actor is created from one." + link: "/docs/kagent/1.x/about/agent-substrate/#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." + link: "/docs/kagent/1.x/about/core-concepts/#agentinstance" + +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 new state: tagging copies the snapshot so that Agent Substrate does not collect it, and a second AgentInstance can be forked from it." + link: "/docs/kagent/1.x/substrate-runtime/suspend-and-resume/#checkpoints" + +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." + link: "/docs/kagent/1.x/about/core-concepts/#agenttemplate" + +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." + link: "/docs/kagent/1.x/about/core-concepts/#harness" + +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." + link: "/docs/kagent/1.x/about/agent-substrate/#workers-and-workerpools" + +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." + link: "/docs/kagent/1.x/about/agent-substrate/#workers-and-workerpools" + + +# 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." + link: "/docs/kagent/1.x/setup/model-providers/about-model-providers/#how-a-modelconfig-reaches-an-agent" + +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." + link: "/docs/kagent/1.x/skills-and-mcp/about-tools/#mcp-tools" + +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." + link: "/docs/kagent/1.x/substrate-runtime/suspend-and-resume/#what-a-snapshot-captures" + +Tag: + short: "An Agent Substrate resource that gives one snapshot a stable, human-meaningful name, so callers do not need to track Substrate's internal snapshot identity. It also acts as a retention pin: Agent Substrate does not collect a snapshot while a tag names it, and only the tag's visibility scope can change afterward." + link: "/docs/kagent/1.x/about/agent-substrate/#suspend-snapshot-and-resume" + +Fork: + 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." + link: "/docs/kagent/1.x/examples/agent-substrate/#fork-the-conversation-into-a-second-agent" + +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." + link: "/docs/kagent/1.x/skills-and-mcp/skills/" + +Plugin package: + short: "A bundle that an AgentTemplate attaches with spec.plugins, carrying skills and optionally declaring Model Context Protocol servers. Packages follow the Agent Plugins format, which kagent consumes rather than defines." + link: "/docs/kagent/1.x/skills-and-mcp/plugins/" + +Tool binding: + short: "One entry in an AgentTemplate's spec.tools list. Each binding selects exactly one source: tools from a Model Context Protocol server, or another AgentTemplate used as a tool." + link: "/docs/kagent/1.x/skills-and-mcp/about-tools/" + +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." + link: "/docs/kagent/1.x/skills-and-mcp/about-tools/#mcp-tools" + +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." + link: "/docs/kagent/1.x/skills-and-mcp/about-tools/#mcp-tools" + +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." + link: "/docs/kagent/1.x/examples/a2a-agents/#about-the-kagent-a2a-service" + +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." + link: "/docs/kagent/1.x/substrate-runtime/sandboxing/#sandbox-classes" diff --git a/docs-site/go.mod b/docs-site/go.mod index f279a3e2..beae2bef 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.3.8 // indirect +require ( + github.com/imfing/hextra v0.12.3 // indirect + github.com/solo-io/docs-theme-extras v0.3.8 // indirect +) diff --git a/docs-site/go.sum b/docs-site/go.sum index 3287469b..89c6000d 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.3.8 h1:adccTdWRD21FHUhxv49RKW3VbP+y7d+jXzZMxADAWoM= github.com/solo-io/docs-theme-extras v0.3.8/go.mod h1:jjjYu/QoD+vMu30zgcpfEuTEGuJOJWs5qai/K18kltg= diff --git a/docs-site/hugo.preview.yaml b/docs-site/hugo.preview.yaml new file mode 100644 index 00000000..fd594580 --- /dev/null +++ b/docs-site/hugo.preview.yaml @@ -0,0 +1,31 @@ +# 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 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: + 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 efaa7950..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. diff --git a/docs-site/layouts/_partials/sidebar.html b/docs-site/layouts/_partials/sidebar.html new file mode 100644 index 00000000..e278bb62 --- /dev/null +++ b/docs-site/layouts/_partials/sidebar.html @@ -0,0 +1,139 @@ +{{- /* + kagent project sidebar override. + + Why this exists: Hextra v0.12 ships layouts/_partials/sidebar.html, which + (per the _partials-shadows-partials precedence rule) wins over docs-theme- + extras' layouts/partials/sidebar.html. Hextra's native sidebar roots the tree + at the current section, so kagent's nav "drills down" as you navigate deeper + instead of showing the whole product tree. + + 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 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 + 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" .) }} +*/ -}} +{{- $context := .context -}} + +{{- /* The site home (_index.md) is the /docs landing itself — it has no single + product tree to show, so suppress the sidebar there. */ -}} +{{- if $context.IsHome -}} + +{{- else -}} + {{- $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 partial "utils/resolve-section-versions.html" $sectionKey -}} + {{- $segments := split (strings.Trim $context.RelPermalink "/") "/" -}} + {{- $sectionIdx := -1 -}} + {{- range $i, $seg := $segments -}} + {{- if and (eq $sectionIdx -1) (eq $seg $sectionKey) -}} + {{- $sectionIdx = $i -}} + {{- end -}} + {{- end -}} + {{- $versionPage := false -}} + {{- if ge $sectionIdx 0 -}} + {{- $versionIdx := add $sectionIdx 1 -}} + {{- if lt $versionIdx (len $segments) -}} + {{- $versionPage = site.GetPage (printf "/%s/%s" $sectionKey (index $segments $versionIdx)) -}} + {{- end -}} + {{- 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. */ -}} +{{- define "kagent-sidebar-tree" -}} + {{- $page := .page -}} + {{- $current := .current -}} + {{- $depth := .depth | default 0 -}} + {{- if gt $depth 4 -}}{{- return -}}{{- end -}} + + {{- $children := $page.Pages -}} + {{- if gt (len $children) 0 -}} + + {{- end -}} +{{- end -}} 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) -}} diff --git a/docs-site/layouts/_shortcodes/gloss.html b/docs-site/layouts/_shortcodes/gloss.html new file mode 100644 index 00000000..652029c8 --- /dev/null +++ b/docs-site/layouts/_shortcodes/gloss.html @@ -0,0 +1,26 @@ +{{- /* kagent override of docs-theme-extras' gloss shortcode. + + Why this exists: upstream hardcodes target="_blank" on the optional + "Learn more" link, which is right for an external reference and wrong + for a link to another page in this docset — it strands the reader in a + new tab for an ordinary cross-reference. That single attribute was the + reason data/glossary.yaml carried no `link` values at all. + + Fix: open a new tab only for an absolute http(s) destination, and add + 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 hugo.Data.glossary $key -}} +{{- if $entry -}} +{{ .Inner | default $key }}{{ $key }}{{ $entry.short }}{{- if $entry.link }}Learn more{{- end }} +{{- else -}} +{{ .Inner | default $key }} +{{- end -}} diff --git a/docs-site/layouts/_shortcodes/glossary-list.html b/docs-site/layouts/_shortcodes/glossary-list.html new file mode 100644 index 00000000..0e902578 --- /dev/null +++ b/docs-site/layouts/_shortcodes/glossary-list.html @@ -0,0 +1,19 @@ +{{- /* Renders every entry in data/glossary.yaml as a description list. + + Why a shortcode rather than a hand-written page: the same file feeds the + inline {{< gloss >}} tooltips, so generating the page from it keeps the + two from drifting. Adding a term to the data file publishes it here with + no edit to the page. + + 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 := hugo.Data.glossary -}} + {{- $terms = $terms | append (dict "key" $key "short" $entry.short "link" $entry.link "sortKey" (lower $key)) -}} +{{- end -}} +
+{{- range sort $terms "sortKey" }} +
{{ .key }}
+
{{ .short }}{{ with .link }} Learn more{{ end }}
+{{- end }} +
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 -}} 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. */ -}} + 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/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 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 = [ "---", 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", }, ];