Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- kagent A2A routing: the inner `kagent-controller` HTTPRoute (on the agentgateway data-plane Gateway) is no longer hostname-scoped. It was rendered with `hostnames: [<public hostname>]` from `kagent.controllerRoute.hostname`, but in-cluster A2A callers — notably klaus-gateway's `--a2a-url`, which targets the agentgateway Service's cluster-DNS name (`agentgateway.<ns>.svc.cluster.local`) — send that Service host, which did not match the public hostname. The request fell through to the catch-all MCP route (`agentic-platform-mcps`, path `/`), was handled as MCP Streamable-HTTP, and was rejected with `406 Not Acceptable ("mcp: client must accept both application/json and text/event-stream")`, so the Slack OBO sre-agent turn never reached the agent (it had passed JWT validation — the human token was forwarded — but died at content negotiation on the wrong route). The inner hop is internal and must match any Host; the `/kagent` prefix is more specific than the MCP `/` route, so a hostname-less route wins for every Host. The outer `kagent-controller-public` route keeps the public `hostname` (required on the shared TLS Gateway).
- klausgateway channel routing: a new `*-dataplane-to-klausgateway` egress policy (cilium + kubernetes flavors, rendered when `klausGateway.agentgatewayRoute.enabled`) lets the agentgateway data-plane reach the `klaus-gateway` Service on `:8080`. The channel paths (`/v1`, `/web`, `/cli/v1`, and `/channels/slack` when `slack.enabled`) are served on the data-plane Gateway and forwarded to klaus-gateway, but the data-plane runs in default-deny egress (the `-dataplane` policy) whose cluster allowance only covers `80`/`443`. klaus-gateway listens on `8080`, so the forward was dropped and every channel request — including inbound Slack events delivered to the public hostname — failed with `503 UpstreamFailure ("Connect: deadline has elapsed")`, so the Slack bot never replied. Mirrors the existing `-dataplane-to-kagent` allowance.
- `agentic-platform-connectivity` `values.schema.json`: allow `klausGateway.slack.{dmOnly,botToken,signingSecret,appToken}`. The umbrella forwards its whole `klausGateway` block to the connectivity HelmRelease via `forwardAllValues`, but the connectivity `slack` schema had `additionalProperties: false` and only declared `enabled`/`mode`/`secretName`, so a real install (gazelle) failed the HelmRelease upgrade with `Additional property dmOnly/botToken/signingSecret/appToken is not allowed`. These keys are consumed by the klaus-gateway subchart, not this chart; they are now declared (and documented as forwarded-only) so validation passes.
- klausgateway Slack OBO egress: a new `klausgateway-obo-egress` NetworkPolicy (cilium + kubernetes flavors, rendered when `klausGateway.obo.enabled`) lets the klaus-gateway pod reach the muster authorization server on 443/10443 for RFC 8414 discovery and the OAuth token exchange. The gateway is put into default-deny egress by the `klausgateway-a2a-egress` policy, which only allowed DNS + the agentgateway data plane; without this allowance the OBO token call to muster's public issuer host (which resolves to the public NLB / private LB VIP) was dropped. Mirrors the existing kagent-agent and oauth2-proxy `world`+`cluster` 443/10443 egress.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ spec:
# HTTPRoute — exposes the kagent API at <pathPrefix> on the agentgateway Gateway.
# Path prefix is stripped (URLRewrite) before forwarding so the controller
# receives requests at /api/... as it expects.
#
# This is the internal data-plane hop. It is deliberately NOT hostname-scoped:
# in-cluster A2A callers (e.g. klaus-gateway's --a2a-url, which points at the
# agentgateway Service's cluster-DNS name) send Host=<svc>.<ns>.svc.cluster.local,
# which would not match the public hostname. A host-scoped inner route lets those
# requests fall through to the catch-all MCP route ("/"), where they are handled
# as MCP Streamable-HTTP and rejected with 406 ("client must accept both
# application/json and text/event-stream"). The path prefix (/kagent) is more
# specific than the MCP "/" route, so a hostname-less route wins for every Host.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
Expand All @@ -38,10 +47,6 @@ spec:
namespace: {{ .Release.Namespace }}
group: gateway.networking.k8s.io
kind: Gateway
{{- if $route.hostname }}
hostnames:
- {{ $route.hostname | quote }}
{{- end }}
rules:
- matches:
- path:
Expand Down