How Agent Substrate Handles Actor Isolation with Atespace: A Technical Deep Dive
Agent Substrate isolates workloads by binding actors to Atespaces, namespace-like boundaries that enforce strict security and resource-ownership perimeters to prevent cross-tenant interference.
Agent Substrate (agent-substrate/substrate) implements robust workload isolation through a specialized construct called Atespace, ensuring that actors operate within strictly defined security domains. This architecture prevents unauthorized access between tenants while maintaining a clear separation between namespaced application components and global infrastructure services.
Understanding Atespace as the Isolation Boundary
An Atespace functions as the fundamental isolation boundary into which an actor is created, acting as a namespace-like construct that defines security and resource-ownership perimeters. According to the protocol definitions in pkg/proto/ateapipb/ateapi.pb.go, the Atespace identifier is stored in metadata.name, serving as the sole source of isolation between workloads.
Actors residing in different atespaces cannot interfere with each other, creating strong multi-tenant boundaries at the platform level. Conversely, global-scoped resources such as Workers maintain an empty metadata.atespace field, placing them outside any specific atespace boundary and allowing universal reference from any actor within the system.
// Atespace is the isolation boundary an Actor is created into. Global-scoped:
// metadata.atespace is always empty; the atespace's identity is metadata.name.
// (source) pkg/proto/ateapipb/ateapi.pb.go#L19-L21
The ObjectRef Reference Model
All Substrate resources are addressed using an ObjectRef struct that carries both the atespace name and the resource name, creating a consistent addressing scheme across the platform. As defined in the protobuf-generated code, the ObjectRef struct enforces scope boundaries through its Atespace field:
type ObjectRef struct {
// The atespace where the resource lives. Empty if the resource is global-scoped.
Atespace string `protobuf:"bytes,1,opt,name=atespace,proto3" json:"atespace,omitempty"`
// The name of the resource. Required. Unique within an atespace, or globally
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
}
// (source) pkg/proto/ateapipb/ateapi.pb.go#L66-L72
The atespace field is required for namespaced resources and must remain empty for global-scoped resources. This dichotomy ensures that resource references explicitly declare their isolation domain, preventing ambiguous addressing that could bypass security boundaries.
Validation and Constraint Enforcement
The Substrate control plane enforces atespace constraints through validation logic implemented in internal/resources/validate.go. This validation layer guarantees that resources cannot be accidentally placed in the wrong isolation domain by enforcing two critical rules:
- Namespaced resources must specify a non-empty
metadata.atespacethat matches the atespace portion of theObjectRefused to address them. - Global-scoped resources must maintain an empty
metadata.atespacefield, ensuring they remain accessible across all atespaces without belonging to any specific tenant boundary.
Any attempt to create or update a resource with mismatched atespace metadata results in immediate validation failure, blocking the operation before it reaches the runtime layer.
Runtime Isolation Mechanisms
At runtime, the Substrate control plane (ate-api) leverages atespace information to enforce isolation through multiple mechanisms. The platform uses the atespace identifier to route RPCs, apply fine-grained policy checks, and configure sandboxing boundaries (such as gVisor containers).
Because the atespace constitutes part of the resource's canonical identity, any attempt to access a resource from outside its declared atespace triggers a permission error before the request reaches the target Worker. This design ensures that isolation failures fail-closed, maintaining security boundaries even under misconfiguration or attempted bypass.
Practical Implementation Examples
The following Go examples demonstrate how to create atespaces, bind actors to isolation boundaries, and reference resources correctly using the ateapi client:
// 1️⃣ Create an Atespace (namespace) via the API
req := &ateapi.CreateAtespaceRequest{
Atespace: &ateapi.Atespace{
Metadata: &ateapi.ResourceMetadata{
Name: "team-a", // atespace name = isolation boundary
},
},
}
resp, err := apiClient.CreateAtespace(context.Background(), req)
// 2️⃣ Create an Actor inside that Atespace
actorReq := &ateapi.CreateActorRequest{
Actor: &ateapi.Actor{
Metadata: &ateapi.ResourceMetadata{
Name: "my-actor",
Atespace: "team-a", // <-- ties the actor to the atespace
},
// Actor spec …
},
}
actorResp, err := apiClient.CreateActor(context.Background(), actorReq)
// 3️⃣ Reference the actor from another component (e.g., a snapshot tag)
tag := &ateapi.ActorSnapshotTag{
Metadata: &ateapi.ResourceMetadata{
Name: "snapshot-tag",
},
Snapshot: &ateapi.ObjectRef{
Atespace: "team-a", // must match the atespace of the target actor
Name: "my-actor",
},
}
_, err = apiClient.CreateActorSnapshotTag(context.Background(), tag)
// 4️⃣ Attempting to reference the actor with the wrong atespace fails validation
badRef := &ateapi.ObjectRef{
Atespace: "team-b", // ← wrong atespace
Name: "my-actor",
}
_, err = apiClient.GetActor(context.Background(), &ateapi.GetActorRequest{Actor: badRef})
// err => validation error: atespace mismatch
These snippets illustrate how the atespace field functions at creation, lookup, and validation time to maintain strict isolation between actors.
Summary
- Atespace serves as the primary isolation boundary in Agent Substrate, functioning as a namespace-like construct that defines security perimeters for actors.
- Global-scoped resources (Workers) use an empty atespace field to remain accessible across all tenants without belonging to any specific isolation domain.
- The
ObjectRefstruct enforces isolation by requiring explicit atespace declaration for all resource references. - Validation logic in
internal/resources/validate.goprevents resource placement in incorrect isolation domains by enforcing atespace matching rules. - Runtime enforcement occurs at the control plane level, where atespace information drives RPC routing, policy application, and sandboxing decisions.
Frequently Asked Questions
What is an Atespace in Agent Substrate?
An Atespace is a namespace-like isolation boundary that defines the security and resource-ownership perimeter for actors in the Substrate platform. It functions as the primary multi-tenant construct, ensuring that actors within different atespaces cannot interfere with each other while allowing global resources to remain accessible across boundaries.
How does Agent Substrate validate atespace constraints?
Validation occurs in internal/resources/validate.go, where the control plane enforces that namespaced resources specify a non-empty metadata.atespace matching their ObjectRef, while global-scoped resources must maintain an empty atespace field. Any mismatch results in immediate validation failure before the resource is persisted or scheduled.
Can actors in different atespaces communicate directly?
No, actors residing in different atespaces are strictly isolated and cannot directly interfere with or access each other's resources. The atespace identifier forms part of the resource's canonical identity, and any cross-atespace access attempt triggers a permission error at the control plane level before reaching the target workload.
What distinguishes global-scoped resources from namespaced resources?
Global-scoped resources (such as Workers) maintain an empty metadata.atespace field and live outside any specific isolation boundary, allowing them to be referenced by any actor in the system. Namespaced resources (such as Actors) require a specific atespace assignment and can only be accessed from within that same atespace boundary.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →