Build and manage custom templates with code

Updated at:

Build, query, update, and delete custom templates by using the Agent Sandbox OpenAPI SDK, and configure the image source, the build method, and the network access of the sandbox after a virtual private cloud (VPC) is connected.

A custom template defines the image and the configurations that a sandbox requires. This topic describes the image sources and build methods, and then the network configurations that take effect after a VPC is connected. The examples use Python to call the Agent Sandbox OpenAPI SDK. The TypeScript, Go, and Java SDKs provide the same capabilities.

Note the following configuration items when you create a template:

  • Image source: official public images, and Container Registry Enterprise Edition (ACR EE) images.

  • Build method and startup configuration: supports the start command (start_command) and the ready command (ready_command).

  • Disk size measurement: disk_size includes the space that the image itself occupies. The writable space = disk size - image size.

  • Log configuration: all examples include log_config.

Before you begin

This section describes the preparations that the following examples have in common. Each later section provides a complete build example based on these preparations. The examples that create and access sandboxes also use the E2B SDK. Install the E2B SDK and configure its credential environment variables in advance.

  1. Activate Function Compute and Agent Sandbox, create a Team in the Agent Sandbox console, and obtain the Team ID.

  2. Prepare an Alibaba Cloud account or a Resource Access Management (RAM) user, and grant the template API permissions to the calling identity. Example of a minimum permission policy:

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "sandbox:CreateTemplate",
            "sandbox:GetTemplate",
            "sandbox:ListTemplates",
            "sandbox:UpdateTemplate",
            "sandbox:DeleteTemplate"
          ],
          "Resource": "*"
        }
      ]
    }

    Template resources support fine-grained authorization by Team. The resource format is acs:sandbox:<region>:<account-id>:teams/<team-id>/templates/*.

  3. Check the region of the template. This example uses cn-hangzhou. Replace it with the destination region.

  4. Prepare the image address. For a private image, prepare the corresponding credentials and image pull network. For more information, see the image source section.

  5. Prepare log resources: create a Simple Log Service (SLS) project and Logstore in the same region as Agent Sandbox so that log_config can deliver build and runtime logs.

Install the SDK. This example uses Python:

python3 -m venv .venv
source .venv/bin/activate
pip install "alibabacloud_sandbox20260820>=1.1.0"

Configure the credential environment variables:

export ALIBABA_CLOUD_ACCESS_KEY_ID="<your-access-key-id>"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="<your-access-key-secret>"
# If you use a Security Token Service (STS) token, also configure:
# export ALIBABA_CLOUD_SECURITY_TOKEN="<your-security-token>"

Common initialization code. All later examples are based on this code:

import os
import time

from alibabacloud_sandbox20260820 import models
from alibabacloud_sandbox20260820.client import Client as SandboxClient
from alibabacloud_tea_openapi import models as open_api_models

REGION = "cn-hangzhou"
TEAM_ID = "<your-team-id>"

config = open_api_models.Config(
    access_key_id=os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"],
    access_key_secret=os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"],
    region_id=REGION,
    endpoint=f"sandbox.{REGION}.aliyuncs.com",
)
pop_client = SandboxClient(config)


def wait_ready(template_id, timeout=900):
    """Poll the template build status until a final state is reached, and return status.state."""
    deadline = time.time() + timeout
    while time.time() < deadline:
        resp = pop_client.get_template(
            template_id, models.GetTemplateRequest(team_id=TEAM_ID))
        state = resp.body.status.state
        if state in ("ready", "error"):
            if state == "error":
                print(f"Build failed: {resp.body.status.reason.message}")
            return state
        time.sleep(10)
    return "timeout"

Image requirements

A custom image must meet the requirements listed in the following table, which are graded as mandatory, conditional, or recommended. MicroVM templates have stricter requirements on the Linux distribution. For more information, see Template configuration.

Level

Requirement

Impact if not met

Mandatory

The architecture is linux/amd64. The manifest list of a multi-architecture image must contain the linux/amd64 variant

The template fails to build

Mandatory

Image acceleration is not enabled for the ACR image

The template fails to build

Mandatory

/etc/passwd and /etc/group are regular files and are writable

The sandbox cannot initialize the default user, and fails to start

Conditional

Bash is located at the fixed path /bin/bash in the image, rather than being discoverable only through PATH

commands.run and pseudo-terminal (PTY) calls fail

Conditional

PATH contains python3 or python

Python run_code is unavailable

Conditional

PATH contains node

JavaScript run_code is unavailable

Conditional

Provide git, openssh-client, CA certificates, and compiler toolchains as needed

The corresponding Git, SSH, HTTPS, and install-from-source operations are unavailable

Recommended

The system PATH contains at least /usr/local/bin, /usr/bin, and /bin

Common commands may be unavailable in the login shell

When you push an image to your own image repository, do not push images with different content to the same tag. Each different image must use a new and unique tag, such as a version number, date, or commit ID, and the template must always reference that specific tag.

Template configuration

Templates are isolated by lightweight virtual machines (MicroVMs) and support snapshots. The start command that runs during the build and the resulting runtime environment are captured in the template snapshot. When you create a sandbox from the template, the runtime state is restored directly. The image must be based on Ubuntu or Debian, and must retain system components such as systemd, openssh-server, and sudo.

As a best practice, always specify disk_size explicitly (this example uses 15360 MB) to avoid specification validation differences caused by platform default values that change between versions.

Select an image source

Official public image

Official public images are provided in all supported regions. The image address is in the fc-e2b-registry.<region>.cr.aliyuncs.com/runtime-v2/<image-name>:<tag> format. No image repository, credentials, or network configurations are required. The region in the image address must be the same as the region of the template.

Example of a minimal build:

resp = pop_client.create_template(
    models.CreateTemplateRequest(
        body=models.CreateTemplateInput(
            name=f"template-gen2-demo-{int(time.time())}",
            team_id=TEAM_ID,
            runtime_config=models.CreateTemplateRuntimeConfig(
                cpu=2,
                memory_size=2048,
                disk_size=15360,
                # Deliver build and runtime logs to SLS in the same region.
                log_config=models.CreateTemplateLogConfig(
                    project="<sls-project>",
                    logstore="<sls-logstore>",
                ),
                sandbox_config=models.CreateTemplateSandboxConfig(
                    image=f"fc-e2b-registry.{REGION}.cr.aliyuncs.com/runtime-v2/base:v0.0.53",
                    generation=2,  # Required. 2 specifies a MicroVM template.
                ),
            ),
        )
    )
)
template_id = resp.body.template_id
state = wait_ready(template_id)
assert state == "ready"

ACR EE image

Use your own image stored in an ACR EE instance.

Preparations:

  1. Create an ACR EE instance in the same Alibaba Cloud account and region as Agent Sandbox. The Economy Edition is not supported.

  2. Add a VPC to the ACR EE instance so that Agent Sandbox can pull images over the VPC.

  3. Create a namespace and an image repository, push the image, and use the VPC domain name of the instance in the image address (-vpc suffix). Example: <instance>-registry-vpc.cn-hangzhou.cr.aliyuncs.com/<namespace>/<image>:<tag>.

Network constraints:

  • At least one VPC association is added on the Access Control page of the ACR EE instance and is in the Active state. Agent Sandbox pulls images over the access IP assigned in the associated VPC. A newly created association is in the Activating state for a period of time, and an expired association causes the pull to fail. Check the association status and access IP on the Access Control page of the instance.

  • The VPC of the image pull network must be a VPC associated with the ACR EE instance. At least one vSwitch in the VPC must be located in a zone supported by Function Compute.

  • The ACR EE image repository, VPC, vSwitch, and Agent Sandbox must be located in the same region.

  • The classless inter-domain routing (CIDR) block of the VPC must use a private address range specified in RFC 1918, which is 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16. A CIDR block that is allocated for use on the Internet cannot be used as a private CIDR block.

  • At least one custom security group must be configured for the VPC, and its outbound rules must allow TCP port 443. By default, the outbound direction of a basic security group allows all access, and no outbound rule is required. By default, the outbound direction of an enterprise security group denies all access, so an outbound rule that allows TCP port 443 must be added.

  • Make sure that the ACR EE instance has an inbound elastic network interface (ENI) in the VPC. If the ENI is deleted, re-associate the VPC to recreate the ENI.

The zones supported by Function Compute change based on regions and features. For the latest list, see Configure network.

Pull method: If only image is specified, the platform derives the ACR EE instance and the repository type from the image address. The platform then pulls the image by using the temporary authorization of the instance and derives the pull network from the VPC associated with the instance. To specify the instance, credentials, or pull network explicitly, also pass acr_instance_id, registry_config.auth_config, and registry_config.network_config. If the pull fails because the vSwitch derived from the instance is located in an unsupported zone, use network_config to explicitly specify the three VPC parameters. The parameters are vpc_id, v_switch_id, and security_group_id.

resp = pop_client.create_template(
    models.CreateTemplateRequest(
        body=models.CreateTemplateInput(
            name=f"template-gen2-acree-{int(time.time())}",
            team_id=TEAM_ID,
            runtime_config=models.CreateTemplateRuntimeConfig(
                cpu=2,
                memory_size=2048,
                disk_size=15360,
                log_config=models.CreateTemplateLogConfig(
                    project="<sls-project>",
                    logstore="<sls-logstore>",
                ),
                sandbox_config=models.CreateTemplateSandboxConfig(
                    image="<instance>-registry-vpc.cn-hangzhou.cr.aliyuncs.com/<namespace>/<image>:<tag>",
                    generation=2,
                    acr_instance_id="cri-xxxxxx",
                    registry_config=models.CreateTemplateRegistryConfig(
                        auth_config=models.CreateTemplateRegistryAuthConfig(
                            user_name="<username>",
                            password="<password>",
                        ),
                        network_config=models.CreateTemplateRegistryNetworkConfig(
                            vpc_id="<vpc-id>",
                            v_switch_id="<vsw-id>",
                            security_group_id="<sg-id>",
                        ),
                    ),
                ),
            ),
        )
    )
)

Configure the start command and ready command

The following example shows how the two commands work together for a pre-deployed HTTP service. During the build, the platform runs start_command as a background process to start the service. The platform then repeatedly runs ready_command until it exits with code 0, which means that the service is ready. Then, the platform creates a template snapshot for the sandbox that is still running. When you create a sandbox from this template, the service is already running and can be accessed immediately. The start command is not run again.

  • Execution time: Both commands are executed only during the template build, and the results are fixed in the snapshot. They are not replayed when a sandbox is created.

  • Format: Both commands are shell commands in string format, and both parameters are optional. If start_command is not specified, no extra start command is executed.

  • Failure handling: If start_command exits prematurely, ready_command keeps failing, or the wait time exceeds 5 minutes, the template build fails. If ready_command is incorrectly specified, the typical symptom is a build timeout instead of a parameter error.

  • Troubleshoot by using logs: Command output and failure causes are delivered to SLS by using log_config. View the logs in the corresponding Logstore.

resp = pop_client.create_template(
    models.CreateTemplateRequest(
        body=models.CreateTemplateInput(
            name=f"template-gen2-service-{int(time.time())}",
            team_id=TEAM_ID,
            runtime_config=models.CreateTemplateRuntimeConfig(
                cpu=2,
                memory_size=2048,
                disk_size=15360,
                log_config=models.CreateTemplateLogConfig(
                    project="<sls-project>",
                    logstore="<sls-logstore>",
                ),
                sandbox_config=models.CreateTemplateSandboxConfig(
                    image=f"fc-e2b-registry.{REGION}.cr.aliyuncs.com/runtime-v2/base:v0.0.53",
                    generation=2,
                    # Run as a background process during the build.
                    start_command="python3 -m http.server 8000",
                    # Run repeatedly. An exit code of 0 once means the service is ready.
                    ready_command="curl -sf http://localhost:8000/ > /dev/null",
                ),
            ),
        )
    )
)
template_id = resp.body.template_id
state = wait_ready(template_id)
assert state == "ready"

After the template is built and becomes ready, use the E2B SDK to create a sandbox and access the service:

from e2b import Sandbox

sandbox = Sandbox.create(
    template=template_id,
    timeout=600,
    # The SDK automatically reads the E2B_API_KEY, E2B_API_URL, and E2B_DOMAIN environment variables.
    api_url=f"https://api.{REGION}.e2b.fc.aliyuncs.com",
    domain=f"{REGION}.e2b.fc.aliyuncs.com",
)
try:
    host = sandbox.get_host(8000)
    print(f"https://{host}")
finally:
    sandbox.kill()

Install storage clients

When you create a custom template, use buildConfig.installStorageClients to automatically install the persistent storage clients. This parameter requires the MicroVM runtime. Set generation: 2 in runtimeConfig.sandboxConfig.

Sample request body:

resp = pop_client.create_template(
    models.CreateTemplateRequest(
        body=models.CreateTemplateInput(
            name=f"template-gen2-storage-{int(time.time())}",
            team_id=TEAM_ID,
            runtime_config=models.CreateTemplateRuntimeConfig(
                sandbox_config=models.CreateTemplateSandboxConfig(
                    image=f"fc-e2b-registry.{REGION}.cr.aliyuncs.com/runtime-v2/base:v0.0.53",
                    generation=2,
                ),
            ),
            build_config=models.CreateTemplateBuildConfig(
                install_storage_clients=True,
            ),
        )
    )
)
template_id = resp.body.template_id
state = wait_ready(template_id)
assert state == "ready"

A successful CreateTemplate call only indicates that the template build task is submitted. Use GetTemplate to query the template state, and create a sandbox from the template only after the state changes to ready.

After you enable this parameter, Template Build pre-installs the storage clients and their runtime dependencies in the template image. This parameter does not create storage resources, perform mounts, or configure the network and access credentials. When you create a sandbox, you must still configure the storage mount parameters, VPC, vSwitch, security group, RAM role, and valid credentials. You must also verify the mount, write, read-back, and delete operations.

The following clients are installed for each storage type:

Storage type

Installed client

OSS / AgenticBucket

ossfs2

JuiceFS

JuiceFS Enterprise Edition client, RADOS runtime libraries, and FUSE 2

AgenticFS

aliyun-alinas-utils (mount.alinas) and nfs-common

For information about how to mount each storage type, see Mount an OSS Volume, Mount an AgenticBucket Volume, Mount a JuiceFS Volume, and Mount an AgenticFS Volume.

Manage templates

Query template information and build status

Use ListTemplates to query Team templates with pagination, and use GetTemplate to query the configuration and build status of a single template. The status.state parameter has the following valid values: pending (waiting for the build), building (build in progress), updating (rebuilding after a configuration update). The remaining values are ready (ready to create sandboxes) and error (the build failed, and status.reason.message provides the cause). Polling at an interval of 5 to 10 seconds is recommended.

Complete example that lists all templates by paging:

import os

from alibabacloud_sandbox20260820 import models
from alibabacloud_sandbox20260820.client import Client as SandboxClient
from alibabacloud_tea_openapi import models as open_api_models

REGION = "cn-hangzhou"
TEAM_ID = "<your-team-id>"

config = open_api_models.Config(
    access_key_id=os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"],
    access_key_secret=os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"],
    region_id=REGION,
    endpoint=f"sandbox.{REGION}.aliyuncs.com",
)
pop_client = SandboxClient(config)

next_token = None
while True:
    request = models.ListTemplatesRequest(team_id=TEAM_ID)
    if next_token:
        request.next_token = next_token
    response = pop_client.list_templates(request)
    for template in response.body.templates:
        print(template.template_id, template.name, template.status.state)
    next_token = response.body.next_token
    if not next_token:
        break

Create a sandbox from a built template

After the template enters the ready state, use the E2B SDK to create a sandbox and check the result:

from e2b import Sandbox

sandbox = Sandbox.create(
    template=template_id,
    timeout=600,
    api_url=f"https://api.{REGION}.e2b.fc.aliyuncs.com",
    domain=f"{REGION}.e2b.fc.aliyuncs.com",
)
try:
    result = sandbox.commands.run("printf hello")
    print(result.stdout)
finally:
    sandbox.kill()

Modify configurations and rebuild

Use UpdateTemplate to modify configuration items in place, such as the image, specification, and network configurations. After you submit the request, the platform automatically rebuilds the template, and the template returns to the updating state and restores the ready state after the build is complete:

pop_client.update_template(
    template_id,
    models.UpdateTemplateRequest(
        team_id=TEAM_ID,
        body=models.PublicUpdateTemplateInput(
            runtime_config=models.PublicUpdateTemplateRuntimeConfig(
                cpu=4,
                memory_size=4096,
            ),
        ),
    ),
)
state = wait_ready(template_id)
assert state == "ready"
  • Pass only the configuration items that you want to modify. The items that you do not pass keep their original values.

Delete a template that is no longer used

pop_client.delete_template(
    template_id, models.DeleteTemplateRequest(team_id=TEAM_ID))
  • A template can be deleted in any state, including the building state. The deletion terminates the build in progress.

Network configuration (advanced)

This section uses a custom template as an example to describe how a sandbox accesses resources after vpc_config is configured, and focuses on how vpc_config works with internet_access. If no VPC is configured, the sandbox can access the Internet over the platform egress by default, and the egress IP address is not fixed.

Select a scenario

Scenario

vpc_config

internet_access

Internet egress requirements of the VPC

Internet access result

Access the VPC, and access the Internet over the platform egress

Configured

Enabled (default)

No fixed Internet egress is required

The Internet is accessible, and the egress IP address is not fixed

Access the VPC, but not the Internet

Configured

Disabled

The VPC provides no Internet egress

The Internet is inaccessible

Access the VPC, and access the Internet over a fixed IP address

Configured

Disabled

The VPC provides an Internet NAT gateway, an elastic IP address (EIP), and the corresponding routes and source network address translation (SNAT) rules

The Internet is accessible over the specified fixed egress IP address

Note that the CIDR block of the VPC must use a private address range specified in RFC 1918 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16). The vSwitch must be located in a zone supported by Function Compute.

Scenario 1: Access the VPC and the Internet over a non-fixed egress IP address

Configure vpc_config, and keep internet_access enabled, which is the default:

runtime_config=models.CreateTemplateRuntimeConfig(
    cpu=2,
    memory_size=2048,
    disk_size=15360,
    internet_access=True,
    vpc_config=models.CreateTemplateVPCConfig(
        vpc_id="<vpc-id>",
        v_switch_ids=["<vsw-id>"],
        security_group_id="<sg-id>",
    ),
    log_config=models.CreateTemplateLogConfig(
        project="<sls-project>",
        logstore="<sls-logstore>",
    ),
    sandbox_config=models.CreateTemplateSandboxConfig(
        image=f"fc-e2b-registry.{REGION}.cr.aliyuncs.com/runtime-v2/base:v0.0.53",
        generation=2,
    ),
)

Verification: After the sandbox is created, access a resource in the VPC, such as an internal domain name or private IP address, and an Internet address, such as curl https://www.aliyun.com. Both are accessible. This method does not provide a fixed Internet egress IP address.

Scenario 2: Access only the VPC but not the Internet

Configure vpc_config, and disable internet_access. Also make sure that the VPC itself provides no Internet egress:

runtime_config=models.CreateTemplateRuntimeConfig(
    cpu=2,
    memory_size=2048,
    disk_size=15360,
    internet_access=False,
    vpc_config=models.CreateTemplateVPCConfig(
        vpc_id="<vpc-id>",
        v_switch_ids=["<vsw-id>"],
        security_group_id="<sg-id>",
    ),
    log_config=models.CreateTemplateLogConfig(
        project="<sls-project>",
        logstore="<sls-logstore>",
    ),
    sandbox_config=models.CreateTemplateSandboxConfig(
        image=f"fc-e2b-registry.{REGION}.cr.aliyuncs.com/runtime-v2/base:v0.0.53",
        generation=2,
    ),
)

Verification: The sandbox can access resources in the VPC, but access to Internet addresses times out or is rejected.

Scenario 3: Access the VPC and the Internet over a fixed egress IP address

Configure vpc_config, and disable internet_access. In the VPC, provide an Internet NAT gateway, an EIP, and the corresponding routes and SNAT rules, so that Internet traffic egresses through the specified gateway. For detailed instructions, see Configure a fixed public IP for a sandbox instance.

  1. VPC preparations: Configure an Internet NAT gateway for the VPC and associate an EIP with the gateway. For the related vSwitches, configure routes that point to the NAT gateway and add SNAT rules. Make sure that the traffic of the vSwitch that hosts the sandbox can reach the Internet over this egress.

  2. Template configurations: the same parameters as Scenario 2 (internet_access=False + vpc_config).

Verification: Query the egress IP address in the sandbox, for example curl ifconfig.me. The EIP that you configured is returned.

The template build parameters of Scenario 2 and Scenario 3 are the same. The difference is whether the VPC provides an Internet egress. Therefore, after internet_access is disabled, the network configuration of the VPC must still be checked to determine whether the sandbox can access the Internet.

FAQ

Why do all build examples include log configurations?

log_config delivers logs from the template build and the sandbox runtime to SLS in your account, which helps locate issues during build and runtime verification. During the build, the logs show the output of the start command and the ready command, and the cause of a build failure. During the run, the logs show the output of the processes inside the sandbox. View the logs in the project and Logstore that you configure in the SLS console. Both must be in the same region as Agent Sandbox.

Why can the Internet still be accessed after internet_access is disabled?

internet_access controls only the Internet egress on the platform side. If the VPC that the template connects to already provides an Internet egress (NAT gateway, EIP, and SNAT rules), the sandbox can still access the Internet over that egress. To completely isolate the sandbox from the Internet, check both the template parameters and the network configuration of the VPC.

How do I obtain a fixed Internet egress IP address?

Use the configuration of Scenario 3. On the template side, disable internet_access and configure vpc_config. On the VPC side, provide an Internet NAT gateway and an EIP, and configure the corresponding routes and SNAT rules. Then check whether the egress IP address in the sandbox is the EIP that you configured.

How do I troubleshoot image pull failures, build failures, or start failures?

  1. Use GetTemplate to query status.reason.message, which provides the failure stage and the cause.

  2. View detailed logs in the SLS Logstore configured by log_config.

  3. Troubleshoot by failure stage:

    • Image pull failure: Check that the image address and tag are correct, the credentials have the pull permission, and the pull network is reachable. Confirm that the VPC association of the ACR EE instance is active and that the outbound direction of the security group allows TCP port 443.

    • Build failure: Check that the image meets the image requirements, such as the linux/amd64 architecture, the /bin/bash path, and /etc/passwd being writable.

    • Start command or ready check failure: Check that start_command does not exit prematurely, and that ready_command probes the real readiness condition and passes within 5 minutes.