Integrating any endpoint
Shadow is not tied to a list of applications. If something sends HTTP requests to a model API, Shadow can sit in front of it. This page shows how to decide where to plug it in.
Decision guide
Section titled “Decision guide”- Can you set a base URL? Use gateway mode. Most SDKs, CLIs and frameworks (LangChain, LlamaIndex, Vercel AI SDK, LiteLLM, the OpenAI and Anthropic SDKs) accept one, often from
OPENAI_BASE_URLorANTHROPIC_BASE_URL. - Does it honour
HTTPS_PROXYor the system proxy? Use proxy mode. This covers most IDE extensions, Electron apps, Python and Node scripts, and CI jobs, as long as they call an intercepted AI host. Tools that talk to their vendor’s own backend instead (GitHub Copilot, Cursor) are not masked unless you add that host withextra_hosts, and then only if Shadow can parse their request format. - Is it your own Rust code? Embed
shadow-core. - Is the endpoint not a built-in provider? Add a route or an intercepted host for it (below).
A custom or self-hosted model API
Section titled “A custom or self-hosted model API”Any HTTPS endpoint that accepts JSON prompts can be protected: an internal LLM gateway, a vLLM or TGI server on another machine, a vendor API that wraps a model.
[proxy]# proxy mode: decrypt and mask traffic to these hosts tooextra_hosts = ["llm.internal.example.com"]
[proxy.routes]# gateway mode: http://127.0.0.1:8877/gw/internal/... -> https://llm.internal.example.com/...internal = "https://llm.internal.example.com"Shadow masks every string value in a JSON request body, except protocol keys such as model, role and type, so it works with request shapes it has never seen. Responses are restored in full JSON bodies and in SSE or NDJSON streams. Streams of unknown formats are still restored string by string; only the cross-event reassembly of split fakes is format-specific (OpenAI Chat Completions and Responses, Anthropic, Gemini, Cohere and Ollama-style NDJSON).
Non-JSON request bodies are forwarded as they are, except for file uploads, which are masked.
Agents and tool calls
Section titled “Agents and tool calls”Agents are where privacy and usefulness collide: the model has to act on real values. Shadow handles this with the intent-aware policy:
- The person the instruction asks the agent to contact or act on is the recipient and passes through as written, logged, so the model addresses the right person (
[policy.act] targets, defaultkeep;surrogatefakes it). - When the agent’s tools run on your side (your code executes the tool call), the model sees fakes for everything else and writes tool calls with them. Shadow restores the real values in the tool-call arguments before they reach your code.
- When tools run in the provider’s cloud (hosted MCP servers, server-side tools), Shadow cannot restore values there. By default it keeps real what the action needs (the contact details, people, companies, addresses, usernames and IBANs named in the instruction, and for a follow-up that names no email or phone, the emails, phones and people anywhere in the request), keeps secrets, cards and IDs masked, and logs each keep. You can change this.
Details and examples in Tool calls and agents.
IDEs and coding assistants
Section titled “IDEs and coding assistants”Coding assistants send file contents, paths, hostnames and pasted configuration, which is exactly what Shadow is good at protecting. Usernames in paths (/Users/jdoe/...), internal hostnames, IPs and API keys are masked, and the code intent keeps identifiers readable.
- VS Code and JetBrains extensions. Most use the IDE’s proxy setting or
HTTPS_PROXY. Set the IDE’s HTTP proxy tohttp://127.0.0.1:8877and make sure the CA is trusted by the OS (VS Code uses the OS store; JetBrains IDEs can be pointed at it in Settings → Tools → Server Certificates). - Terminal assistants and CLIs. Start them from a shell where
env.shis sourced, or set their base URL variable. - Desktop chat apps. Use the PAC file or system proxy for apps that call a provider API with your key. The ChatGPT and Claude desktop apps talk to their consumer backends (chatgpt.com, claude.ai), which are not intercepted. Apps that pin certificates will refuse the local CA; there is no workaround for those besides using a different client.
Backend services in any language
Section titled “Backend services in any language”Point the service’s model client at the gateway URL through configuration, and run Shadow next to it as a service or sidecar. No code change is required beyond the base URL.
# Python, Node, Go, Java: any OpenAI-compatible clientOPENAI_BASE_URL=http://127.0.0.1:8877/gw/openai/v1 ./my-serviceChecklist
Section titled “Checklist”- Run
shadow scanon a few representative prompts and documents to see what is detected before you rely on it. - Add your organisation names, codenames and customers with
organization,termsorshadow terms add. - Decide how actions in provider-hosted tools are handled (
[policy.act] remote_tool_targets). - Keep Shadow on loopback, or inside the pod.
- Check the log line per request (
masked N value(s)) during rollout.
Frequently asked questions
Does Shadow work with Claude Code and other coding assistants?
Yes, when the tool accepts a base URL such as ANTHROPIC_BASE_URL or honours HTTPS_PROXY and calls an intercepted AI API host. Usernames in paths, internal hostnames, IPs and API keys are masked.
Does it work with Cursor or GitHub Copilot?
Not by default. They talk to their vendors' own backends, which are not on the intercept list; you can add a host with extra_hosts, but it is masked only if Shadow can parse the request format.
Can I protect a self-hosted or internal model API?
Yes. Add its host to [proxy] extra_hosts for proxy mode, or a route under [proxy.routes] for gateway mode. Shadow masks every string value in a JSON body, so unknown request shapes work too.
Are the ChatGPT and Claude desktop apps covered?
No. They talk to their consumer backends, chatgpt.com and claude.ai, which are not intercepted.