Network allowlist
Neens calls your LLM connections from its own servers. To stop a connection from being used to
reach internal systems, Neens refuses any connection whose address is private (a 10.x,
172.16–31.x or 192.168.x address, or a host name that resolves to one) unless that host is on
your company’s network allowlist. Add your private model gateway or self-hosted model here
and every judge, insight, assistant reply and other LLM feature can use it. Your list applies
only to your company; no other company can use it.
At a glance
| Where | Settings → Network allowlist |
| API | GET /api/settings/llm-allowed-hosts, PUT /api/settings/llm-allowed-hosts |
| Lists | Company-wide (every agent in your company) and This agent only (extra hosts for one agent) |
| Entry types | Exact host name, IP address, or CIDR range |
| Who can edit | Company-wide list: a company-wide admin. Agent list: an admin with access to that agent. Everyone else can view |
| Limit | Up to 50 entries per list |
| Audit | Every change is recorded in the audit log as egress_allowlist.update, with the list before and after |
When you need it
You only need the allowlist when an LLM connection points somewhere that is not on the public internet, for example:
- a model gateway inside your network, such as
https://llm-gateway.internal.example.com/v1; - a self-hosted model server (vLLM, Ollama, LM Studio) on a private address;
- an entire private subnet where your model servers live, such as
10.20.0.0/16.
Public endpoints (OpenAI, Anthropic, Google, OpenRouter, a public LiteLLM proxy) never need an entry.
Add a host in Settings
Open Settings → Network allowlist
Everyone can open the screen. If you can’t edit a list, the screen tells you who can.
Choose the list
Use Company-wide for hosts every agent in your company should reach. Use This agent only for a host just the agent you have selected should reach (for example, a model server dedicated to one team). An agent can reach the company-wide hosts plus its own.
Enter the host, IP address or CIDR range
Type an exact host name (llm-gateway.internal.example.com), an IP address (10.20.0.5) or a
CIDR range (10.20.0.0/16), then select Add. The list saves immediately. If the entry isn’t
accepted, the reason appears under the field.
Test the connection
Go back to Settings → LLM providers and click Test on the connection. It should now reach your host.
To remove an entry, select Remove next to it. Changes take effect within a minute.
Manage the list with the API
Use an API key or a session token in the Authorization header.
Reading works with any credential that can see the agent; changing a list needs an admin
user, so a project API key (nk_live_…) can read the lists but gets 403 on PUT. In the
examples below, $ADMIN_TOKEN stands for the session token of a signed-in admin.
curl -s https://neens.example.com/api/settings/llm-allowed-hosts \
-H "Authorization: Bearer nk_live_…"{
"projectId": "project_123",
"selfServiceEnabled": true,
"maxEntries": 50,
"platformManaged": [],
"company": {
"entries": [
{"entry": "10.20.0.0/16", "addedAt": "2026-10-01T09:12:00+00:00", "addedByName": "Ava Lindqvist"},
{"entry": "llm-gateway.internal.example.com", "addedAt": "2026-10-01T09:12:00+00:00", "addedByName": "Ava Lindqvist"}
],
"canEdit": false
},
"project": {"entries": [], "canEdit": false}
}PUT replaces the whole list for that scope with entries (send [] to clear it) and
returns the same body as GET. scope defaults to company.
{
"projectId": "project_123",
"selfServiceEnabled": true,
"maxEntries": 50,
"platformManaged": [],
"company": {
"entries": [
{"entry": "llm-gateway.internal.example.com", "addedAt": "2026-10-02T14:03:00+00:00", "addedByName": "Ava Lindqvist"},
{"entry": "10.20.0.0/16", "addedAt": "2026-10-02T14:03:00+00:00", "addedByName": "Ava Lindqvist"}
],
"canEdit": true
},
"project": {"entries": [], "canEdit": true}
}Responses and error codes
| Status | detail.error | Meaning |
|---|---|---|
200 | Saved. The body is the updated allowlist | |
403 | company_admin_required | You are an admin for some orgs only; the company-wide list reaches agents outside them |
403 | self_service_disabled | Self-service is turned off for your account; contact your Neens administrator. Saved entries are not in effect |
403 | (text) | Your role can’t change the allowlist (members, viewers and API keys) |
422 | invalid_entries | One or more entries were rejected. detail.errors lists each one with its index, code and message |
422 | invalid_scope | scope must be company or project |
Entry error codes: invalid_host, invalid_cidr, wildcard_not_allowed, url_not_allowed,
port_not_allowed, cidr_too_broad, always_refused, internal_name_not_allowed,
ipv6_transition_not_allowed, empty_entry, and too_many_entries (reported once, with index: -1).
Entry rules
| You enter | Accepted? | Notes |
|---|---|---|
llm-gateway.internal.example.com | Yes | Matched exactly by name, case-insensitively. Any port on that host is allowed |
10.20.0.5 | Yes | One address |
10.20.0.0/16 | Yes | Every address in the range. Saved in canonical form (10.20.1.7/16 becomes 10.20.0.0/16) |
*.internal.example.com | No | Wildcards aren’t supported: list each host name |
gateway, vllm.default.svc.cluster.local | No | internal_name_not_allowed: single-word names and cluster-internal service names (.svc, .cluster.local) can’t be listed. Use your gateway’s fully qualified name or its IP address |
https://gw.example.com/v1 or gw.example.com:8080 | No | Enter only the host, without a scheme, path or port |
10.0.0.0/7, 0.0.0.0/0 | No | Too broad. The widest range is /8 for IPv4 and /32 for IPv6 |
169.254.169.254, fe80::/64, 127.0.0.2 | No | Always refused (see below) |
64:ff9b::/96, 2002::/16 | No | ipv6_transition_not_allowed: IPv6 translation ranges (NAT64, 6to4, Teredo) can’t be listed. List the IPv4 address or range instead |
What is always refused
Some addresses are refused even if you list them, because reaching them from Neens’ servers would expose the platform itself rather than your model:
- Cloud metadata endpoints, such as
169.254.169.254andmetadata.google.internal, which hand out server credentials; - link-local addresses (
169.254.0.0/16,fe80::/10); - loopback addresses, the unspecified address, and multicast;
- address ranges reserved by the platform for its own infrastructure.
The check runs when Neens connects, after looking up the host name, not just when you save. A host name on your list that resolves to one of these addresses is still refused, and so is one that resolves to several addresses if any of them is refused.
Only list hosts you control. An entry lets every LLM feature of the agents it covers send prompts, which can include trace content, to that host.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Saving or testing a connection fails with “is a private/loopback/link-local address and is not on the network allowlist” | The base URL is a private IP address that isn’t listed for your company or agent | Add the IP or its CIDR range to the Company-wide list or This agent only |
| Test fails with “The base URL’s host resolves to a private address that is not on the network allowlist…” | The base URL’s host name resolves to a private address that isn’t listed | Add the exact host name (or the address range it resolves to) |
| A judge or other LLM feature errors with “LLM connection base_url is not allowed” | Same as above, seen when the feature runs | Add the host, then re-run |
| The error says the address “is always refused” | The host is, or resolves to, a metadata, link-local, loopback or platform-reserved address | Point the connection at a different address. These can’t be allowlisted |
| It works for one agent but not another | The host is on This agent only for the first agent | Add it to the Company-wide list, or to the other agent’s own list |
| The screen says editing is turned off | Self-service is turned off for your account | Contact your Neens administrator; while it is off, saved entries are not in effect |
| You can view but not edit | You aren’t an admin, or (for the company-wide list) you are an admin for some orgs only | Ask a company-wide admin |
Related
- LLM connections — create and test the connections the allowlist applies to.
- Members & roles — who counts as an admin.
- Audit log — the
egress_allowlist.updatehistory.