> ## Documentation Index
> Fetch the complete documentation index at: https://docs.langchain.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy LangSmith on GCP with Terraform

> End-to-end walkthrough for provisioning LangSmith self-hosted on GCP GKE using the LangChain Terraform modules.

Deploy LangSmith to GCP with the public [Terraform modules](https://github.com/langchain-ai/terraform/tree/main/modules/gcp). Managing the deployment as code lets you version, review, and reproduce your LangSmith environment across projects instead of clicking through the Google Cloud console.

The install runs in two stages:

1. **Infrastructure**: Terraform provisions VPC, GKE, Cloud SQL, Memorystore, GCS, and Workload Identity.
2. **Application**: the LangSmith chart, installed with the deploy script or the Terraform `app` layer.

After the base install, enable optional add-ons by setting flags and redeploying.

```mermaid actions={false} theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
%%{init: {'flowchart': {'nodeSpacing': 25, 'rankSpacing': 30}}}%%
graph TB
    subgraph stage1["Set up infrastructure"]
        direction LR
        Start["setup-env.sh<br/>secrets to Secret Manager"]
        TF["terraform apply"]
        Infra["VPC · GKE · Cloud SQL<br/>Memorystore · GCS<br/>Workload Identity"]
        Bootstrap["Bootstrap workloads<br/>cert-manager · KEDA<br/>Envoy Gateway"]
        Start --> TF --> Infra -->|GKE ready| Bootstrap
    end
    subgraph stage2["Deploy the application"]
        direction LR
        Deploy["make init-values + deploy<br/>helm install langsmith"]
        DNS["Point DNS A record<br/>at Gateway IP"]
        Cert["cert-manager issues<br/>Let's Encrypt cert"]
        Running["LangSmith running<br/>all pods healthy"]
        Deploy --> DNS --> Cert --> Running
    end
    stage1 --> stage2

    classDef trigger fill:#F6FFDB,stroke:#6E8900,stroke-width:2px,color:#2E3900
    classDef process fill:#E5F4FF,stroke:#006DDD,stroke-width:2px,color:#030710
    classDef neutral fill:#F2FAFF,stroke:#40668D,stroke-width:2px,color:#2F4B68
    classDef output fill:#EBD0F0,stroke:#885270,stroke-width:2px,color:#441E33

    class Start,DNS trigger
    class TF,Bootstrap,Deploy,Cert process
    class Infra neutral
    class Running output

    style stage1 fill:none,stroke:#40668D,stroke-width:1px
    style stage2 fill:none,stroke:#40668D,stroke-width:1px
```

## Prerequisites

### Required tools

| Tool                        | Version | Purpose                                                   |
| --------------------------- | ------- | --------------------------------------------------------- |
| Google Cloud SDK (`gcloud`) | 450     | Authenticate, query GCP resources, manage GKE credentials |
| Terraform                   | 1.5     | Run the infrastructure modules                            |
| `kubectl`                   | 1.28    | Inspect the GKE cluster                                   |
| Helm                        | 3.12    | Install and manage the LangSmith chart                    |

Install on macOS:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
brew install --cask google-cloud-sdk
brew install kubectl helm
brew tap hashicorp/tap && brew install hashicorp/tap/terraform

gcloud version
terraform version
kubectl version --client
helm version
```

### Required GCP APIs

Terraform enables these automatically on first apply, but `cloudresourcemanager.googleapis.com` must be enabled first so Terraform can enable the rest. Enable everything manually for fast first runs:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
gcloud services enable \
  container.googleapis.com \
  compute.googleapis.com \
  sqladmin.googleapis.com \
  redis.googleapis.com \
  storage.googleapis.com \
  iam.googleapis.com \
  secretmanager.googleapis.com \
  certificatemanager.googleapis.com \
  servicenetworking.googleapis.com \
  cloudresourcemanager.googleapis.com \
  logging.googleapis.com \
  monitoring.googleapis.com \
  --project <your-project-id>
```

### Required IAM roles

The principal running Terraform needs the following roles on the target project. Trim to least-privilege after the initial deployment is stable.

| Role                                    | Purpose                                                               |
| --------------------------------------- | --------------------------------------------------------------------- |
| `roles/container.admin`                 | Create and manage GKE clusters                                        |
| `roles/compute.networkAdmin`            | Create VPC, subnets, firewall rules                                   |
| `roles/iam.serviceAccountAdmin`         | Create service accounts for Workload Identity                         |
| `roles/cloudsql.admin`                  | Create and manage Cloud SQL instances                                 |
| `roles/redis.admin`                     | Create and manage Memorystore Redis                                   |
| `roles/storage.admin`                   | Create GCS buckets and lifecycle policies                             |
| `roles/resourcemanager.projectIamAdmin` | Grant IAM bindings during provisioning                                |
| `roles/servicenetworking.networksAdmin` | Create private service connections (required for Cloud SQL and Redis) |

### Authenticate

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
gcloud auth login
gcloud config set project <your-project-id>
gcloud auth application-default login
```

You also need a LangSmith license key ([contact sales](https://www.langchain.com/contact-sales)) and a domain or subdomain that resolves to GCP.

## Quickstart

<Tip>
  For a condensed cheat sheet of `make` targets, required variables, and common constraints, see the [GCP quick reference](/langsmith/self-host-terraform-gcp-quick-reference).
</Tip>

For the fastest path from zero to a running LangSmith instance, run these commands in order:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# 1. Clone the public modules
git clone https://github.com/langchain-ai/terraform.git
cd terraform/modules/gcp

# 2. Generate terraform.tfvars interactively (Enter accepts current values)
make quickstart

# 3. Load secrets into Secret Manager
#    Must be sourced, not executed
source infra/scripts/setup-env.sh

# 4. Validate environment
make preflight

# 5. Provision infrastructure (~25 to 35 min)
make init
make plan
make apply

# 6. Configure kubectl
make kubeconfig
kubectl get nodes

# 7. Deploy LangSmith via Helm (~8 to 12 min)
make init-values
make deploy

# 8. Get the Gateway IP for DNS
kubectl get gateway -n langsmith \
  -o jsonpath='{.items[0].status.addresses[0].value}'
```

The following sections cover each phase in detail.

## Provision infrastructure

Terraform provisions the following GCP resources:

| Resource                            | Purpose                                                |
| ----------------------------------- | ------------------------------------------------------ |
| VPC + subnet + Cloud NAT            | Private network for the cluster and managed services   |
| Private service connection          | VPC peering for Cloud SQL and Memorystore private IPs  |
| GKE cluster (Standard or Autopilot) | Kubernetes compute, Workload Identity enabled          |
| Cloud SQL PostgreSQL                | LangSmith operational data, HA standby, private IP     |
| Memorystore Redis                   | Queue and cache, STANDARD\_HA tier, private IP         |
| GCS bucket                          | Trace payload blob storage, lifecycle rules            |
| Workload Identity service account   | Per-pod GCP access without static keys                 |
| cert-manager, KEDA, Envoy Gateway   | Bootstrap workloads installed alongside infrastructure |

### Clone and configure

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
git clone https://github.com/langchain-ai/terraform.git
cd terraform/modules/gcp
```

All subsequent commands run from `modules/gcp/`. Run `make help` for the full target list.

Generate `terraform.tfvars` with the interactive wizard:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make quickstart
```

The wizard prompts for project ID, naming prefix, region, GKE sizing, TLS source, external vs in-cluster services, and the optional add-on flags. It writes `infra/terraform.tfvars`. Re-running preselects existing values; press Enter at each prompt to keep the current config.

Prefer to edit manually:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
cp infra/terraform.tfvars.example infra/terraform.tfvars
vi infra/terraform.tfvars
```

The minimum required variables:

```hcl theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
project_id            = "<your-gcp-project-id>"
name_prefix           = "ls"
environment           = "prod"
langsmith_license_key = "<your-license-key>"
langsmith_domain      = "langsmith.example.com"

region = "us-west2"
zone   = "us-west2-a"

postgres_source   = "external"
postgres_password = "<strong-password>"   # or: export TF_VAR_postgres_password=...

redis_source = "external"

clickhouse_source = "in-cluster"

tls_certificate_source = "letsencrypt"
letsencrypt_email      = "ops@example.com"

enable_langsmith_deployment = true
```

See the [GCP variables reference](/langsmith/self-host-terraform-gcp-variables) for every input variable.

<Tip>
  Configure a remote state backend before applying. Copy `infra/backend.tf.example` to `infra/backend.tf` and point it at a GCS bucket you control. Local state is fragile and can be lost during directory restructuring.
</Tip>

### Load secrets into Secret Manager

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
source infra/scripts/setup-env.sh
```

The script reads `terraform.tfvars`, derives the secret prefix, and for each secret either reuses an exported value, reads the existing Secret Manager secret, auto-generates one (for salts and Fernet keys), or prompts you. The license key and admin password are the two values you supply interactively. The script must be sourced because `make` cannot export environment variables back to the parent shell.

Verify the secrets are present:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make secrets
```

### Preflight checks

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make preflight
```

`make preflight` validates that the active `gcloud` credentials can perform each required action, that the required GCP APIs are enabled, and that the target region has the SKUs the modules request. Catching gaps here is faster than discovering them mid-`terraform apply`.

### Apply

<Note>
  Provisioning the GCP cloud foundation takes 25 to 35 minutes on a clean project. Do not interrupt the apply.
</Note>

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make init
make plan
make apply
```

`make plan` shows the proposed diff. Review the output before applying. `make apply` provisions in dependency order: VPC and networking, then GKE (about 10 to 15 minutes), private service connection, Cloud SQL (about 10 minutes with HA), Memorystore, GCS, and the bootstrap workloads.

Equivalent direct Terraform flow:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
cd modules/gcp/infra

terraform init
terraform plan -var-file=terraform.tfvars
terraform apply -var-file=terraform.tfvars
```

### Configure kubectl

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make kubeconfig
kubectl get nodes
```

All nodes should report `Ready`.

### Verify bootstrap components

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl get pods -n cert-manager
kubectl get pods -n keda
kubectl get secrets -n langsmith
```

cert-manager, KEDA, and the LangSmith namespace secrets should all be in place.

## Deploy LangSmith

Use one of the three supported deployment paths:

| Path                                                                                | Command                                                    | When to use                                                                                                 |
| ----------------------------------------------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| [Script-driven Helm deploy *(recommended)*](#script-driven-helm-deploy-recommended) | `make init-values && make deploy`                          | Interactive output, kubeconfig refresh, preflight checks. Best for first-time deploys and day-2 re-deploys. |
| [Terraform-managed Helm release](#terraform-managed-helm-release)                   | `make init-app && make apply-app`                          | Helm release managed in Terraform state alongside infrastructure. Best for GitOps and CI/CD pipelines.      |
| [Manual Helm install](#manual-helm-install)                                         | `helm upgrade --install langsmith langchain/langsmith ...` | Direct `helm` usage without the wrapper scripts. Best for teams with existing Helm tooling.                 |

### Script-driven Helm deploy (recommended)

Two commands install the LangSmith chart with sensible defaults wired from Terraform outputs:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
cd modules/gcp

make init-values
make deploy
```

`init-values.sh` prompts for the admin email, then reads `sizing_profile` and the `enable_*` flags from `terraform.tfvars` and copies matching values files from `helm/values/examples/` into `helm/values/`. It also generates `values-overrides.yaml` with your hostname, Workload Identity annotations, and GCS bucket name.

`make deploy` runs `helm/scripts/deploy.sh`, which refreshes the kubeconfig, runs preflight checks, applies the layered values files, and runs `helm upgrade --install`.

Expect 8 to 12 minutes for the chart to install and pods to become ready.

If you completed the script-driven deploy, skip to [Verify and configure DNS](#verify-and-configure-dns). The following two paths are alternatives to the script-driven deploy.

### Terraform-managed Helm release

Keep the entire deployment under Terraform. The `app` layer wraps the same chart and layered values files as the deploy script, managed as a `helm_release` resource.

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
cd modules/gcp

make init-values  # generate the layered values files
make init-app     # pull infra outputs into app/infra.auto.tfvars.json
make apply-app    # terraform apply the Helm release
```

Set app-layer inputs in `app/terraform.tfvars` (`admin_email` is required; `hostname`, `chart_version`, `sizing`, and the `enable_*` flags are optional). The `app` layer uses its own variable names: `sizing` (not `sizing_profile`) and `enable_agent_deploys` (not `enable_deployments`). `make init-app` populates the infra-derived inputs (cluster, bucket, Workload Identity annotation) into `app/infra.auto.tfvars.json`.

The release is applied with `wait = false` because operator-spawned agents can take 10+ minutes on a cold cluster; a passing `terraform apply` means the release was accepted, not that every pod is ready.

If you completed the Terraform-managed Helm release, skip to [Verify and configure DNS](#verify-and-configure-dns). The following path is an alternative.

### Manual Helm install

Best for teams running `helm` directly without the scripts. Generate the required secrets first:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
export API_KEY_SALT=$(openssl rand -base64 32)
export JWT_SECRET=$(openssl rand -base64 32)
export AGENT_BUILDER_ENCRYPTION_KEY=$(python3 -c \
  "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())")
export INSIGHTS_ENCRYPTION_KEY=$(python3 -c \
  "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())")
export ADMIN_EMAIL="admin@example.com"
export ADMIN_PASSWORD="<strong-password>"
```

The shipped `helm/values/values.yaml` sets `config.blobStorage.engine: GCS` (native GCS mode), so blob storage authenticates through Workload Identity with no HMAC keys. The per-component Workload Identity annotations live in `values-overrides.yaml`; generate it with `make init-values`, or add each component's `serviceAccount.annotations."iam.gke.io/gcp-service-account"` by hand.

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
helm repo add langchain https://langchain-ai.github.io/helm
helm repo update

helm upgrade --install langsmith langchain/langsmith \
  --namespace langsmith \
  --create-namespace \
  --version ~0.15.1 \
  -f ../helm/values/values.yaml \
  -f ../helm/values/values-overrides.yaml \
  --set config.langsmithLicenseKey="<your-license-key>" \
  --set config.apiKeySalt="$API_KEY_SALT" \
  --set config.basicAuth.jwtSecret="$JWT_SECRET" \
  --set config.hostname="<your-langsmith-domain>" \
  --set config.basicAuth.initialOrgAdminEmail="$ADMIN_EMAIL" \
  --set config.basicAuth.initialOrgAdminPassword="$ADMIN_PASSWORD" \
  --set config.agentBuilder.encryptionKey="$AGENT_BUILDER_ENCRYPTION_KEY" \
  --set config.insights.encryptionKey="$INSIGHTS_ENCRYPTION_KEY" \
  --set config.blobStorage.bucketName="$(terraform output -raw storage_bucket_name)" \
  --set gateway.enabled=true \
  --set ingress.enabled=false \
  --wait --timeout 15m
```

<Note>
  To use S3-compatible blob storage instead of Workload Identity, add `--set config.blobStorage.engine=S3` and pass HMAC keys with `--set config.blobStorage.accessKey=<key>` and `--set config.blobStorage.accessKeySecret=<secret>`. Create the HMAC key under Cloud Storage → Settings → Interoperability.
</Note>

### Verify and configure DNS

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl get pods -n langsmith

EXTERNAL_IP=$(kubectl get svc -n envoy-gateway-system \
  -l gateway.envoyproxy.io/owning-gateway-name=langsmith-gateway \
  -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')

echo "Create A record: $EXTERNAL_IP -> <your-langsmith-domain>"

kubectl get certificate -n langsmith
```

cert-manager cannot issue the Let's Encrypt certificate until the DNS A record resolves to the Gateway IP. Create the record at your DNS provider, wait for propagation, then re-check the certificate status.

### Sizing profiles

Set `sizing_profile` in `terraform.tfvars`, then re-run `make init-values && make deploy`.

```hcl theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
sizing_profile = "production"   # default | minimum | dev | production | production-large
```

| Profile            | When to use                                                          |
| ------------------ | -------------------------------------------------------------------- |
| `default`          | Chart defaults, no overlay applied                                   |
| `minimum`          | Absolute floor, fits `e2-standard-4`. Cost parking or CI smoke tests |
| `dev`              | Single replica, minimal resources                                    |
| `production`       | Multi-replica with HPA. Recommended for real workloads               |
| `production-large` | High memory, high CPU. 50+ users or 1000+ traces/sec                 |

### Expected pods

```txt theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
langsmith-ace-backend-xxx          1/1  Running    0
langsmith-backend-xxx              1/1  Running    0
langsmith-backend-auth-bootstrap   0/1  Completed  0
langsmith-backend-migrations       0/1  Completed  0
langsmith-clickhouse-0             1/1  Running    0
langsmith-frontend-xxx             1/1  Running    0
langsmith-ingest-queue-xxx         1/1  Running    0
langsmith-platform-backend-xxx     1/1  Running    0
langsmith-playground-xxx           1/1  Running    0
langsmith-queue-xxx                1/1  Running    0
```

## Enable add-ons

Each add-on is gated by a flag in `infra/terraform.tfvars`. Set the flag, re-apply Terraform, then re-run `make init-values && make deploy`.

### LangSmith Deployment

Adds `host-backend`, `listener`, and `operator`. Required before enabling Agent Builder or Insights. KEDA is installed automatically when `enable_langsmith_deployment = true`.

```hcl theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# infra/terraform.tfvars
enable_deployments = true
```

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
cd modules/gcp

make apply        # push the enable_deployments flag
make init-values  # pick up the change
make deploy       # roll out host-backend + listener + operator
```

Verify:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl get pods -n langsmith | grep -E "host-backend|listener|operator"
kubectl get lgp -n langsmith
kubectl get crd | grep langchain
kubectl get pods -n keda
```

<Warning>
  `config.deployment.url` must include `https://`. Without the protocol, operator-spawned agents stay stuck in `DEPLOYING` indefinitely.
</Warning>

### Fleet

<Note>
  Fleet is the current form of the feature formerly called Agent Builder, deployed as a standalone service (chart v0.15+).
</Note>

You can enable Fleet with `enable_fleet`. Unlike the deprecated `enable_agent_builder` path, it does not require LangSmith Deployment. Terraform provisions a dedicated `fleet` database on Cloud SQL and wires the `langsmith-fleet-postgres` and `langsmith-fleet-redis` secrets to the existing Cloud SQL and Memorystore instances. Fleet reuses `langsmith_agent_builder_encryption_key`, so migrating from `enable_agent_builder` keeps the same key and data.

<Note>
  Fleet requires the LangSmith Helm chart `>=0.15.0` and the Agent Builder or Fleet entitlement in your license.
</Note>

```hcl theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# infra/terraform.tfvars
enable_fleet = true
```

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
cd modules/gcp

make apply        # provision the fleet Cloud SQL database + secrets
make init-values  # copy langsmith-values-fleet.yaml
make deploy       # roll out the standalone-fleet-* services
```

Verify:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl get pods -n langsmith | grep standalone-fleet
```

<Warning>
  Do not enable `enable_fleet` and `enable_agent_builder` together. The Fleet values file sets `config.agentBuilder.enabled: false`, so the two add-ons are mutually exclusive.
</Warning>

### Agent Builder (deprecated)

<Note>
  On GCP, `enable_agent_builder` is deprecated in favor of [Fleet](#fleet) (`enable_fleet`, chart v0.15+). Use Fleet for new deployments. This section documents the older path for existing installs.
</Note>

Prerequisite: LangSmith Deployment healthy. Adds `agent-builder-tool-server`, `agent-builder-trigger-server`, and an `agentBootstrap` Job that registers the Polly agent URL.

```hcl theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# infra/terraform.tfvars
enable_agent_builder = true
```

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make init-values
make deploy
```

Verify:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl get pods -n langsmith | grep -E "tool-server|trigger-server|bootstrap"
```

Roll the frontend after `agentBootstrap` completes so it picks up the `langsmith-polly-config` ConfigMap:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl rollout restart deployment langsmith-frontend -n langsmith
```

<Warning>
  Skipping the frontend restart makes Polly show "Unable to connect to LangGraph server".
</Warning>

### Insights and Polly

Prerequisite: Agent Builder healthy. Insights enables ClickHouse-backed trace analytics. Polly is the AI eval and monitoring agent. Enable both together.

```hcl theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# infra/terraform.tfvars
enable_insights = true
enable_polly    = true
```

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
make init-values
make deploy
```

Verify:

```bash theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
kubectl get pods -n langsmith | grep -E "clio|polly"
kubectl get pods -n langsmith -w
```

<Warning>
  `insights_encryption_key` and `polly_encryption_key` must never change after first enable. Rotating either permanently breaks existing encrypted data.
</Warning>

### Expected pods by add-on

**LangSmith Deployment adds:** `langsmith-host-backend`, `langsmith-listener`, `langsmith-operator`.

**Fleet adds:** `standalone-fleet-api-server`, `standalone-fleet-tool-server`, `standalone-fleet-trigger-server`, `standalone-fleet-queue`.

**Agent Builder adds:** `langsmith-agent-builder-tool-server`, `langsmith-agent-builder-trigger-server`, `langsmith-agent-builder-bootstrap` (Completed), `agent-builder-<hash>` (operator-spawned).

**Insights and Polly add:** `clio-<hash>` (Insights analytics), `smith-polly-<hash>` (Polly agent), `lg-<hash>-0` (LangGraph StatefulSet).

## Key watchouts

* `config.deployment.url` must include `https://`. Without it, operator-spawned agents stay stuck in `DEPLOYING`.
* `config.deployment.enabled: true` is required for LangSmith Deployment. Setting only the URL without `enabled: true` causes the chart to silently skip `listener` and `operator`.
* Encryption keys must never change after first enable. Rotating `insights_encryption_key` or `polly_encryption_key` permanently breaks existing encrypted data.
* Roll the frontend after first Polly enable. `agentBootstrap` creates the `langsmith-polly-config` ConfigMap after registering. Frontend pods started before bootstrap completes do not pick it up automatically.
* Envoy Gateway IP changes on teardown. GCP releases the external IP when the Gateway is deleted. After a re-apply, a new IP is issued, so update your DNS A record.
* `langsmith-ksa` annotation is not permanent. The operator creates `langsmith-ksa` at runtime; it does not survive namespace deletion. `deploy.sh` re-annotates it idempotently. Re-run `make deploy` if operator pods lose GCS access after a cluster rebuild.

## Next steps

* Reference the [GCP variables](/langsmith/self-host-terraform-gcp-variables) and the [quick reference](/langsmith/self-host-terraform-gcp-quick-reference).
* Review the [GCP architecture](/langsmith/self-host-terraform-gcp-architecture) for module structure, traffic flow, and Workload Identity.
* When something breaks, check the [GCP troubleshooting guide](/langsmith/self-host-terraform-gcp-troubleshooting).
* Enable agent deployment in the UI with [LangSmith Deployment](/langsmith/deploy-self-hosted-full-platform).

***

<div className="source-links">
  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>

  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/self-host-terraform-gcp-deploy.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>
</div>
