Repository navigation
Description
Summary
Add a first-class streaming Exec RPC that lets a client run an arbitrary command inside a running actor's gVisor sandbox, with bidirectional stdin / stdout / stderr, exit code, optional TTY, and window resize — analogous to
kubectl exec for Pods, or to E2B's Sandbox.commands.run / Sandbox.pty.create APIs for sandboxed code-execution platforms.
This is a management-plane channel, separate from the L7 actor traffic that atenet routes. It does not change the Actor lifecycle and is purely additive.
Motivation
Substrate is positioned as the runtime for agentic / sandboxed code-execution workloads (see README.md:199 "Sandbox Demo" and docs/api-guide.md:168 LangChain section). For that class of workload, "run a command in the
sandbox and stream the result back" is the single most fundamental primitive — it's what platforms like E2B, Modal sandboxes, and Daytona expose to end users. Today Substrate has no equivalent:
- pkg/proto/ateapipb/ateapi.proto — Control service exposes Create / Suspend / Resume / Delete / Get / List only.
- internal/proto/ateletpb/atelet.proto — AteomHerder exposes Run / Checkpoint / Restore only, all unary, Streams: [] confirmed in the generated atelet_grpc.pb.go:221.
- internal/proto/ateompb/ateom.proto — Ateom mirrors the same three unary RPCs.
- cmd/ateom-gvisor/runsc.go wraps runsc create / start / wait / kill / checkpoint / restore — runsc exec is not wrapped, even though it exists upstream.
- cmd/kubectl-ate/internal/cmd/ has create / get / delete / suspend / resume / logs / admin — no exec. logs_actors.go:73 falls back to kubelet Pods().GetLogs(...), i.e. log streaming is delegated to Kubernetes today.
Concretely this blocks the following use cases:
- Agent tool calls that exec untrusted code (the canonical E2B use case). Today an agent has to embed an HTTP/RPC server in its image and let atenet route to it — every template author re-implements the same exec-server
boilerplate. - Interactive debugging of a stuck actor. SREs currently have to kubectl exec into the privileged atelet DaemonSet pod (which mounts the host's /run/ateom-gvisor) and hand-craft a runsc -root
/run/ateom-gvisor/actors/::/runsc-state exec ... invocation. This works but bypasses the control plane entirely (no audit, no lock against concurrent suspend/checkpoint, RBAC granularity = "all actors on the
cluster"). - One-shot setup commands for templates (npm install, db migrate, …) without baking them into the container image or the workload entrypoint.
Activity
rogeroger-yu commentedon Jun 16, 2026
One related requirement from our side is an E2B-compatible SDK/API layer on top of this lower-level Exec primitive.
Many early sandbox/code-execution workloads are already driven through the E2B SDK, and a number of open-source sandbox runtimes have chosen to expose E2B-compatible interfaces for that reason. For our planned usage, we expect hundreds of thousands of sandbox instances/workloads over time. Substrate's Kubernetes-native architecture is one of the core reasons we are evaluating it, because it fits much better with our existing infrastructure and operations model.
However, without an E2B-compatible SDK or API surface, migration becomes significantly harder. It would require multiple business teams to modify application code and replace existing E2B SDK integrations, which is a much larger organizational cost than changing the underlying sandbox runtime.
So I think this issue is important not only as "kubectl exec for actors", but also as the foundation for an E2B-style compatibility layer. For example,
Sandbox.commands.runandSandbox.pty.createcould be mapped onto Substrate's Exec channel. Even if the SDK itself is tracked as a separate issue, it would be valuable to keep this migration path in mind when designing the Exec API.Julian Gutierrez Oschmann (@juli4n) I would like to know what suggestions or opinions the community has about the needs of this scene? We can pitch in and build together
juli4n commentedon Jun 23, 2026
I personally think that substrate should be "batteries included" and have built-in support for something like this. Requiring every user to assemble their own solution will hurt UX and adoption.
thockin commentedon Jul 20, 2026
Having exec-into-actor seems important in order to debug the actor itself, but I don't think that should be the API by which we offer "execution environments". I do think it makes sense to have a substrate-native execution environment thing in the project (but a new repo?)
The way I mapped that mentally is a "simple" process which serves an API (REST or RPC) which is more or less rsh++ or ssh++, with OCI images built around the 1-3 most useful base-images that can be used to install tools and things that such environments might need (debian, ubuntu, ...)
I see a distinction between what ate offers for ALL actors and what an actor-template which is specifically supposed to be an execution environment for higher-order harnesses offers.
Specifically, exec-into-actor should get all the same env vars, CWD, and other settings as the actor's "main" process, while exec-environ's API almost certainly wants to offer more control - env vars, CWD, possibly even a notion of sub-container (chroot, cgroup, ...).
eliranw commentedon Jul 21, 2026
We have 2 types of use cases where we would need some type of exec into actors:
cuda-checkpoint. Actor lifecycle hooks #450thockin commentedon Jul 21, 2026
Lifecycle hooks is a good use-case (I'd call it #3) but is probably simpler than either debugging or execution environments. Why?
Debugging needs to route an interactive session from a user's desktop to the actor, transiting all the things between. In K8s that includes the primary API server, and I expect that to be true here too (for authz if nothing else).
Intentional execution environment actors will want to keep the API server out of the data path, relying on the general actor authz, and almost certainly want more robust features than are needed for debug.
Lifecycle hooks are simpler - only between the atelet and actor or maybe even just ateom and actor - no real authz needed. They will be short-lived and not need TTY support.
But I agree it's a use-case.
ptone commentedon Oct 1, 2026
Here is additional feedback and concrete integration findings from multi-tenant testing on Substrate
d277088bregarding exec, attach, and TTY APIs:Summary
Substrate has no exec, attach or TTY RPC, and kubectl-ate has no exec command.
kubectl execon the worker pod lands in the distroless ateom container, not in the actor. Integrators that need to run commands in an actor, deliver input to an interactive process, or debug a broken actor have to build their own server inside the actor. That server typically has to stay privileged, and it is unavailable exactly when the actor is broken.Impact
Environment
d277088b(v1alpha), ateapi proto, kubectl-ate.Steps to reproduce / evidence
d277088b). The ateapiControlservice (pkg/proto/ateapipb/ateapi.proto:25-146) has no exec or attach RPC. kubectl-ate's verbs are get, create, update, delete, pause, resume, suspend, logs and top (cmd/kubectl-ate/internal/cmd/verbs.go:24-32), plusadmin,revertandtag; there is no exec or attach command.kubectl execinto the worker pod reaches the ateom container, which is distroless, and not the gVisor sandbox where the actor runs.Proposed behaviour / API sketch
ExecActorstreaming RPC:ttyflag;ttyis set;AttachActorstreaming RPC that attaches to the main process's stdio or pty.kubectl ate execandkubectl ate attach.Workaround
An integrator can:
The server has to be designed to survive workload failures, and it becomes a privileged, security-sensitive component. Interactive attach can be left unsupported.