Skip to content

feat(config): replace application env vars with explicit schemas - #3153

Open
EItanya wants to merge 13 commits into
mainfrom
feat/explicit-config
Open

EItanya wants to merge 13 commits into
mainfrom
feat/explicit-config

Conversation

@EItanya

@EItanya EItanya commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Application settings are spread across env vars, which makes defaults and validation hard to follow. This PR moves the CLI and controller to explicit YAML/JSON configuration backed by protobuf schemas and Protovalidate.

  • CLI precedence is defaults, config file, then explicitly supplied flags. Config commands validate and inspect settings without connecting to services.
  • The controller loads its config once and passes typed settings to the components that own them. Helm renders the top-level config values into a mounted file and projects secret files separately.
  • Runtime settings move into the existing Go/JSON structs, with the shared contract mirrored in Python. Runtime config stays out of protobuf for now.
  • Standard OTEL_* env vars override file defaults within each process. Controller overrides do not affect managed runtimes.

This is a complete cutover, with no application env fallback or Kubernetes object metadata. Provider credentials, SDK inputs, and private runtime bootstrap payloads keep their existing interfaces.

The configuration documentation covers the schemas, precedence, and examples.

Validation: Go tests with the race detector excluding E2E, 311 Helm tests, and Helm lint pass locally. All CI checks pass, including Go/Python lint and tests, UI tests, protobuf and generated-artifact checks, and both gVisor and microVM E2E suites.

Replaces #3152 so follow-up PRs can stack on the branch in this repository.

@EItanya EItanya added enhancement New feature or request work-in-progress labels Oct 11, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 11, 2026
@EItanya
EItanya added this pull request to stack #3154 October 11, 2026 21:40
@blacksmith-sh

This comment has been minimized.

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 11, 2026
@EItanya
EItanya force-pushed the feat/explicit-config branch from 57abd5b to b68a5c6 Compare October 11, 2026 22:05
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Oct 11, 2026
@blacksmith-sh

This comment has been minimized.

@EItanya
EItanya force-pushed the feat/explicit-config branch from 9e7c596 to a2ea69c Compare October 12, 2026 01:52
Comment thread helm/kagent/templates/controller-configmap.yaml
Comment thread helm/kagent/values.yaml
jjamroga
jjamroga previously approved these changes Oct 12, 2026
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Pass compiled identity to the shared telemetry resource builder and stamp service.version even when no OTEL resource environment is present. Configure sandbox MCP token propagation through runtime defaults in CI.

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Scope config initialization bypasses to the root version and config schema commands. Use protobuf getters for config consumers, remove obsolete env setup and documentation, and isolate OTEL startup tests from cached SDK settings.

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
"gateway" (dict "publicUrl" $apiURL "push" (dict))
"runtimeDefaults" (dict "controlPlaneUrl" $apiURL "gatewayUrl" $apiURL)
-}}
{{- $config := mergeOverwrite $base (deepCopy .Values.config) -}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old otel.* values are now silently ignored, so upgrading with otel.traces.enabled=true turns all export off. How about adding a fail for .Values.otel, like rbac.clusterScoped, that points to config.telemetry and config.runtimeDefaults.telemetry.

for _, signal := range signals {
resolved := c.signal(signal)
if !resolved.Enabled {
raw = tracing.ResourceEnvironment(telemetry.Environment(raw, cfg), resourceIdentity(identity))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTEL_SERVICE_NAME is gone and resourceIdentity has no service.name, so BYO SDKs report unknown_service. Let's add service.name=<agent> to the resource attributes here so an image's own OTEL_SERVICE_NAME still wins, and restore the dropped test assertion.

Comment on lines +119 to 121
for key, value := range opts.Config.ResourceAttributes {
detectors = append(detectors, resource.WithAttributes(attribute.String(key, value)))
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File attributes come after opts.Defaults, so resourceAttributes: {service.name: x} or service.namespace overwrites every agent's identity. Reject these keys in the schema or move them into Identity.

attributes[_SERVICE_NAMESPACE] = identity.agent_namespace
def _resource_attributes(identity: Identity, config: ExporterConfig) -> dict[str, str]:
attributes = {SERVICE_NAME: identity.agent_name, _SERVICE_NAMESPACE: identity.agent_namespace}
attributes.update(config.resource_attributes)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def _install_providers(identity: Identity, config: ExporterConfig) -> None:
if os.getenv("OTEL_SDK_DISABLED", "").strip().lower() == "true":
return
OpenTelemetryConfigurator().configure(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The try/except around configure() was removed, so a bad value like OTEL_TRACES_EXPORTER=jaeger in Harness.spec.env now crashes the agent. Let's restore it so Python logs and continues like the Go runtimes.

continue
}
if variable.Name == env.KagentAPIURL.Name() || claudeconfig.OwnsEnvironment(variable.Name) || translator.OwnsTelemetryEnvironment(variable.Name) {
if claudeconfig.OwnsEnvironment(variable.Name) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without OwnsTelemetryEnvironment, Harness.spec.env can turn on content capture or send OTLP to any endpoint, and egress opens to it. That means captureContent: false is no longer enforced. Let's keep capture under controller control.

Comment thread helm/kagent/values.yaml
bindAddress: ":8443"
secure: true
telemetry: {}
runtimeDefaults:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller and runtime telemetry are now 2 blocks with no shared endpoint or resourceAttributes, so values like deployment.environment.name can drift apart. Let's default runtimeDefaults.telemetry from telemetry in the chart?

Comment thread go/pkg/telemetry/environment.go Outdated
{signal.vars.Protocol, env.OTELExporterOTLPProtocol, signal.config.Protocol},
{signal.vars.Timeout, env.OTELExporterOTLPTimeout, strconv.FormatInt(signal.config.timeout().Milliseconds(), 10)},
} {
if !supplied(option.generic.Name()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A generic env override replaces only half of the file's endpoint and protocol pair. With OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf and a file grpc endpoint, the SDK sends http/protobuf to :4317 with no /v1/traces. Let's treat endpoint and protocol as one unit.

Comment thread go/pkg/telemetry/environment.go Outdated
}{
{signal.vars.Endpoint, env.OTELExporterOTLPEndpoint, signal.config.Endpoint},
{signal.vars.Protocol, env.OTELExporterOTLPProtocol, signal.config.Protocol},
{signal.vars.Timeout, env.OTELExporterOTLPTimeout, strconv.FormatInt(signal.config.timeout().Milliseconds(), 10)},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always writing TIMEOUT=10000 (the SDK default) plus per-signal endpoint and protocol gives BYO 16 OTEL_* entries, against Substrate's limit of 32. Skip the defaults, use generic vars when all signals match, and add BYO to the env budget test.

if c.Exporters != nil {
cfg = *c.Exporters
}
raw = telemetry.Environment(raw, cfg)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lists the sampler as a supported setting, but the "sampling belongs in the collector" line was removed from telemetry.md. SDK samplers set per Harness give partial traces, so let's restore that guidance.

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Comment thread helm/kagent/values.yaml Outdated
schema: kagent
vectorSchema: extensions
vectorEnabled: false
migrations: apply

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of this vs the previous skipMigrations: <bool> approach. Saw it while glancing through this as it's the area I've been in a lot lately. 🙂

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
@blacksmith-sh

blacksmith-sh Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
github.com/kagent-dev/kagent/go/core/test/e2e/TestAgentA2ACreatesConversation View Logs
github.com/kagent-dev/kagent/go/core/test/e2e/TestSessionAskUserSurvivesSuspension View Logs

Blacksmith runners detected OOM events on the following jobs:

Job Details
test-e2e (microvm) View Job

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request work-in-progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants