Local API
The daemon serves a loopback HTTP API — 127.0.0.1:7645 by default, or a
Unix socket. It is the seam every co-located collector uses: SDKs, the hook
guard, wrapped MCP servers, your own scripts.
Health and introspection
curl -s 127.0.0.1:7645/v1/health | jq # liveness — what installers poll
curl -s 127.0.0.1:7645/v1/policy | jq # which policy id/version is loaded
curl -s 127.0.0.1:7645/v1/status | jq # what `lumen-agent status` reads:
# pid, supervisor, proxy upstreams,
# spool depth, control state, heartbeat
One-shot inspection
curl -s 127.0.0.1:7645/v1/inspect \
-d '{"stage":"input","text":"the key is AKIAIOSFODNN7EXAMPLE"}'
{
"action": "redact",
"text": "the key is [REDACTED:credentials]",
"spans": [[11, 31, "credentials.aws_access_key"]]
}
stage is input (prompt rules) or output (response rules). The response
carries the effective action, the post-action text, and the span list.
Streaming: hold and release
A secret split across streaming chunks matches nothing on its own. The stream API accumulates deltas, forwards only the provably clean prefix, and holds the tail until it can be judged:
SID=$(curl -s 127.0.0.1:7645/v1/stream/start -d '{"stage":"output"}' | jq -r .stream_id)
curl -s 127.0.0.1:7645/v1/stream/chunk -d "{\"stream_id\":\"$SID\",\"text\":\"The backup key is AKIAIOSFO\"}"
curl -s 127.0.0.1:7645/v1/stream/chunk -d "{\"stream_id\":\"$SID\",\"text\":\"DNN7EXAMPLE, keep it safe.\"}"
curl -s 127.0.0.1:7645/v1/stream/end -d "{\"stream_id\":\"$SID\"}"
Each chunk call returns what may be delivered now and how much is
held; end flushes the remainder post-action. The user never sees a
character of the secret — see
demo 11.
The capturing proxy uses this same hold-and-release window internally for SSE responses, so clients keep their streaming UX while the output is still enforced.