Skip to content

ateapi: remove SandboxConfig from ActorTemplate - #2780

Merged
Dmitry Berkovich (dberkov) merged 6 commits into
agent-substrate:mainfrom
shrutiyam-glitch:remove-sc-2
Oct 17, 2026
Merged

Dmitry Berkovich (dberkov) merged 6 commits into
agent-substrate:mainfrom
shrutiyam-glitch:remove-sc-2

Conversation

@shrutiyam-glitch

@shrutiyam-glitch shrutiyam-glitch commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to #2660 and #2755.

Sandbox runtime and version selection live on the WorkerPool: its sandboxClasses entry resolves a SandboxConfig, atelet reports the enabled versions on WorkerStatus as defaultRuntime/restorableRuntimes, and the chosen runtime is stamped onto WorkerAssignment and Snapshot and sent to atelet on Run and Restore. The ActorTemplate no longer has a say in which sandbox an actor runs in, so its sandbox_config field goes.

Breaking: ActorTemplate.sandbox_config and the SandboxConfig message are removed from the Control API. ate-api-server rejects unknown fields, so manifests or clients still sending sandboxConfig fail with InvalidArgument. Stored templates are unaffected (proto bytes; the old field is carried as unknown). kubectl ate get actortemplates loses its SANDBOX CLASS column.

API

  • Remove sandbox_config and the SandboxConfig message from ActorTemplate in ateapi.proto, and its validation from ate-api-server.
  • Remove sandboxConfig from kubectl-ate output, e2e fixtures, demo and benchmark ActorTemplate manifests (sweperf included), and the docs.

ateapi

  • sandbox_assets on Run/Restore is unchanged on the wire; ateapi now resolves it from the assigned worker's pool instead of the template: WorkerAssignment → WorkerPool → the controller-confirmed SandboxConfig (WorkerPool.ResolvedSandboxConfig(), new) → default version. ActorWorkflow takes a WorkerPoolLister for this; the sandboxconfigs RBAC stays. Marked TODO: this lookup, both listers and the RBAC go once atelet resolves the version from sandbox_runtime and sandbox_assets is dropped (the follow-up noted in atelet: pass SandboxRuntime on Run and Restore #2755).
  • Scheduler: Constraints.SandboxClass is no longer taken from the template. It is the class of the snapshot the actor restores from (local, else latest durable, golden tags included), empty on a cold boot — so a worker of another class is never a candidate, not even as the volumes-only fallback when RequiredRuntime is relaxed. A cold-booting actor gets the class of the pools its workerSelector matches.
  • Repointing actor_template on a SUSPENDED actor no longer requires the same SandboxConfig; the snapshot's class and runtime checks on resume cover compatibility.
  • Metrics: ate.sandbox.class on lifecycle and scheduler operations is derived from the actor's assignment or snapshot runtime rather than the template, and omitted when neither is known yet; registry updated.

Behavior change to flag: a template with no workerSelector whose actor has no snapshot can be placed on a pool of any class. Previously sandboxConfig.sandboxClass alone pinned the class; now the selector has to.

Tests

  • TestResolveSandboxAssets covers pool-based resolution (resolved, unresolved pool, missing pool, missing config, no default version).
  • Scheduler Applies cases for the snapshot-class pin; assignWorkerAttempt proves a microvm worker is never the fallback for a gvisor snapshot at MEMORY or VOLUMES fidelity.
  • Wire-request tests seed the pool lister; the "missing SandboxConfig" cases now go through the pool.
  • Functional tests write the pool's status.sandboxClasses[].configRef via UpdateStatus (status subresource) and wait for it in the informer.
  • ReleaseWindowWorkflows makes the worker ineligible via workerSelector instead of a sandbox-class mismatch.

No atelet changes beyond two comments.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

@shrutiyam-glitch
shrutiyam-glitch force-pushed the remove-sc-2 branch 2 times, most recently from e7beb26 to 2268e05 Compare October 16, 2026 23:14
@shrutiyam-glitch
shrutiyam-glitch marked this pull request as ready for review October 16, 2026 23:19
Sandbox runtime and version selection live on the WorkerPool, via its
sandboxClasses and the SandboxConfig the controller resolves for them, and
are reported on WorkerStatus as DefaultRuntime and RestorableRuntimes,
stamped onto WorkerAssignment and Snapshot during actor execution, and
passed to atelet on Run and Restore. The ActorTemplate no longer has a say
in which sandbox an actor runs in, so its sandbox_config field goes.

ateapi still sends atelet the sandbox assets on Run and Restore; it now
resolves them from the assigned worker's pool instead of the template: the
pool's confirmed SandboxConfig at its default version, which is the runtime
the worker reports as its default. WorkerPool.ResolvedSandboxConfig exposes
that lookup.

The scheduler's SandboxClass constraint is now the class of the snapshot
the actor restores from rather than the template's, and empty on a cold
boot. A snapshot's files, its durable volumes included, are written by one
class's worker and read back by the same, so the class holds for every
fidelity and is never relaxed; a cold-booting actor gets the class of the
pools its workerSelector matches.

Remove sandbox_config and the SandboxConfig message from ActorTemplate in
ateapi.proto, drop its validation from ate-api-server, derive the
ate.sandbox.class metric attribute from the actor's assignment or snapshot
runtime, and remove sandboxConfig from kubectl-ate, e2e fixtures, demo and
benchmark ActorTemplate manifests, and docs.
func resolveTemplateSandboxConfig(
// resolvePoolSandboxConfig resolves the SandboxConfig the controller confirmed
// for the WorkerPool of the actor's assigned worker.
func resolvePoolSandboxConfig(

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.

Not needed in this PR: we should remove this once the atelet-side changes for resolving hash->assets have landed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yeah, hence added a todo to remove it after 2731 gets merged.
But currently, the sandbox asset is still being passed to the atelet. So, need to resolve the value for that I guess ?

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.

yes, need to keep the resolver for now.

if worker.GetSandboxClass() == "" {
return false
}
if constraints.SandboxClass != "" && worker.GetSandboxClass() != constraints.SandboxClass {

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.

when does constraints.SandboxClass == "" ? should we throw an error?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

When snapshotSandboxClass found no snapshot on the actor — the cold-boot case.

basically, this was case there earlier too, but Sandbox_class from the template and it was required filed on the template. This is now replaced with the sandbox class from with either of the snapshots.
https://github.com/agent-substrate/substrate/pull/2780/changes#diff-36ddf680db489a13b32821a56fe2ab2f8b358a80baa531bc78f61ce2e6d2ce0eL679-R701

added this behavior in the pr description too -

Behavior change to flag: a template with no workerSelector whose actor has no snapshot can be placed on a pool of any class. Previously sandboxConfig.sandboxClass alone pinned the class; now the selector has to.

With sandbox_config gone from ActorTemplate the helper returned an empty
template with nothing gVisor-specific about it, and its name suggested a
constraint the tests no longer place. The rest of the file already writes
&ateapipb.ActorTemplate{} inline, so do the same at its call sites.
…ndbox class

With sandbox_config gone from ActorTemplate, the WorkerPool decides the
sandbox class an actor runs in, and a template reaches a pool only through
worker_selector. Say so on the field and in the API guide: a cluster with
pools of more than one class needs a selector that points only at pools
of the class the workload wants, since an actor booting with no snapshot
and no selector may land on any class and keeps it from its first
checkpoint on. The actor-level worker_selector only narrows the
template's choice, so point it at the template field.
# Conflicts:
#	cmd/ateapi/internal/controlapi/workflow_suspend.go
@zoez7
Zoe Zhao (zoez7) added this pull request to the merge queue Oct 17, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 17, 2026
@dberkov
Dmitry Berkovich (dberkov) added this pull request to the merge queue Oct 17, 2026
Merged via the queue into agent-substrate:main with commit 0443aec Oct 17, 2026
15 checks passed
Haowei Cai (Roy) (roycaihw) pushed a commit to roycaihw/substrate that referenced this pull request Oct 19, 2026
…t-substrate#2879)

Completes the removal of `sandbox_assets` from the `ate-api-server` ->
`atelet` wire protocol following agent-substrate#2780 and agent-substrate#2781. Since `atelet` now
resolves the pause image and sandbox binaries for `Run` and `Restore`
directly from `sandbox_runtime` via its advertised-runtime index,
`ate-api-server` no longer needs to resolve `SandboxConfig` or send
`SandboxAssets` on `RunRequest` and `RestoreRequest`.

- **`ateletpb` & validation**: Remove `sandbox_assets` from `RunRequest`
and `RestoreRequest`, delete `SandboxAssets`, `ArchAssets`, and
`AssetFile`, and make `sandbox_runtime` required on both RPCs.
- **`cmd/ateapi` & RBAC**: Delete `sandbox_assets.go`, remove
`sandboxConfigLister` and `workerPoolLister` from `ActorWorkflow` and
`NewRPCService`, drop `sandboxconfigs` from `ate-api-server` RBAC, and
require a non-nil `DefaultRuntime` in `scheduler.Applies`.
- **`cmd/atelet`**: Read `op.sandboxClass` from `sandbox_runtime` in
`Restore`, delete dead `recordFromRequest`, and replace `poolConfigName`
with `WorkerPool.ResolvedSandboxConfig()`.

- [ ] Tests pass
- [ ] Appropriate changes to documentation are included in the PR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants