Skip to main content

Local proxy & autoconfig

A passive agent monitors nothing: something has to route AI traffic to it. The agent solves this itself. It runs a local LLM API proxy, and autoconfig points the machine's AI tooling at it. From the moment it is installed, the AI traffic it can reach is inspected and logged without anyone wiring anything by hand.

The proxy

client ──► lumen-agent proxy (127.0.0.1:7646) ──► api.anthropic.com

├─ prompt inspected before it leaves the machine
├─ completion inspected before the client sees it
└─ finding recorded for both
  • Providers. Anthropic (/v1/messages) and OpenAI-compatible (/v1/chat/completions, /v1/responses, …) are recognized by path; --upstream name=url sends a provider somewhere else.
  • Redact rewrites the request body, so the secret never reaches the provider. Block returns the vendor's own error shape, so the client reports a normal API failure, not a broken connection.
  • Streaming relays SSE through the hold-and-release window — only the provably clean prefix is forwarded.
  • Provenance-aware. A chat request carries the whole transcript. The newest user turn is enforced in full; a tool_result is judged by response rules (third-party data is indirect injection); earlier turns are logged but never blocked — otherwise one paragraph about prompt injection in the history would wedge the session for good.
  • Never in the way. Unparseable bodies, unknown paths, provider errors: forwarded unchanged. Oversized bodies (> 8 MB) are relayed uninspected with a capture_skipped finding — never a 413.
  • Credentials pass through and are never logged, stored, or written to a finding.

Standalone use, without a service:

lumen-agent proxy # 127.0.0.1:7646
export ANTHROPIC_BASE_URL=http://127.0.0.1:7646
export OPENAI_BASE_URL=http://127.0.0.1:7646/v1

In an install, the daemon serves the proxy whenever the config carries a proxy: section — one engine, one policy, one findings file.

Autoconfig

lumen-agent autoconfig status # what is here, and what is routed
lumen-agent autoconfig apply # point it at the proxy
lumen-agent autoconfig revert # put everything back
TargetWhat is changed
Shell profileOne managed block exporting ANTHROPIC_BASE_URL / OPENAI_BASE_URL, guarded by a sub-second health probe
Claude Codeenv.ANTHROPIC_BASE_URL in its settings file — opt-in (--only claude-code) because a JSON setting cannot fail open
Zedlanguage_models.{anthropic,openai}.api_url — opt-in (--only zed), same reason
Claude Code hooksThe guard registered on UserPromptSubmit, PreToolUse, PostToolUse
MCP serversReported, not rewritten — the wrap command is printed instead

Because this edits other programs' configuration, four rules hold:

  1. Every change is backed up next to the original.
  2. Every change is reversible with revert, which restores the file.
  3. A target already pointed somewhere else is never hijacked — a corporate gateway is reported as a conflict and skipped; --force is required to override.
  4. Redirection fails open, never closed. A stopped, crashed or uninstalled agent must never cut the machine off from its AI providers. apply refuses to route at a proxy that does not answer GET /lumen/health; the shell block probes before exporting; and the targets that cannot be made conditional are opt-in.

Applying twice changes nothing the second time. autoconfig revert is always the panic button.

The Claude Code hook collector

The proxy sees the conversation with the model; it cannot see what the agent then does on the machine. lumen-agent hook covers those moments:

EventWhat it seesWhat it can do
UserPromptSubmitthe typed prompt, before the modelBlock (the contract offers no rewrite, so Redact blocks and says why)
PreToolUsethe tool and its arguments, before executionDeny, or replace the arguments
PostToolUsethe tool's result, before the model reads itBlock, or rewrite — where indirect injection from a fetched page is neutralized

The guard is a fresh process per event and never talks to the daemon: it keeps enforcing after the daemon is stopped, crashed, or uninstalled. A guard that breaks the session is worse than no guard, so an unparseable payload or an internal error lets the action proceed and reports on stderr.

autoconfig apply --managed registers the guard in Claude Code's enterprise policy file — outranks user settings, applies to every user, needs administrator rights. That is the difference between a convenience and a control.

What is captured, and what is not

SurfaceStatus
Claude Code, and any tool honouring ANTHROPIC_BASE_URLCaptured, prompt and completion, streaming included
What Claude Code does locally (commands, writes, fetched pages)Captured through the hook collector
Scripts, notebooks, CLIs using OpenAI/Anthropic SDKsCaptured through the shell profile export
MCP tool calls and resultsCaptured when wrapped with lumen-agent mcp
Browser AI (ChatGPT, Claude.ai)Not yet — that is the browser extension
Closed desktop apps with no base-URL settingNot capturable this way

The honest summary: after autoconfig apply, developer AI traffic on the machine is monitored.