Egress control · agent containers
Decide what your containers can reach.
Then prove it.
By default, an LLM agent in a container can reach the public internet, your internal network, and the host's localhost services. Outcall says no in the kernel: nftables, DNS, and an HTTP proxy your container can't bypass — and every allow you write becomes an nft list table counter you can read.
# /etc/outcall/rules.d/agent.yaml
# Default-block is implicit. Write only what the agent may do.
# HTTPS is matched by hostname (SNI). Method/path are visible
# only for plaintext HTTP — no TLS interception.
version: "1"
rules:
- id: allow-openai
description: "agent may call the OpenAI API over HTTPS"
condition: 'http.host == "api.openai.com"'
action: allow
egress:
mode: proxy
- id: allow-github-clone
condition: |
dns.query == "github.com" ||
http.host == "github.com"
action: allowWhat's in the box
One daemon. Six surfaces. Same source of truth.
Outcall ships the network plumbing, the policy plane, and the operator UX as a single binary. You don't stand up six tools to enforce egress — you stand up one.
Each agent host gets one Linux bridge with `policy drop` on FORWARD. Allow rules you write compile to nftables verdicts and hit-counters. Verify any rule is live with `nft list table inet outcall`.
The bridge gateway answers only for hosts in your rule set. Unlisted lookups return NXDOMAIN — agents fail immediately at name resolution, not after a 30-second TCP timeout that taints retries.
A forward proxy on the bridge matches plaintext HTTP on host + method + path, and HTTPS on CONNECT host + TLS SNI — no decryption, by design. A per-rule intercept mode is specified (S011) but intentionally not implemented in v0.1; HTTPS method/path/body is not visible inside the encrypted tunnel.
A Unix socket inside each container lets the agent ask the daemon via `outcall fetch <url>` (or `outcall exec`, `outcall file`, etc.) before acting, and submit new rule requests for operator approval. The agent never touches host policy directly; rule changes are auditable.
Drop YAML into `/etc/outcall/rules.d` and `outcall rules reload`. Networks and containers outlive the daemon — you can ship a rule change in seconds without rolling a single agent.
The `outcall` CLI, the JSON API on `/run/outcall/host.sock`, and the web dashboard all read the same daemon state. What you see in the UI is what `outcall rules list` prints — no separate inventory to drift.
How it fits together
One bridge. One source of truth.
The daemon is the only thing on the host that can change policy. Operators talk to the host socket. Containers talk to the agent socket. Neither side reaches the other.
Stop trusting agents.
Start enforcing them.
Outcall is open source. Spec-first, default-deny, and Linux-native. If you run agents that touch the network, you owe yourself a look.