Skip to main content
Modal sandboxes are containers you create from code to run an agent. The agent in a sandbox runs commands that a prompt can influence, so any API key you give the sandbox can leak through a prompt injection. With Agent Vault, you don’t give the sandbox any API keys. Each sandbox runs an Agent Vault proxy in a sidecar, a second container in the same sandbox. The agent’s container can’t reach the internet directly, so every request it makes goes through the proxy, and the proxy attaches the real credential to requests for the APIs you allowed. For each run, your code does the following:
  1. Creates an Agent Vault session for the run
  2. Creates a sandbox with no internet access, and starts the proxy in a sidecar
  3. Starts the agent in the sandbox with the session token
  4. Revokes the session and terminates the sandbox when the agent finishes
Every sidecar starts its proxy from the same proxy token, so you create the proxy in Infisical once, no matter how many sandboxes you run.
A proxy outside the sandbox doesn’t work well on Modal:
  • Modal can place sandboxes in the same region on different clouds, and its private network doesn’t connect sandboxes across clouds, so a proxy in another sandbox can’t reach every agent
  • A sandbox can only allow a hostname for HTTPS on port 443, and the proxy listens for plain HTTP on port 17323, so you’d have to allow the proxy by a fixed IPv4 address
  • If the proxy is reachable from the internet, anyone who gets a session token can use it from anywhere until the session ends
A sidecar is only reachable from its own sandbox, so nothing outside the sandbox can send requests through it.

Prerequisites

  • The Admin role in Agent Vault
  • A Modal account, with a Modal token on the machine that runs your code (run modal setup, or set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET)
  • The Modal SDK for your language: the modal and requests packages for Python, the modal package for TypeScript, or the Modal Go SDK
  • The API keys your agent uses, such as your Anthropic API key

Step 1: Set up Agent Vault

Create an access bundle

Create an access bundle that contains a service for each API the agent calls.
1
In Infisical, open Agent Vault from the product switcher and go to Access Bundles.
2
Select Create Access Bundle. Give the access bundle a Name, such as modal-agent, then select Create Access Bundle.
3
Select the access bundle you just created, then select Add Service.
4
On the Choose a template panel, pick the template for the API, such as Anthropic, or select Custom.
5
On the Details step, check the hosts the service covers, or enter the API’s host if you selected Custom, then select Continue.
6
On the Credential step, paste the real API key.
If the API expects the key somewhere other than a header, such as in the URL, add a substitution instead, and have the agent send the placeholder you enter in Replace.
7
Select Add Service. Repeat from the third step for each remaining API.

Create a proxy

1
In Agent Vault, go to Proxies and select Create Proxy.
2
Enter a Name, such as modal-sandboxes, and expand Advanced Options. Under Traffic Policy, choose Access bundle hosts only, and add any hosts the agent needs without a credential to Exceptions, such as registry.npmjs.org.The sidecar can reach the internet, so with Any host, the agent could send requests through the proxy to any host. Learn more about the traffic policy.
3
Select Create, then copy the proxy token from the Proxy Token dialog. Infisical shows the token only once.

Create a machine identity for your code

Your code creates a session for each run as a machine identity. Give the machine identity the Member role and access to only this access bundle, because an Agent Vault admin can create sessions for every access bundle.
1
In Agent Vault, go to Access Control > Machine Identities and select Add Machine Identity.
2
On the Create New tab, enter a Name, choose Member in Role, then select Create. Infisical creates the machine identity with Universal Auth and opens its page.
To use a machine identity that already exists in your organization, select the Assign Existing tab instead.
3
On the machine identity’s page, select Universal Auth under Authentication. Copy the Client ID, then select Add Client Secret and copy the client secret.
4
Go to Access Bundles and open the access bundle the agent uses. Select Options > Manage Access, then select Grant Access. Select the machine identity, then select Grant Access.

Step 2: Store the credentials

The proxy token and the machine identity’s credentials stay out of the agent’s container.

Store the proxy token in Modal

In the Modal dashboard, create a custom secret named agent-vault-proxy with this key, set to the proxy token:
Only the sidecar gets the agent-vault-proxy secret. Modal runs each sidecar in its own container with its own kernel, so the agent can’t read the sidecar’s environment or files.
If you use EU Cloud or self-host Infisical, add this key as well:
Set the key to https://eu.infisical.com for EU Cloud, or the URL of your self-hosted instance.

Give your code the machine identity’s credentials

Set INFISICAL_UNIVERSAL_AUTH_CLIENT_ID and INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET in the environment of the code that starts your sandboxes.

Step 3: Build the sandbox image

The agent’s container and the sidecar use the same image, which has the Infisical CLI and your agent. This example installs Claude Code:
  • Infisical CLI: replace <cli-version> with <min-cli-version> or later, because earlier versions can’t start a proxy from a proxy token
  • The agent user: Modal runs commands as root, and Claude Code won’t skip its permission prompts as root, so the agent runs as this user
  • Building the image first: Modal can’t build a sidecar’s image when it starts the sidecar, so the code builds the image before it creates any sandbox

Step 4: Run an agent in a sandbox

This function runs one prompt in a new sandbox. Replace <access-bundle-name> at the top with your access bundle’s name. If you use EU Cloud or self-host Infisical, also replace https://app.infisical.com with https://eu.infisical.com for EU Cloud or the URL of your self-hosted instance:
For more about creating sessions from code, see Create sessions with the API. For the flags the agent starts with, see the agent-vault run CLI reference. To run a different agent, install it in the image, replace the claude command in the script that starts the agent with the agent’s non-interactive command, such as codex exec, and replace the Claude Code settings in the agent’s environment variables. For an agent you built yourself, run it the same way, or set the proxy in its HTTP client as Connect your own agent describes.
Modal sidecars are in beta, and Modal may change the sidecar API, so pin the version of the Modal SDK your code uses.

Step 5: Verify it works

Call the function with a prompt that needs an API in the access bundle:
Claude Code replies, even though its sandbox has no Anthropic API key and can’t reach the internet.
Each run now gets its own sandbox, proxy, and session. The only credential in the agent’s container is a session token, and your code revokes the session when the run ends.
To check which requests the agent made, set up session logs, then view the session’s logs in Agent Vault. Requests that got a credential have the outcome Brokered.

Security considerations

Network access from the sandbox

The agent’s container can’t connect to the internet directly, but it has two kinds of network access:
  • DNS: Modal answers DNS lookups in a sandbox even with an empty allowlist, so the agent can look up hostnames
  • Hosts through the proxy: with Access bundle hosts only, the agent can reach the hosts that services in the session’s access bundle cover, and the proxy’s exceptions

Compromised sandboxes

Each sidecar has a copy of the proxy token. If you think someone took control of a sandbox, rotate the proxy’s token, then put the new token in the agent-vault-proxy secret in Modal.

Troubleshooting

The function’s error includes the proxy’s log. If the log says The provided access token is malformed, the proxy token is wrong. Check the following:
  • The agent-vault-proxy secret in Modal has the current proxy token (a token stops working when you rotate it)
  • If you use EU Cloud or self-host Infisical, the secret has INFISICAL_DOMAIN
  • The image has an Infisical CLI version that can start a proxy from a proxy token
Modal doesn’t show a sidecar’s output, and it removes a sidecar as soon as its command exits. That’s why the code starts the proxy with || sleep 600: if the proxy exits, the sidecar keeps running, and the function can read the proxy’s log.
The session expired or was revoked. Set the session’s ttl a few minutes longer than the sandbox’s timeout, so the session lasts as long as the sandbox can run.
The proxy’s traffic policy blocks hosts that no service in the access bundle covers. Add a service for the host, or add the host to the proxy’s exceptions.
No. That option sends the agent’s HTTPS connections to the sidecar without a session token, and the proxy needs the session token to know which credentials to attach. Use infisical agent-vault run, or set the proxy in the agent’s HTTP client.

Next steps

Create sessions with the API

Create a session for each agent run from your own code.

Session logs

Record every request an agent makes during a session.