---
title: Network Egress (public)
description: A Harness Runtime sandbox reaches any host by default, and naming even one allowed host turns on an allowlist that denies everything else.
product: Managed Agents
url: https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/egress/
last_updated: "2026-09-21"
---

> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document).

# Network Egress (public)

DigitalOcean Harness Runtime provides managed, hardware-isolated microVM sandboxes with built-in tools such as Chromium to run harnesses and execute arbitrary code. Rich lifecycle APIs preserve conversational history and working state across sessions, letting you pause, resume, and fork work to control costs and adapt to the nonlinear nature of agentic workflows. Scale complete agents such as Claude Code or use sandboxes independently for code execution, all through the same service. See [What You Can Build](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/details/what-you-can-build/index.html.md) for example use cases.

Egress is the outbound network access a Harness Runtime sandbox has. By default there is no restriction: a session with no `egress` field in its [environment spec](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/reference/environment-spec/index.html.md) reaches any host it wants.

Restricting egress is opt-in, and it is a switch rather than a dial. The moment you name one allowed host, the allowlist turns on and every host you did not name is denied.

**Note**:

  Because the default is open, an environment that handles sensitive data should set an explicit allowlist. Code running in a sandbox can send workspace contents to any reachable host, so the allowlist is what bounds where data can go.

## The Three Forms

The `egress` field takes exactly one of three shapes.

| Form | Example | Meaning |
|---|---|---|
| Omitted | no `egress` field | Unrestricted. The session reaches any host, and no platform defaults are added. |
| Scalar | `egress: unrestricted` | The same thing, stated explicitly. Cannot be combined with an allowlist or a VPC. |
| Host list | `egress: [api.github.com, pypi.org]` | Allowlist on. Hostnames only. Platform defaults are merged in. |
| Object | see [Allowlists and VPCs](#allowlists-and-vpcs) | Allowlist and VPC path together, through `allow_hosts`, `allow_ips`, `vpc_uuid`, and `subnet_uuid`. |

The omitted and scalar forms mean the same thing. Writing `unrestricted` explicitly is worth doing when you want a reader of the spec to see that the choice was deliberate.

## What the Platform Adds

Once the allowlist is on, the platform merges in the hosts a session cannot function without, so a short allowlist does not break the basics:

- Platform hosts, currently `api.github.com`, `github.com`, and `registry.digitalocean.com`.
- Hosts the adapter requires. A `codex-agentapi` session gets the OpenAI endpoints it depends on.
- The model inference endpoints configured for the session.

Omitting `egress` never adds these, because an unset field must not restrict a session that would otherwise be unrestricted. There is nothing to add to when there is no allowlist.

One exception is worth knowing. An allowlist built only from `allow_ips` does not pull in the platform hosts, since injecting hostnames into an IP-only request would invent destinations you never named. That allowlist is still on, so hostname traffic, including GitHub and model endpoints, is denied. Session creation returns a warning when it sees this. Pair `allow_ips` with `allow_hosts` when you need both.

## Allowlists and VPCs

The object form separates two independent choices: which destinations are allowed, and which path the traffic takes out.

```yaml
egress:
  allow_hosts: [api.github.com, mcp.example.com]
  allow_ips: ["203.0.113.10"]
  vpc_uuid: 01901234-5678-7890-abcd-ef0123456789
```

`allow_hosts` and `allow_ips` are the destination allowlist. `allow_ips` takes exact IPv4 or IPv6 literals rather than CIDR ranges, and it matches only traffic addressed to a literal IP. A hostname that resolves to an allowed IP is still denied unless that hostname also appears in `allow_hosts`.

`vpc_uuid` and `subnet_uuid` choose the path. Without them, traffic leaves through public NAT. With them, it leaves through your VPC. An object that sets only `vpc_uuid` and no allowlist gives you the VPC path with unrestricted destinations. Adding `allow_hosts` turns the allowlist on as well.

Your team must own the VPC and it must be in a region the service runs in, both checked when the session is created. VPC attachment cannot change afterward, so a session cannot be moved onto or off a VPC once it exists. Setting `subnet_uuid` without `vpc_uuid` is rejected.

## Requesting Hosts

When you do set an allowlist, declare every host the agent needs: package registries the build pulls from, your own APIs, and self-hosted services.

```yaml
egress:
  - registry.npmjs.org
  - api.internal.example.com
```

The most common omission is an MCP server. Attaching one under `tools` does not reliably allowlist its host, so list that host under `egress` as well.

Tools reached through [Action Gateway](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/how-to/connect-action-gateway/index.html.md) are the exception that needs no entry. The gateway calls the provider from its own infrastructure rather than from your sandbox, so the provider’s host never appears in your allowlist.

A connection to a host outside an active allowlist fails inside the sandbox. That failure usually surfaces as a tool or command that times out rather than as a permissions error, which makes a missing host harder to diagnose than it should be. When a build hangs fetching a dependency, an absent egress entry is the first thing to check.

## Egress Requests Are Narrowed, Never Widened

Everything in an environment spec is a request. The platform resolves the final policy by combining your request with team and platform policy, and that resolution can only narrow the result. A host your team’s policy prohibits stays blocked no matter what the spec asks for.

The same principle governs the relationship between egress and permissions. The `permissions.network` block restricts what the agent may reach within whatever egress allows. It is a second, tighter gate, not an alternative route to a host egress excludes. See [Permission Policies](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/concepts/permissions/index.html.md).

## Traffic to Third-Party Services

Outbound HTTPS to a service you declared travels as ordinary TLS. DigitalOcean does not terminate it, inspect it, or add identity to it. A third-party MCP server therefore cannot tell which session called it from the connection alone, and must rely on the credential you configured.

Requests to DigitalOcean-operated endpoints are treated differently. The platform stamps session identity onto them at the network boundary and overwrites any values the sandbox tried to set, so an agent cannot present itself as a different session.

## Inbound Connections

Egress covers outbound traffic. Sandboxes accept no inbound connections from the internet, and a service the agent starts is not reachable by URL. To use one, tunnel to it with [port forwarding](https://docs.digitalocean.com/products/managed-agents/agent-harness-runtime/how-to/forward-ports/index.html.md), which opens a local port on your machine rather than exposing the sandbox.