VPN exits

Your agent's traffic, out another door.

An agent thread browses through a WireGuard exit node, so a site never sees your home address. Pick an exit, or let auto pick the nearest.

How a packet leaves

One thread, one tunnel.

On Linux an agent thread runs in its own network namespace, and WireGuard is its only route. The coordinator holds public keys only.

How an agent thread's traffic reaches the internet through an exitAn agent thread runs in its own network namespace on your computer, with WireGuard as its only route. Its packets go to a CommandAGI exit node, which drops mail ports and blocklisted addresses and sends the rest to the site. A Durable Object reaches the same exit through its CONNECT proxy. The coordinator, the api worker, gives each node its netmap and keeps public keys and usage, never a packet.WireGuard/UDPCONNECTnetmap 15 s · usage 60 sAgent threadits own net namespace, wg0 itsonly routeA Durable Objecta monitor's read, via: vpnExit: fsn-1 · hel-1 · nbg-1nftables NAT, blocklists, no SMTPThe sitesees the exit's addressCoordinatorapi worker + D1: keys, netmaps,usage → creditsHow an agent thread's traffic reaches the internet through an exitAn agent thread runs in its own network namespace on your computer, with WireGuard as its only route. Its packets go to a CommandAGI exit node, which drops mail ports and blocklisted addresses and sends the rest to the site. A Durable Object reaches the same exit through its CONNECT proxy. The coordinator, the api worker, gives each node its netmap and keeps public keys and usage, never a packet.WireGuard/UDPCONNECTnetmap 15 s · usage 60 sAgent threadits own netnamespace, wg0 itsonly routeA Durable Objecta monitor's read, via:vpnExit: fsn-1 · hel-1 ·nbg-1nftables NAT,blocklists, no SMTPThe sitesees the exit's addressCoordinatorapi worker + D1:keys, netmaps,usage → credits

Three exits, answering now.

CommandAGI's own account asked the coordinator for its exits. Each one had polled its netmap seconds before. CommandAGI's monitors read sites through them, and each read holds credits first (see credits). Overlay keys and public addresses are left out here.

Read by scripts/sites/case-studies.mjs; kept in case-studies/vpn-exits/stats.json in CommandAGI's Drive.

GET /v1/vpn/nodes · user-commandagireal answer · production · 2026-11-04 16:53 UTC
16:53:39.258 fsn-1  operator=commandagi  DE · EU  hetzner  $0.0013/GB  proxy: yes  ok
16:53:37.787 hel-1  operator=commandagi  FI · EU  hetzner  $0.0013/GB  proxy: yes  ok
16:53:43.523 nbg-1  operator=commandagi  DE · EU  hetzner  $0.0013/GB  proxy: yes  ok

Exits as code

An exit is one line of code.

CommandAGI's exits are files in its own Drive: infra/vpn/<name>/exit.tsx. Ten are declared; three are on. make infra-plan compares the files with what the providers run.

tsx
// infra/vpn/fsn-1/exit.tsx
import { HetznerExit } from "../hetzner.tsx";

export default () => <HetznerExit name="fsn-1" region="fsn1" country="DE" continent="EU" size="cax11" maxMonthlyUsd={6.99} />;

auto picks for you

Your own exits first, then CommandAGI's: the same country, then the same continent, then the lowest measured round trip.

It fails closed

Once a thread has an exit, it never goes out another way. An exit that refuses the thread stops the turn.

Billed by the byte

Hetzner's price, $0.0013 a GB with headroom for the exchange rate, held from your credits before the bytes move.

Give an agent its own exit.

Make an exit grant for the agent in settings → network, and its thread goes out through it.