Outbound connections

Node and plugin outbound connections

Node and plugin outbound connections for cluster operators and plugin authors.

For: cluster operators and plugin authors.

The node

HostWhyWhenTurn it off
github.com (uv), releases.astral.sh (Python), pypi.org and files.pythonhosted.org (the runtime's packages), nodejs.org (Node.js)What a node installs before its runtime startsOnly when the edge mirrors no toolchain, and the node lacks it. make dist and make toolchain build the mirror; with it, nodes download all of this from the edgeServe dist/toolchain from the edge, and run nodes with oz0-node run --offline (or OZ0_NODE_OFFLINE=1) so they never fall back
pypi.org, registry.npmjs.org, or the index a plugin namesA plugin's own packages, while it installs (uv, npm), and on a node with a release age, how old its lock's pins areWhen a plugin with Python or npm dependencies installsAn offline node takes a plugin's Python packages from the edge's toolchain: add them with oz0-node toolchain fetch --plugin <folder>. npm packages are not mirrored: an offline node still downloads them from registry.npmjs.org, so set npm_config_registry on the node to your mirror (and UV_DEFAULT_INDEX on a node that is not offline)
pypi.org and files.pythonhosted.org (mlx-lm and the packages it needs)The node's own mlx-lm for the MLX servers it starts, from the lock built into the node: every package at its version and hashOnly when models.yaml has a kind: mlx server whose start: begins with mlx_lm.server or mlx.launch, on macOS on Apple silicon, the first time the node runs one of this lockMirror it on the edge (oz0-node toolchain fetch --platform darwin/arm64 --mlx-lm) and run the node offline, or start an mlx-lm of your own by its absolute path
The URLs in a harness's binaries (such as GitHub releases for OpenCode and goose)The harness program, checked against its SHA-256, over https only and to public addresses only, redirects included (at most five). Through an HTTP proxy the operator set (HTTPS_PROXY), the node checks the addresses the name resolves to before it hands the request to the proxy, which resolves the name again: there the proxy's own rules decide where it connectsWhen a plugin with such a harness installsPlugins without them. The edge does not mirror them: an offline node downloads them too
A remote MCP server a plugin's url: tool names, or, for a remote tool on a connection whose host is a param, the host the connection was connected forThe runtime is the remote server's client: it lists the server's tools when it starts and makes each call; a remote tool on a connection opens a session per call with that call's token, follows no redirect and reaches that origin onlyOnly in a tenant with such a plugin installed (on a connection, once it is connected), when the runtime starts and when an agent calls the toolUninstall the plugin, or a kill switch on the tool
Your local model serverslocal/<model> agentsOnly as listed in the node's models.yamlLeave it empty
Whatever a tool callsA tool is a plugin's codeWhen an agent calls itSandbox tier 1 denies every host not on the allowlist; the tool policy
None from a microVM's monitor: smolvm runs in tier 1's empty network namespace, and its VMs have no network device; Apple's container may download its own kernel when the operator runs container system startA tool with isolation: microvm (microVMs); a Mac or Windows node fetches the Linux node binary for its VMs from its edge onlyApple's downloads only when the operator installs and starts itOZ0_MICROVM=off, or do not install a microVM runtime
The remote-sandbox service the node's operator configured: E2B Cloud (api.e2b.app, sandbox.e2b.app), a self-hosted E2B or CubeSandbox, through ai.oz0/sandbox-e2bCreating, keeping alive, listing and destroying remote sandboxes, and the MCP traffic of the tools that run in them; a tool's code and its calls' data go there (Sandbox tier 2)Only with run --remote-sandbox: at the node's start (a list of its own sandboxes, which also checks the key) and while a tenant that allowed remote sandboxes runs a tool with isolation: remoteLeave --remote-sandbox unset, or oz0 tenant remote-sandbox <tenant> deny

The node fetches its own new binaries and runtimes from the edge only, checked against the release key (see Upgrades). The edge's mirror needs no signature of its own: the node checks uv and Node.js against the checksums in its binary, uv checks the Python build against the checksums in uv, and every package against the hashes in the runtime's requirements.txt or the plugin's lock.

The node's loopback proxy, which uv reaches the edge's Python builds and wheels through, answers any local process, so it forwards only the files toolchain.json lists, by their listed path, writes the wheels' index pages itself, follows no redirect, and reaches the edge without the node's certificate: what it can fetch is what the edge serves anyone.

On an offline node whose edge serves an offline folder, the proxy also forwards GET requests for the edge's PyPI and npm mirrors, which answer the cluster's nodes only, with the node's certificate: plain path segments only, no redirect followed, and nothing but those two routes.

The mirror counts a wheel as covering a platform only if nodes there can install it: no newer than glibc 2.28 on Linux (RHEL 8, Debian 10; the Node.js the node pins needs it too), musl 1.2 on Alpine, and macOS 11. A package with no such wheel for a platform is listed as missing in toolchain.json, and toolchain fetch warns about it: nodes there install it from a package index.

uv sends its version and the machine's platform (operating system, distribution, CPU, Python) in its User-Agent to the package index it downloads from, as pip does; PyPI publishes download statistics from it. Nodes that install from the edge send it to the edge only.

The runtime on the node

The Python runtime reaches Temporal and the models through the node's local proxies, and sends its traces to the edge. Of its libraries:

  • OpenAI Agents SDK: its tracing would send each run, prompts included, to OpenAI. It is off, in code and with OPENAI_AGENTS_DISABLE_TRACING=1.
  • Pydantic AI: no banner (PYDANTIC_AI_NO_BANNER=1), no Logfire (only its no-op API is installed), and model prices from the copy it was released with: it never downloads a new list unless code asks it to.
  • MCP servers over HTTP that a plugin names are called when an agent uses them.

The official plugins

Each reaches only what its job needs, when an agent calls it. Its own code checks each connection against the hosts its manifest declares and the tenant's list. The node's egress proxy holds it to them too on every node with tier 1, whether the server is a job's or the plugin's own (--plugin-sandbox strict, the default). On a node with no tier 1, or one its operator runs with --plugin-sandbox auto, an installed plugin's servers keep the host's network, and the declared hosts are what the plugin's own code holds to:

PluginHost
ai.oz0/github, ai.oz0/pr-reviewerapi.github.com, or your GitHub Enterprise address
ai.oz0/slackslack.com (or slack-gov.com)
ai.oz0/discorddiscord.com
ai.oz0/teamsThe Bot Framework's service for Teams (smba.trafficmanager.net, or your government cloud's), only at the serviceUrl a delivery's verified token names
ai.oz0/webThe search backend the tenant chose (your SearXNG, or Brave's API) and the pages an agent fetches
ai.oz0/servicenowYour ServiceNow instance's host, which you give its connections, only once a tenant admin has connected it: the Table API when an agent calls it, the instance's token endpoint when the edge connects or renews the token, and, only when you turn it on, the instance's MCP Server Console; turn it off by removing the connection or the plugin
ai.oz0/cve-triageapi.osv.dev, or none with an OSV mirror
ai.oz0/net-diagThe hosts an agent is asked to diagnose
ai.oz0/host-healthNone
remote-claude-managedapi.anthropic.com (Managed Agents)
harness-claudeNone of its own: Claude Code runs with its telemetry, error reporting and update checks off, and its model calls go through the node's LLM proxy
harness-acpNone of its own for Codex (check_for_update_on_startup and analytics off), OpenCode (update checks, LSP downloads and the models.dev list off) and goose (telemetry off). Gemini CLI 0.62.0 sends usage statistics to Google unless its settings file turns them off, which no environment variable can do: in sandbox tier 1 that is denied, like every host not on the allowlist
ai.oz0/a2a-remote, ai.oz0/a2a-agentcore, ai.oz0/a2a-foundryNone of their own. An outside A2A agent's card origin and token endpoint, which the plugin that defines the agent lists (AgentCore's bedrock-agentcore.<region>.amazonaws.com and a Cognito endpoint, Foundry's <account>.services.ai.azure.com and login.microsoftonline.com), only while a job runs that agent; turn it off by removing the plugin that defines it, or with a kill switch on the agent
ai.oz0/ai-spendapi.anthropic.com and api.openai.com, the providers' admin cost and usage APIs, only while a tenant has it installed with an admin key set and runs its import (its daily routine, or a person); turn it off by deleting the keys (AI_SPEND_*_ADMIN_KEY), the routine, or the plugin
ai.oz0/atlassian, ai.oz0/atlassian-dcCloud MCP calls and Data Center REST calls leave the node; authentication leaves the edge. See destinations and switches.
ai.oz0/gitlabMCP calls leave the node; OAuth sign-in and refresh use the browser and edge. See destinations and switches.

Atlassian connection traffic

Atlassian Cloud uses mcp.atlassian.com for Rovo MCP calls from the node, once to list tools at runtime startup and then for each call. Sign-in and token refresh use auth.atlassian.com from the edge.

Jira and Confluence Data Center use the connected instance's host. REST calls leave the node, while /rest/oauth2/latest/token is called by the edge.

These connections run only while the tenant has the plugin installed and connected. Remove the plugin or delete the connection to stop them, for example oz0 connection delete atlassian-cloud.

GitLab connection traffic

GitLab traffic goes to the connected instance's host, gitlab.com unless the tenant selects its own. The node reaches /api/v4/mcp once to list tools at runtime startup and for each call. The person's browser and the edge use /oauth/authorize and /oauth/token for sign-in and refresh.

This traffic starts only after the tenant connects the gitlab connection. Stop it with oz0 connection delete gitlab or by removing the plugin. GitLab webhooks arrive at the edge; they are not outbound connections.

Copyright © 2026