Skills Development LangChain Production Architecture Blueprint

LangChain Production Architecture Blueprint

v20260423
langchain-reference-architecture
This blueprint provides a scalable, production-grade reference architecture for advanced LLM applications using LangChain. It guides the implementation of layered design, provider abstraction (allowing seamless switching between LLMs like OpenAI and Anthropic), dynamic chain registry, robust RAG pipelines, and complex multi-agent orchestration. Ideal for building enterprise-level, maintainable, and highly flexible AI systems.
Get Skill
162 downloads
Overview

LangChain Reference Architecture

Overview

Production architectural patterns for LangChain: layered project structure, provider abstraction for vendor flexibility, chain registry for dynamic management, RAG architecture, and multi-agent orchestration.

Layered Architecture

src/
├── api/                    # HTTP layer (Express/Fastify/FastAPI)
│   ├── routes/
│   │   ├── chat.ts         # POST /api/chat, /api/chat/stream
│   │   └── documents.ts    # POST /api/documents/ingest
│   └── middleware/
│       ├── auth.ts         # JWT/OAuth validation
│       └── rateLimit.ts    # Per-user rate limiting
├── core/                   # Business logic (pure, testable)
│   ├── chains/
│   │   ├── summarize.ts    # Summarize chain factory
│   │   ├── qa.ts           # Q&A chain factory
│   │   └── rag.ts          # RAG chain factory
│   ├── agents/
│   │   └── assistant.ts    # Agent with tools
│   └── tools/
│       ├── calculator.ts
│       └── search.ts
├── infra/                  # External integrations
│   ├── llm/
│   │   └── factory.ts      # LLM provider factory
│   ├── vectorStore/
│   │   └── pinecone.ts     # Vector store setup
│   └── cache/
│       └── redis.ts        # Response caching
├── config/
│   ├── index.ts            # Config loader + validation
│   └── models.ts           # Model configurations
└── index.ts                # App entry point

Provider Abstraction (LLM Factory)

// src/infra/llm/factory.ts
import { ChatOpenAI } from "@langchain/openai";
import { ChatAnthropic } from "@langchain/anthropic";
import { BaseChatModel } from "@langchain/core/language_models/chat_models";

type Provider = "openai" | "anthropic";

interface ModelConfig {
  provider: Provider;
  model: string;
  temperature?: number;
  maxRetries?: number;
  timeout?: number;
}

const DEFAULT_CONFIG: Partial<ModelConfig> = {
  temperature: 0,
  maxRetries: 3,
  timeout: 30000,
};

export function createModel(config: ModelConfig): BaseChatModel {
  const merged = { ...DEFAULT_CONFIG, ...config };

  switch (merged.provider) {
    case "openai":
      return new ChatOpenAI({
        model: merged.model,
        temperature: merged.temperature,
        maxRetries: merged.maxRetries,
        timeout: merged.timeout,
      });

    case "anthropic":
      return new ChatAnthropic({
        model: merged.model,
        temperature: merged.temperature,
        maxRetries: merged.maxRetries,
      });

    default:
      throw new Error(`Unknown provider: ${merged.provider}`);
  }
}

// Usage: swap providers without touching chain code
const model = createModel({
  provider: "openai",
  model: "gpt-4o-mini",
});

Chain Registry

// src/core/chains/registry.ts
import { Runnable } from "@langchain/core/runnables";

class ChainRegistry {
  private chains = new Map<string, Runnable>();

  register(name: string, chain: Runnable) {
    this.chains.set(name, chain);
  }

  get(name: string): Runnable {
    const chain = this.chains.get(name);
    if (!chain) throw new Error(`Chain not found: ${name}`);
    return chain;
  }

  list(): string[] {
    return Array.from(this.chains.keys());
  }
}

export const registry = new ChainRegistry();

// At startup:
registry.register("summarize", summarizeChain);
registry.register("qa", qaChain);
registry.register("rag", ragChain);

// In API routes:
app.post("/api/chain/:name/invoke", async (req, res) => {
  const chain = registry.get(req.params.name);
  const result = await chain.invoke(req.body.input);
  res.json({ result });
});

RAG Architecture

// src/core/chains/rag.ts
import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { PineconeStore } from "@langchain/pinecone";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { RunnableSequence, RunnablePassthrough } from "@langchain/core/runnables";

export function createRAGChain(vectorStore: PineconeStore) {
  const retriever = vectorStore.asRetriever({ k: 4 });
  const model = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0 });

  const prompt = ChatPromptTemplate.fromTemplate(`
Answer based only on the provided context.
If the answer is not in the context, say "I don't have that information."

Context:
{context}

Question: {question}`);

  return RunnableSequence.from([
    {
      context: retriever.pipe(
        (docs) => docs.map((d: any) => d.pageContent).join("\n\n")
      ),
      question: new RunnablePassthrough(),
    },
    prompt,
    model,
    new StringOutputParser(),
  ]);
}

Multi-Agent Orchestration

// src/core/agents/orchestrator.ts
import { ChatOpenAI } from "@langchain/openai";
import { createToolCallingAgent, AgentExecutor } from "langchain/agents";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";

interface SpecializedAgent {
  name: string;
  description: string;
  executor: AgentExecutor;
}

class AgentOrchestrator {
  private agents: SpecializedAgent[] = [];
  private router: any;

  register(agent: SpecializedAgent) {
    this.agents.push(agent);
  }

  async route(input: string): Promise<string> {
    // Use LLM to pick the right agent
    const model = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0 });
    const agentList = this.agents
      .map((a) => `- ${a.name}: ${a.description}`)
      .join("\n");

    const routerPrompt = ChatPromptTemplate.fromTemplate(`
Given these specialized agents:
${agentList}

Which agent should handle this request? Reply with just the agent name.
Request: {input}`);

    const routerChain = routerPrompt.pipe(model).pipe(new StringOutputParser());
    const agentName = (await routerChain.invoke({ input })).trim();

    const agent = this.agents.find((a) => a.name === agentName);
    if (!agent) {
      return `No agent found for: ${input}`;
    }

    const result = await agent.executor.invoke({ input, chat_history: [] });
    return result.output;
  }
}

// Usage
const orchestrator = new AgentOrchestrator();
orchestrator.register({
  name: "code-reviewer",
  description: "Reviews code for bugs and best practices",
  executor: codeReviewAgent,
});
orchestrator.register({
  name: "data-analyst",
  description: "Analyzes data and generates reports",
  executor: dataAnalystAgent,
});

Configuration-Driven Design

// src/config/index.ts
import { z } from "zod";
import "dotenv/config";

const ConfigSchema = z.object({
  llm: z.object({
    provider: z.enum(["openai", "anthropic"]),
    model: z.string(),
    temperature: z.number().min(0).max(2).default(0),
    maxRetries: z.number().default(3),
  }),
  vectorStore: z.object({
    provider: z.enum(["pinecone", "faiss", "memory"]),
    indexName: z.string().optional(),
  }),
  server: z.object({
    port: z.number().default(8000),
    cors: z.boolean().default(true),
  }),
  langsmith: z.object({
    enabled: z.boolean().default(false),
    project: z.string().default("default"),
  }),
});

export type Config = z.infer<typeof ConfigSchema>;

export function loadConfig(): Config {
  return ConfigSchema.parse({
    llm: {
      provider: process.env.LLM_PROVIDER ?? "openai",
      model: process.env.LLM_MODEL ?? "gpt-4o-mini",
      temperature: Number(process.env.LLM_TEMPERATURE ?? 0),
    },
    vectorStore: {
      provider: process.env.VECTOR_STORE_PROVIDER ?? "memory",
      indexName: process.env.PINECONE_INDEX,
    },
    server: {
      port: Number(process.env.PORT ?? 8000),
    },
    langsmith: {
      enabled: process.env.LANGSMITH_TRACING === "true",
      project: process.env.LANGSMITH_PROJECT ?? "default",
    },
  });
}

Error Handling

Issue Cause Fix
Circular imports Wrong layering Core should never import from API layer
Provider not found Unknown in factory Add to factory switch statement
Chain not registered Missing startup init Register all chains in app bootstrap
Config validation fail Missing env var Add to .env.example, validate on startup

Resources

Next Steps

Use langchain-multi-env-setup for environment management.

Info
Category Development
Name langchain-reference-architecture
Version v20260423
Size 6.02KB
Updated At 2026-04-28
Language