feat(controller): reconcile SandboxAgents when referenced header Secrets change - #2438
Draft
voltagebots wants to merge 1 commit into
Draft
Conversation
…ets change Adds a Secret watch to the SandboxAgent controller so that changes to a Secret referenced by an agent's request headers trigger reconciliation. Resolves referencing agents through two paths: direct tool.HeadersFrom references, and indirect references via a RemoteMCPServer whose own HeadersFrom references the Secret (namespace-access-checked via AllowedNamespaces). A data-aware predicate gates events on actual Data/StringData changes so no-op Secret updates don't trigger a re-render. Fixes kagent-dev#2404 Signed-off-by: Franklin Okpako <franklin.okpako075@gmail.com>
voltagebots
marked this pull request as ready for review
August 13, 2026 20:52
voltagebots
marked this pull request as draft
August 13, 2026 20:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a
Secretwatch to the SandboxAgent controller so that changes to a Secret referenced by an agent's request headers trigger reconciliation. The watch resolves referencing agents through two paths:HeadersFromreferences the Secret.RemoteMCPServerwhoseHeadersFromreferences the Secret (namespace-access-checked viaAllowedNamespaces).An
UpdateFuncpredicate (secretDataChangedPredicate) gates events on actualData/StringDatachanges, andremoteMCPServerReferencesSecretis extended to match header-sourced Secret refs.Why
Before this change, rotating a Secret used only for request headers left running agents with stale credentials until an unrelated reconcile happened to fire. Watching the Secret closes that gap and makes header-credential rotation take effect deterministically.
Fixes #2404.
Accepted tradeoff — rollout on rotation
The agent's rendered config hash includes the resolved header value, so a genuine token rotation changes the hash and rolls the pod. This is intended and accepted: a rotated credential should propagate to a fresh pod. The predicate ensures only real
Data/StringDatachanges qualify, so no-op Secret updates do not churn workloads.Note — graceful degradation on RemoteMCPServer-list failure
The Secret finder deliberately does not fail closed if the
RemoteMCPServerlist call errors (documented in-code). Failing closed there would also drop the directHeadersFrommatches, which never depended on that list. Instead the path degrades to indirect-incomplete — direct matches are always returned; only indirect (via-RemoteMCPServer) matches may be missed on a transient list error, and are recovered on the next reconcile. Covered by an explicit test, including the empty-apiGroupRemoteMCPServer reference form.Testing
go build ./core/internal/controller/...— passesgo test -race -skip 'TestE2E.*' -v ./core/internal/controller/— all pass, including 7 newTestSandboxAgentSecretFindercases (direct/indirect/cross-namespace/empty-apiGroup/list-failure-degradation) and the data-changed predicate testgo vet ./core/internal/controller/...— cleanOpening as draft per the contribution guide's process for changes >100 lines — happy to discuss approach before this is ready for review.