Try Lens Agents Locally#
Run the full Lens Agents platform on your own machine — in a dedicated local single-node cluster, its own minikube profile isolated from any existing clusters — then launch Prism, Lens Agents' ready-made managed agent, and chat with it in your browser. Use this for a self-serve evaluation; for a guided evaluation with an environment tailored to your stack, see Getting Started.
Fastest way — let a coding agent do the whole thing
Have a local coding agent (Claude Code, Codex, and so on)? Paste this prompt into it and send — then just follow the agent's instructions:
Follow this guide to install Lens Agents locally and launch Prism, then give me the chat URL: https://docs.k8slens.dev/lens-agents/getting-started/local-trial/
Prefer to run it yourself? Every shell step below is copy-paste safe — just work through Steps 1–5 in order.
If you are that coding agent
Your job isn't done when the platform is running. Work all the way through Steps 4 and 5 — activate, connect over MCP, launch Prism — and finish by handing the user the chat URL. Don't stop after the install and wait to be asked "what's next." The only steps that need the person are the browser sign-ins (activation in Step 4, and the one-time MCP sign-in in Step 5); pause for those, then continue.
Always open sign-in URLs in the user's own system browser — print the URL and have them open it there, never in an embedded or in-agent browser (e.g. Codex's built-in browser). Password managers and any existing Lens ID session live in the real browser; an embedded one usually can't complete the sign-in.
Container-level isolation only
This local setup shares the node's host kernel. You get the standard sandbox harness — privilege dropping, kernel-level network lockdown (nftables/iptables), and proxy-mediated egress — but not microVM isolation. Production deployments add per-sandbox microVM isolation with a Kata Containers or gVisor runtime class, which a local minikube cluster cannot provide. Contact us to scope a production-grade environment.
What you'll end up with#
minikube (docker driver)
└── lens-agents (Helm release)
├── nexus ← platform server: MCP + REST + Auth + Policies + Audit
├── postgresql ← bundled database
└── lens-agents-sandbox namespace
└── prism-agent ← your agent, in an isolated sandbox
- Platform API and UI on
http://localhost:3002(via port-forward) - MCP endpoint on
http://localhost:3002/mcp - Prism chat UI on
http://<slug>.localtest.me:3002
Prerequisites#
Install these on the host, and confirm each responds:
| Tool | Purpose | Check |
|---|---|---|
docker |
minikube's driver (see the note below) | docker info |
minikube |
the local cluster | minikube version |
kubectl |
talk to the cluster | kubectl version --client |
helm (v3.8+) |
install the chart | helm version |
openssl |
generate the encryption key | openssl version |
curl |
health checks and REST calls | curl --version |
You also need outbound internet (to pull images and complete activation) and a Lens ID account. Sign up at app.k8slens.dev if you don't have one.
You also need one inference-provider credential for the platform's managed inference — the agent's LLM runs through it. Two providers are supported today, and you pick one in Step 2:
- AWS Bedrock — a Bedrock API key.
- Azure — a Microsoft Foundry resource URL and API key, with a Claude deployment.
Need a different provider (OpenAI, Google, self-hosted)? Contact Team Lens — we add them promptly.
minikube must use the Docker driver
Sandboxes lock down their network with nftables, so the node kernel needs nf_tables. The --driver=docker runs the node on your host kernel, which has it. minikube's VM drivers (vfkit, qemu, hyperkit) ship an ISO kernel built without nf_tables: the platform runs but every sandbox fails to start. Docker Desktop Kubernetes and kind work for the same reason. Do not substitute a VM driver.
Step 1 — Start the cluster#
Use a fresh, dedicated cluster — never an existing minikube
minikube start with no profile reuses the default minikube cluster if one already exists, which can collide with a cluster you rely on — and the teardown in this guide (helm uninstall, PVC deletes, minikube delete) could then remove workloads that aren't part of this trial. Always create a dedicated, named profile (-p lens-agents below) for Lens Agents, and never point the install or teardown at a shared context. A coding agent must not reuse, reconfigure, or delete any other minikube profile. Check what already exists first:
minikube profile list # inspect existing instances — do NOT reuse them
Give it enough headroom — the platform, PostgreSQL, and a sandbox each need real resources.
minikube start -p lens-agents --driver=docker --cpus=4 --memory=6g
kubectl config use-context lens-agents
kubectl cluster-info
kubectl get nodes should show one Ready node. Every later kubectl/helm command in this guide runs against this lens-agents context.
Step 2 — Install the platform#
The platform ships as a Helm chart published to GHCR as an OCI artifact. It bundles PostgreSQL and defaults its identity provider to Lens ID, so a local install needs an encryption key, the URL it answers on, the wildcard host used for sandbox port exposure, and one inference-provider credential so the agent's LLM has somewhere to run.
Managed inference means the platform holds the provider credential and proxies every LLM call, so usage is metered, gated, and audited. Pick the tab for the provider whose credential you have; you'll select the matching provider on the policy in Step 5.
helm install lens-agents oci://ghcr.io/lensapp/lens-agents \
--set encryption.key="$(openssl rand -hex 32)" \
--set config.publicUrl=http://localhost:3002 \
--set sandboxIngress.host=localtest.me \
--set inference.bedrock.token="<bedrock-api-key>" \
--wait --timeout 10m
inference.bedrock.token— your Amazon Bedrock API key, forwarded upstream as a bearer token.
helm install lens-agents oci://ghcr.io/lensapp/lens-agents \
--set encryption.key="$(openssl rand -hex 32)" \
--set config.publicUrl=http://localhost:3002 \
--set sandboxIngress.host=localtest.me \
--set inference.azure.baseUrl="https://<resource>.services.ai.azure.com" \
--set inference.azure.token="<azure-api-key>" \
--wait --timeout 10m
inference.azure.baseUrl— the Foundry resource root on the*.services.ai.azure.comhost (not the Azure OpenAI*.openai.azure.comhost). Leave the surface suffix off; the proxy appends/anthropicitself. Copy the host from your Claude deployment's Target URI in the Foundry portal.inference.azure.token— that deployment's Key, forwarded as theapi-keyheader.- Optional:
--set inference.azure.anthropic.model="<deployment>"sets the default Claude deployment name (defaults toclaude-opus-4-8).
The three flags shared by both tabs:
encryption.key— 64 hex chars, used for at-rest encryption.config.publicUrl— the URL the platform answers on.sandboxIngress.host=localtest.me— required for sandbox web UIs.localtest.meis public wildcard DNS that resolves*.localtest.meto127.0.0.1, so a sandbox's exposed port becomes reachable over your port-forward with no ingress.
Keeping the token out of your shell history
Both providers also accept the token from an existing Kubernetes Secret instead of --set …token: --set inference.<provider>.existingSecret=<secret-name> (default key NEXUS_BEDROCK_TOKEN / NEXUS_AZURE_TOKEN; override with existingSecretKey). On a real cluster (EKS) Bedrock can also resolve credentials from an IAM role and skip the token entirely.
Confirm the rollout:
kubectl rollout status deploy/lens-agents --timeout=5m
kubectl get pods
The lens-agents-* and lens-agents-postgresql-* pods should be Running.
Step 3 — Expose the platform#
Port-forward the service, and keep it running for the rest of the session.
kubectl port-forward svc/lens-agents 3002:3002
Confirm it answers:
curl -fsS http://localhost:3002/health && echo OK
The forward binds 127.0.0.1, and because *.localtest.me also resolves to 127.0.0.1, both the platform and every sandbox web UI are reachable from this machine over this one forward.
Note
If your resolver blocks public names that point at loopback (DNS-rebinding protection), add an /etc/hosts entry for the sandbox host from Step 6, or run a local dnsmasq wildcard for *.localtest.me.
Step 4 — Activate and sign in#
This step needs a person and their own system browser — open the URL there, not in an agent's embedded/in-app browser, so your password manager and existing Lens ID session are available.
- Open http://localhost:3002.
- On the activation screen, follow the device-flow prompt to register this install with Lens Cloud.
- Sign in with your Lens ID. The account you activate with becomes the organization admin, which you need to create sandboxes.
You land in the platform UI, logged in, with an organization. The platform is running, but the evaluation isn't finished — continue to Step 5 to launch your first agent.
Step 5 — Create the policy and launch Prism#
Prism reaches its LLM through the platform's managed inference, so it needs a policy that enables inference and a sandbox that attaches it. Create these over MCP — the recommended path, and the one a coding agent should always use — or by hand in the UI.
Match the provider you enabled in Step 2
The steps below show the Bedrock default. If you enabled Azure in Step 2, change bedrock to azure in the two spots each path marks:
- Policy —
managedInference.provider(omit it and it defaults tobedrock). - Sandbox — the
LLM_PROVIDERenvironment variable, so the agent routes to the Azure surface.
The platform, policy, and sandbox must all name the same provider.
Coding agents: always use the MCP server
To work with the Lens Agents platform, a coding agent should always connect through the platform's MCP server — not by scripting the web UI, and not by asking the user to create an API token. Add the server (Option A below), authenticate in the browser when prompted, then call the platform's tools. The UI path (Option B) is for a person clicking through by hand.
Option A — Connect over MCP (recommended)#
Connect a local coding agent to the platform's MCP endpoint at http://localhost:3002/mcp and let it create everything.
No API token needed — authenticate interactively. The MCP endpoint supports OIDC sign-in. Add the server and sign in from the CLI (Claude Code v2.1.186+):
claude mcp add --scope user --transport http lens-agents http://localhost:3002/mcp
claude mcp login lens-agents # opens the browser for Lens ID sign-in; caches the token
Sign in in your system browser
claude mcp login (and the codex mcp login equivalent below) opens a Lens ID OAuth page. Complete it in your default system browser, not an agent's embedded/in-app browser — password managers and any existing Lens ID session live in the real browser. If a coding agent is driving this, have it print the URL for you to open rather than opening it in-agent.
If Claude Code is running this setup for you
A running Claude Code session does not hot-load a server added mid-session (/mcp only authenticates already-configured servers), so don't try to call the tools in the same session that added them. To avoid restarting the orchestrating session, run the launch in a fresh headless child — it reuses the token cached by claude mcp login:
claude -p "Using the lens-agents MCP server, create the Prism agent: call list_orgs and pick the first org (create_org only if none exist); create or reuse a project named demo; create a policy prism-base with managedInference enabled and provider bedrock; bind it to everyone as prism-everyone; create_sandbox named prism-demo with image ghcr.io/lensapp/prism-agent:latest, command 'exec ./start.sh', env AGENT_NAME='Prism Demo' TEAM_NAME=Demo AGENT_ID=prism-demo-1 LLM_PROVIDER=bedrock, volume mountPath /data, exposed port name chat port 3003 auth public, attach prism-base; poll get_sandbox until state is running and print exposedPorts[0].url." \
--allowedTools "mcp__lens-agents"
For Azure, say provider azure and LLM_PROVIDER=azure in that prompt instead. A person using Claude Code interactively can instead just restart the session after claude mcp login and continue.
For another MCP client, add an HTTP MCP server at the same URL and complete the browser sign-in with the admin account from Step 4 when prompted.
Using Codex — drive it from the CLI
Codex keeps MCP servers in ~/.codex/config.toml and sandboxes its in-session tools, so configure and run Lens Agents from the Codex CLI, not the in-app session:
codex mcp add lens-agents --url http://localhost:3002/mcp
codex mcp login lens-agents # completes the OAuth sign-in in your browser
- If the
lens-agentstools don't appear right after login, run the steps with a freshcodex exec— it re-reads the config and picks up the authenticated server. In-session hot-loading of a just-added MCP server isn't reliable; a new CLI run is. - Keep the Step 3 port-forward alive. Every run needs
http://localhost:3002reachable — if a run reports the platform as unreachable, the forward has died (restart it) rather than an auth problem. - Codex sandboxes model-run shell commands with network off by default. That doesn't affect MCP tool calls (use those) — it only matters if you shell out to the REST API directly, which then needs network access (
codex exec --sandbox danger-full-access …). - Prefer a token over OAuth?
codex mcp add lens-agents --url http://localhost:3002/mcp --bearer-token-env-var LENS_TOKEN(see the fallback below).
Then have the agent call these MCP tools in order, finishing with the chat URL:
list_orgs— pick the organization id. (Create one withcreate_orgonly if none exist.)create_project { orgId, name: "demo", displayName: "Demo" }— note the project id, or reuse one fromlist_projects.create_policy { projectId, name: "prism-base", description: "Managed inference for Prism", managedInference: { enabled: true, provider: "bedrock" } }— note the policy id. (Azure: useprovider: "azure".)create_policy_binding { projectId, name: "prism-everyone", policyIds: [policyId], subjects: [{ kind: "everyone" }] }.-
create_sandbox— with the Prism runtime:{ "projectId": "<projectId>", "name": "prism-demo", "image": "ghcr.io/lensapp/prism-agent:latest", "command": "exec ./start.sh", "env": { "AGENT_NAME": "Prism Demo", "TEAM_NAME": "Demo", "AGENT_ID": "prism-demo-1", "LLM_PROVIDER": "bedrock" }, "volumes": [{ "mountPath": "/data" }], "exposedPorts": [{ "name": "chat", "port": 3003, "auth": "public" }], "policies": ["<policyId>"] }(Azure: set
"LLM_PROVIDER": "azure"to match the policy.) -
Poll
get_sandbox { projectId, sandboxId }untilstateisrunningandexposedPorts[0].urlis set. That URL (http://prism-demo-xxxx.localtest.me:3002) is Prism's chat UI — hand it to the user and open it in a browser on this machine.
MCP client can't do interactive OAuth? Authenticate it with a token
If your client can't complete the browser sign-in, authenticate it with a bearer token — you still drive the platform through MCP. As the admin from Step 4, open API tokens in the UI, create one named local-demo, copy the value, and pass it as a header when you add the server:
claude mcp add --transport http lens-agents http://localhost:3002/mcp \
--header "Authorization: Bearer <paste-the-token>"
Then call the same tools as above (steps 1–6, including the Azure markings). Every operation is also on the platform's REST API if you'd rather script it directly — the OpenAPI spec is at http://localhost:3002/v1/openapi.json and an interactive reference at http://localhost:3002/v1/docs.
auth: public vs private
auth: "public" makes the chat URL openable without a platform session — convenient for a local trial. Use "private" (requires platform auth) for anything beyond evaluation.
Option B — Platform UI (by hand)#
Prefer this only when a person is setting things up by hand. Click through the web UI at http://localhost:3002.
- Project. Use the default project, or create one under Projects (for example,
demo). - Policy. Under the project's Policies, create a policy named
prism-base, enable Managed inference, and choose the provider that matches Step 2 (AWS Bedrock or Azure — Azure appears only when the platform was installed withinference.azure.*set). Save. - Binding. Add a policy binding named
prism-everyonethat attachesprism-baseto the subject everyone. -
Sandbox. Under Sandboxes, click Create and set:
Field Value Image ghcr.io/lensapp/prism-agent:latestCommand exec ./start.shEnv AGENT_NAME=Prism Demo,TEAM_NAME=Demo,AGENT_ID=prism-demo-1,LLM_PROVIDER=bedrock(orazure, matching the policy)Volume mount path /dataExposed port name chat, port3003, authpublicPolicy attach prism-base -
Open it. When the sandbox reaches running, the UI shows the exposed port's link (
http://<slug>.localtest.me:3002). Open it — that's Prism's chat UI.
Troubleshooting#
| Symptom | Cause and fix |
|---|---|
Codex signs in but the lens-agents tools never appear |
In-session hot-loading is unreliable. Run the steps with a fresh codex exec, which re-reads ~/.codex/config.toml. See the "Using Codex" note in Option A. |
| Claude Code added the server but can't see its tools | Servers added mid-session don't hot-load. After claude mcp login lens-agents, run the steps in a fresh claude -p child (see Option A) or restart the session. |
| Codex reports the platform unreachable mid-run | The Step 3 port-forward died — restart kubectl port-forward svc/lens-agents 3002:3002. It's not an auth failure. |
Sandbox stuck in creating/error, platform fine |
Almost always the nftables kernel — you're on a minikube VM driver. Recreate the profile with minikube delete -p lens-agents && minikube start -p lens-agents --driver=docker …. |
exposedPorts[0].url stays null |
sandboxIngress.host wasn't set at install. Reinstall (Step 2) with --set sandboxIngress.host=localtest.me. |
| Chat URL won't resolve in the browser | Your resolver blocks loopback DNS. Add an /etc/hosts entry for the <slug>.localtest.me host, or use dnsmasq. |
Token auth returns 401 |
The bearer token is wrong or expired, or the account isn't an org member. Re-issue it under API tokens in the UI. |
| Prism UI loads but the agent doesn't answer | The platform has no inference credential. Reinstall Step 2 with inference.bedrock.token or inference.azure.baseUrl + inference.azure.token. The chat link itself still works. |
| Agent answers on Bedrock but fails after switching to Azure | Provider mismatch. The platform (inference.azure.*), the policy (managedInference.provider: azure), and the sandbox (LLM_PROVIDER=azure) must all name Azure. See Models. |
Pods Pending |
Cluster too small. minikube stop -p lens-agents && minikube start -p lens-agents --driver=docker --cpus=4 --memory=6g. |
Useful logs:
kubectl logs deploy/lens-agents --tail=100
kubectl get pods -n lens-agents-sandbox
Clean up#
Confirm you're on the trial's context first (kubectl config current-context → lens-agents), then:
helm uninstall lens-agents --wait
kubectl delete pvc -l app.kubernetes.io/instance=lens-agents --ignore-not-found
To discard the whole cluster: minikube delete -p lens-agents. This removes only the dedicated profile — other minikube instances are untouched.
Ready for production?
This trial is deliberately minimal: container-level isolation, port-forward access, a bundled database, and a single inference credential passed at install. A production deployment adds microVM sandbox isolation (Kata or gVisor runtime classes), real ingress and TLS, a managed database, RBAC, and hardened inference-credential management. Contact us and we'll help you size and stand up a production-grade cluster.