Skip to content

Network Access Control

By default, agents with the web_fetch capability can access any public URL. Network access lists let you restrict which hosts and URLs an agent can reach, giving you fine-grained control over outbound network access.

Access lists are configured at three levels — harness, agent, and session — and each layer can only make access more restrictive, never less.

A network access list has two fields:

FieldPurposeDefault
allowedIf non-empty, only matching URLs are permitted[] (no restriction)
blockedAlways denied, even if matched by allowed[]

Patterns support three formats:

FormatExampleMatches
Exact domainapi.example.comAny URL on that exact domain
Wildcard domain*.example.comThe domain and all subdomains
URL prefixhttps://api.example.com/v1/URLs starting with that prefix

Domain matching is case-insensitive. Blocked patterns always take precedence over allowed patterns.

Set a network access list when creating or updating an agent:

POST /v1/agents
{
"name": "Research Agent",
"system_prompt": "You are a research assistant.",
"network_access": {
"allowed": ["*.github.com", "api.openai.com"],
"blocked": ["evil.example.com"]
}
}

Restrict a specific session further:

POST /v1/sessions
{
"agent_id": "agent_...",
"network_access": {
"blocked": ["internal.corp"]
}
}

To clear a network access list on update, send an empty object:

PATCH /v1/agents/{id}
{
"network_access": {}
}

Network access lists merge across three layers using restrictive semantics — each layer can only narrow what the parent allows:

Harness (baseline)
∩ Agent (can only restrict further)
∩ Session (can only restrict further)

The merge rules:

FieldRuleRationale
allowedIntersection — child entries kept only if covered by a parent patternChild cannot grant access the parent didn’t allow
blockedUnion — all blocked patterns combinedChild cannot un-block a parent’s block

If a child layer doesn’t set allowed, it inherits the parent’s list unchanged.

Given this configuration:

Harness: allowed: ["*.github.com", "*.openai.com"]
Agent: allowed: ["api.github.com"], blocked: ["evil.com"]
Session: blocked: ["malware.github.com"]

The effective policy for the session is:

  • Allowed: ["api.github.com"] — kept because it’s a subset of *.github.com; *.openai.com dropped because the agent didn’t include it
  • Blocked: ["evil.com", "malware.github.com"] — union of all layers

Only api.github.com is reachable, and both evil.com and malware.github.com are explicitly denied.

If a harness inherits from a parent harness (via parent_harness_id), the network access list is merged through the inheritance chain before any agent or session layer is applied. The same intersection/union rules apply.

The merged network access list is checked in web_fetch before every HTTP request. If a URL doesn’t match the effective policy, the tool returns an error:

URL blocked by network access policy: https://blocked-domain.com/path

Standard SSRF protections (blocking private IPs, loopback, cloud metadata endpoints) are always enforced regardless of the network access list.

CapabilityEnforcedNotes
web_fetchYesChecked before every HTTP request
virtual_bashN/ANo network builtins (curl/wget not available)