Show HN: Production-grade LangGraph template A developer released a production-grade open-source template for building multi-agent LangGraph systems on GitHub. The template includes a hardened FastAPI API, Helm and Terraform stubs, CI/CD, observability, and a mock provider for zero-cost testing, targeting ML and data engineers who want to self-host agent stacks on Kubernetes. It ships under the MIT license with features like per-run USD budgets, multi-version pack routing, and signed container images. Production-grade templatefor multi-agent LangGraph systems — hardened FastAPI API, domain packs, Helm, Terraform stubs, CI, and observability. Multi-tenant identity isyourlayer Security guide . A real session against the built-in mock provider — no API key, zero token cost, deterministic output ideal for exploring the API, tests, and CI : A deployable starting point for ML / data engineers who want a real agent stack—not a notebook demo. The default pipeline is Research → Analysis ResearchAgent + AnalystAgent , exposed over FastAPI with SSE streaming, session history, cost tracking, and pack-based routing. Included: Docker, Helm chart, Terraform entry points GKE / EKS / AKS , rate limiting, input validation, structured logging, Prometheus metrics, CI security scans, GHCR images with SBOM + Cosign on main . Not included: OAuth2/OIDC, per-tenant API keys, or billing. The built-in API KEY is a single shared Bearer secret for internal / single-tenant use. …LangGraph Platform? LangGraph Platform is a legitimate, well-supported managed option — use it if you want a hosted control plane and don't want to run infrastructure yourself. This repo is for the opposite case: you self-host on your own Kubernetes cluster, keep full control of observability Prometheus/OTel and per-run cost data, and ship under the MIT license with zero vendor lock-in. Neither is objectively "better" — it's a build-vs-buy trade-off, and this template is for teams who'd rather own the stack. …a generic agent-service-toolkit template? Beyond the usual FastAPI-around-LangGraph scaffolding, this repo ships production concerns already wired in: per-run USD budgets that return HTTP 402 on overrun, multi-version pack routing with canary traffic weights, and a supply chain that signs container images with Cosign and publishes an SBOM on every release. Prerequisites: Python 3.12+, uv https://docs.astral.sh/uv/getting-started/installation/ package manager . git clone https://github.com/brescou/langgraph-agent-stack.git cd langgraph-agent-stack uv sync --extra anthropic cp .env.example .env set ANTHROPIC API KEY uv run uvicorn api.main:app --reload Try it without any API key.Set LLM PROVIDER=mock in .env or LLM PROVIDER=mock uv run uvicorn api.main:app --reload to get deterministic, zero-cost responses from every endpoint — useful for exploring the API, running the test suite, or CI, before wiring up a real provider. Web search is also mocked by default SEARCH PROVIDER=mock ; set SEARCH PROVIDER=tavily or serpapi for real results. Legacy default pipeline research analysis pack curl -X POST http://localhost:8000/run \ -H "Content-Type: application/json" \ -d '{"query": "What are the latest advances in quantum computing?"}' Pack registry curl http://localhost:8000/packs curl -X POST http://localhost:8000/packs/meeting prep/run \ -H "Content-Type: application/json" \ -d '{"company": "Acme", "person": "Jane", "meeting goal": "discovery"}' Interactive API docs: http://localhost:8000/docs disabled when ENVIRONMENT=production . Cost: with a real provider, a research analysis run 6 LLM calls costs roughly $0.01–0.05 on Claude Sonnet 5 pricing $0.003 / $0.015 per 1K input/output tokens — a rough order of magnitude from the pricing table in core/cost.py , not a measured benchmark. Set PACK DEFAULT BUDGET USD=0.50 to cap spend per run; requests over budget return HTTP 402 . Client → FastAPI auth · rate limit · validation → PackRegistry / control plane policies → domain packs/ LangGraph workflows → agents/ reusable agent nodes → core/ LLM · memory · security · cost · observability → connectors/ optional retrieval | Layer | Path | Role | |---|---|---| | HTTP | api/ | FastAPI app app.py , middlewares, endpoints, pack router factory | | Kernel | pack kernel/ | BaseDomainPack , PackRegistry , versioning, traffic split | | Workflows | domain packs/ | Packs grouped by domain — see | agents/ ResearchAgent , AnalystAgent , … control plane/ control plane/README.md /Brescou/langgraph-agent-stack/blob/main/control plane/README.md connectors/ connectors/README.md /Brescou/langgraph-agent-stack/blob/main/connectors/README.md core/connectors.py is a compat shim core/ infra/ core/graph.py is a compatibility shim MultiAgentGraph → ResearchAnalysisPack . New orchestration belongs in a domain pack. 13 built-in packs registered in pack kernel/builtin packs.py : | Category | Examples | |---|---| Research domain packs/research/ | research analysis , research only , analysis only | Productivity domain packs/productivity/ | summariser , meeting prep , rfp assistant , support triage , executive brief | HR domain packs/hr/ | talent screening , job description writer , hr policy qa | Finance domain packs/finance/ | financial memo | Legal domain packs/legal/ | contract reviewer | Each pack gets typed POST /packs/{pack id}/run and /run/stream when schemas are declared. Versioning, traffic weights, and sticky sessions: GET /packs , GET /packs/{id}/versions , headers X-Pack-Version / X-Pack-Version-Used . Full catalogue and authoring guide: domain packs/README.md . The HR, legal, and finance packs demonstrate the pack system on regulated-adjacent use cases, but they are off by default REGULATED PACKS ENABLED=false — calling them with a valid body returns HTTP 403 until you complete the pack's COMPLIANCE.md checklist and explicitly opt in a body that fails schema validation returns 422 first, as on any pack route . Third-party packs ship as regular Python packages declaring an entry point in the langgraph agent stack.packs group: project.entry-points."langgraph agent stack.packs" sentiment = "acme packs.sentiment:SentimentPack" Discovery is opt-in and allowlisted PACK PLUGINS ENABLED=true + PACK PLUGINS ALLOWLIST=sentiment : loading a plugin executes third-party code, so nothing loads by default. At load time each class is validated against the pack contract — BaseDomainPack subclass, complete metadata, and strict extra="forbid" input/output schemas — and a broken plugin is logged and skipped, never crashing startup. Built-in pack ids cannot be overridden. Registered plugins get the same typed /packs/{id}/run routes, versioning, and canary weights as built-ins. Packaging walkthrough: examples/custom pack/README.md /Brescou/langgraph-agent-stack/blob/main/examples/custom pack/README.md . | Method | Path | Description | |---|---|---| GET | /packs | List registered packs and metadata | POST | /packs/{pack id}/run | Run a pack typed body per pack schema | POST | /packs/{pack id}/run/stream | SSE stream for a pack | POST | /run , /run/stream | Legacy routes → DEFAULT PACK ID research analysis | POST | /research | Research phase only | GET | /health , /ready | Probes | GET | /sessions/{id}/history | Session run history | GET | /metrics | Prometheus with observability extra | Responses include cost usd when cost tracking is active; HTTP 402 on budget exceed. See /docs for request/response schemas. Opt-in streamable-HTTP MCP endpoint that auto-generates one tool per registered domain pack same Pydantic schemas as POST /packs/{id}/run . Every tool call goes through the existing kernel auth, rate limits, budgets → tool error mirroring HTTP 402, regulated-pack gating . uv sync --extra mcp .env MCP SERVER ENABLED=true LLM PROVIDER=mock optional — CI / no API key Endpoint: http://localhost:8000/mcp mounted only when the flag is on . Regulated packs are omitted from the tool list while REGULATED PACKS ENABLED=false . When API KEY is set, pass the same Bearer token the REST API expects — for example in Claude Desktop / a generic MCP client config: { "mcpServers": { "langgraph-agent-stack": { "url": "http://localhost:8000/mcp", "headers": { "Authorization": "Bearer YOUR API KEY" } } } } Install the matching client transport for streamable HTTP; stdio is not shipped in this release. Set LLM PROVIDER and install the matching extra. Details and gateway overrides: .env.example . | Provider | Value | Extra | Key env vars | |---|---|---|---| | Anthropic | anthropic | --extra anthropic | ANTHROPIC API KEY | | OpenAI | openai | --extra openai | OPENAI API KEY | google | --extra google | GOOGLE API KEY | | | Bedrock | bedrock | --extra bedrock | AWS REGION , BEDROCK MODEL | | Azure OpenAI | azure | --extra openai | AZURE OPENAI | | Ollama | ollama | --extra ollama | OLLAMA BASE URL | | Mock CI/dev | mock | none | — | Docker Compose docker compose -f infra/docker-compose.yml up docker compose -f infra/docker-compose.yml --profile redis up Redis memory backend Helm helm install langgraph ./infra/helm/langgraph-agent-stack \ -f infra/helm/langgraph-agent-stack/values.prod.yaml \ --namespace langgraph-agents --create-namespace Production: set secrets.existingSecret External Secrets Operator , config.environment=production , networkPolicy.enabled=true . Autoscaling defaults to KEDA on active pipelines not CPU . See chart values.yaml / values.prod.yaml . Scaling note. MEMORY BACKEND=sqlite default is for development and single-replica deployments only — it's a local file, so state is not shared across pods. For production, multi-replica deployments, switch to MEMORY BACKEND=redis or MEMORY BACKEND=postgres so checkpointing and session history are consistent across replicas. Terraform — entry points under infra/terraform/{gke,eks,aks}/ no shared root module . Configure a remote backend before production apply. GKE module expects External Secrets Operator /Brescou/langgraph-agent-stack/blob/main/docs/security.md 3-secret-management installed before ClusterSecretStore resources. Infra CI locally: make infra-check template Checkov profile . Before production hardening: make infra-check-prod checklist /Brescou/langgraph-agent-stack/blob/main/docs/security.md before-going-to-production-checkov . Rate limiting memory or Redis , request body cap, prompt-injection / SSRF input validation, security headers, optional API KEY Bearer auth, graceful shutdown drain. Full model, env vars, K8s hardening, and scanning pipeline: docs/security.md . make help all targets make check ruff + pyright CI lint make test 800+ tests, mocked by default — no network, no API key required make eval golden-dataset pack evaluations deterministic make infra-check helm lint + kubeconform + checkov | Symptom | Cause / fix | |---|---| POST /run returns 502 with LLM provider 'anthropic' rejected the request credentials | Your API key is missing or invalid. Set ANTHROPIC API KEY or your provider's key in .env , or set LLM PROVIDER=mock to run without one. | Responses say Mock insight 1: Key trend identified. | You are on LLM PROVIDER=mock deterministic canned output, $0 . Set a real provider + key in .env . | GET /metrics returns 404 | Prometheus metrics need the observability extra: uv sync --extra observability . | Regulated pack talent screening , contract reviewer , … returns 403 | Expected: these packs are gated behind REGULATED PACKS ENABLED=false until you complete the pack's COMPLIANCE.md . A 422 means your request body doesn't match the pack's input schema — check /docs . | 402 on /run or a pack route | The per-run USD budget PACK DEFAULT BUDGET USD was exceeded. Raise it or unset it. | /docs is missing | Interactive docs are disabled when ENVIRONMENT=production . | | State/history lost across replicas | MEMORY BACKEND=sqlite default is single-replica only — switch to redis or postgres for multi-replica deployments. | Not covered here? Check the pinned FAQ in Discussions Q&A https://github.com/brescou/langgraph-agent-stack/discussions/categories/q-a before opening an issue. evals/ runs golden datasets evals/datasets/