Skip to content

Exposed ports#

An agent that serves a chat UI, a dashboard, or an HTTP API needs a way for people to reach it. An exposed port publishes one container port at a stable URL derived from the sandbox's slug.

curl -fsS -X POST \
  -H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
  -H "Content-Type: application/json" \
  https://agents.example.com/v1/projects/$PROJECT_ID/sandboxes \
  -d '{
    "image": "ghcr.io/acme/agent:1.2",
    "command": "./start.sh",
    "cpu": "500m", "memory": "2Gi",
    "exposedPorts": [{"name": "web", "port": 8080, "auth": "private"}]
  }'
Create a sandbox in production from ghcr.io/acme/agent:1.2 running
"./start.sh" with 500m CPU and 2Gi memory. Publish port 8080 as
"web" with private auth, and give me the URL.
nexusctl sandbox create --project production \
  --image ghcr.io/acme/agent:1.2 \
  --command "./start.sh" \
  --cpu 500m --memory 2Gi \
  --port name=web,port=8080,auth=private

Or in a spec file:

exposedPorts:
  - name: web
    port: 8080
    auth: private

A sandbox supports one exposed port today. The field is a list so multiple ports can be added without a breaking change.


The URL#

The platform publishes the port at:

https://<sandbox-slug>.<sandboxIngress.host>

The slug is assigned at creation and never changes, so the URL is stable across restarts, image upgrades, and rollbacks.

Read it back from the sandbox:

curl -fsS -H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
  https://agents.example.com/v1/projects/$PROJECT_ID/sandboxes/$SANDBOX_ID \
  | jq -r '.exposedPorts[].url'
What URL is the nightly-refactor sandbox in production serving on?
nexusctl sandbox get nightly-refactor --project production -o json \
  | jq -r '.exposedPorts[].url'

The URL is null without sandboxIngress.host

If the install was deployed without sandboxIngress.host, exposed ports still exist but resolve to no URL. Set the value and make sure *.<host> resolves to your ingress. See Install on Kubernetes.


Fields#

Field Rules
name Lowercase DNS label fragment, ^[a-z][a-z0-9-]{0,30}$. Identifies the port within the sandbox.
port TCP port 1–65535. The supervisor dials it on 127.0.0.1 inside the container.
auth private or public.

The agent binds the port on loopback inside its own container. Nothing else about the sandbox's network is opened by exposing a port — outbound traffic is still governed by policy, and no other port becomes reachable.


Authentication modes#

private#

Requests must carry a valid platform session. Anyone without one is sent to sign in, and access is checked against the project the sandbox belongs to.

This is the default and the right choice for anything beyond a demo.

public#

The URL opens with no platform session at all. Anyone who has the URL can reach the service.

Use public for a local trial, a demo, or a service that does its own authentication. Treat the URL as a secret, and remember that the agent behind it is running with real credentials and real access.


Health checks pair with exposed ports#

A sandbox that serves HTTP is usually worth probing. Point an HTTP health check at the same port so the platform can tell "running" from "running and answering":

exposedPorts:
  - name: web
    port: 8080
    auth: private

healthCheck:
  type: http
  http:
    path: /healthz
    port: 8080