Disclosure: this issue was written by an AI agent (Claude) while documenting kagent's
egress and observability surfaces, and reviewed by a human before filing.
Summary
kagent computes an egress hostname allowlist per revision and writes it to the database and
nowhere else. Nothing applies it to the Actor, even though Substrate now implements an
ActorEgressPolicy API that could consume it. Separately, the OTLP exporter endpoint is
never added to that list, so enabling enforcement later would silently break tracing and
audit logging.
Filing these together because they are one gap with one landing zone, but they can be split
if preferred.
1. The computed list has no consumer
Every harness compiler sets it:
go/core/internal/translator/kagent/compiler.go — EgressDestinations: slices.Compact(compiled.Egress)
go/core/internal/translator/byo/compiler.go, claude/compiler.go, codex/compiler.go — same
go/core/internal/controller/reconciler.go then stores it on the revision row. A full
grep -rn 'EgressDestinations' --include='*.go' go shows consumers only under
internal/database/, internal/translator/, and that one reconciler line. Nothing under
internal/substrate/ reads it, so it reaches the ActorTemplate nowhere and is recorded
metadata rather than an allowlist.
grep -rn 'EgressPolicy\|ActorEgressPolicy' --include='*.go' go returns zero hits,
while substrate exposes Get/Create/Update/DeleteActorEgressPolicy with a real
server-side implementation (cmd/ateapi/internal/controlapi/egress_policy.go).
Note substrate's EgressPolicy is documented as default-deny — "A request is denied when no
rule matches" — so whichever component starts creating policies decides the failure mode for
everything not on the list.
2. The OTLP endpoint is missing from the list
agentConfigDestinations in go/core/internal/translator/adkconfig/builder.go derives
destinations from HTTP tools, SSE tools, and the model provider's hosts.
CompileSkillResources (translator/skills.go, appendArtifactSourceDestination) adds the
registry or repository host per skill source. The OTel exporter endpoint is never added.
That is harmless only while the list is unenforced. Once it is enforced, an Actor loses its
route to the collector and both documented observability paths break with no error and no
failure message — no traces, no audit records, nothing pointing at egress.
Expected
- The computed
EgressDestinations are applied to the Actor, presumably as an
ActorEgressPolicy, or the field is documented as informational until they are.
- The configured OTLP endpoint is included whenever tracing or logging export is enabled, so
turning on enforcement does not silently disable telemetry.
Related
Summary
kagent computes an egress hostname allowlist per revision and writes it to the database and
nowhere else. Nothing applies it to the Actor, even though Substrate now implements an
ActorEgressPolicyAPI that could consume it. Separately, the OTLP exporter endpoint isnever added to that list, so enabling enforcement later would silently break tracing and
audit logging.
Filing these together because they are one gap with one landing zone, but they can be split
if preferred.
1. The computed list has no consumer
Every harness compiler sets it:
go/core/internal/translator/kagent/compiler.go—EgressDestinations: slices.Compact(compiled.Egress)go/core/internal/translator/byo/compiler.go,claude/compiler.go,codex/compiler.go— samego/core/internal/controller/reconciler.gothen stores it on the revision row. A fullgrep -rn 'EgressDestinations' --include='*.go' goshows consumers only underinternal/database/,internal/translator/, and that one reconciler line. Nothing underinternal/substrate/reads it, so it reaches theActorTemplatenowhere and is recordedmetadata rather than an allowlist.
grep -rn 'EgressPolicy\|ActorEgressPolicy' --include='*.go' goreturns zero hits,while substrate exposes
Get/Create/Update/DeleteActorEgressPolicywith a realserver-side implementation (
cmd/ateapi/internal/controlapi/egress_policy.go).Note substrate's
EgressPolicyis documented as default-deny — "A request is denied when norule matches" — so whichever component starts creating policies decides the failure mode for
everything not on the list.
2. The OTLP endpoint is missing from the list
agentConfigDestinationsingo/core/internal/translator/adkconfig/builder.goderivesdestinations from HTTP tools, SSE tools, and the model provider's hosts.
CompileSkillResources(translator/skills.go,appendArtifactSourceDestination) adds theregistry or repository host per skill source. The OTel exporter endpoint is never added.
That is harmless only while the list is unenforced. Once it is enforced, an Actor loses its
route to the collector and both documented observability paths break with no error and no
failure message — no traces, no audit records, nothing pointing at egress.
Expected
EgressDestinationsare applied to the Actor, presumably as anActorEgressPolicy, or the field is documented as informational until they are.turning on enforcement does not silently disable telemetry.
Related
where it blocks skill materialization outright rather than degrading telemetry.
and Actor network policy should support in-cluster service / ClusterIP like OpenTelemetry Collector endpoint agent-substrate/substrate#960 (keep in-cluster services such as the OTel Collector
reachable once policy is enforced) are the substrate-side halves.