Skip to content

Support default egress policies in ActorTemplates - #1558

Closed
Eitan Yarmush (EItanya) wants to merge 4 commits into
agent-substrate:mainfrom
kagent-dev:feat/template-default-egress
Closed

Eitan Yarmush (EItanya) wants to merge 4 commits into
agent-substrate:mainfrom
kagent-dev:feat/template-default-egress

Conversation

@EItanya

Copy link
Copy Markdown
Collaborator

Allow ActorTemplates to define a default egress policy, validated like an EgressPolicy and copied atomically when an Actor is created. Actors without a configured default retain the current behavior; copied policies can be updated or deleted independently.

Validation: make verify passed, including rollback and policy lifecycle tests.

Fixes #1324

Allow actor templates to supply metadata-free initial egress rules, validated like actor egress policies. Copy them into a default policy in the actor creation transaction so policy write failures cannot leave an actor without its configured policy.

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Use one CreateActor store operation for actors with or without an initial policy, preserving transactional writes when a policy is supplied. Update callers to pass nil when no policy is needed and remove redundant service wiring.

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

Copy link
Copy Markdown
Collaborator

@LiorLieberman

Lior Lieberman (LiorLieberman) commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

hmmm - plus one on having support for actor default egress policies. But I think our controller / egress policy implementation should just be deny-by-default regardless if the api has the policy within the actor. Its kinda orthogonal but wanted to make sure we are on the same page that we dont want to couple having that default empty egress policy in order to trigger deny by default


// Initial egress policy, copied atomically when an Actor is created from
// this template. The policy is named "default" in the Actor's atespace.
// Later template changes do not affect existing Actors' policies, which

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Later template changes do not affect existing Actors' policies: should we make this configurable?

I imagine there are cases where users would like existing actors to pick up a EgressPolicyTemplate change automatically.

if diff := cmp.Diff(tt.policy.Rules, policy.Rules, protocmp.Transform()); diff != "" {
t.Errorf("copied rules mismatch (-want +got):\n%s", diff)
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The tests below this line does not seem to be related to the test table defined above. Please move them to a separate test.

@EItanya

Copy link
Copy Markdown
Collaborator Author

hmmm - plus one on having support for actor default egress policies. But I think our controller / egress policy implementation should just be deny-by-default regardless if the api has the policy within the actor. Its kinda orthogonal but wanted to make sure we are on the same page that we dont want to couple having that default empty egress policy in order to trigger deny by default

100%, this doesn't change that. The implementation will always be deny by default, this is just a way to add default policy for all actors in a template.

…changes

Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
@bowei Bowei Du (bowei) added kind/feature An enhancement / feature request or implementation area/api User-facing API changes area/network labels Sep 17, 2026
@bowei Bowei Du (bowei) self-assigned this Sep 21, 2026
Quentin Bisson (QuentinBisson) added a commit to giantswarm/substrate that referenced this pull request Sep 29, 2026
… note the rootfs root dependency of kagent-upstream#125 (agent-substrate#1918)
Quentin Bisson (QuentinBisson) added a commit to giantswarm/substrate that referenced this pull request Oct 1, 2026
… root dependency of kagent-upstream#125 (#94)

docs(fork): the egress default's upstream exit is agent-substrate#1558; note the rootfs root dependency of kagent-upstream#125 (agent-substrate#1918)
Quentin Bisson (QuentinBisson) added a commit to giantswarm/kagent-upstream that referenced this pull request Oct 5, 2026
…ress policy as its default

ActorTemplateForRevision sets default_egress_policy from the revision's
egress destinations and credentials, the same allowlist the session
workflow creates for each Actor. Substrate copies it onto every Actor it
creates from the template, including the golden Actor the template
reconciler creates, which no client call could give a policy before it
boots: without one the golden boot is denied all egress (403) and a
workload that fetches git skills before readyz never gets its snapshot.
The workflow's EnsureActorEgressPolicy stays as the idempotent check.
The revision digest carries an actorTemplateFormat marker so templates
compiled before this change are re-created instead of conflicting.

Field names follow agent-substrate/substrate#1558
(ActorTemplate.default_egress_policy, EgressPolicyTemplate.rules).

Refs kagent-dev#2604, agent-substrate/substrate#1324
Quentin Bisson (QuentinBisson) added a commit to giantswarm/kagent-upstream that referenced this pull request Oct 5, 2026
…ress policy as its default

ActorTemplateForRevision sets default_egress_policy from the revision's
egress destinations and credentials, the same allowlist the session
workflow creates for each Actor. Substrate copies it onto every Actor it
creates from the template, including the golden Actor the template
reconciler creates, which no client call could give a policy before it
boots: without one the golden boot is denied all egress (403) and a
workload that fetches git skills before readyz never gets its snapshot.
The workflow's EnsureActorEgressPolicy stays as the idempotent check.
The revision digest carries an actorTemplateFormat marker so templates
compiled before this change are re-created instead of conflicting.

Field names follow agent-substrate/substrate#1558
(ActorTemplate.default_egress_policy, EgressPolicyTemplate.rules).

Refs kagent-dev#2604, agent-substrate/substrate#1324
@EItanya

Copy link
Copy Markdown
Collaborator Author

Closing this in favor of #2159

Da Huang (git286) added a commit to git286/substrate that referenced this pull request Oct 19, 2026
- kubectl ate logs uses the singular 'actor' subcommand; the not-running
  error names atespace/name; quote the crash log message exactly.
- GKE telemetry goes to the GKE managed OTel collector, not straight to
  GMP.
- Workers normally export through the atelet relay, so an endpoint change
  reaches them when atelet restarts; the controller copy is the fallback.
- List why atelet may start no relay (https, conflicting per-signal
  endpoints or compression, unparsable headers), per-signal endpoints as
  a fallback destination, and that ate-controller injects the endpoint
  only when it has one.
- The probes moved to :9091 (agent-substrate#2424); agent-substrate#1558 was closed unmerged.
- Drop the removed pause from the lifecycle and snapshot-kind text.
- The registry table now lists events.yaml.
- Kind Prometheus does not show the metrics that ateworker,
  atecontroller and the credential provider only push over OTLP.
- Tracing is head-sampled, and the roadmap metrics already exist.
Da Huang (git286) added a commit to git286/substrate that referenced this pull request Oct 19, 2026
- kubectl ate logs uses the singular 'actor' subcommand; the not-running
  error names atespace/name; quote the crash log message exactly.
- GKE telemetry goes to the GKE managed OTel collector, not straight to
  GMP.
- Workers normally export through the atelet relay, so an endpoint change
  reaches them when atelet restarts; the controller copy is the fallback.
- List why atelet may start no relay (https, conflicting per-signal
  endpoints or compression, unparsable headers), per-signal endpoints as
  a fallback destination, and that ate-controller injects the endpoint
  only when it has one. A socket left by an earlier atelet keeps
  ateworker on the relay, failing every export instead of falling back.
- The probes moved to :9091 (agent-substrate#2424); agent-substrate#1558 was closed unmerged.
- Drop the removed pause from the lifecycle and snapshot-kind text.
- The registry table now lists events.yaml.
- Kind Prometheus does not show the metrics that ateworker and
  atecontroller only push over OTLP; the credential provider does not
  read ate-otel-config, so its OTLP push never reaches the collector.
- Tracing is head-sampled, and the roadmap metrics already exist.

Checked on a Kind cluster built from main and on a GKE install.
Da Huang (git286) added a commit to git286/substrate that referenced this pull request Oct 20, 2026
- kubectl ate logs uses the singular 'actor' subcommand; the not-running
  error names atespace/name; quote the crash log message exactly.
- GKE telemetry goes to the GKE managed OTel collector, not straight to
  GMP.
- Workers normally export through the atelet relay, so an endpoint change
  reaches them when atelet restarts; the controller copy is the fallback.
- List why atelet may start no relay (https, conflicting per-signal
  endpoints or compression, unparsable headers), per-signal endpoints as
  a fallback destination, and that ate-controller injects the endpoint
  only when it has one. A socket left by an earlier atelet keeps
  ateworker on the relay, failing every export instead of falling back.
- The probes moved to :9091 (agent-substrate#2424); agent-substrate#1558 was closed unmerged.
- Drop the removed pause from the lifecycle and snapshot-kind text.
- The registry table now lists events.yaml.
- Kind Prometheus does not show the metrics that ateworker and
  atecontroller only push over OTLP; the credential provider does not
  read ate-otel-config, so its OTLP push never reaches the collector.
- Tracing is head-sampled, and the roadmap metrics already exist.

Checked on a Kind cluster built from main and on a GKE install.
Scott Funkenhauser (sfunkenhauser) pushed a commit to sfunkenhauser/substrate that referenced this pull request Oct 20, 2026
…2886)

- kubectl ate logs uses the singular 'actor' subcommand; the not-running
error names atespace/name; quote the crash log message exactly.
- GKE telemetry goes to the GKE managed OTel collector, not straight to
GMP.
- Workers normally export through the atelet relay, so an endpoint
change reaches them when atelet restarts; the controller copy is the
fallback.
- List why atelet may start no relay (https, conflicting per-signal
endpoints or compression, unparsable headers), per-signal endpoints as a
fallback destination, and that ate-controller injects the endpoint only
when it has one. A socket left by an earlier atelet keeps ateworker on
the relay, failing every export instead of falling back.
- The probes moved to :9091 (agent-substrate#2424); agent-substrate#1558 was closed unmerged.
- Drop the removed pause from the lifecycle and snapshot-kind text.
- The registry table now lists events.yaml.
- Kind Prometheus does not show the metrics that ateworker and
atecontroller only push over OTLP; the credential provider does not read
ate-otel-config, so its OTLP push never reaches the collector.
- Tracing is head-sampled, and the roadmap metrics already exist.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api User-facing API changes area/network kind/feature An enhancement / feature request or implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support a default egress policy in ActorTemplate

4 participants