From langchain-pack
Implements production LangChain architecture: layered structure, LLM provider abstraction, chain registry, RAG pipelines, multi-agent orchestration.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin langchain-packThis skill is limited to using the following tools:
Production architectural patterns for LangChain: layered project structure, provider abstraction for vendor flexibility, chain registry for dynamic management, RAG architecture, and multi-agent orchestration.
Guides LangChain architecture for LLM apps: agents (ReAct, OpenAI Functions), chains (LLMChain, SequentialChain), memory (Buffer, Summary), document processing, callbacks. Use for AI agents, workflows, integrations.
Designs LLM applications using LangChain framework with agents, chains, memory, tool integration, and document processing. Use for building AI agents, complex workflows, and production apps.
Designs LLM applications using LangChain 1.x and LangGraph for agents, state management, memory, tool integration, and workflows.
Share bugs, ideas, or general feedback.
Production architectural patterns for LangChain: layered project structure, provider abstraction for vendor flexibility, chain registry for dynamic management, RAG architecture, and multi-agent orchestration.
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
// 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",
});
// 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 });
});
// 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(),
]);
}
// 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,
});
// 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",
},
});
}
| 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 |
Use langchain-multi-env-setup for environment management.