AI Agents

  • Fixed

    • Meta-tool calls no longer rebuild the session’s catalogue from the definition source and the capability store on every call (#1225). call_tool, describe_tool, filter_tools, list_tools and the resource/prompt meta-tools each listed the caller’s catalogue afresh: every workflow definition was fetched from the API server twice per call (once for the tool’s arguments, once to derive its read-only hint – 8182 GET workflows in the two minutes of one agent turn with 282 workflows), and every session-authenticated server’s capabilities were read from Valkey with their own HGET and GET (~160 round trips per call with 81 such servers). Together that was a floor of about 3 s per meta-tool call on a warm session while the backend answered in 22 ms. Now the aggregator’s own tools (core_*, workflow_<name>) are built once and kept until a workflow definition changes – through muster’s tools or, for a resource applied outside them, through the workflow reconciler – with the step tools carried on the tool so the read-only hint is derived in-process; a session’s capabilities are read with one HGETALL, and the content-addressed documents behind the references are decoded once per process and shared by every session that references them; the servers a session is authenticated to are read with one HKEYS. A warm meta-tool call costs two Valkey commands regardless of how many servers are registered. Toolset scoping, session-scoped visibility and the capability freshness mechanisms are unchanged.
    • tools/call response and Error log lines carry duration_s, the time since the request reached the transport, so a slow call is visible in the log without subtracting the request line’s timestamp (#1225).
  • Changed

    • Anthropic prompt caching is on for every Anthropic ModelConfig the platform renders; the kagent line moves to v0.11.0-gs.15 (giantswarm/giantswarm#37788). The kagent Go ADK sent every Anthropic request without cache_control, so each model call of an agent loop re-processed its whole prefix — system prompt, tool schemas, the growing history — at full input price, with a time to first token that followed the uncached prefix (gazelle, 2026-09-14: 0.7-1.5 s at 6 k input tokens, 9.7-13.5 s at 33-40 k; one twelve-call status question re-sent 340 k input tokens for $0.73). kagent 0.11.0-gs.15 carries kagent-dev/kagent#2788: spec.anthropic.promptCaching / cacheTTL on the ModelConfig CRD, three cache_control breakpoints in the Go ADK (the last tool definition, the last system block, the last content block of the latest turn), cache_read_input_tokens in the usage. The meta chart sets kagent.providers.anthropic.config.promptCaching: true and cacheTTL: "5m", which the kagent chart renders into the default ModelConfig next to the LLM cut-over’s baseUrl; the connectivity chart’s kagent.modelConfigs[] Anthropic entries inherit both from that block (an entry’s own promptCaching / cacheTTL win, false included; a Bedrock entry takes its own keys under spec.bedrock; any other provider refuses the keys naming the entry, and a cacheTTL outside 5m / 1h fails the render — the API server would prune or refuse them after the render said nothing). components.kagent / components.kagent-crds move to >=0.11.0-gs.15 <0.11.1-0: the floor, because an older CRD prunes the two fields at admission and the models stay uncached in silence. make verify-prompt-caching asserts the forwarding to both releases, the inheritance, the precedence, the Bedrock block, the chart-alone default and the guards; tests/verify-kagent-crds.py validates the cached shape against the gs.15 CRD; the BOM and tests/verify-components.py follow the pin. Lab proof (agentlab on 4.15.5 with the LLM listener on, the kagent controller and Go ADK built from the cherry-pick, promptCaching: true on the default ModelConfig, claude-sonnet-4-6, a five-call tool turn on a ~4.3 k-token prefix): stock gs.14 wrote and read nothing (five calls, $0.085); on the patch the first call wrote 4 302 tokens and every later call read 97-99 % of its prompt from the cache (the turn $0.037), and the next turn’s first call read 3 961 tokens the previous turn had written ($0.019 for that turn); agentgateway’s LLM listener passes cache_control through unchanged. Every installation rolls kagent once (the controller, then the platform Harness recompiles every admitted AgentTemplate) and its Anthropic ModelConfigs gain the two fields, which recompiles their templates again; from then on the first call of a turn writes the cache (1.25×) and every call after reads it (0.1×) — UPGRADE.md, including the opt-out.
  • Fixed

    • Every agent turn ended 3 s late: the actors could not reach the OTLP gateway, and the Go ADK’s pre-response trace flush spent its full deadline on every turn (giantswarm/agent-platform#456; gazelle, 2026-09-14, nine of nine turns). The kagent controller sets KAGENT_PRE_RESPONSE_TRACE_FLUSH=true on Substrate actors (a checkpoint runtime has no later export window), so the Go ADK force-flushes a turn’s spans before the A2A response closes, with a detached deadline of KAGENT_TRACE_FLUSH_TIMEOUT_MS (3 s by default). The actors’ exporters point at the OTLP gateway kagent.otel names (http://otlp-gateway.kube-system.svc:4317), but the connectivity chart’s substrate-atenet-egress policy — the actors’ egress allow-list, since every connection an actor opens leaves through Substrate’s egress gateway — opened nothing towards it: every flush ran into traces export: context deadline exceeded at exactly +3.000 s, then the checkpoint, then the controller’s SendStreamingMessage closed; the caller (Swarmgeist’s ✅, the portal’s receipt) saw a one-word answer “done” 3.3–3.6 s after the text. The actors’ log exporter was broken twice over: the controller forwards only its tracing variables to the actors, so the Go ADK’s built-in log exporter (HTTP, /v1/logs) posted to the gRPC port and every batch ended in EOF. Three changes, one path: (1) the connectivity chart opens the OTLP gateway on the egress gateway and — through the same helper, agent-platform.kagent.otlpEgress — on the kagent controller’s egress policy, one rule per distinct destination of the kagent.otel signals that are on, selecting the pods of the endpoint’s namespace (<svc>.<ns>.svc[.cluster.local]) on the endpoint’s port (kube-system on 4317 by default, once for both signals; a second endpoint a second rule; an endpoint that is not a Service address the cluster entity on its port, as the controller’s rule was for every endpoint before); nothing when both signals resolve off. (2) The platform Harness’s env (kagent.harness.env) gains OTEL_LOGGING_ENABLED=true — the Go ADK exports the actors’ logs over gRPC to the tracing endpoint instead of the HTTP fallback — and OTEL_EXPORTER_OTLP_HEADERS=X-Scope-OrgID=giantswarm, the tenant header the controller sends and deliberately keeps from the actors; the meta chart drops the former when kagent.otel.logging resolves off and the latter when both exporters do (agent-platform.shape.dropEnv, the rule the controller’s header already followed). (3) KAGENT_TRACE_FLUSH_TIMEOUT_MS=500 on the Harness caps the flush: an in-cluster export takes tens of milliseconds, and a slow or unreachable collector can now cost a turn half a second, not three. make verify-actor-telemetry-egress asserts the rules (both policies, the default, a second endpoint, the port following the protocol, both signals off, auto off without the monitoring API, one signal on, the kubernetes flavour rendering no Substrate egress policy); tests/verify-kagent-harness.py the env in every exporter state. The lab renders no network policies (kind runs no Cilium): the policy is render-verified and live-verified on gazelle (hubble observe --verdict DROPPED on the egress gateway stays empty during a turn); the flush cap is lab-verified against an unreachable collector. Substrate’s own telemetry (the ateom worker’s periodic failed to upload metrics: … dial tcp [::1]:4317, substrate.otel.endpoint unset in the meta chart, the atelet OTLP relay socket absent on a worker that started before its atelet) is a separate finding, not on a turn’s path — a follow-up issue.
  • Changed

    • The agentgateway data plane moves to the line’s v1.5.1-gs.4 (agentgateway.proxy.image.tag in the connectivity chart, rendered into AgentgatewayParameters; giantswarm/giantswarm#37758): the Giant Swarm line of agentgateway re-pinned from upstream v1.5.0 onto upstream main @ c1d24607 (2026-09-14 — the substrate protocol of upstream #3237/#3318/#3409/#3428 that the Substrate line’s v0.0.29 router speaks; upstream has released nothing since v1.5.0), still carrying the GRPCRoute method-match translation and the resuming-actor admission. The giantswarm/agentgateway packaging chart moved the controller to the same release (giantswarm/agentgateway#52, released 2.1.2), so the data plane follows it here — controller and data plane are one build again. Proven in agentlab with both on gs.4 under 4.15.2: platform-test 7/7, a2a-test 5/5 (the GRPCRoute and its JWT policy through the edge), toolsets-test 11/11. Every installation with the agentgateway component on rolls its data-plane pods once. The Substrate and kagent line re-pins that belong to the same move follow in the next release.
    • The three Bumblebee upstream lines re-pin together — agentgateway v1.5.1-gs.4, Substrate v0.0.30-gs.1, kagent v0.11.0-gs.14 (giantswarm/giantswarm#37742, #37010, #37757, #37758): components.substrate / components.substrate-crds move to >=0.0.30-gs.1 <0.0.31-0 (the Substrate line on upstream kagent-dev/substrate v0.0.29, its ten carried patches replayed — the egress gateway’s frontend policy is upstream’s own from v0.0.29 under agentgateway#3318’s name, kagent-dev/substrate#33 fell away — and its router and egress gateway on the agentgateway line’s v1.5.1-gs.4), components.kagent / components.kagent-crds to >=0.11.0-gs.14 <0.11.1-0 (the kagent line on upstream kagent-dev/kagent main @ 800015de, 2026-09-14 — kagent-dev/kagent#2802 moves kagent to Substrate v0.0.29 and its a2a gateway addresses an actor by the ate-target-actor header, which the 0.0.27 router did not know, so a kagent past #2802 on the previous Substrate fails every turn; the #2739 cherry-pick fell away, upstream has it — whose chart stamps the 0.0.30-gs.1 worker image) (the agentgateway line’s v1.5.1-gs.4 — upstream main @ c1d24607 — is the release the controller and data plane already run since the previous entry and the Substrate chart pins for its router). Proven in agentlab on the three lines’ dev builds together on this chart’s 4.15.2 (an upgrade from 0.0.27-gs.9 / 0.11.0-gs.13 / v1.5.1-gs.3): platform-test, agents-test, skills-test, toolsets-test, a2a-test and a headless turn through the edge. Every installation on the 4.x line rolls once: the Substrate control plane and the WorkerPool (the workers restart — an actor mid-turn on a rolled worker loses that turn, every golden snapshot is retaken on the new worker image), the kagent controller and UI — UPGRADE.md. BOM, tests/verify-components.py and tests/verify-kagent-crds.py follow the pins.
  • Changed

    • (deps) Update gsoci.azurecr.io/giantswarm/agent-manager docker tag to v1.1.4 in #459 by @renovate[bot]

    Full Changelog: https://github.com/giantswarm/agent-platform/compare/v4.15.3...v4.15.4

  • Added

    • The muster release detects and corrects drift (#287). The muster HelmRelease carries spec.driftDetection.mode: enabled (components.muster.driftDetection), the second release to carry it after kagent: on every reconcile — gitops.interval — helm-controller compares the release manifest with the cluster and re-applies what differs or is missing, as a server-side apply without a Helm revision. On a management cluster that came through the agentic-platform → agent-platform rename the live CiliumNetworkPolicy muster kept the old namespace in its egress selectors while the release manifest named the new one; Helm’s three-way merge patches only what changed between two release manifests, so the object stayed drifted across every upgrade and muster’s egress to Valkey stayed denied. No ignore rule: nothing of the platform edits this release’s objects in place. An installation that sets muster.autoscaling.enabled: true must add one for /spec/replicas on the Deployment (UPGRADE.md). tests/verify-kagent-wiring.py asserts the set of releases that carry drift detection; the ATS smoke edits an object of the muster release and sees it reverted.
  • Fixed

    Full Changelog: https://github.com/giantswarm/klaus/compare/v0.1.15...v0.1.16

  • Changed

    • (renovate) Charts/flux-engine/Chart.yaml appVersion follows the Flux Operator image tag in #453 by @teemow

    Full Changelog: https://github.com/giantswarm/agent-platform/compare/v4.15.1...v4.15.2

  • Changed

    • (deps) Update ghcr.io/controlplaneio-fluxcd/flux-operator docker tag to v0.60.0 in #392 by @renovate[bot]

    Full Changelog: https://github.com/giantswarm/agent-platform/compare/v4.15.0...v4.15.1

  • Added

    • (meta) Components.vm-manager from gsoci and the giantswarm catalog (>=0.20.0); the guest image is a fetched artifact, no node paths in #452 by @teemow

    Full Changelog: https://github.com/giantswarm/agent-platform/compare/v4.14.0...v4.15.0