Privacy
Agent Relay is local-first. Every byte written by the always-on layer
lands in ~/.relay/ on your machine. Nothing uploaded unless you
explicitly opt into the proxy mode or telemetry — and even then, the
defaults stay conservative.
What gets captured
| Adapter | Captures |
|---|---|
| Claude Code hook | Tool name on each invocation, stop reasons, notification text. |
| PTY wrapper | Process lifecycle + line-level rate-limit detection from stdout. The agent's full stdout is mirrored to your terminal, not copied to disk. |
| VS Code extension | File-edit events (path + hunk count, not content). Session lifecycle. Manual handoff triggers. |
| Warp MCP | Whatever the Warp agent decides to call relay_log_event with — under the agent's control. |
| Proxy mode (opt-in) | LLM API response headers (rate-limit counters, retry-after). Request/response bodies are seen in flight but never written to disk. |
What gets redacted
By default (privacy.redact_secrets = true), every adapter applies the
same redaction rules before writing:
- Object keys matching
(secret|key|token|password|credential|bearer|api[_-]?key)→ value replaced with[redacted]. - Inline values matching well-known token formats → replaced inline:
sk-…(Anthropic / OpenAI)ghp_…(GitHub personal access tokens)xox[abp]-…(Slack)
- Tool argument values are not captured by default
(
privacy.capture_tool_args = false) — we keep the structure ("agent calledEditwith these arg names") but drop the values. Flip the flag if you want lossless capture and trust your redaction rules.
Same rules apply across the Python daemon, the VS Code extension, and
the Warp MCP server. Source: src/agent_relay/daemon/redact.py and
extensions/vscode/src/redact.ts.
Where it lives on disk
~/.relay/
├── VERSION # layout version
├── config.toml # your settings
├── sessions/ # per-session manifests
├── events/<session>.jsonl # append-only event log
├── snapshots/<id>.md # handoff primers
├── logs/daemon.log # daemon stdout/stderr
├── relay.sock # unix socket (POSIX)
└── telemetry-id # random UUID, only present if you opt in
To inspect everything captured for a session:
cat ~/.relay/events/<session>.jsonl # raw events
relay snapshots # the resulting primers
relay daemon status # in-memory viewTo wipe everything captured:
relay uninstall # remove adapters + launch agent
rm -rf ~/.relay # delete the dataTelemetry
Off by default. Toggle on in ~/.relay/config.toml:
[telemetry]
enabled = true
endpoint = "https://telemetry.agent-relay.dev/v1/ingest"When enabled we send aggregate-only counters: which adapters are in use,
handoff success rate, the daemon version. No event content, no file
paths, no environment variables, no per-session anything. The install id
is a random UUID stored at ~/.relay/telemetry-id; deleting it rotates
the id.
What gets sent (full schema):
{
"schema": "agent-relay.telemetry/v1",
"event": "handoff.fired",
"install_id": "01HRZ…",
"sdk_version": "0.1.0",
"properties": { … aggregate counters … }
}The full source is at
src/agent_relay/daemon/telemetry.py.
Sends are background-threaded with a 3-second timeout and silently
dropped on failure — telemetry can never block the daemon.
What we never store
- Your source code.
- LLM prompts or responses.
- Environment variables.
.envfile contents.- Tool argument values (with the default config).
- Anything resembling an API key — even when the proxy is on.
Reporting concerns
If you find a redaction miss or a place where data leaves the machine unexpectedly, please open an issue at github.com/bethvourc/agent--relay. This is the area we treat as a hair-trigger bug class.