Back to Infisical

Agent Proxy quickstart

docs/documentation/platform/agent-proxy/quickstart.mdx

0.162.1415.9 KB
Original Source

This tutorial takes you from an Infisical project to an agent making authenticated API calls through the Agent Proxy, with real credentials it never sees.

Before you begin

To follow along, you'll need:

  • An Infisical Secrets Management project.
  • A GitHub account (this guide's running example) or any other API you'd rather broker. The steps are the same either way.
  • Two hosts in the same private network: one for the agent proxy and one for the agent. The agent host must be able to reach the proxy on its port (17322 by default).
  • The Infisical CLI installed on both the proxy host and the agent host.
  • Optional: GitHub's gh CLI on the agent host, for the recommended verification in step 7. A curl fallback is provided, so this is not required.

1. Add a secret

First, get a GitHub personal access token to broker:

  1. Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens.
  2. Click Generate new token, give it a name, set an expiration, and choose the resource owner.
  3. Leave the permissions at their defaults. The verification in step 7 calls GET /user, which any valid token can reach, so no permissions are needed here; later, grant only what your agent actually does.
  4. Click Generate token and copy the github_pat_… value. GitHub only shows it once.

Then, in your Infisical project, create a folder for the agent (for example /coding-agent in the dev environment) and add a secret named GITHUB_PAT with that token as its value. It is a regular Infisical secret.

2. Create a proxied service

A proxied service maps a host to the secret the proxy applies. In the same folder, open the Add Secret dropdown and select Add Proxied Service, then work through the steps:

<Steps> <Step title="Pick the GitHub template"> The template fills everything in for you: the host `api.github.com` and a **Secret Substitution** rule that hands the agent a realistic `ghp_…` placeholder and swaps in the real token on the way out.
![The proxied service template picker with GitHub available](/images/platform/agent-proxy/quickstart-template-picker.png)
</Step> <Step title="Details"> Keep the service name `github` and the host pattern `api.github.com`.
![The Details step with the service name and host pattern](/images/platform/agent-proxy/service-details.png)
</Step> <Step title="Header Rewrites"> This step is skipped automatically for GitHub. The token does travel in the `Authorization` header, but this template handles that with **Secret Substitution** (next step): the agent itself puts a placeholder in the header, and the proxy swaps it for the real token. </Step> <Step title="Secret Substitution"> Select `GITHUB_PAT` as the secret holding the real value.
Here is how the pieces fit together. When your agent connects, it gets an environment variable `GITHUB_TOKEN` (the placeholder name the GitHub template uses) set to the fake `ghp_…` placeholder. The agent uses it like any GitHub token and sends `Authorization: Bearer <placeholder>`. As the request passes through the proxy, the placeholder is replaced with the real value of your `GITHUB_PAT` secret. The template scopes this swap to headers, since that is where GitHub expects the token; a substitution can also target the URL path, query, or body.

![The Secret Substitution step swapping a placeholder for the real secret](/images/platform/agent-proxy/secret-substitution.png)
</Step> <Step title="Review and create"> Double-check the host pattern and the substitution rule, then click **Create Proxied Service**.
![The Review step showing the Secret Substitution rule for GITHUB_PAT](/images/platform/agent-proxy/quickstart-review.png)
</Step> </Steps> <Note> Not on the template list? Pick **Custom** and configure a [header rewrite or secret substitution](/documentation/platform/agent-proxy/proxied-services) by hand. </Note>

3. Create the proxy identity

The proxy and the agent authenticate as two separate machine identities with opposite access. That split is the whole security model: the proxy can read your secrets, the agent never can.

<Note> The two templates have similar names but are for different identities: use **Agent Proxy Policies** for the proxy (this step) and **Agent Policies** for the agent (next step). Pick the one that matches the identity you are creating. </Note>

The proxy identity reads the secrets.

<Steps> <Step title="Create the identity"> In your project, go to **Access Control → Machine Identities** and click **Add Machine Identity to Project → Create New**. Name it (for example `agent-proxy`), leave the **Role** as **No Access**, select the **Agent Proxy Policies** template under **Additional Privileges**, and create it.
![Creating the agent-proxy identity with the Agent Proxy Policies template selected under Additional Privileges](/images/platform/agent-proxy/quickstart-create-identity.png)

<Note>
  **Agent Proxy Policies** grants the proxy these permissions, project-wide:

  - `Read Value` and `Describe Secret` on **Secrets**: fetch real secret values
  - `Lease` on **Dynamic Secrets**: mint credentials for brokered [dynamic secrets](/documentation/platform/agent-proxy/proxied-services#using-dynamic-secrets)
  - `Report Usage` on **Proxied Services**: report service usage back to Infisical

  This template is the identity's entire access, so its project **Role** stays **No Access**. For a production deployment, grant these scoped to your services' environments and paths with a [custom role](/documentation/platform/access-controls/role-based-access-controls) or a conditional [additional privilege](/documentation/platform/access-controls/additional-privileges). See [Permissions](/documentation/platform/agent-proxy/security#permissions).
</Note>
</Step> <Step title="Generate a Client Secret"> Open the identity and go to its [Universal Auth](/documentation/platform/identities/universal-auth) authentication method.
![The machine identity's Universal Auth authentication method highlighted](/images/platform/agent-proxy/quickstart-universal-auth.png)

Click **Add Client Secret**.

![The Add Client Secret button highlighted on the Universal Auth panel](/images/platform/agent-proxy/quickstart-add-client-secret.png)

Save the **Client ID** and the **Client Secret**; you will pass both to the proxy in step 5.
</Step> </Steps>

4. Create the agent identity

The agent identity routes traffic but reads no secrets. It needs the Proxy permission and nothing else.

<Steps> <Step title="Create the identity"> In your project, go to **Access Control → Machine Identities** and click **Add Machine Identity to Project → Create New**. Name it (for example `agent`), leave the **Role** as **No Access**, select the **Agent Policies** template under **Additional Privileges**, and create it.
![Creating the agent identity with the Agent Policies template selected under Additional Privileges](/images/platform/agent-proxy/quickstart-create-agent-identity.png)

<Note>
  **Agent Policies** grants the agent one permission, project-wide:

  - `Proxy` on **Proxied Services**: route traffic and have credentials applied, with no secret read access

  This template is the identity's entire access, so its project **Role** stays **No Access**. For a production deployment, grant it scoped to your services' environments and paths with a [custom role](/documentation/platform/access-controls/role-based-access-controls) or a conditional [additional privilege](/documentation/platform/access-controls/additional-privileges). See [Permissions](/documentation/platform/agent-proxy/security#permissions).
</Note>
</Step> <Step title="Generate a Client Secret"> Open the identity and add a **Client Secret** under Universal Auth, exactly as in the previous step. Save the **Client ID** and the **Client Secret**; you will pass both to the agent in step 6. </Step> </Steps>

5. Start the agent proxy

<Steps> <Step title="Install the Infisical CLI"> On the proxy host, a separate machine in your agent's private network, install the [Infisical CLI](/cli/overview). Or use Docker for the container option below. </Step> <Step title="Authenticate as the proxy identity"> Set `INFISICAL_UNIVERSAL_AUTH_CLIENT_ID` and `INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET` to the Client ID and Client Secret you saved in step 3. <Tabs> <Tab title="Infisical Cloud (US)"> ```bash # Authenticate as the proxy identity (from step 3) export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-proxy-client-id> export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-proxy-client-secret> ``` </Tab> <Tab title="Infisical Cloud (EU)"> ```bash # Authenticate as the proxy identity (from step 3), pointed at EU Cloud 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 ``` </Tab> <Tab title="Self-Hosted"> ```bash # Authenticate as the proxy identity (from step 3), pointed at your instance export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-proxy-client-id> export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-proxy-client-secret> export INFISICAL_DOMAIN=https://infisical.your-domain.com ``` </Tab> </Tabs> </Step> <Step title="Start the proxy"> The proxy listens on port `17322` by default. Use the CLI or Docker: <Tabs> <Tab title="CLI"> ```bash infisical secrets agent-proxy start ``` </Tab> <Tab title="Docker"> ```bash # -e without a value passes through the variables you exported above docker run -p 17322:17322 \ -e INFISICAL_UNIVERSAL_AUTH_CLIENT_ID \ -e INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET \ -e INFISICAL_DOMAIN \ infisical/cli:latest secrets agent-proxy start ``` </Tab> </Tabs>

Remember this host's address; the next step points INFISICAL_AGENT_PROXY_ADDRESS at it. For production deployment, see Deployment.

</Step> </Steps>

6. Connect your agent

<Steps> <Step title="Install the Infisical CLI"> On the agent host, install the [Infisical CLI](/cli/overview); `connect` is a CLI command. </Step> <Step title="Set the connection details"> Set the agent's authentication and connection details as environment variables: <Tabs> <Tab title="Infisical Cloud (US)"> ```bash # Authenticate as the agent identity (from step 4) export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-client-id> export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-client-secret>
# Scope: your project, plus the environment and folder from step 1
export INFISICAL_PROJECT_ID=<project-id>
export INFISICAL_ENVIRONMENT=dev
export INFISICAL_SECRET_PATH=/coding-agent

# The agent proxy to route through (from step 5)
export INFISICAL_AGENT_PROXY_ADDRESS=<proxy-host>:17322
```
</Tab> <Tab title="Infisical Cloud (EU)"> ```bash # Authenticate as the agent identity (from step 4), pointed at EU Cloud export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-client-id> export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-client-secret> export INFISICAL_DOMAIN=https://eu.infisical.com
# Scope: your project, plus the environment and folder from step 1
export INFISICAL_PROJECT_ID=<project-id>
export INFISICAL_ENVIRONMENT=dev
export INFISICAL_SECRET_PATH=/coding-agent

# The agent proxy to route through (from step 5)
export INFISICAL_AGENT_PROXY_ADDRESS=<proxy-host>:17322
```
</Tab> <Tab title="Self-Hosted"> ```bash # Authenticate as the agent identity (from step 4), pointed at your instance export INFISICAL_UNIVERSAL_AUTH_CLIENT_ID=<agent-client-id> export INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET=<agent-client-secret> export INFISICAL_DOMAIN=https://infisical.your-domain.com
# Scope: your project, plus the environment and folder from step 1
export INFISICAL_PROJECT_ID=<project-id>
export INFISICAL_ENVIRONMENT=dev
export INFISICAL_SECRET_PATH=/coding-agent

# The agent proxy to route through (from step 5)
export INFISICAL_AGENT_PROXY_ADDRESS=<proxy-host>:17322
```
</Tab> </Tabs> </Step> <Step title="Launch the agent"> Launch the agent through `connect`. Everything after `--` is the agent's own command: <Tabs> <Tab title="Claude Code"> ```bash infisical secrets agent-proxy connect -- claude ``` </Tab> <Tab title="Codex"> ```bash infisical secrets agent-proxy connect -- codex ``` </Tab> <Tab title="Any command"> ```bash infisical secrets agent-proxy connect -- <your-agent-command> ``` </Tab> </Tabs>

The agent starts and behaves exactly as if you had launched it directly; nothing about it looks different. In its environment it finds GITHUB_TOKEN, set by connect to the fake placeholder, and uses it like a normal token. Its traffic now routes through the proxy: on calls to api.github.com the placeholder is swapped for the real token, and everything else passes through untouched. The next step makes that visible.

<Note> Every setting here can also be passed as a flag or set in `.infisical.json`. See [Connecting Agents](/documentation/platform/agent-proxy/connecting-agents) for how `connect` works and what it puts in the agent's environment. </Note> </Step> </Steps>

7. Verify it works

Each method below makes the same GET /user call to api.github.com. The client sends only the ghp_… placeholder that connect put in the environment; as the request passes through the proxy, the placeholder is swapped for the real value of your GITHUB_PAT secret. GitHub returns your account profile even though the real token never reached the client. That is the whole point: real authenticated work without the caller ever holding the credential.

<Tabs> <Tab title="Through your agent"> The agent you launched in step 6 is already brokering. In its session, send:
> Run `gh api user` and show me the output.

[GitHub's `gh` CLI](https://cli.github.com/) reads `GITHUB_TOKEN` from the environment on its own, so the agent needs no token wiring; it just runs the command and GitHub returns your profile. Requires `gh` on the host where the agent runs.
</Tab> <Tab title="gh CLI"> Not driving an interactive agent? Run the check through `connect` directly, in the shell where you set the step 6 variables:
```bash
infisical secrets agent-proxy connect -- gh api user
```

`gh` reads `GITHUB_TOKEN` automatically, so there is nothing else to pass. Requires `gh` on the host where you run this.
</Tab> <Tab title="curl"> No `gh`? Any HTTP client works the same way. `curl` sends the placeholder in the header and the proxy swaps it:
```bash
infisical secrets agent-proxy connect -- \
  sh -c 'curl -sS https://api.github.com/user -H "Authorization: Bearer $GITHUB_TOKEN"'
```
</Tab> </Tabs> <Note> Getting a `401`? The proxy could not apply the credential and forwarded the placeholder unchanged (it does not block the call). Check the proxy's logs, and confirm the agent identity has `Proxy` on the service and the proxy identity has `Read Value` on `GITHUB_PAT`. </Note>

Next steps

<CardGroup cols={2}> <Card title="Proxied Services" icon="right-left" href="/documentation/platform/agent-proxy/proxied-services"> Host patterns, header rewrites, and secret substitution in depth. </Card> <Card title="Deployment" icon="server" href="/documentation/platform/agent-proxy/deployment"> Take the Agent Proxy to production: placement, deployment methods, and HA. </Card> </CardGroup>