AI Agents

  • Fixed

    • The agentgateway data plane exports traces: the connectivity chart renders a Gateway-scoped -tracing policy, its egress policy and the tenant pod label (giantswarm/giantswarm#36711). The proxy reads OTEL_EXPORTER_OTLP_* only as overrides of a tracing configuration, so the env of gateway.parameters.dataPlaneEnv started no exporter and no data-plane span reached Tempo. New: AgentgatewayPolicy <release>-tracing on the data-plane Gateway with frontend.tracing to the endpoint and protocol the env names (global.observability.traces.otlp wins when its endpoint is set), at agentgateway’s default sampling: a request with a sampled traceparent is traced, one without is not. <release>-dataplane-otlp-egress allows DNS plus the endpoint’s namespace on its port, in both policy flavours. The exporter sends no headers, so the new gateway.parameters.podLabels carries observability.giantswarm.io/tenant: giantswarm from the meta chart, the label otlp-gateway routes by. verify-metric-labels now counts templates with a frontend.metrics section, not any frontend section. make verify-dataplane-tracing asserts all of it. Every installation with the agentgateway data plane gets two new objects and rolls the data-plane pods once (the pod label).
  • Added

    • gpu-operator.dcgmExporter.serviceMonitor.additionalLabels carries the tenant label (giantswarm/giantswarm#36711). The upstream chart turns the DCGM exporter’s ServiceMonitor on by default with additionalLabels: {}, and this chart forwarded nothing to fill it, so an installation that enables components.gpu-operator would scrape GPU metrics into no tenant and report no error — the failure klaus-gateway had before agent-platform#621. gpu-operator.dcgmExporter.serviceMonitor.additionalLabels."observability.giantswarm.io/tenant" is giantswarm. No installation runs this component yet, so nothing changes until one does.

    Fixed

    • muster’s OTLP export reaches the collector: the connectivity chart renders -muster-otlp-egress (giantswarm/giantswarm#36711). muster’s own network policy (muster sub-chart) allows egress to the cluster entity on 80/443 only, so with muster.muster.observability.otel.endpoint set every export was dropped at the SYN, and no muster span or OTLP log reached Tempo or Loki. The new policy selects muster by name and allows DNS plus the endpoint’s namespace on its port (the cluster entity for a host that is not an in-cluster Service), in both policy flavours, through the same agent-platform.otlpTarget / agent-platform.otlpEgressRule helpers as -klausgateway-otlp-egress. It renders exactly while the endpoint is set, with networkPolicy.enabled and the muster component on. make verify-muster-otlp asserts it. Every installation with muster on gets one new object; no pod rolls.
  • Added

    • muster and Substrate export OTLP traces (muster also logs) to otlp-gateway.kube-system.svc:4317 (giantswarm/giantswarm#36711). muster.muster.observability.otel.endpoint carries the collector and .headers sets X-Scope-OrgID: giantswarm, the same tenant header kagent, agentgateway and klaus-gateway send; substrate.otel.endpoint does the same for ate-api-server, ate-controller, atenet-router and atelet, whose otel.traces / otel.metrics / otel.logs blocks were already enabled: true with no endpoint to reach. The Substrate chart carries no OTLP-headers key for any of its four components, so its signals reach the collector without the tenant header until it grows one.
  • Changed

    • (helm) Declare the owning team on the chart in #493 by @teemow

    Full Changelog: https://github.com/giantswarm/klaus/compare/v0.1.24...v0.1.25

  • Added

    • vm-manager.serviceMonitor.enabled, auto by default like every other monitor of this platform (giantswarm/giantswarm#36711). The vm-manager component’s chart rendered no ServiceMonitor, so vm_manager_* and vm_guest_* reached no Prometheus. The meta chart resolves auto from the same global.observability.metrics.serviceMonitor.enabled detection as the rest of the platform and sets vm-manager.serviceMonitor.labels."observability.giantswarm.io/tenant" so the scrape routes to the right Mimir instance. components.vm-manager.versionRange and the customer BOM’s pin move to 0.22.0 (giantswarm/vm-manager#73), the release that carries serviceMonitor.enabled / .labels — an older release in the prior range rejects the forwarded block, its schema being closed.
  • Fixed

    • The capability poll asks for what a server declared, one listing at a time. Every poll re-listed each connected server’s tools, resources and prompts – three requests, whether or not the server had declared resources or prompts at its handshake – and started every listing at the tick: every server and every pooled session, all at once, every interval. A backend with a per-caller rate limit answered a pooled session’s tools/list with rate_limit_exceeded, and the cached list stayed as designed. A re-listing, from the poll or after a list_changed, now asks for resources and prompts only when the server declared the capability, so a tools-only server costs one request; and a poll walks its listings over the interval, one every interval/n in the order of the server names and sessions, at most eight at a time, so each backend sees one listing per interval at a steady rate. The walk runs on the process clock: a poll’s listings are done before the next tick, and the harness’s test_advance_clock makes every remaining listing due at once. A connection the pool dropped between the tick and its slot is left alone instead of listed through a closed client. (#1307)
  • Added

    • The tool list follows a backend redeployed behind its Service. A server’s tools were read at registration and again only when the server sent notifications/tools/list_changed or its definition changed. A backend rolled to an image with another tool set does neither: the new process has never seen muster’s session, so it notifies nobody, and the session recovery and the health probe heal the connection without re-reading the tools. The old list stayed until a restart – a tool the new image dropped kept failing with tool not found, a tool it added stayed invisible. The aggregator now re-lists every connected server every MUSTER_AGGREGATOR_CAPABILITY_POLL_INTERVAL (default 5m) and updates what changed, through the same refresh and the same notifications to clients as after a list_changed: a server with a shared client once, a server served per session through each session’s own live connection into that session’s list. Nothing is polled that is not connected, a listing that fails leaves the cached list as it is, and the log names the trigger (Capability refresh (poll): updated 3 tools for <server>). The harness’s test_redeploy_mock_server gained add_tools and remove_tools – a new image with another tool set, announced to nobody – and two scenarios roll a backend that way and see the poll re-list it on the production schedule, for a shared connection and for a signed-in session’s pooled one. (#494)
  • Changed

    • The klaus-gateway ServiceMonitor carries the tenant label: klausGateway.serviceMonitor (giantswarm/giantswarm#36711, giantswarm/klaus-gateway#316). The chart’s monitor was on and carried the chart’s own labels only, so Mimir routed its scrape to no tenant and every klaus_gateway_* series was lost on every installation (seen on gazelle, chart 1.19.1). klausGateway.serviceMonitor.labels sets observability.giantswarm.io/tenant: giantswarm and klausGateway.serviceMonitor.enabled is auto, resolved to the boolean the chart takes from the same answer as every other monitor of this chart. Pin first: components.klaus-gateway.versionRange is >=1.20.0 <2.0.0 and examples/customer-bom.yaml pins 1.20.0, the release that opens the labels key; an older chart’s schema refuses it. verify-klausgateway-otlp asserts the resolution and the label; verify-components-charts names 1.20.0 as UNRELEASED until it exists.
  • Added

    • Four more boards in Shared Org / Agent Platform, from the connectivity chart’s dashboards/ directory (giantswarm/giantswarm#36711). LLM usage (uid agent-platform-llm-usage) and Usage by person (uid agent-platform-usage-by-person) move here from giantswarm/dashboards, unchanged, where they were loaded into the staff-only Giant Swarm organization; the agent_platform sub-chart there goes with them. LLM usage lives under dashboards/llm-routing/ and renders only with llmRouting.enabled: every panel of it reads a GenAI series the LLM listener alone produces. Usage by person reads the data plane’s request series by user and renders whenever the boards do. Two new boards: Klaus Gateway (uid agent-platform-klaus-gateway) over the klaus_gateway_* families the gateway’s admin port serves: requests by route and status, turns by outcome, the phases of a turn from the message’s arrival to the final flush, the Slack streaming lifecycle and rate limiting. And Valkey (uid agent-platform-valkey) over the redis_* series of the wrapper chart’s redis_exporter sidecar: memory against the limit, evictions, keys, commands, clients, hit ratio, network, rejected connections, for every instance in the platform’s namespaces. Both gate their rows on the series they read, the Overview pattern, so an installation without the component opens an empty board rather than one of “No data”. The Overview’s intro table names the four and its Valkey panels link to the Valkey board. verify-llm-routing asserts the LLM usage ConfigMap follows the switch and Usage by person does not.

    Changed

    • The agentgateway packaging chart’s own monitors and dashboard are on: agentgateway.monitoring.enabled (giantswarm/giantswarm#36711, giantswarm/agentgateway#60). It follows the resolved global.observability.metrics.serviceMonitor.enabled like every other monitor of this chart (auto | true | false), at the fleet’s 60s interval and with the observability.giantswarm.io/tenant label on both monitors. It turns on three objects the platform did not have: the controller ServiceMonitor, which nothing scraped, and with it the only view of the control plane that serves the data planes their config; upstream’s proxy PodMonitor; and upstream’s own Grafana board — Overview, Requests, LLM, MCP tool calls, Latency, XDS, Runtime — vendored in the packaging chart since 2.0.0 and never rendered. The MCP and runtime series it reads were already collected and had no consumer. The board is upstream’s to maintain, so a version bump carries its fixes; the boards the platform writes itself (LLM cost per agent and per person) ship in this chart’s dashboards/ directory.
  • Fixed

    • A 429 on a session’s initialize is a transient refusal, not a legacy SSE server. When a remote MCP server answered a person’s session initialize POST with 429 Too Many Requests – GitHub’s hosted MCP server does when many tool calls of one session are in flight – muster logged failed to initialize MCP protocol: ... server returned 4xx for initialize POST, likely a legacy SSE server and sent whoever read the log after a transport mismatch that was not there. mcp-go reduces every 4xx on the initialize POST to that one sentinel and drops the status; the per-session client (DynamicAuthClient, the person’s grant, a forwarded or exchanged token) never typed it, so the connect failed with the generic message while the tool-call path already named the status. Now a 429 or 503 to the initialize is classified as retry-later on both connect paths: the client records the status and the Retry-After header off the wire and returns a typed InitializeRefusedError carrying both, the log and the CR status name the status (endpoint answered the initialize POST with HTTP 429 Too Many Requests; retry after 1s), the reconnect is scheduled for the Retry-After the server asked for rather than muster’s doubling backoff, and the session’s grant is kept so the next call reconnects. The generic 4xx message no longer claims a legacy SSE server for a status that has its own meaning – likely a legacy SSE server is said only for the 405 that means it. The scenario oauth-session-initialize-429-is-retry-later answers one grant-adoption initialize with 429 and Retry-After: 1, and pins that the server stays connected, the log names the status without the legacy-SSE line, and the next tool call succeeds without a reconnect. (#1303)