Egress and network access control
The sameproxy_config that injects credentials also controls which destinations a sandbox can reach. Access control is enforced per connection on the sandbox host, so changes to access_control take effect immediately.
How egress works
- Access control applies to every outbound TCP connection, HTTP or not.
- HTTPS to a host matched by a rule or callback is decrypted by the proxy so it can inject headers; sandboxes trust the proxy’s CA. HTTPS to unmatched hosts and every non-HTTP connection, including PostgreSQL, SSH, and Redis, passes through unchanged. Ports 80 and 443 are reserved for HTTP and TLS; a non-HTTP protocol on either port does not work.
- Address destinations by hostname. A direct raw TCP connection to a literal IP address on a non-HTTP port is dropped, even when that IP is on an
allow_list. HTTPS to a literal IP is dropped too, because the proxy needs a hostname in the TLS handshake. Only cleartext HTTP on port 80 works against a literal IP. - Only TCP leaves the sandbox. UDP (including QUIC) and ICMP are dropped.
Default egress posture
With noaccess_control, every hostname is reachable on every TCP port, unless your organization is on restricted egress. The only exception is hosts that resolve to private, loopback, or cloud-metadata addresses, which the proxy always refuses to dial. Add an access_control to restrict this.
To allow HTTP and HTTPS to any host while blocking every other port, use a port-qualified allow list. * matches every hostname:
host:PORT entries to open specific raw TCP destinations on top of that, such as db.example.com:5432.
Allow and deny lists
Add anaccess_control object to proxy_config with either an allow_list or a deny_list (not both—the request is rejected if both are set):
Both lists apply to HTTP, HTTPS, and raw TCP alike. Neither mode distinguishes protocols; use a port suffix to restrict an entry to one port.
Pattern syntax
Eachallow_list/deny_list entry uses the following forms:
Matching is on the destination exactly as the sandbox addressed it. A hostname entry matches requests made to that hostname; an IP or CIDR entry matches requests made to a literal IP address. Neither is resolved:
deny_list: ["203.0.113.0/24"] does not block foo.example.com even when it resolves into that range, and allow_list: ["203.0.113.7"] does not allow it either. Because raw TCP and HTTPS to a literal IP are dropped before access control runs (see How egress works), IP and CIDR entries only ever affect cleartext HTTP requests on port 80 that name the IP directly.
Entries that do not parse—example.com:abc, example.com:99999, or a CIDR with a port—are rejected when the sandbox is created or updated.
Organization-level restricted egress
An organization can be placed on restricted egress. When it is, LangSmith replaces each sandbox’saccess_control with a fixed allow list of package registries, OS package mirrors, source-code and container-image hosts, CDNs, and model-provider APIs, each pinned to specific ports (HTTPS, plus HTTP for the Ubuntu and Debian mirrors). Caller-supplied allow_list and deny_list values are accepted by the API but have no effect while the policy is active.
Connecting to a database (raw TCP)
To let sandbox code reach an external PostgreSQL database withpsql, dbt, or any driver, allow-list the host on its port. Because allow_list is default-deny, also list any HTTP(S) hosts the sandbox needs. Pin them to :443 unless you need other ports too:
db.example.com:5432 is passed through at the TCP layer with no interception, so the PostgreSQL wire protocol—and TLS, host-key checking, and any other end-to-end protocol on top of it—works unchanged.
Creating a sandbox boots it and returns once it reports
ready, so there is no wait step to add. GET /api/v2/sandboxes/boxes/{name}/status reports the current state if you need to re-check it later.Configure via SDK
Configure auth proxy rules
Add aproxy_config when creating a sandbox, or update an existing sandbox by patching its proxy_config. A proxy_config has:
Each rule specifies:
Header types
Each header has a requiredtype that controls how its value is stored and displayed:
Set environment variables from a rule
A rule’senv_vars are plaintext environment variables set for every command in the sandbox while that rule is enabled. Use them for tools that refuse to run unless a credential variable is present, even though the proxy injects the real credential on the wire: give the variable a placeholder value so the command starts, and the proxy supplies the real credential.
Values are plaintext and are returned by the API, so never put a secret in env_vars. Use a header with the workspace_secret or opaque type instead.
Environment variables resolve in this order, from lowest precedence to highest:
- The snapshot image’s
ENV, when the sandbox opted intoapply_image_config. - Enabled proxy rules: When two enabled rules declare the same name, the later rule in
ruleswins. - The sandbox’s own
env_vars: Explicit per-sandbox values override values from rules.
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_EC2_METADATA_DISABLED, AWS_CA_BUNDLE; CLOUDSDK_AUTH_ACCESS_TOKEN, CLOUDSDK_CORE_CUSTOM_CA_CERTS_FILE) sit outside this order: a rule or a sandbox env_vars entry that declares one of them is rejected while the matching auth rule is enabled.
Every sandbox also has the common CA-bundle environment variables pointed at the system trust store, which includes the proxy’s CA, so tools that pin their own bundle still verify proxy-injected hosts. Set any of them yourself to override.
Authenticate AWS requests
Use an AWS auth rule when sandbox code needs to call AWS services with an AWS SDK or CLI. The proxy keeps the real AWS credentials outside the sandbox, then signs outbound HTTPS requests to*.amazonaws.com endpoints with AWS SigV4.
This is useful when agent code needs to inspect S3 objects, call Bedrock, or use another AWS endpoint without exposing long-lived AWS access keys in sandbox files, environment variables, shell history, or logs. The sandbox receives placeholder AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY values (plus AWS_EC2_METADATA_DISABLED=true and AWS_CA_BUNDLE) so SDK credential detection works, while the proxy replaces whatever the request carries with a real SigV4 signature. Only service.region.amazonaws.com hosts, S3 virtual-hosted and path-style hosts, and a few global endpoints such as iam, sts, and s3 are signed; plaintext HTTP to a matched AWS host is rejected with 403.
AWS auth rules are different from header injection rules:
- Set
typetoaws. - Put credentials under the
awsobject. - Do not set
match_hosts,match_paths, orheaders; AWS host matching is built into the proxy. - Configure at most one AWS auth rule per sandbox. The limit counts every AWS rule, including disabled ones.
Configure AWS auth via SDK
AWS_REGION through the sandbox’s env_vars or the rule’s env_vars, or most SDK and CLI calls fail before they reach the proxy.
AWS auth proxy rules currently support access key ID and secret access key credentials. They do not include a session token or assume-role configuration.
Authenticate GCP requests
Use a GCP auth rule when sandbox code needs to call Google APIs with Google SDKs or CLIs. The proxy keeps the service account JSON outside the sandbox, then authenticates outbound HTTPS requests togoogleapis.com and its subdomains.
This is useful when agent code needs to inspect GCS objects or call another Google API without exposing service account JSON in sandbox files, environment variables, shell history, or logs. The sandbox receives a placeholder CLOUDSDK_AUTH_ACCESS_TOKEN (plus CLOUDSDK_CORE_CUSTOM_CA_CERTS_FILE) so gcloud runs, while the proxy replaces whatever authorization the request carries with a token minted from the configured service account. Google client libraries that discover credentials through Application Default Credentials do not read these variables and fail to find credentials; only gcloud and direct HTTPS calls are supported.
GCP auth rules are different from header injection rules:
- Set
typetogcp. - Put credentials under
gcp.service_account_json. - Set
gcp.scopesto a non-empty list of OAuth scopes. - The proxy matches
googleapis.comand its subdomains automatically and authenticates those requests with the configured service account. Hosts undergoogle.comare not matched. Plaintext HTTP to a matched host is rejected with403. - Configure at most one GCP auth rule per sandbox. The limit counts every GCP rule, including disabled ones.
gcp_auth and gcpAuth helpers build this same rule shape.
Configure GCP auth via SDK
gcloud or direct HTTPS calls to googleapis.com hosts normally inside the sandbox. The proxy applies the real GCP authentication without exposing service account JSON inside the sandbox.
Single API example
Create a sandbox that automatically injects an OpenAI API key into outbound requests:api.openai.com are now authenticated by the proxy; no real key is stored in the sandbox. SDKs that refuse to start without an API key still need a placeholder—set one with the rule’s env_vars, as in the GitHub example.
Multiple API example
Add multiple rules to authenticate with several services at once:GitHub example
Open SWE authenticates GitHub access by minting a short-lived GitHub App installation token outside the sandbox, then patching the sandbox with write-onlyopaque proxy rules. This keeps the short-lived GitHub access token out of the sandbox filesystem and out of deployment environment variables.
Configure two rules:
Python
configure_github_proxy after creating or reattaching to a sandbox. GitHub App installation tokens expire, so refresh the proxy config whenever you reuse a sandbox for a new run.
The github-api rule sets GH_TOKEN to a non-secret placeholder, which satisfies the gh CLI’s local credential check. Commands then run without a per-command prefix:
Authorization header into the outbound request.
Configure via SDK
Callback credential example
Staticworkspace_secret rules pull credentials from your workspace when the proxy configuration is applied, and opaque rules let your application patch in short-lived credentials such as the GitHub token example. For credentials that must be resolved by your own service at proxy time, use a callback. The proxy POSTs to a URL you provide, your endpoint returns the headers to inject, and the proxy caches the result.
Callbacks are configured alongside rules under proxy_config:
Static rules win. If an enabled header-injection rule matches both the host and the path, the callback is skipped for that request. Within rules, first-match-wins; the same applies between callbacks if multiple match.
Callback contract
The proxy makes the following request whenever it needs to resolve credentials for a matched host on a cache miss:identity tells your endpoint which sandbox is asking, so one callback URL can serve many sandboxes and mint per-sandbox or per-user credentials. ls_user_id is the creating user and is omitted when the sandbox was created with a workspace or service key. Ignore fields and headers you do not recognize; the proxy may add more.
Your endpoint must respond 2xx with a JSON body:
ttl_seconds. Any non-2xx response, transport error, or malformed JSON fails closed: the sandbox’s request is rejected with 502 callback resolution failed (no headers injected, response not cached). Redirects are not followed and count as failures.
Verify callback requests
request_headers let your endpoint check a shared secret you chose. To verify that a request came from LangSmith and was not altered in transit, check the X-LangSmith-Signature-JWT header. It is a JWT signed with an Ed25519 key (alg: EdDSA) whose public half is published at <LANGSMITH_ENDPOINT>/.well-known/jwks.json, selected by the token’s kid.
Verify the signature against the JWKS, check every claim above, hash the body you received, and compare it to
body_sha256. Then trust identity in the body.
Example
Use a callback when your OAuth tokens are minted on demand by your own service:Configure via SDK
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

