langchain-multi-env-setup

Configure LangChain multi-environment setup for dev/staging/prod. Use when managing multiple environments, configuring environment-specific settings, or implementing environment promotion workflows. Trigger with phrases like "langchain environments", "langchain staging", "langchain dev prod", "environment configuration", "langchain env setup". allowed-tools: Read, Write, Edit version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>

Allowed Tools

No tools specified

Provided by Plugin

langchain-pack

Claude Code skill pack for LangChain (24 skills)

saas packs v1.0.0
View Plugin

Installation

This skill is included in the langchain-pack plugin:

/plugin install langchain-pack@claude-code-plugins-plus

Click to copy

Instructions

# LangChain Multi-Environment Setup ## Overview Configure and manage LangChain applications across development, staging, and production environments. ## Prerequisites - LangChain application ready for deployment - Access to multiple deployment environments - Secrets management solution (e.g., GCP Secret Manager) ## Instructions ### Step 1: Environment Configuration Structure ``` config/ ├── base.yaml # Shared configuration ├── development.yaml # Development overrides ├── staging.yaml # Staging overrides ├── production.yaml # Production overrides └── settings.py # Configuration loader ``` ### Step 2: Create Base Configuration ```yaml # config/base.yaml app: name: langchain-app version: "1.0.0" llm: max_retries: 3 request_timeout: 30 logging: format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" date_format: "%Y-%m-%d %H:%M:%S" cache: enabled: true ttl_seconds: 3600 ``` ### Step 3: Environment-Specific Overrides ```yaml # config/development.yaml extends: base app: debug: true llm: provider: openai model: gpt-4o-mini temperature: 0.7 # Use lower tier in dev logging: level: DEBUG cache: type: memory # In-memory cache for local dev langsmith: tracing: true project: langchain-dev ``` ```yaml # config/staging.yaml extends: base app: debug: false llm: provider: openai model: gpt-4o-mini temperature: 0.5 logging: level: INFO cache: type: redis url: ${REDIS_URL} # From environment langsmith: tracing: true project: langchain-staging ``` ```yaml # config/production.yaml extends: base app: debug: false llm: provider: openai model: gpt-4o temperature: 0.3 max_retries: 5 request_timeout: 60 logging: level: WARNING cache: type: redis url: ${REDIS_URL} langsmith: tracing: true project: langchain-production monitoring: prometheus: true sentry: true ``` ### Step 4: Configuration Loader ```python # config/settings.py import os from pathlib import Path from typing import Any, Dict, Optional import yaml from pydantic import BaseModel, Field from pydantic_settings import BaseSettings class LLMConfig(BaseModel): provider: str = "openai" model: str = "gpt-4o-mini" temperature: float = 0.7 max_retries: int = 3 request_timeout: int = 30 class CacheConfig(BaseModel): enabled: bool = True type: str = "memory" url: Optional[str] = None ttl_seconds: int = 3600 class LangSmithConfig(BaseModel): tracing: bool = False project: str = "default" class Settings(BaseSettings): environment: str = Field(default="development", env="ENVIRONMENT") llm: LLMConfig = Field(default_factory=LLMConfig) cache: CacheConfig = Field(default_factory=CacheConfig) langsmith: LangSmithConfig = Field(default_factory=LangSmithConfig) class Config: env_file = ".env" def load_config(environment: str = None) -> Settings: """Load configuration for specified environment.""" env = environment or os.environ.get("ENVIRONMENT", "development") config_dir = Path(__file__).parent # Load base config config = {} base_path = config_dir / "base.yaml" if base_path.exists(): with open(base_path) as f: config = yaml.safe_load(f) or {} # Load environment-specific overrides env_path = config_dir / f"{env}.yaml" if env_path.exists(): with open(env_path) as f: env_config = yaml.safe_load(f) or {} config = deep_merge(config, env_config) # Resolve environment variables config = resolve_env_vars(config) return Settings(**config) def deep_merge(base: Dict, override: Dict) -> Dict: """Deep merge two dictionaries.""" result = base.copy() for key, value in override.items(): if key in result and isinstance(result[key], dict) and isinstance(value, dict): result[key] = deep_merge(result[key], value) else: result[key] = value return result def resolve_env_vars(config: Any) -> Any: """Resolve ${VAR} patterns in config values.""" if isinstance(config, dict): return {k: resolve_env_vars(v) for k, v in config.items()} elif isinstance(config, list): return [resolve_env_vars(v) for v in config] elif isinstance(config, str) and config.startswith("${") and config.endswith("}"): var_name = config[2:-1] return os.environ.get(var_name, "") return config # Global settings instance settings = load_config() ``` ### Step 5: Environment-Aware LLM Factory ```python # infrastructure/llm_factory.py from config.settings import settings from langchain_openai import ChatOpenAI from langchain_anthropic import ChatAnthropic from langchain_core.language_models import BaseChatModel def create_llm() -> BaseChatModel: """Create LLM based on environment configuration.""" llm_config = settings.llm if llm_config.provider == "openai": return ChatOpenAI( model=llm_config.model, temperature=llm_config.temperature, max_retries=llm_config.max_retries, request_timeout=llm_config.request_timeout, ) elif llm_config.provider == "anthropic": return ChatAnthropic( model=llm_config.model, temperature=llm_config.temperature, max_retries=llm_config.max_retries, ) else: raise ValueError(f"Unknown provider: {llm_config.provider}") ``` ### Step 6: Environment-Specific Secrets ```python # infrastructure/secrets.py import os from google.cloud import secretmanager def get_secret(secret_id: str) -> str: """Get secret from appropriate source based on environment.""" env = os.environ.get("ENVIRONMENT", "development") if env == "development": # Use local .env file in development return os.environ.get(secret_id, "") else: # Use Secret Manager in staging/production client = secretmanager.SecretManagerServiceClient() project_id = os.environ.get("GCP_PROJECT") name = f"projects/{project_id}/secrets/{secret_id}/versions/latest" response = client.access_secret_version(request={"name": name}) return response.payload.data.decode("UTF-8") # Usage openai_key = get_secret("OPENAI_API_KEY") ``` ### Step 7: Docker Compose for Local Environments ```yaml # docker-compose.yml version: '3.8' services: app: build: . environment: - ENVIRONMENT=development - OPENAI_API_KEY=${OPENAI_API_KEY} ports: - "8080:8080" volumes: - ./src:/app/src depends_on: - redis redis: image: redis:7-alpine ports: - "6379:6379" # Local development tools langsmith-proxy: image: langchain/langsmith-proxy:latest environment: - LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY} ``` ## Output - Multi-environment configuration structure - Environment-aware configuration loader - Secrets management per environment - Docker Compose for local development ## Examples ### Running Different Environments ```bash # Development ENVIRONMENT=development python main.py # Staging ENVIRONMENT=staging python main.py # Production ENVIRONMENT=production python main.py ``` ### Environment Promotion Workflow ```bash # 1. Test in development ENVIRONMENT=development pytest tests/ # 2. Deploy to staging gcloud run deploy langchain-api-staging \ --set-env-vars="ENVIRONMENT=staging" # 3. Run integration tests ENVIRONMENT=staging pytest tests/integration/ # 4. Deploy to production gcloud run deploy langchain-api \ --set-env-vars="ENVIRONMENT=production" ``` ## Error Handling | Error | Cause | Solution | |-------|-------|----------| | Config Not Found | Missing YAML file | Ensure environment file exists | | Secret Missing | Not in Secret Manager | Add secret for environment | | Env Var Not Set | Missing .env | Create .env from .env.example | ## Resources - [Pydantic Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) - [GCP Secret Manager](https://cloud.google.com/secret-manager/docs) - [12-Factor App Config](https://12factor.net/config) ## Next Steps Use `langchain-observability` for environment-specific monitoring.

Skill file: plugins/saas-packs/langchain-pack/skills/langchain-multi-env-setup/SKILL.md