# Restrict network egress

Declare the external hosts an agent may reach, understand the tenant ceiling that bounds it, and read a refusal.

By default an agent can reach the platform's own services and nothing else. To let it call an
external API, declare the host in the manifest. The declaration is part of the version's contract:
validated at deploy, frozen for the version, and enforced on every connection at run time.

```yaml title="agent.yaml"
network:
  egress:
    - github.com
    - api.example.com
```

> **Availability:** Author-declared egress is enabled per tenant; without it the list is validated and recorded but no external route exists. See [What is available where](/reference/availability).

- Entries are bare hostnames. An entry covers its subdomains.
- An administrator's per-tenant ceiling only narrows your list; it never adds to it.
- A declaration outside the ceiling fails the deploy in seconds, naming the entry and the ceiling.
- Platform destinations, such as the LLM gateway, are added for you and are not declarable.

## Allow arbitrary public websites

For an agent that needs to browse websites it cannot enumerate in advance, use:

```yaml title="agent.yaml"
network:
  egress_mode: public
```

Omit `egress`, or leave it empty. A non-empty hostname list combined with `public` is rejected.
Without `egress_mode`, the existing hostname-list behavior applies; `allowlist` can also be explicit.

An unset tenant ceiling permits public mode. Any configured hostname ceiling, including an empty
one, rejects it at deploy and session admission. Public-mode `cog agent deploy --dry-run` performs
an authenticated read-only ceiling validation; it creates no build and uploads no source.

Public means any canonical public **hostname through the managed proxy**. Private, metadata,
reserved and platform infrastructure addresses remain blocked, including when public DNS points
to them. It does not enable raw IP destinations, direct sockets, UDP or QUIC. Clients must use the
proxy; transport and port limits still apply. Platform credentials and other policy controls remain
unchanged.

**Availability:** Public mode requires runtime-api, cr-node and cr-helper versions supporting the
versioned egress policy, plus an enabled external route and trusted resolver. An older receiver
refuses activation. Deploy the supporting platform release before deploying a public-mode agent.

The declaration is immutable per agent version. Ceiling tightening blocks new sessions and resumes;
it does not close an active connection. Stop affected sessions for immediate revocation, then start
new sessions under the updated ceiling. Session responses expose `external_egress_policy`, and
connection ledger records identify the mode and ceiling revision in their policy ID.

## Write a valid entry

Each entry is a lowercase hostname with at least two labels, no scheme, port, path, or trailing
dot. Anything else is refused at deploy rather than rewritten, so what you wrote is what is
enforced.

| Not allowed | Why |
|---|---|
| `*.github.com` | No wildcards. `github.com` already covers `api.github.com`. |
| `https://github.com`, `github.com:443`, `github.com/path` | The match is on host alone. |
| `140.82.121.4` | An address has no DNS identity; the allowlist matches the host the agent asks for. |
| loopback or in-cluster names | Names for the sandbox itself or the platform's own network are never declarable. |
| `GitHub.com`, `github.com.` | Not canonical. Write `github.com`. |

Declare the narrowest name that covers what you need. `github.com` admits `api.github.com`; it
does not admit `notgithub.com`.

## The tenant ceiling

Your administrator can set a ceiling for the tenant. Your declaration is intersected with it:

- A ceiling of `github.com` admits a declaration of `api.github.com`, because that is narrower.
- A declaration of `example.com` under a ceiling that does not include it fails the deploy with
  the entry and the ceiling named, before any build is created.
- An unconfigured tenant admits any public hostname, so an unset ceiling behaves as though only
  your manifest applied.

## What is enforced, and where

- **At deploy**: the grammar and the tenant ceiling, before a build exists.
- **At run time**: the managed proxy admits the platform's destinations plus your declared hosts,
  or public hostnames when `egress_mode: public` is selected. Every external destination must
  resolve to a checked public address. A refused connection fails at the agent with the host named.

## Change the list

The list is immutable for a version. To add or remove a host, change the manifest and deploy a new
version, then roll it out. See [Deploy a version](/guides/deploy/deploy-a-version).

## Where to go next

- [Policy, approvals, and evidence](/concepts/governance): how egress fits with the other
  ceilings.
- [Agent manifest](/reference/agent-manifest#network): the field reference.
