Skip to content

Configuration#

The Lens Prism runtime is configured entirely through environment variables. For a native install they go in ~/.prism/.env (restart the service after editing); for Docker, pass them with -e. Only an LLM credential is required — everything else has a sensible default.

Provider selection#

The runtime talks to one LLM provider per container, chosen by LLM_PROVIDER.

Variable Description Default
LLM_PROVIDER LLM platform: bedrock (AWS Bedrock runtime), bedrock-mantle (AWS Bedrock Mantle endpoint), or azure (Claude via Microsoft Foundry). Any other value falls back to bedrock. bedrock

All three serve Claude through the Anthropic Messages API. azure mode runs the agent on Claude deployed in Microsoft Foundry (https://{resource}.services.ai.azure.com/anthropic/v1/messages). On Azure, memory embeddings come from an Azure OpenAI text-embedding-3 deployment (Anthropic has no embedding model), defaulting to text-embedding-3-small; if that deployment doesn't exist, memory embedding fails open (search degraded, no crash).

bedrock-mantle targets AWS's Bedrock Mantle inference endpoint, a second endpoint separate from the Bedrock runtime. It reaches models the Bedrock runtime does not and draws on a separate quota pool. Like azure, it speaks the Anthropic Messages API surface. Direct mode authenticates with AWS_BEARER_TOKEN_BEDROCK (sent as the x-api-key header); routed through Nexus, the gateway holds it. Mantle serves chat only — memory embeddings still route through the Bedrock runtime.

Each platform can run direct or through Nexus (the LLM gateway). Routing is automatic: set NEXUS_API_URL and the runtime routes through Nexus, otherwise it talks to the platform directly. Through Nexus the gateway holds the platform credentials, so no local LLM credential is needed.

Credentials#

Variable Description
AWS_BEARER_TOKEN_BEDROCK Bedrock API key. The AI SDK auto-selects bearer auth when this is set. This is the one credential required for chat on Bedrock, and the only one on bedrock-mantle.
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY Bedrock AWS SigV4 credentials, as an alternative to the bearer token on the Bedrock runtime.
AZURE_API_KEY Azure Foundry resource key, sent as the x-api-key header. Required for direct mode only — when routing through Nexus the gateway holds the key for both chat and embeddings. May be a __nexus_cred:<uuid>__ sentinel the proxy rewrites on the wire.
AZURE_RESOURCE_NAME Azure (direct) Foundry resource name — derives the chat endpoint https://{resource}.services.ai.azure.com/anthropic/v1 and the embeddings endpoint https://{resource}.openai.azure.com.
AZURE_FOUNDRY_BASE_URL Azure. Override the derived Foundry Anthropic chat endpoint (must end at /anthropic/v1).
SLACK_BOT_TOKEN Slack bot token (xoxb-…). Enables the Slack adapter; validated via auth.test on boot.
SLACK_APP_TOKEN Slack app-level token (xapp-…) for Socket Mode.
SLACK_EXPECTED_APP_ID Optional safety check — the bot token's app ID must match this if set.

See Slack for how the tokens are used. Bedrock is not mandatory — set the credentials for whichever provider LLM_PROVIDER selects.

Core#

Variable Description Default
PORT HTTP port the runtime listens on. 3003
DATABASE_URL SQLite URL for the agent database. The Docker image's start.sh sets this to file:/data/agent.db; locally it resolves next to the Prisma schema. file:/data/agent.db (Docker)
AGENT_ID Pin the agent's UUID. Unset generates a fresh UUID on first boot and reuses it thereafter. generated
AGENT_NAME Display name on first boot. Prism
TEAM_NAME Team name on first boot. Local
OWNER_USER_ID Owner user ID on first boot. local sentinel UUID
SHELL_WORKSPACE_ROOT Working directory for the agent's shell tools. install workspace dir (Docker: /home/node)
PRISM_DATA_DIR Persistent data dir for skills, plugins, and the Claude Code config. The Docker image sets this to the /data volume. /data (Docker), else ~/.prism
PRISM_SKILLS_DIR Override the skills directory specifically. <data dir>/skills
PRISM_PLUGINS_DIR Override the plugins directory specifically. <data dir>/plugins

AGENT_NAME, TEAM_NAME, and OWNER_USER_ID only matter on the first boot with an empty database; later boots reuse the stored workspace.

Webhooks need no environment variables — the receiver toggle and subscriptions live in the database, managed from the web UI. The runtime doesn't authenticate inbound webhook calls itself (auth is the platform's job in front of the container), so don't expose the runtime port directly to the internet.

Chat verbosity#

The verbose setting controls how multi-step chat turns are delivered.

Mode Behavior
Concise (default, verbose=false) Only the final text step of a turn is delivered to the channel. Intermediate steps are still saved but marked internal, so they stay hidden both live and when the thread is reloaded. The final message must be self-contained.
Verbose (verbose=true) Every text step is delivered as it arrives — the streaming behavior.

This is a per-agent database setting, not an environment variable. Set it via the Profile page toggle in the web UI, PATCH /agents/verbose with { "verbose": true | false }, or by asking the agent (the update_settings tool accepts verbose).

Persistence is unchanged — every step is always stored, and concise mode only flags the intermediate ones as internal — so the model's context window is correct regardless of mode.

Locked-in mode#

The lockedIn setting stops the agent from rewriting its own identity documents. While the lock is on, the agent's document-writing and memory-writing tools are withheld and any such write is refused, so the agent keeps running but cannot reshape who it is or add to what it knows.

Frozen while locked Editable while locked
Soul, User, Memory (the curated summary), Vision, Heartbeat config, Bootstrap, and searchable memory entries (memory_write, memory_delete) Behavioral settings (heartbeat interval, timezone, verbose), and the agent's name (rename_self)

Searchable memory stays readable: memory_search is available while the lock is on.

The Agent Guide is in neither column — no tool writes it, so it is read-only to the agent whether the lock is on or off.

Turning the lock on takes effect immediately. A locked agent asked to change one of the frozen documents says what it would have changed and points to this setting. Onboarding is paused while the lock is on: a locked agent with a non-empty Bootstrap document does not run the first-run script, because it could not clear it afterward. The document is kept, so onboarding runs once you unlock the agent.

An agent cannot unlock itself. Set the lock two ways:

  • The Locked-in mode toggle on the Profile page in the web UI.
  • PATCH /agents/locked-in with { "lockedIn": true | false }.

Warning

Locked-in mode is a guardrail against drift, not a security boundary. The shell is never withheld, so an agent with shell access can write the documents straight into the database or reach the unlock endpoint on the local runtime; POST /agents/import is also ungated and can stage a replacement database. Treat the lock as protection against accidental self-modification, not against a determined agent.

Models#

Which set applies depends on LLM_PROVIDER. Bedrock model IDs are Bedrock model identifiers; Azure model IDs are Foundry deployment names (which default to Claude model IDs when you deploy without renaming).

bedrock-mantle reuses the same BEDROCK_* variables, but its model IDs must be bare — no us. cross-region inference-profile prefix and no version suffix (for example anthropic.claude-opus-5 rather than us.anthropic.claude-opus-5). The BEDROCK_MODEL_ID default below carries the prefix, so set it explicitly on Mantle. Embedding IDs are unaffected: embeddings always run through the Bedrock runtime.

Variable Description Default
BEDROCK_MODEL_ID Bedrock main model (the agent's reasoning loop). us.anthropic.claude-opus-5
BEDROCK_CLASSIFICATION_MODEL_ID Bedrock fast model for the heartbeat DELIVER/SUPPRESS gate. a Claude Haiku model
BEDROCK_EMBEDDING_MODEL_ID Bedrock embedding model for searchable memory. amazon.titan-embed-text-v2:0
AWS_REGION Bedrock AWS region. us-east-1
AZURE_MODEL_ID Azure main model — a Claude chat deployment name. claude-opus-5
AZURE_CLASSIFICATION_MODEL_ID Azure fast Claude deployment for the heartbeat gate. claude-haiku-4-5
AZURE_EMBEDDING_MODEL_ID Azure OpenAI embedding deployment (a text-embedding-3 model; truncated to 1024 dims to match the memory index). The deployment must exist on the resource, else memory embedding fails open. Set to '' to skip embeddings entirely. text-embedding-3-small
AZURE_API_VERSION Azure OpenAI API version (embeddings only). SDK default (preview)
CONTEXT_WINDOW_TOKENS Input-context window (tokens) to assume for the agent's model. Only needed when the catalog doesn't recognize it. Ignored unless a positive integer. derived from the model ID
MODELS_DEV_URL Refresh the model-window catalog from a registry once at startup. Unset means no outbound call, bundled catalog only. disabled

The main model can also be set per-agent at runtime (web UI Profile, the TUI /model command, or by asking the agent), which overrides the env default. On Azure, per-agent overrides are Foundry deployment names.

Heartbeat and scheduled (cron) runs can each use their own model, set the same ways — the web UI Profile page or the TUI /heartbeat-model and /cron-model commands. Both default to empty and fall back to the main model (which falls back to BEDROCK_MODEL_ID), so you can run routine heartbeats on a cheaper model while chat stays on a stronger one. The heartbeat gate always uses the active platform's classification model, independent of this.

Context-window size#

The web UI and terminal UI show how much of the model's context window a conversation has used. The runtime reads it from a bundled catalog of Claude window sizes sourced from models.dev. That bundled copy needs no network and is the only source by default.

Set MODELS_DEV_URL=https://models.dev/api.json to also refresh the catalog once at startup, so a model released after the build gets a window. Enable it deliberately — models.dev is community-maintained, so a wrong number upstream reaches your deployment without review.

Warning

In a sandboxed or egress-filtered deployment, enabling MODELS_DEV_URL means allow-listing models.dev — and an allow-list is not per-process. Once the domain is reachable, it's reachable by the agent's own tools too, not just the startup refresh. Treat it as adding a domain of untrusted, community-edited content to the web the agent can reach and act on.

When a model is in neither layer the indicator is hidden rather than guessed. That's most likely on Azure, where model IDs are deployment names you chose: AZURE_MODEL_ID=my-opus-deploy can't appear in any catalog. Set CONTEXT_WINDOW_TOKENS to that model's input-context size (for example 1000000) to bring it back. It applies to every model the agent uses, so the main and heartbeat models can't be given different windows.

Conversation compaction#

As a thread grows, the runtime keeps it within the model's context window by compacting older history rather than dropping it. After a turn that belongs to a stored thread, once context occupancy reaches COMPACTION_THRESHOLD_PERCENT of the window, the runtime summarizes older messages and keeps the newest COMPACTION_TAIL_MESSAGES verbatim. Each thread carries a single summary: a new compaction folds the previous summary into its replacement, so cost stays bounded. Slack threads are exempt — they re-read their history live from Slack on each turn.

Variable Description Default
COMPACTION_THRESHOLD_PERCENT Context-window occupancy (percent) that triggers compaction after a turn in a stored thread. 0 disables compaction. 90
COMPACTION_TAIL_MESSAGES Number of most-recent messages kept verbatim when compacting; older history is summarized. 6

Compaction can also be run on demand with the /compact slash command.

Bootstrap model defaults#

When the runtime first creates an agent (empty database), it seeds the three model overrides from ~/.prism/settings.json if present — the same file the prism TUI reads.

Key Seeds
modelId the main model
heartbeatModelId the heartbeat model
cronModelId the scheduled-task model

Each is optional; an unset, blank, or malformed value leaves that override empty (and it falls back as above). These apply only at creation — editing them later doesn't touch an existing agent; use the Profile page or the TUI commands for that.

Voice meetings#

Voice meetings let the agent join a Google Meet call and take part by voice. The tools appear only when OPENAI_API_KEY is set and the host has the browser and audio toolchain, which ships in the container image.

The voice model is OpenAI's Realtime API — the one model call that does not route through the configured provider or the Nexus gateway (Bedrock, Azure, and Bedrock Mantle serve no realtime voice surface). The socket connects straight to api.openai.com, so an egress-filtered deployment must allow that host, plus Google's meeting and accounts hosts, including WebRTC UDP. The signed-in browser profile is persisted under the data directory, so sign-in happens once rather than per meeting.

Variable Purpose Default
OPENAI_API_KEY Enables voice meetings. May be a managed-credential sentinel. — (disabled)
OPENAI_REALTIME_MODEL Realtime model for the in-meeting voice. gpt-realtime-mini is materially cheaper. gpt-realtime-2.1
OPENAI_REALTIME_VOICE Voice name. marin
OPENAI_TRANSCRIPTION_MODEL Transcriber used to decide whether the agent was addressed. Runs on every call, billed per minute of audio; never fed to the model. The default is the only streaming model that also accepts name hints. gpt-live-transcribe
GOOGLE_BOT_EMAIL Google account the agent signs into for meetings. Effectively required — Google auto-denies automated anonymous guests. Use a dedicated account.
GOOGLE_BOT_PASSWORD Password for that account. Must be the real password in plain text — a credential sentinel does not work here, because the browser types it into Google's sign-in form rather than sending it as a header. Accounts with a phone or hardware-key challenge, or enforced SSO, cannot be signed in unattended.
MEETING_TIMEOUT_MINUTES Hard cap on one call. A non-positive or malformed value falls back to the default. 60
MEETING_ADMISSION_TIMEOUT_SECONDS How long to wait in the waiting room for a host to admit the agent, counted from when the join request goes in. 300

Observability#

All optional; each is off until its variable is set. Langfuse traces every LLM call (model, tokens, tool calls, latency); OpenTelemetry exports product telemetry to a collector. Structured logs (Pino) are always on.

Variable Description Default
LANGFUSE_SECRET_KEY Enables Langfuse LLM tracing when set.
LANGFUSE_PUBLIC_KEY Langfuse public key.
LANGFUSE_BASE_URL Langfuse server URL. http://localhost:3100
OTEL_EXPORTER_OTLP_ENDPOINT Enables OpenTelemetry export when set.
OTEL_EXPORTER_OTLP_API_KEY Collector auth, sent as x-api-key.
DEPLOYMENT_ENVIRONMENT Tags OTel records (production / staging / development). production (published images)

With OpenTelemetry enabled, the runtime emits product telemetry events. They carry only identifiers, flags, and counts — never credentials, URLs, file paths, or message content.

Installer variables#

These affect the native installer, not the running agent.

Variable Description Default
PRISM_HOME Install directory. ~/.prism (%USERPROFILE%\.prism)
PRISM_HTTP_URL Runtime URL the prism TUI connects to. http://localhost:3003