Skip to main content
Policy normally decides one thing: may this caller invoke this tool with these arguments. That check sees what the model asked for. It does not see where a tool actually goes on the network. A tool that shells out to curl, or an SDK that makes its own HTTP calls, can reach any host without the tool-argument policy noticing. The egress proxy adds a second check. It routes the process’s outbound HTTP(S) through an in-process forward proxy and asks the same PolicyEnforcer about each request, keyed on the destination host. Egress becomes another gated tool, net.http_request, sharing the decision type and the audit trail with everything else. This is separate from the workspace sandbox, which enforces network rules in the kernel for the bash tool only. The egress proxy is framework-agnostic and covers any HTTP client running in the agent’s process.

Turn it on

egress_guard starts the proxy and points the process’s HTTP clients at it (via HTTP_PROXY / HTTPS_PROXY, which most clients read by default). The agent’s request code does not change.
Requests to api.github.com connect. Anything else is refused before a byte leaves the process, and the deny lands in the audit stream next to the tool-call decisions.

Write the policy

In code, net_allow renders the host allowlist into constraints:
The same rule in YAML, where egress is the net.http_request tool:
Pass subdomains=["example.com"] to match the apex and any *.example.com. A host restriction is required: net_allow() with only a scheme or port filter raises, since a rule with no host clause would allow every host. Use any_host=True when you do want that.

What the proxy sees

For HTTPS, the client opens the connection with a plaintext CONNECT api.github.com:443 line before TLS starts. The proxy decides on the host there, then relays the encrypted bytes without touching them. It never holds the keys, so on HTTPS a request exposes only its host, port, and scheme. Almost all API traffic is HTTPS, so plan around host-level control. Reading the path or body of an HTTPS request needs TLS interception, which the SDK does not do (see Limits).

Layering

Egress control sits alongside the other enforcement points. Deploy whichever combination fits the threat model.

Limits

  • Bypassable unless the runtime forces it. The proxy relies on HTTP_PROXY / HTTPS_PROXY. Code that sets trust_env=False, or a tool that unsets those vars, skips it. Treat it as intent-shaping in a plain SDK deployment. A sandbox that forces all egress through the proxy is the hard boundary.
  • Host-level on HTTPS. Path, query, and body are encrypted. Constraining those needs TLS interception, which belongs to a controlled runtime rather than a library.
  • One guard per process. egress_guard sets process-global proxy env vars, so a nested or concurrent guard raises instead of clobbering the first.
For destinations that don’t speak HTTP (a Postgres or Redis connection, say), the same policy shape works but the proxy would have to understand that protocol. That’s not covered today.