docs/documentation/platform/agent-proxy/standalone-agent-proxy.mdx
A standalone proxy serves agents that run somewhere other than your own computer, and is the setup to use when a team shares one proxy. agent-proxy start runs it as one long-lived process on a machine of its own, and agent-proxy connect launches each agent behind it. Because the agent is on a different host, it has no access at all to the process holding the real credentials; that separation is the security boundary, and most of what follows exists to keep it intact.
+---- Your private network -------------------+
| |
| +--------------+ |
| | Agent host |----+ | +------------------+
| +--------------+ | | +-->| External APIs |
| | +----------------+ | | +------------------+
| +-->| Agent Proxy |-------+
| | | its own host |-------+
| +--------------+ | +----------------+ | | +------------------+
| | Agent host |----+ | +-->| Infisical |
| +--------------+ port 17322, | +------------------+
| agents only |
+---------------------------------------------+
This page is the reference behind that arrangement: how an agent is authorized on every request, how to deploy it, where it belongs in your network, and what it keeps in memory.
The Agent Proxy is pinned to one organization, the one its own machine identity belongs to, but nothing narrower: no project, environment, path, or services are configured on it. It discovers those per agent. When an agent connects, the Agent Proxy uses the agent's token to look up which proxied services that agent may use in the agent's folder scope. It then fetches the real secret values with its own machine identity. One Agent Proxy instance can serve many agents across projects and environments in the org while keeping them isolated: an agent can never receive credentials it was not granted Proxy access to, even on a shared instance.
The Agent Proxy's security boundary is machine identity: what an agent can reach is decided entirely by its permissions:
407 and a Proxy-Authenticate: Basic response. A request whose token is present but invalid, expired, or revoked is rejected with 403. Both checks happen before anything else.start runs the proxy, connect launches an agent behind it. They live on different hosts and are always used as a pair:
# On the proxy host
infisical secrets agent-proxy start
# On each agent host; everything after -- is the agent's own command
infisical secrets agent-proxy connect --proxy=<proxy-host>:17322 --projectId=<project-id> --env=dev --path=/coding-agent -- claude
Each authenticates as its own machine identity via Universal Auth, and the proxy's is always separate from the agents'. The proxy needs read access to the secrets its services reference; an agent needs only Proxy on the services it uses. Permissions covers both in full.
connect puts in the agent's environmentconnect requires no code changes in the agent: it points the agent's HTTP clients at the proxy, so the agent's normal outbound requests route through it. Each request carries the agent's Infisical token and folder scope, which is how the proxy knows which identity is asking and which of that folder's proxied services apply. Concretely, it sets:
HTTPS_PROXY and HTTP_PROXY point at the Agent Proxy. NO_PROXY always includes localhost,127.0.0.1; add more hosts with --no-proxy or an existing NO_PROXY.connect then injects the value into the agent's environment, like any secret the identity can read. This is for values the agent uses in its own code; for credentials it sends to an external API, broker them instead. An agent with only the Proxy permission gets no real values, just the routing and placeholders above. Brokered credentials are never injected here; the Agent Proxy adds them to each outbound request itself, so they reach the destination but never the agent.Every option resolves from the same sources, in order: the flag → an environment variable → .infisical.json → the built-in default. An explicitly-passed flag always wins. Where the environment variables are already set on the host, the flags fall away and only your agent command remains: infisical secrets agent-proxy connect -- claude.
| Option | Flag | Environment variable | .infisical.json |
|---|---|---|---|
| Auth | --client-id / --client-secret | INFISICAL_UNIVERSAL_AUTH_CLIENT_ID / _SECRET | — |
| Instance | --domain | INFISICAL_DOMAIN | domain |
| Project | --projectId | INFISICAL_PROJECT_ID | workspaceId |
| Environment slug | --env | INFISICAL_ENVIRONMENT | defaultEnvironment |
| Secret path | --path | INFISICAL_SECRET_PATH | defaultSecretPath |
| Proxy address | --proxy | INFISICAL_AGENT_PROXY_ADDRESS | — |
See the CLI reference for every flag on both subcommands.
Starting the proxy in a shell is fine while you are trying it out, but it dies with the terminal. Pick one of these instead. Whichever you choose, provide the identity's credentials, publish port 17322 to your agent machines only, and set INFISICAL_DOMAIN for EU Cloud or self-hosted.
```bash
export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-proxy-client-id>
export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-proxy-client-secret>
# export INFISICAL_DOMAIN=https://eu.infisical.com # EU Cloud or self-hosted
infisical secrets agent-proxy start
```
```bash
docker run -p 17322:17322 \
-e INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-proxy-client-id> \
-e INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-proxy-client-secret> \
infisical/cli:latest secrets agent-proxy start
```
Add `-e INFISICAL_DOMAIN=https://eu.infisical.com` for EU Cloud or a self-hosted instance.
- **Image:** `infisical/cli:latest`
- **Start command:** `secrets agent-proxy start`
- **Environment:** `INFISICAL_UNIVERSAL_AUTH_CLIENT_ID`, `INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET`, and `INFISICAL_DOMAIN` if not on US Cloud
- **Port:** `17322`, exposed on a private network your agents can reach, not the public internet
On Render, this is a private service pointed at the image with the start command above.
Check that the proxy sits where the diagram above shows it:
Outbound, the Agent Proxy only needs to reach your Infisical instance and the APIs your proxied services define.
Run multiple Agent Proxy instances with the same machine identity behind a TCP load balancer. Instances coordinate through Infisical rather than with each other:
The Agent Proxy keeps everything it needs in memory, so steady-state requests involve no Infisical calls:
--poll-interval), the Agent Proxy re-fetches services, permissions, and secret values for active agents. Changes such as a rotated secret or an edited service take effect within one poll interval, with no agent restart. Authorization fails closed on the same cycle. If an agent's identity, role, or Proxy grant is revoked, or its token expires, the Agent Proxy drops that agent's cached credentials on the next poll and stops applying them.--poll-interval, factor in your instance's API rate limits; a longer interval reduces load at the cost of slower propagation.When an agent requests a host no proxied service matches, the --unmatched-host flag decides what happens:
allow (default): the request is forwarded untouched, with no credentials applied. This is the normal mode, because much of an agent's traffic does not need a brokered credential at all: reading documentation, cloning public repos, installing packages, or calling services the agent legitimately authenticates to itself. All of that flows through untouched, while matched hosts still get credentials applied.block: the request is rejected with 403. Use this to restrict agents to an allowlist of exactly the services you have defined.CONNECT tunnels; plain http:// traffic arrives as regular forward-proxy requests (useful for internal services without TLS). An https:// URL sent as a plain forward-proxy request is rejected, so the Agent Proxy can never be used to downgrade TLS.connect refuses to start: the agent would receive that value directly and bypass the Agent Proxy. Pass --allow-readable-brokered-secrets to override the guardrail.For the Agent Proxy to read and modify HTTPS requests, agents must trust the certificates it presents. The chain has three tiers, and the sensitive part never leaves Infisical:
flowchart LR
A["Root CA
(in Infisical, per org)"] -->|signs| B["Intermediate CA
(in Agent Proxy memory)"]
B -->|signs| C["Leaf certificates
(one per hostname)"]
The root CA is generated automatically per organization and stored encrypted in Infisical; its private key never leaves the server, and all signing happens server-side. At startup, the Agent Proxy generates a keypair locally and has Infisical sign it into a short-lived intermediate certificate (7 days, re-signed automatically before expiry). This certificate can mint leaf certificates but no further CAs. Leaf certificates (valid 24 hours, cached in memory) are minted locally per hostname, for the exact hostname the agent requested, with no Infisical round-trip.
On the agent machine, the connect wrapper downloads the root CA to ~/.infisical/agent-proxy/mitm-ca.pem and points the standard trust environment variables (SSL_CERT_FILE, NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, GIT_SSL_CAINFO, DENO_CERT) at it. The Agent Proxy's connection to the real service is standard HTTPS with normal certificate verification, so real credentials always travel encrypted.
Proxied services have their own project-level permission subject. Alongside the usual Read, Create, Modify, and Remove actions for managing services, it adds the one that defines the security model: Proxy. An identity with Proxy has a service's secrets applied to its traffic without ever being able to read the values, which is why it is the permission you grant agent machine identities.
Roles. Grant each identity the minimum permissions it needs with a custom role or an additional privilege, scoped to the environments and paths its services live in. The Agent Proxy Policies and Agent Policies templates (offered under Additional Privileges when creating an identity) apply these permissions in a single step and are the fastest way to get started, but they grant them project-wide. For production use, prefer a custom role or additional privilege scoped with conditions to the environments and paths your services occupy. This is the minimum each identity needs:
| Identity | Minimum permissions | Notes |
|---|---|---|
| Agent | Proxy on Proxied Services, scoped to the environments and paths where its services live | This alone lets it route traffic and have credentials applied. It does not need to read any secret. |
| Agent Proxy | Read Value and Describe Secret on Secrets, covering every secret the services reference; Manage Leases on Dynamic Secrets for any dynamic secret a service brokers; and Report Usage on Proxied Services | This is the identity that fetches the real values, mints leases, and records service usage. Describe Secret determines whether a secret is visible to the identity at all, Read Value reveals its value, Manage Leases lets it mint a brokered dynamic secret, and Report Usage lets it stamp a service's "last used" time. It never holds Proxy; routing traffic is the agent's job alone. |
The key thing to get right for the Agent Proxy: it needs Read Value on every secret referenced by every service any of its agents use, across the relevant environments and paths. If a referenced secret comes from a secret import, the read permission has to cover the secret's real location (the import source), not just the folder it is imported into. If a grant is missing, that credential is skipped.
For a service that brokers a dynamic secret, the Agent Proxy identity needs Manage Leases on that dynamic secret. The agent identity must not have Manage Leases on it, or agent-proxy connect refuses to start.
The Agent Proxy also records each time it brokers a service, which surfaces as a "last used" time on the proxied service. This is why it needs Report Usage. Usage is always reported by the Agent Proxy identity, never the agent's: the agent runs in an untrusted environment, so letting it report would allow a compromised agent to forge usage. The proxy is the trusted observer.
Records go to stderr, so whatever supervises the proxy collects them, and --log-file additionally writes json for a collector to pick up. Activity Logs covers the fields, the decisions, and how --log-level filters them.