Repository navigation
Route first-party Claude Desktop traffic through agentgateway without third-party mode #182
Description
Problem
Today, agentdesktop sends Claude Desktop traffic to agentgateway in third-party inference mode. To do this, it writes inferenceProvider: "gateway" and inferenceGatewayBaseUrl to the managed settings (reconcile.rs#L158).
In third-party mode, Claude Desktop does not sign in to an Anthropic account. The claude.ai chat history, connectors, and organization-managed settings (Claude Team and Enterprise) do not apply in this mode. If an organization uses these features, it cannot put agentgateway in the path, because its users lose the features.
Goal
- Claude Desktop stays signed in to claude.ai (first-party mode).
- Claude Desktop sends its Anthropic traffic through agentgateway. agentgateway applies its policies: authentication, guardrails and DLP, audit, and telemetry.
- agentdesktop does not replace or change the claude.ai login of the user.
Proposed approach
- Local intercepting proxy. The daemon listens on loopback for HTTPS
CONNECTrequests. The current LLM proxy is a reverse proxy with fixed routes, and it refusesCONNECT(llm_proxy.rs#L794). The new proxy can reuse its credential cache and its tunnel relay. - Proxy selection with a PAC file. The daemon serves a PAC file. The PAC file sends only the allowlisted Anthropic hosts to the proxy, with no
DIRECTfallback. All other hosts connectDIRECT. The host allowlist is a configuration value. There are two ways to apply the PAC file. As the system's automatic proxy configuration, it also steers browsers. With Claude's managed keyegressProxyPacUrl, it steers only Claude Desktop. - TLS termination for allowlisted hosts only. The proxy issues leaf certificates from a device-local CA, or from a CA that the admin supplies. Name constraints limit the CA to the allowlisted domains. For other hosts, the proxy tunnels the traffic without change. It must not refuse them, because the Code tab agent sends all of its traffic to one proxy.
- Upstream to an agentgateway passthrough route. The proxy does not change the
CookieandAuthorizationheaders. It adds a separate identity header, which agentgateway validates and removes before it sends the request upstream. The header carries the gateway OIDC token or the controller-issued credential. Which one to use, and which daemon runs the listener, is still open: the current loopback proxy runs in user mode only. - First-party mode for the Claude Desktop provider. In this mode, the provider writes no third-party inference keys. It also removes the keys that it wrote before.
- Claude Code. In the Desktop Code tab, Claude Code already uses the app's proxy and trusts the System keychain. The standalone CLI can use
HTTPS_PROXY, andNODE_EXTRA_CA_CERTSif it is necessary. This is not tested yet.
Alternative: agentgateway is the forward proxy and does the TLS interception. This option needs less code on the device. But agentgateway must support forward-proxy mode and TLS interception, and the identity must go in the Proxy-Authorization header. Both options need a CA that the device trusts. This proposal keeps the interception on the device, so agentgateway stays a normal reverse proxy.
The full design proposal, with the work items: #185
Open questions
A spike on macOS answered some of these questions. Results: spike results comment
- Does Claude Desktop use the OS proxy and PAC settings and the OS trust store? Does it pin certificates? This is the go/no-go question. Yes, for the app, the Code tab agent, the helpers and the updater. It does not pin certificates. The Cowork VM is not checked.
- Which hosts and protocols (HTTP/2, SSE, WebSocket) does Claude Desktop use in first-party mode for chat, uploads, connectors, and telemetry? Answered in the spike results for Cowork sessions and the Code tab. Chat mode is not confirmed.
- With interception on, do these features continue to work: sign-in with SSO, org-managed settings, connectors, and history? Partly answered. Org-managed settings and connectors work. Sign-in and history sync are not tested.
- Can agentgateway pass claude.ai traffic through and keep streaming intact? Can it apply guardrails to request bodies that do not use the Messages API format?
- Who owns the CA, and how does the trust install work? The install is for system mode only. On macOS, the System keychain needs admin authentication or an MDM profile. On Windows, the target store is LocalMachine\Root. Partly answered. Full trust in the System keychain works for the Claude processes that were tested. Who owns the CA is still open.
- If the gateway is not available, does the proxy fail open or fail closed? Partly answered. When the local proxy is down, Claude Desktop fails closed with a PAC file that has no
DIRECTfallback. It reconnects when the proxy comes back. A gateway outage is not tested. The proposal is to fail closed by default. - How does the proxy work with an enterprise proxy that already inspects TLS? Topics: chaining to an upstream proxy, and double interception.
Out of scope for now
This issue does not include browser-based clients, for example chatgpt.com or Microsoft 365 Copilot on the web. Later, the configurable host allowlist can extend the same mechanism to these clients.
Activity
ilackarms commentedon Oct 20, 2026
Spike results: first-party Claude Desktop through a local intercepting proxy
Setup. Claude Desktop 2.42304.2 ran on macOS 26.6. It used an organization account on claude.ai. The app had no third-party inference keys. mitmproxy 12.2.3 was the local proxy, and a PAC file on loopback pointed the traffic to it. The mitmproxy CA had full trust in the System keychain.
Verdict: go, with conditions. Claude Desktop follows the OS proxy settings and trusts the OS trust store. It does not pin certificates. The conditions are under "Still open" below.
Design. The design proposal that uses these results is in #185.
Answers to the open questions
OS proxy, PAC and trust store; certificate pinning (go/no-go): Yes.
The app, its renderer, the Code tab agent, the helper processes and the updater all used the PAC and accepted the local CA. In about 3,100 requests, the proxy recorded 0 client TLS failures. The Code tab agent did not need
NODE_EXTRA_CA_CERTS. It gets its proxy from the app when the session starts.Control test: I removed the trust for the CA and restarted the app. Then every connection from the app to claude.ai failed. The app log showed
ERR_CERT_AUTHORITY_INVALID. This result shows that the app validates certificates.Hosts and protocols:
claude.ai: HTTP/2 only. It carries org settings, session events, uploads, connector calls and telemetry. Event streams use SSE.api.anthropic.com: traffic from the Code tab agent (HTTP/1.1, Messages API with SSE, one WebSocket) and the update check.bridge.claudeusercontent.com: WebSockets for Remote Control and the browser extension bridge.assets-proxy.anthropic.com,s-cdn.anthropic.com,a.claude.ai: static app files only.assets-proxyhad more than half of all requests.downloads.claude.ai: large binaries. The proxy tunneled this host and did not decrypt it.eventsarray toPOST claude.ai/v1/code/sessions/{id}/events. The reply comes back on an SSEevents/stream. I did not see a classic chat completion endpoint. I did not confirm if Chat mode uses the same endpoints.Sign-in, org-managed settings, connectors, history: Partly tested.
Org settings loaded. A claude.ai connector tool call worked (
POST …/mcp/servers/{id}/tools/callwith{tool_name, arguments}). Cowork sessions worked with and without file attachments. Remote Control and the update check worked. I did not test sign-in (including SSO) or history sync between devices.agentgateway passthrough and guardrails on bodies that do not use the Messages API: Not tested here.
Inputs for that test:
eventsarrays (sessions), multipart{file}(uploads),{tool_name, arguments}(connectors), and the Messages API (Code tab).CA ownership and trust install.
Full root trust in the System keychain works for the Claude processes that I tested. These are the app, the Code tab agent, the helpers and the updater. I did not test the Cowork VM or local MCP servers. This needs admin rights or an MDM profile. Each process reads trust when it starts. After an admin installs, rotates or removes the CA, Claude must restart. A web browser also kept the old trust after I removed it, probably because of a cache.
Fail open or fail closed: Fails closed when the local proxy is down.
The PAC had no
DIRECTfallback. While the proxy was down, messages failed, and no traffic went around the proxy. When the proxy came back, the app reconnected after about 6 seconds, without a restart. Code tab sessions keep the proxy address from their start, so they also fail until the proxy returns. I did not test a gateway outage, because the test had no gateway.Enterprise proxies that already inspect TLS: Not tested.
Still open
bad record macalert to mitmproxy immediately after a 1.1 MB upload. Five uploads of the same size to a different host had no errors. I will test this again with the real daemon.egressProxyPacUrlmanaged key, which can steer only Claude Desktop. A system-wide PAC also sends browser traffic for claude.ai to the proxy.claude.ai,api.anthropic.com, and optionallybridge.claudeusercontent.com. Static hosts anddownloads.claude.aican stay direct.Implications for the implementation
CONNECTrequests for hosts that are not on the allowlist. Do not refuse them. The Code tab agent sends all of its traffic to the one proxy it gets.