- Infrastructure: Terraform provisions VPC, GKE, Cloud SQL, Memorystore, GCS, and Workload Identity.
- Application: the LangSmith Helm chart, installed with the deploy script or with
helmdirectly.
tls_certificate_source = "letsencrypt". With tls_certificate_source = "none" and langsmith_domain = "", LangSmith serves HTTP on the Gateway IP.
Prerequisites
Required tools
Install on macOS:
Required GCP APIs
Terraform enables these automatically on first apply, butcloudresourcemanager.googleapis.com must be enabled first so Terraform can enable the rest. Enable everything manually for fast first runs:
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.
Add
roles/secretmanager.admin so setup-env.sh and the optional secrets module can write to Secret Manager, roles/dns.admin when enable_dns_module = true, and roles/cloudkms.admin on the key when smithdb_bucket_kms_key is set. The module’s PERMISSIONS.md lists the full set.
Authenticate
Quickstart
For the fastest path from zero to a running LangSmith instance, run these commands in order. They deploy Helm chart 0.17. To deploy chart 0.16, see Clone and configure.Provision infrastructure
Terraform provisions the following GCP resources:Clone and configure
modules/gcp/. Run make help for the full target list.
The Notes that start with “On chart 0.16” describe where the 0.16 line differs. To move an existing deployment to chart 0.17, see Upgrade from chart 0.16.
main branch and v0.17.x release tags deploy Helm chart 0.17, and this guide describes them. v0.16.x tags deploy chart 0.16. To stay on chart 0.16, list the tags and check out the latest v0.16.x tag:terraform.tfvars with the interactive wizard:
infra/terraform.tfvars. Re-running preselects existing values; press Enter at each prompt to keep the current config.
Prefer to edit manually:
infra/terraform.tfvars.minimum instead. A typical production configuration:
terraform.tfvars. setup-env.sh stores them in Secret Manager and exports them as TF_VAR_* variables. See the GCP variables reference for every input variable.
Load secrets into Secret Manager
project_id, name_prefix, environment, and region from terraform.tfvars and stores each secret as langsmith-<name_prefix>-<environment>-<key>. For each secret it reuses an exported value, reads the existing Secret Manager secret, auto-generates one (for the API key salt, JWT secret, and Fernet keys), or prompts you. You supply the Postgres password, the license key, and the initial admin password. The admin password needs at least 12 characters with a lowercase letter, an uppercase letter, and a symbol. The script must be sourced because make cannot export environment variables back to the parent shell.
make deploy reads these TF_VAR_* values and LANGSMITH_ADMIN_EMAIL from the same shell, so run it from the shell where you sourced the script. To list, read, or rotate a secret later, run make secrets.
Preflight checks
make preflight validates the gcloud authentication, project billing, the required GCP APIs, the IAM permissions Terraform needs, and regional quotas such as CPUs. Pass ARGS="--domain <your-domain>" to also check for a matching Cloud DNS zone. Catching gaps here is faster than discovering them mid-terraform apply.
Apply
Provisioning the GCP cloud foundation takes 25 to 35 minutes on a clean project. Do not interrupt the 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:
Configure kubectl
Ready.
Verify bootstrap components
Deploy LangSmith
Use one of the two supported deployment paths:Script-driven Helm deploy (recommended)
Two commands install the LangSmith chart with sensible defaults wired from Terraform outputs:init-values.sh takes the admin email from LANGSMITH_ADMIN_EMAIL (or prompts for it), 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. The file also holds secrets in plaintext: the license key, the API key salt, the JWT secret, the admin password, and the OIDC client secret when SSO is on. The module’s .gitignore excludes it, so do not commit or share it.
make deploy runs helm/scripts/deploy.sh, which refreshes the kubeconfig, runs preflight checks, builds the langsmith-config Kubernetes Secret from the TF_VAR_* values and LANGSMITH_ADMIN_EMAIL, applies the layered values files, and runs helm upgrade --install.
The deploy script installs Helm chart version
~0.17.0 by default and refuses versions outside the 0.17 line. To pin a specific 0.17 release, set langsmith_helm_chart_version in terraform.tfvars or export CHART_VERSION.On chart 0.16, the default is ~0.16.0, and the script refuses versions outside the 0.16 line.Manual Helm install
Best for teams runninghelm directly without the scripts. Generate the required secrets first:
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.
The following command installs chart 0.17. On chart 0.16, use --version ~0.16.0.
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.Verify and configure DNS
make tf ARGS="output -raw ingress_ip". The output reads pending until the Gateway has an address; use the kubectl get gateway lookup above in that case. The Gateway is named <name_prefix>-<environment>-gateway.
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
Setsizing_profile in terraform.tfvars, then re-run make init-values && make deploy.
Expected pods
Enable add-ons
Each add-on is gated by a flag ininfra/terraform.tfvars. Set the flag, then re-run make init-values && make deploy. Run make apply first for add-ons that create cloud resources:
- SmithDB and Sandboxes.
- Fleet, standalone Polly, and standalone Insights, when Postgres or Redis is external.
The add-ons in this section require Helm chart version 0.16.0 or later.
LangSmith Deployment
Addshost-backend, listener, and operator. Required before enabling the deprecated Agent Builder path or enable_polly. KEDA is installed by Terraform when enable_langsmith_deployment = true (the default).
--wait --timeout 15m line:
config.deployment.enabled: true and enables host-backend, listener, and operator.
Verify:
Fleet
Fleet is the current form of the feature formerly called Agent Builder, deployed as a standalone service.
enable_fleet. Unlike the deprecated enable_agent_builder path, it does not require LangSmith Deployment. With external Postgres and Redis, Terraform provisions a dedicated langsmith_fleet database on Cloud SQL and creates the langsmith-fleet-postgres and langsmith-fleet-redis secrets that point at 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.
Fleet requires the Agent Builder or Fleet entitlement in your license.
Agent Builder (deprecated)
On GCP,
enable_agent_builder is deprecated in favor of Fleet (enable_fleet). Use Fleet for new deployments. This section documents the older path for existing installs.Insights and Polly
Insights enables ClickHouse-backed trace analytics. Polly is the AI eval and monitoring agent.clickhouse_source = "in-cluster", init-values.sh writes the Insights values file directly. With an external ClickHouse, it prompts for the connection details and creates the langsmith-clickhouse Kubernetes Secret.
To run Insights or Polly against the Cloud SQL and Memorystore instances instead of in-cluster databases, also set enable_standalone_insights = true or enable_standalone_polly = true. Neither requires LangSmith Deployment. With external Postgres and Redis, run make apply first so Terraform creates the dedicated databases and secrets.
Verify:
SmithDB
SmithDB is the columnar store and query engine that runs alongside ClickHouse in the LangSmith release.enable_smithdb provisions a dedicated Cloud SQL metastore (PostgreSQL 18), a GCS object-store bucket, a Workload Identity service account, and cache and compute node pools. SmithDB requires GKE Standard; Terraform rejects it on Autopilot.
Two variables shape the deployment:
smithdb_sizing:minimal,small,medium, orlarge. When unset, it followssizing_profile. Theminimalsize creates no SmithDB node pools and runs on the general node pool.smithdb_cache_storage:local-ssdfor Local SSD cache nodes, ornetwork-diskfor a Hyperdisk Balanced volume per pod on a C3 cache pool. When unset,minimalusesnetwork-diskand the other sizes uselocal-ssd.
langsmith-values-smithdb-sizing.yaml sets the SmithDB resources, cache volumes, and node placement. Do not set those in langsmith-values-smithdb.yaml. To change the size or cache later, run make smithdb-configure SIZING=<size> [CACHE=<local-ssd|network-disk>], then make deploy-all.
LangSmith then moves to SmithDB in stages. ClickHouse stays enabled throughout. make smithdb-phase sets the stage flags in terraform.tfvars. Run make deploy-all after each stage, and move to the next stage only after the previous one is healthy:
make smithdb-phase PHASE=dual-writesetssmithdb_ingestion_enabled = true, which routes new writes to SmithDB as well as ClickHouse.make quickstartstarts new installs in this stage.make smithdb-phase PHASE=backfillalso setssmithdb_migration_enabled = true, which backfills historical data from ClickHouse. To choose where the backfill starts, addSTART_TIME=<RFC 3339 timestamp>.make smithdb-phase PHASE=cutoversetssmithdb_query_enabled = trueand turns the backfill off, so UI and API reads come from SmithDB. The target refuses cutover until the backfill finishes. With no backfill to wait for, addFORCE=true.
make smithdb-status reports the current stage, sizing, pods, Jobs, and backfill progress.
While the backfill runs, every chart version change requires deleting the backfill Job before the next deploy. make deploy stops and prints the kubectl delete job command. Backfill progress is kept, so the new Job resumes rather than starting over.
On chart 0.16, SmithDB always uses Local SSD and compute node pools, and
smithdb_sizing, smithdb_cache_storage, and the make smithdb-* targets do not exist. Set the three stage flags in terraform.tfvars by hand, and run make deploy-all after each change. The backfill stage needs its make apply step: Terraform grants the SmithDB service account read access to the traces bucket and raises the namespace quota only when smithdb_migration_enabled = true. The backfill stage requires Helm chart version 0.16.6 or later.Sandboxes
enable_sandboxes provisions the infrastructure for LangSmith Sandboxes: a KVM-capable sandbox-host node pool, a dedicated Memorystore instance for JuiceFS metadata, and the JuiceFS configuration Secret. The sandbox-host pods mount JuiceFS themselves, and a juicefs-format Job prepares the volume on the first deploy. Sandboxes require GKE Standard and enable_gcp_iam_module = true, and the module expects external Redis (redis_source = "external").
langsmith, set platform_backend_component_label to <release-name>-platform-backend so the sandbox host can reach the platform backend.
The deploy script sets the sandbox-host image tag from the chart’s app version, so the image always matches the chart.
On chart 0.16, sandboxes mount JuiceFS through a JuiceFS CSI driver that the chart installs, and
sandbox_host_image_tag is required in terraform.tfvars. Chart 0.17 ignores that variable.Expected pods by add-on
LangSmith Deployment adds:langsmith-host-backend, langsmith-listener, langsmith-operator.
Fleet adds: langsmith-standalone-fleet-api-server, langsmith-standalone-fleet-queue, langsmith-fleet-tool-server, langsmith-fleet-trigger-server.
Agent Builder adds: langsmith-fleet-tool-server, langsmith-fleet-trigger-server.
Insights and Polly add: langsmith-standalone-insights-api-server, langsmith-standalone-polly-api-server, and their queue workloads. With enable_insights or enable_polly instead of the standalone flags, each also runs in-cluster -postgres and -redis StatefulSets.
SmithDB adds: langsmith-smithdb-cluster-manager, langsmith-smithdb-ingestion, langsmith-smithdb-query, langsmith-smithdb-compaction, langsmith-smithdb-compaction-worker.
Upgrade from chart 0.16
To move a deployment from av0.16.x tag to chart 0.17:
-
Check out
mainor the latestv0.17.xtag. -
Before you run
make apply, editinfra/terraform.tfvars:- Remove
sandbox_host_image_tagif it is set. The 0.17 module ignores it. - Clear a
0.16.xvalue inlangsmith_helm_chart_version, or set a0.17.xpatch, and rununset CHART_VERSIONif your shell sets it.deploy.shreads the pin from the Terraform output, so a change interraform.tfvarstakes effect only aftermake apply. - With SmithDB, choose the size. An unset
smithdb_sizingnow followssizing_profile:productiongivesmedium,production-largegiveslarge, andminimumgivesminimal, which has no SmithDB node pools. Formediumandlarge, Terraform replaces the cache pool, and forlargealso the compute pool.largeruns 12 SmithDB pods that request about 350 vCPU. To keep the chart 0.16 pools, runmake smithdb-configure SIZING=small CACHE=local-ssd. - With SmithDB and a created metastore, an unset
smithdb_metastore_tiernow follows the size, and the resize takes Cloud SQL offline for less than 60 seconds. To keep the current tier, setsmithdb_metastore_tier = "db-custom-2-8192". - With SmithDB, remove
smithdb_metastore_use_ssl = true. The Cloud SQL Auth Proxy is now the default for a created metastore, and the plan fails while both are set. To keep connecting without the proxy (mode 2, for test and staging only), setsmithdb_metastore_use_auth_proxy = false. - With sandboxes,
sizing_profileset toproductionorproduction-large, and nosandbox_host_machine_type, setsandbox_host_machine_type = "n2-standard-8". The pin keeps the current sandbox-host nodes and their mounted volumes until the drain in step 7.
- Remove
- With SmithDB, delete a completed backfill Job. The chart keeps a finished Job for 7 days, and the upgrade changes its pod template. For the command, see Deploy refuses because the SmithDB backfill Job changed.
-
With SmithDB, replace the 0.16 overlay, which chart 0.17 rejects. Then add back only the edits that do not set
nodeSelector,tolerations,volumes,volumeMounts, orresources: -
Run
make apply. Withingress_type = "envoy"(the default), it also upgrades Envoy Gateway to v1.9.2. Plan a maintenance window: the control plane must run Kubernetes 1.33 to 1.36, the Envoy proxy restarts one time, and connections open longer than 60 seconds drop. With SmithDB enabled,make init-valuesfails until the Terraform state includes the 0.17 module outputs. -
Run
make init-valuesto regenerate the sandbox values without the chart 0.16sandboxes.juicefs.csiblock. -
Run
make deploy. With Sandboxes enabled, the deploy stops while sandbox volumes are still mounted through the JuiceFS CSI driver, and prints thekubectl deletecommands for the sandbox-host workload and JuiceFS claims. Run them, wait until onlyjuicefs-csi-*pods remain, then runmake deployagain. Running sandboxes stop, but their data stays in object storage and Redis, and chart 0.17 mounts the same JuiceFS volume. -
If you pinned
sandbox_host_machine_typein step 2, remove the pin and runmake applyagain. GKE recreates every sandbox-host node for the new machine type, and running sandboxes stop.
engine.usageSigningSecret (at least 32 characters), or an engine_usage_signing_secret key in the Secret that config.existingSecretName names.
The 0.17 module also stops granting the LangSmith service account project-wide Secret Manager access. If a workload you added reads Secret Manager as that service account, set grant_project_secret_accessor = true or grant access to the specific secrets.
For the full list of changes, see MIGRATION-0.16-to-0.17.md and the SmithDB upgrade steps in the Terraform repository.
Key watchouts
config.deployment.urlmust includehttps://. Without it, operator-spawned agents stay stuck inDEPLOYING.config.deployment.enabled: trueis required for LangSmith Deployment. Setting only the URL withoutenabled: truecauses the chart to silently skiplistenerandoperator.- Encryption keys must never change after first enable. Rotating
langsmith_insights_encryption_keyorlangsmith_polly_encryption_keypermanently breaks existing encrypted data. - 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-ksaannotation is not permanent. Terraform createslangsmith-ksain thek8s-bootstrapmodule, outside the Helm release, so it does not survive namespace deletion.deploy.shre-creates and re-annotates it idempotently. Re-runmake deployif operator pods lose GCS access after a cluster rebuild.
Next steps
- Reference the GCP variables and the quick reference.
- Review the GCP architecture for module structure, traffic flow, and Workload Identity.
- When something breaks, check the GCP troubleshooting guide.
- Enable agent deployment in the UI with LangSmith Deployment.
Connect these docs to your agent of choice via MCP for real-time answers.

