Production & headless agents

Getting a deployed agent — a LangChain worker in Docker, a CrewAI job on Kubernetes, an SDK agent in CI — governed and reporting to the console. This is the path for machines with no human at the keyboard and no git repo, which is where the laptop instructions quietly stop working.

Read Connect to the platform for the identity model, and your framework's page (e.g. LangChain) for the code-level wrap.

The short version

FROM python:3.12-slim
RUN pip install "prismor[langchain]"

# Identity: a deviceless agent key, minted in the console.
ENV PRISMOR_AGENT_KEY=prism_agent_...
ENV PRISMOR_AGENT_LABEL=checkout-worker

# Required for a repo-less workload — see "Workspace scope" below.
ENV PRISMOR_WORKSPACE_SCOPE=managed

# Prismor needs a writable home for the policy cache, spool and heartbeat.
ENV PRISMOR_HOME=/var/lib/prismor
VOLUME /var/lib/prismor

COPY worker.py .
CMD ["python", "worker.py"]
# worker.py
from prismor.langchain import guard_tools
tools = guard_tools([run_shell, fetch_url])   # every call policy-checked

Then verify from inside the container:

prismor doctor

Every check must be . The four that decide whether anything reaches the console are enrollment, workspace scope, telemetry sink and remote policy.

1. Identity: mint an agent key

A deployed workload has no browser, so prismor login does not apply. Two options:

Agent key (recommended). Console → Connections → SDK & deployed agents (or Admin → Devices) → Mint agent key. Copy it immediately — it is shown once. Set it as PRISMOR_AGENT_KEY. The key is read from the environment and never written to disk, so it survives a read-only root filesystem.

PRISMOR_AGENT_KEY=prism_agent_xxxxxxxx
PRISMOR_AGENT_LABEL=checkout-worker      # optional, names it in the fleet
PRISMOR_API_BASE=https://www.prismor.dev # optional, for self-hosted

Enrollment token. Mint a token in the console and run prismor enroll <token> at container start. This writes $PRISMOR_HOME/identity.json, so the home must be writable and persistent, and the token is single-use — a restarting container will fail the second time. Prefer the agent key.

Every event from an agent key is attributed to the admin who minted it, since the underlying service identity needs an owner. Mint one key per workload and label it, so the fleet view stays readable.

2. Workspace scope: the setting that decides if anything is reported

This is the most common reason a correctly-installed agent shows up empty.

Scope is normally inferred from the workspace's git remote: a repo matching one of your org's claimed patterns is managed, anything else is the developer's personal space. Scope gates the org policy overlay — and that overlay is what carries the telemetry sink. A container has no git remote, so if your org has claimed any repo patterns, a deployed workspace falls through to local and reports nothing at all.

Set it explicitly:

PRISMOR_WORKSPACE_SCOPE=managed

Requires prismor >= 1.37.0. On earlier versions, run prismor workspace managed at container start instead (needs a writable $PRISMOR_HOME and the same working directory every run).

An org-claimed repo pattern always wins over this variable, so a deployment can never use it to opt company code out of governance. Use personal to deliberately keep a workload's traffic out of the org.

3. A writable PRISMOR_HOME

Prismor keeps the verified policy cache, its signature, the telemetry spool, the heartbeat counter and the agent register under $PRISMOR_HOME (default ~/.prismor). Every write is best-effort: on a read-only filesystem they fail silently, and the result is a re-pull of the policy on every process, a heartbeat that never accumulates, and spooled events lost on restart.

If you harden the container with --read-only (see Docker & containers), mount a writable volume and point PRISMOR_HOME at it:

docker run --read-only \
  -v prismor-state:/var/lib/prismor \
  -e PRISMOR_HOME=/var/lib/prismor \
  -e PRISMOR_AGENT_KEY=prism_agent_... \
  -e PRISMOR_WORKSPACE_SCOPE=managed \
  your-agent:latest

4. Verify it end to end

prismor doctor

doctor makes one authenticated call to the control plane, so it fails on a revoked or mistyped key rather than reporting "enrolled" from a local file. What to look for:

CheckHealthyIf it fails
enrollmentverified with the control plane — org …Key is wrong, revoked, or points at another org
workspace scopemanaged (env_override)Nothing will be reported — set PRISMOR_WORKSPACE_SCOPE=managed
telemetry sinkauthenticated to https://…Cannot deliver; check egress and the key
remote policyv<N>, Ed25519 signature verifiedPolicy has not been pulled yet — it lands on the first tool call
captureFULL or redactedSee below

prismor enroll-status gives the same identity summary in short form, including a verified: line.

In the console, the workload appears under Connections → SDK & deployed agents with a last-seen time. If it says never seen, the container has not completed a single authenticated call yet.

Requires prismor >= 1.37.0 for the authenticated checks; on earlier versions doctor reports reachability only and cannot detect a bad key.

5. What actually gets logged

Two things to calibrate before you judge the console empty.

Findings, not every call. The runtime uploads events for calls that produce a finding — blocked, warned, or would-block. A benign git status emits nothing. A well-behaved agent therefore produces a per-minute activity count and little else, which reads like a broken install but is not one. To confirm the pipeline, run something that trips a rule:

prismor check "rm -rf / --no-preserve-root"

Redacted by default. Uploaded events carry severity, category, rule id, tool name, session, subject and an evidence hash — not your content. An org admin can opt into full capture (Admin → Org Settings), after which flagged events also carry the scrubbed evidence. This is org-wide and server-enforced: the ingest route stores no detail while it is off, whatever the client sends.

Retention is per-org (Org Settings → telemetry retention, default 90 days, clamped 7–365).

6. Policy, IAM and approvals in production

  • Mode. Once a machine is enrolled, the org's signed policy is authoritative: a locally-passed mode="observe" no longer suppresses a block. Dry-run a fleet from the console (org or per-agent), not from a keyword argument. See frameworks overview.
  • Per-user attribution. Wrap request handling in use_subject("user:alice") so multi-tenant traffic is attributable and per-user IAM applies.
  • Approvals. A step_up rule holds a call for a human. Headless agents post the request to the control plane and wait — set a wait budget with PRISMOR_APPROVAL_TIMEOUT and make sure a route or webhook is configured, or the call fails closed after the timeout. See Human-in-the-loop approvals.

Checklist

  • Agent key minted and set as PRISMOR_AGENT_KEY
  • PRISMOR_WORKSPACE_SCOPE=managed (repo-less workloads)
  • PRISMOR_HOME writable and persistent across restarts
  • Tools wrapped (guard_tools(...) or your framework's equivalent)
  • prismor doctor all from inside the container
  • A deliberate violation appears in the console
  • Full capture and retention set to your policy
  • An approval route or webhook exists if any rule uses step_up