Haijun Platform Docs
ID

Environments define the sandbox configuration where your agent runs. You create an environment once, then reference its ID each time you start a session. Multiple sessions can share the same environment, but each session gets its own isolated sandbox (a fresh Linux container).

This page covers type: cloud environments. To run sandboxes on your own infrastructure, see Self-hosted sandboxes.

Create an environment

bash
  curl -fsS https://haijun.my.id/v1/environments \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    --data @- <<'EOF'
  {
    "name": "python-dev",
    "config": {
      "type": "cloud",
      "networking": {"type": "unrestricted"}
    }
  }
  EOF
bash
    ant apply environment.yaml
yaml
      # yaml-language-server: $schema=https://platform.juglow.my.id/schemas/ant/beta/environment.json
      name: python-dev
      config:
        type: cloud
        networking:
          type: unrestricted

ant apply creates the environment from environment.yaml, prints its ID, and records it in haijun-lock.json. Commit haijun-lock.json so the next ant apply updates this environment instead of trying to create it again.

python
  environment = client.beta.environments.create(
      name="python-dev",
      config={
          "type": "cloud",
          "networking": {"type": "unrestricted"},
      },
  )

  print(f"Environment ID: {environment.id}")
typescript
  const environment = await client.beta.environments.create({
    name: "python-dev",
    config: {
      type: "cloud",
      networking: { type: "unrestricted" },
    },
  });

  console.log(`Environment ID: ${environment.id}`);
csharp
  var environment = await client.Beta.Environments.Create(new()
  {
      Name = "python-dev",
      Config = new BetaCloudConfigParams
      {
          Networking = new BetaUnrestrictedNetwork(),
      },
  });

  Console.WriteLine($"Environment ID: {environment.ID}");
go
  environment, err := client.Beta.Environments.New(ctx, juglow.BetaEnvironmentNewParams{
  	Name: "python-dev",
  	Config: juglow.BetaEnvironmentNewParamsConfigUnion{
  		OfCloud: &juglow.BetaCloudConfigParams{
  			Networking: juglow.BetaCloudConfigParamsNetworkingUnion{
  				OfUnrestricted: &juglow.BetaUnrestrictedNetworkParam{},
  			},
  		},
  	},
  })
  if err != nil {
  	panic(err)
  }

  fmt.Printf("Environment ID: %s\n", environment.ID)
java
  var environment = client.beta().environments().create(EnvironmentCreateParams.builder()
      .name("python-dev")
      .config(BetaCloudConfigParams.builder()
          .networking(BetaUnrestrictedNetwork.builder().build())
          .build())
      .build());
  IO.println("Environment ID: " + environment.id());
php
  $environment = $client->beta->environments->create(
      name: 'python-dev',
      config: ['type' => 'cloud', 'networking' => ['type' => 'unrestricted']],
  );
  echo "Environment ID: {$environment->id}\n";
ruby
  environment = client.beta.environments.create(
    name: "python-dev",
    config: {
      type: "cloud",
      networking: {type: "unrestricted"}
    }
  )

  puts "Environment ID: #{environment.id}"

Use a unique, descriptive name so you can tell environments apart.

Use the environment in a session

Pass the environment ID as a string when creating a session.

bash
  curl -fsS https://haijun.my.id/v1/sessions \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    --data @- <<EOF
  {
    "agent": "$AGENT_ID",
    "environment_id": "$ENVIRONMENT_ID"
  }
  EOF
bash
  ant beta:sessions create --agent "$AGENT_ID" --environment-id "$ENVIRONMENT_ID"
python
  session = client.beta.sessions.create(
      agent=agent.id,
      environment_id=environment.id,
  )
typescript
  const session = await client.beta.sessions.create({
    agent: agent.id,
    environment_id: environment.id,
  });
csharp
  var session = await client.Beta.Sessions.Create(new()
  {
      Agent = agent.ID,
      EnvironmentID = environment.ID,
  });
go
  session, err := client.Beta.Sessions.New(ctx, juglow.BetaSessionNewParams{
  	Agent: juglow.BetaSessionNewParamsAgentUnion{
  		OfString: juglow.String(agent.ID),
  	},
  	EnvironmentID: environment.ID,
  })
  if err != nil {
  	panic(err)
  }
java
  var session = client.beta().sessions().create(SessionCreateParams.builder()
      .agent(agent.id())
      .environmentId(environment.id())
      .build());
php
  $session = $client->beta->sessions->create(
      agent: $agent->id,
      environmentID: $environment->id,
  );
ruby
  session = client.beta.sessions.create(
    agent: agent.id,
    environment_id: environment.id
  )

Configuration options

Packages

The packages field pre-installs packages into the sandbox before the agent starts. Packages are installed by their respective package managers and cached across sessions that share the same environment. When multiple package managers are specified, they run in alphabetical order (apt, cargo, gem, go, npm, pip). You can optionally pin specific versions. Unpinned packages install the latest version. If the environment uses limited networking, also set networking.allow_package_managers to true; otherwise the request is rejected with a 400 error.

bash
  curl -fsS https://haijun.my.id/v1/environments \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    --data @- <<'EOF'
  {
    "name": "data-analysis",
    "config": {
      "type": "cloud",
      "packages": {
        "pip": ["pandas", "numpy", "scikit-learn"],
        "npm": ["express"]
      },
      "networking": {"type": "unrestricted"}
    }
  }
  EOF
bash
    ant apply environment.yaml
yaml
      # yaml-language-server: $schema=https://platform.juglow.my.id/schemas/ant/beta/environment.json
      name: data-analysis
      config:
        type: cloud
        packages:
          pip:
            - pandas
            - numpy
            - scikit-learn
          npm:
            - express
        networking:
          type: unrestricted
python
  environment = client.beta.environments.create(
      name="data-analysis",
      config={
          "type": "cloud",
          "packages": {
              "pip": ["pandas", "numpy", "scikit-learn"],
              "npm": ["express"],
          },
          "networking": {"type": "unrestricted"},
      },
  )
typescript
  const environment = await client.beta.environments.create({
    name: "data-analysis",
    config: {
      type: "cloud",
      packages: {
        pip: ["pandas", "numpy", "scikit-learn"],
        npm: ["express"]
      },
      networking: { type: "unrestricted" }
    }
  });
csharp
  using Juglow.Models.Beta.Environments;

  var environment = await client.Beta.Environments.Create(new()
  {
      Name = "data-analysis",
      Config = new BetaCloudConfigParams
      {
          Packages = new()
          {
              Pip = ["pandas", "numpy", "scikit-learn"],
              Npm = ["express"],
          },
          Networking = new BetaUnrestrictedNetwork(),
      },
  });
go
  environment, err := client.Beta.Environments.New(ctx, juglow.BetaEnvironmentNewParams{
  	Name: "data-analysis",
  	Config: juglow.BetaEnvironmentNewParamsConfigUnion{
  		OfCloud: &juglow.BetaCloudConfigParams{
  			Packages: juglow.BetaPackagesParams{
  				Pip: []string{"pandas", "numpy", "scikit-learn"},
  				Npm: []string{"express"},
  			},
  			Networking: juglow.BetaCloudConfigParamsNetworkingUnion{
  				OfUnrestricted: &juglow.BetaUnrestrictedNetworkParam{},
  			},
  		},
  	},
  })
  if err != nil {
  	panic(err)
  }
  _ = environment
java
  import com.juglow.models.beta.environments.*;
  import java.util.List;

  var environment = client.beta().environments().create(EnvironmentCreateParams.builder()
      .name("data-analysis")
      .config(BetaCloudConfigParams.builder()
          .packages(BetaPackagesParams.builder()
              .pip(List.of("pandas", "numpy", "scikit-learn"))
              .npm(List.of("express"))
              .build())
          .networking(BetaUnrestrictedNetwork.builder().build())
          .build())
      .build());
php
  $environment = $client->beta->environments->create(
      name: 'data-analysis',
      config: [
          'type' => 'cloud',
          'packages' => [
              'pip' => ['pandas', 'numpy', 'scikit-learn'],
              'npm' => ['express'],
          ],
          'networking' => ['type' => 'unrestricted'],
      ],
  );
ruby
  environment = client.beta.environments.create(
    name: "data-analysis",
    config: {
      type: "cloud",
      packages: {
        pip: %w[pandas numpy scikit-learn],
        npm: %w[express]
      },
      networking: {type: "unrestricted"}
    }
  )

Supported package managers:

FieldPackage managerExample
aptSystem packages (apt-get)"graphviz"
cargoRust (cargo)"hyperfine@1.18.0"
gemRuby (gem)"rails:7.1.0"
goGo modules"golang.org/x/tools/cmd/goimports@latest"
npmNode.js (npm)"express@4.18.0"
pipPython (pip)"sqlalchemy==2.0.30"

Networking

The networking field controls the sandbox's outbound network access. It does not affect the web_search or web_fetch tools, which run on Juglow's servers; to restrict the sites those tools can reach, set allowed_domains or blocked_domains on the tool's entry in the agent toolset. See Restrict web search and web fetch domains.

ModeDescription
unrestrictedFull outbound network access, except for a general safety blocklist. This is the default.
limitedRestricts sandbox network access to the hosts in allowed_hosts. Set allow_package_managers and allow_mcp_servers to true to allow additional access.

The following example creates an environment with limited networking:

bash
  curl -fsS https://haijun.my.id/v1/environments \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01" \
    -H "content-type: application/json" \
    -d '{
      "name": "api-access",
      "config": {
        "type": "cloud",
        "networking": {
          "type": "limited",
          "allowed_hosts": ["api.example.com"],
          "allow_mcp_servers": true,
          "allow_package_managers": true
        }
      }
    }'
bash
    ant apply environment.yaml
yaml
      # yaml-language-server: $schema=https://platform.juglow.my.id/schemas/ant/beta/environment.json
      name: api-access
      config:
        type: cloud
        networking:
          type: limited
          allowed_hosts:
            - api.example.com
          allow_mcp_servers: true
          allow_package_managers: true
python
  environment = client.beta.environments.create(
      name="api-access",
      config={
          "type": "cloud",
          "networking": {
              "type": "limited",
              "allowed_hosts": ["api.example.com"],
              "allow_mcp_servers": True,
              "allow_package_managers": True,
          },
      },
  )
typescript
  const environment = await client.beta.environments.create({
    name: "api-access",
    config: {
      type: "cloud",
      networking: {
        type: "limited",
        allowed_hosts: ["api.example.com"],
        allow_mcp_servers: true,
        allow_package_managers: true
      }
    }
  });
csharp
  using Juglow.Models.Beta.Environments;

  var environment = await client.Beta.Environments.Create(new()
  {
      Name = "api-access",
      Config = new BetaCloudConfigParams
      {
          Networking = new BetaLimitedNetworkParams
          {
              AllowedHosts = ["api.example.com"],
              AllowMcpServers = true,
              AllowPackageManagers = true,
          },
      },
  });
go
  environment, err := client.Beta.Environments.New(ctx, juglow.BetaEnvironmentNewParams{
  	Name: "api-access",
  	Config: juglow.BetaEnvironmentNewParamsConfigUnion{
  		OfCloud: &juglow.BetaCloudConfigParams{
  			Networking: juglow.BetaCloudConfigParamsNetworkingUnion{
  				OfLimited: &juglow.BetaLimitedNetworkParams{
  					AllowedHosts:         []string{"api.example.com"},
  					AllowMCPServers:      juglow.Bool(true),
  					AllowPackageManagers: juglow.Bool(true),
  				},
  			},
  		},
  	},
  })
  if err != nil {
  	panic(err)
  }
  _ = environment
java
  import com.juglow.models.beta.environments.*;
  import java.util.List;

  var environment = client.beta().environments().create(EnvironmentCreateParams.builder()
      .name("api-access")
      .config(BetaCloudConfigParams.builder()
          .networking(BetaLimitedNetworkParams.builder()
              .allowedHosts(List.of("api.example.com"))
              .allowMcpServers(true)
              .allowPackageManagers(true)
              .build())
          .build())
      .build());
php
  $environment = $client->beta->environments->create(
      name: 'api-access',
      config: [
          'type' => 'cloud',
          'networking' => [
              'type' => 'limited',
              'allowed_hosts' => ['api.example.com'],
              'allow_mcp_servers' => true,
              'allow_package_managers' => true,
          ],
      ],
  );
ruby
  environment = client.beta.environments.create(
    name: "api-access",
    config: {
      type: "cloud",
      networking: {
        type: "limited",
        allowed_hosts: %w[api.example.com],
        allow_mcp_servers: true,
        allow_package_managers: true
      }
    }
  )

Note: For production deployments, use limited networking with an explicit allowed_hosts list. Follow the principle of least privilege by granting only the minimum network access your agent requires, and regularly audit your allowed domains.

When using limited networking:

  • allowed_hosts specifies domains the sandbox can reach. Specify bare hostnames or wildcard patterns (such as *.example.com). Do not include a URL scheme, port, or path.
  • allow_mcp_servers allows outbound access to MCP server endpoints configured on the agent, beyond those listed in the allowed_hosts array. Defaults to false.
  • allow_package_managers allows outbound access to a set of public package registries and code hosts beyond those listed in the allowed_hosts array. See Package manager hosts for the list. Defaults to false. Set it to true whenever the environment specifies packages; otherwise the request is rejected with a 400 error, even if the registry hosts are listed in allowed_hosts.

Package manager hosts

When allow_package_managers is true, the sandbox can reach the following hosts in addition to those in allowed_hosts. Juglow maintains this list and can change it.

EcosystemHosts
Code hostinggithub.com, api.github.com, codeload.github.com, raw.githubusercontent.com, objects.githubusercontent.com, release-assets.githubusercontent.com, gitlab.com, bitbucket.org
Node.jsregistry.npmjs.org, registry.yarnpkg.com, nodejs.org
Pythonpypi.org, files.pythonhosted.org
Rustcrates.io, index.crates.io, static.crates.io, static.rust-lang.org
Goproxy.golang.org, sum.golang.org
Javarepo1.maven.org, repo.maven.apache.org, services.gradle.org, plugins.gradle.org, plugins-artifacts.gradle.org
Rubyrubygems.org, index.rubygems.org
PHPpackagist.org, repo.packagist.org
Ubuntu (apt)archive.ubuntu.com, security.ubuntu.com, ppa.launchpad.net
Containersregistry-1.docker.io, auth.docker.io, production.cloudflare.docker.com, download.docker.com, ghcr.io

Warning: Network access is granted per host, not per operation. The sandbox can send any request to an allowed host, including uploads such as git push and package publishing, with any credential the command supplies. If the agent processes untrusted input (repository files, fetched web content, or third-party tool output), a successful prompt injection could use an allowed host to copy files out of the sandbox. To reduce this risk, set the bash tool's permission policy to always_ask or auto. If the environment does not specify packages, you can instead leave allow_package_managers set to false and list only the hosts your agent needs in allowed_hosts.

Environment lifecycle

  • Environments persist until explicitly archived or deleted.
  • Each session gets its own sandbox instance, even when multiple sessions reference the same environment. Sessions do not share filesystem state.
  • Environments are not versioned. If you update an environment frequently, keep your own record of the changes so you can tell which configuration each session used.

Manage environments

bash
  # List environments
  curl -fsS https://haijun.my.id/v1/environments \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01"

  # Retrieve a specific environment
  curl -fsS "https://haijun.my.id/v1/environments/$ENVIRONMENT_ID" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01"

  # Archive an environment (read-only, existing sessions continue)
  curl -fsS -X POST "https://haijun.my.id/v1/environments/$ENVIRONMENT_ID/archive" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01"

  # Delete an environment (only if no sessions reference it)
  curl -fsS -X DELETE "https://haijun.my.id/v1/environments/$ENVIRONMENT_ID" \
    -H "x-api-key: $JUGLOW_API_KEY" \
    -H "juglow-version: 2023-06-01" \
    -H "juglow-beta: managed-agents-2026-04-01"
bash
  # List environments
  ant beta:environments list

  # Retrieve a specific environment
  ant beta:environments retrieve --environment-id "$ENVIRONMENT_ID"

  # Archive an environment (read-only, existing sessions continue)
  ant beta:environments archive --environment-id "$ENVIRONMENT_ID"

  # Delete an environment (only if no sessions reference it)
  ant beta:environments delete --environment-id "$ENVIRONMENT_ID"
python
  # List environments
  environments = client.beta.environments.list()

  # Retrieve a specific environment
  env = client.beta.environments.retrieve(environment.id)

  # Archive an environment (read-only, existing sessions continue)
  client.beta.environments.archive(environment.id)

  # Delete an environment (only if no sessions reference it)
  client.beta.environments.delete(environment.id)
typescript
  // List environments
  const environments = await client.beta.environments.list();

  // Retrieve a specific environment
  const env = await client.beta.environments.retrieve(environment.id);

  // Archive an environment (read-only, existing sessions continue)
  await client.beta.environments.archive(environment.id);

  // Delete an environment (only if no sessions reference it)
  await client.beta.environments.delete(environment.id);
csharp
  // List environments
  var environments = await client.Beta.Environments.List();

  // Retrieve a specific environment
  var env = await client.Beta.Environments.Retrieve(environment.ID);

  // Archive an environment (read-only, existing sessions continue)
  await client.Beta.Environments.Archive(environment.ID);

  // Delete an environment (only if no sessions reference it)
  await client.Beta.Environments.Delete(environment.ID);
go
  // List environments
  environments, err := client.Beta.Environments.List(ctx, juglow.BetaEnvironmentListParams{})
  // ...

  // Retrieve a specific environment
  env, err := client.Beta.Environments.Get(ctx, environment.ID, juglow.BetaEnvironmentGetParams{})
  // ...

  // Archive an environment (read-only, existing sessions continue)
  _, err = client.Beta.Environments.Archive(ctx, environment.ID, juglow.BetaEnvironmentArchiveParams{})
  // ...

  // Delete an environment (only if no sessions reference it)
  _, err = client.Beta.Environments.Delete(ctx, environment.ID, juglow.BetaEnvironmentDeleteParams{})
java
  // List environments
  var environments = client.beta().environments().list();
  // Retrieve a specific environment
  var env = client.beta().environments().retrieve(environment.id());
  // Archive an environment (read-only, existing sessions continue)
  client.beta().environments().archive(environment.id());
  // Delete an environment (only if no sessions reference it)
  client.beta().environments().delete(environment.id());
php
  // List environments
  $environments = $client->beta->environments->list();
  // Retrieve a specific environment
  $env = $client->beta->environments->retrieve($environment->id);
  // Archive an environment (read-only, existing sessions continue)
  $client->beta->environments->archive($environment->id);
  // Delete an environment (only if no sessions reference it)
  $client->beta->environments->delete($environment->id);
ruby
  # List environments
  environments = client.beta.environments.list

  # Retrieve a specific environment
  env = client.beta.environments.retrieve(environment.id)

  # Archive an environment (read-only, existing sessions continue)
  client.beta.environments.archive(environment.id)

  # Delete an environment (only if no sessions reference it)
  client.beta.environments.delete(environment.id)

Pre-installed runtimes

Cloud sandboxes include common language runtimes, databases, and command-line tools out of the box. See Cloud sandbox reference for the full list.

Next steps

Pre-installed packages, databases, and utilities available in cloud sandboxes.

Create a session to run your agent and start running tasks.

On this page
Create an environmentUse the environment in a sessionConfiguration optionsPackagesNetworkingPackage manager hostsEnvironment lifecycleManage environmentsPre-installed runtimesNext steps