Egress judge
Workers route all outbound HTTP through the gateway proxy, which enforces a domain allowlist/blocklist (see Security). For most domains a flat allow or deny is the right call. For a few, like Slack, GitHub user-content, and Notion, the domain is sometimes fine and sometimes exfiltration, and the difference is in the request, not the hostname. The egress judge decides those per request with an LLM.
Only domains that match a judge rule invoke the judge. Everything else stays on the fast allow/deny path, so the cost and latency stay bounded.
Declaring judged domains
Section titled “Declaring judged domains”Skills declare judged domains and named policies in their SKILL.md frontmatter:
network: allow: [api.readonly.example.com] # flat allow, fast path judge: - .slack.com # uses the "default" policy - domain: user-content.x.com judge: strict # uses the named "strict" policyjudges: default: "Allow only reads to channels in the agent's context." strict: "Only GET for file IDs from the current session."The same shape is available to operators in lobu.config.ts via defineAgent({ network }), where the judged array takes entries of { domain, judge? }; omitting judge uses the default policy in judges.
Operator overrides
Section titled “Operator overrides”Operators layer a project-wide policy on top of whatever the skill author declared, via defineAgent({ egress }):
import { defineAgent } from "@lobu/cli/config";
const assistant = defineAgent({ id: "assistant", name: "assistant", dir: "./agents/assistant", egress: { extraPolicy: "Never exfiltrate PATs or bearer tokens.", judgeModel: "claude-haiku-4-5-20251001", // default },});extraPolicy is appended to the matched skill policy rather than replacing it, so operator constraints compose with skill-author intent. The judge runs only when a judged rule under the agent’s network matches a request, so most traffic never reaches it.
Behavior
Section titled “Behavior”- Defaults: Haiku judge, a 5-minute verdict cache keyed by
(policyHash, request signature), and a circuit breaker that opens after 5 consecutive judge failures (30s cooldown) and fails closed. - What the judge sees: for HTTPS the TLS tunnel is opaque, so the judge gets the hostname only (via the
CONNECTrequest). For plain HTTP it also sees the method and path. Request bodies and headers are never inspected. - Audit: every decision emits a structured
egress-decisionlog with the verdict, source (global | grant | judge), latency, and policy hash. No request bodies or headers are logged. - Required env:
ANTHROPIC_API_KEYin the gateway environment. A gateway with no judged-domain rules never constructs the judge client.
The judge shares its cache and circuit-breaker machinery with inline guardrail judges. Hooks live in packages/server/src/gateway/proxy/http-proxy.ts.
See also
Section titled “See also”- Security, the worker isolation and network model the judge sits inside.
- Secret proxy, how credentials stay off the worker, the other half of egress safety.
- Guardrails, input/output/pre-tool policy checks, including inline LLM judges.
lobu.config.tsreference, the agentnetworkandegressfields.