Endpoint agent
lumen-agent is the host sensor: a single static Go binary that runs as an
OS service, whether systemd, launchd or SCM, and needs zero inbound
ports. It is the hardest and most valuable piece of the product, the
collector that makes a machine observable the moment the agent is installed.
What runs on the device
lumen-agent (Go daemon / service)
├─ Local inspection API loopback HTTP, 127.0.0.1:7645 — for SDKs, hooks, apps
├─ LLM proxy 127.0.0.1:7646 — captures provider traffic itself
├─ MCP proxy stdio wrapper for agentic tool traffic
├─ Claude Code hook guard fresh process per event, enforces without the daemon
├─ Context enricher process, user, device posture
├─ Local detection engine regex, Aho-Corasick, entropy, classifier, bloom filter
├─ Policy cache hot-reloaded, ~2 s after a file change
├─ Spooler on-disk queue, survives restarts and offline windows
└─ Transport outbound-only HTTPS to the Lumen cloud
The parts worth knowing
- The inspection API answers "is this dangerous?" for anything on the machine that asks. See Local API.
- The proxy is what makes the agent capture rather than wait to be
called: AI tooling is pointed at
127.0.0.1:7646by autoconfig, and prompts are inspected before they leave the machine. - The hook guard covers what the proxy cannot see, namely the shell commands, file writes and fetched pages of an agentic session, and keeps enforcing even if the daemon is stopped or uninstalled. It also covers Claude Desktop's Code tab, which runs Claude Code: its prompts and tool calls, not the model's replies.
- The spooler buffers findings on disk with backpressure, so capture never blocks the user's AI tool and nothing is lost offline. A record the control plane cannot store, even on its own, is moved to a bounded dead-letter bucket in the same spool instead of being retried forever, so one bad record can never stop the records behind it from uploading.
- Policy hot-reload: save the file, and the running agent picks the change up within about two seconds. An invalid edit is rejected and the previous version stays live.
Enrollment and transport
The agent enrolls with a tenant-scoped enrollment token, passed as
install.sh --token=… or pushed by MDM. It posts that token together with the
machine's hostname, operating system, architecture and agent version, and
receives a device id and a device credential: an opaque 256-bit bearer
token issued once, which the control plane stores only as a hash. The agent
writes it to /var/lib/lumen/device.json with mode 0600, then empties the
token file, so a spent token cannot be replayed.
The tenant is never self-asserted. The enrollment request carries no tenant field at all. The token resolves to its own tenant on the server, and every later request inherits that binding.
Everything after enrollment is outbound HTTPS presenting the device credential as a bearer token:
| Direction | Call | Carries |
|---|---|---|
| up | heartbeat, every 60 seconds by default | agent version, the autoconfig coverage report, and counts of the records the agent did not upload |
| up | findings | gzip NDJSON batches drained from the disk spool, in two lanes |
| down | policy | the assigned policy, with a version check answering 304 when nothing changed |
Findings go first. The spool drains in two lanes, each sending one batch at a time:
| Lane | Carries | Drains |
|---|---|---|
| Findings | every finding, and the response to a request that produced one | every 3 seconds |
| Activity | everything else, including matches that are not findings | once a minute, or sooner once 2 MB or 256 records are waiting; every 5 minutes on a day the endpoint is past its allowance, when that text is not stored anyway |
After a full batch a lane waits at least a second before the next one, so an endpoint uploads at most about two requests a second however much it has queued. Each lane backs off on its own, so a slow or rate-limited activity lane never holds back findings. The heartbeat's answer can suggest other intervals, and the agent keeps them within 1 to 10 seconds for findings and 3 seconds to 10 minutes for activity. An upload that meets the service-wide rate limit is retried after a backoff, and one that overlaps another upload from the same endpoint waits the few seconds the service asks for; neither loses anything. When the agent stops, each lane uploads what it can for up to 10 seconds, and the rest stays queued on disk for the next start. Agents released before the service limits drain one lane every 3 seconds.
Before a record is queued for upload, the agent leaves out clean copies of what its own proxy is capturing in the same session, such as a Claude Code prompt the proxy's next request also carries, and cuts the text of anything that is not a finding to 8 KB. It counts each record it leaves out and reports the counts on the heartbeat. The findings file on the machine still holds every record the agent leaves out of the upload, with up to 64 KB of text, until the file rotates. See Service limits.
The heartbeat's answer also carries where the endpoint stands against its daily
allowance, and lumen-agent status prints it, with a second line for the two
lanes (how often each uploads, what is queued, and when it last succeeded):
limits Service limits (UTC 2026-09-30): 2,140 of 2,000 agent events stored with text, borrowing
lanes findings every 3s, 0 queued, last upload 2s ago; other events every 1m0s, 41 queued, last upload 18s ago
An enrollment token is single-use. One already spent, or past its expiry, is refused. An enrollment that would take an organization past its endpoint allowance is also refused, and deliberately before the token is consumed, so the same install command works again once there is room. How much of the allowance is used is shown on the console's Endpoints page, and the allowance each plan carries is in Plans and pricing.
Platforms
Every release builds {linux, darwin, windows} × {amd64, arm64} with
CGO_ENABLED=0: one dependency-free file per platform. Building for a platform
is not the same as supporting it:
| Platform | Support level |
|---|---|
| macOS (Apple silicon and Intel) | Supported. The platform Lumen is tested on |
| Linux | Preview. Builds and packages ship; not yet tested or supported |
| Windows | Preview. Builds ship; not yet tested or supported. The installer registers the Claude Code hooks; shell routing needs Git Bash, and there are known gaps in browser wiring. The service logs to the Application event log, source lumen-agent |
What the installer does on each is in Install the agent.