LangChain.js Patterns
Quick Guide: Use LangChain.js (v1.x) to build composable LLM applications. Use LCEL (
prompt.pipe(model).pipe(parser)) for all chain composition -- never use legacyLLMChain. UsewithStructuredOutput(zodSchema)for typed responses. UsecreateAgent()(LangGraph-backed) for agentic workflows --AgentExecutoris legacy. All@langchain/*packages must share the same@langchain/coreversion or you get cryptic type errors at runtime.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use LCEL pipe composition (prompt.pipe(model).pipe(parser)) for all chains -- never use legacy LLMChain, ConversationChain, or SequentialChain)
(You MUST ensure all @langchain/* packages depend on the same version of @langchain/core -- version mismatches cause cryptic runtime errors)
(You MUST use withStructuredOutput(zodSchema) for structured LLM responses -- never manually parse JSON from completion text)
(You MUST use createAgent() from langchain for new agent code -- AgentExecutor and createToolCallingAgent are legacy patterns)
(You MUST never hardcode API keys -- use environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.))
</critical_requirements>
Auto-detection: LangChain, langchain, @langchain/core, @langchain/openai, @langchain/anthropic, @langchain/google-genai, ChatOpenAI, ChatAnthropic, ChatPromptTemplate, StringOutputParser, RunnableSequence, pipe, withStructuredOutput, createAgent, createToolCallingAgent, AgentExecutor, tool, DynamicStructuredTool, RecursiveCharacterTextSplitter, MemoryVectorStore, OpenAIEmbeddings, LCEL, LangSmith, LANGCHAIN_TRACING_V2
When to use:
- Building LLM applications that compose prompts, models, and output parsers into chains
- Creating agentic workflows where models decide which tools to call
- Implementing RAG pipelines with document loading, splitting, embedding, and retrieval
- Needing structured output from LLMs with type-safe Zod schema validation
- Streaming LLM responses token-by-token to users
- Switching between LLM providers (OpenAI, Anthropic, Google) with a unified interface
- Tracing and debugging LLM applications with LangSmith
Key patterns covered:
- Chat model initialization and provider switching (ChatOpenAI, ChatAnthropic, ChatGoogleGenerativeAI)
- LCEL chain composition with
.pipe()andRunnableSequence - Prompt templates (
ChatPromptTemplate,MessagesPlaceholder) - Structured output with
withStructuredOutput()and Zod schemas - Tool definition with
tool()function and Zod schemas - Agent creation with
createAgent()(LangGraph-backed) - RAG pipelines: document loaders, text splitters, vector stores, retrievers
- Streaming from chains, models, and agents
- LangSmith tracing setup
When NOT to use:
- You only call one LLM provider and want the thinnest wrapper -- use the provider's SDK directly
- You need React-specific chat UI hooks (
useChat,useCompletion) -- use a framework-integrated AI SDK - You want a simple single-call completion with no chaining -- a direct SDK call is simpler
- You need real-time bidirectional communication -- LangChain does not cover WebSocket/Realtime APIs
Examples Index
- Core: Setup, LCEL & Chat Models -- Package installation, chat model init, LCEL chains, prompt templates, output parsers
- Structured Output & Tools --
withStructuredOutput, tool definition, binding tools to models - Agents --
createAgent, tool-calling agents, chat history, streaming agents - RAG Pipelines -- Document loaders, text splitters, vector stores, retrieval chains
- Streaming -- Model streaming, chain streaming, agent streaming
- Quick API Reference -- Package map, import paths, environment variables, model IDs
<philosophy>
Philosophy
LangChain.js provides a composable framework for building LLM-powered applications. Its core abstraction is the Runnable -- any component that takes an input and produces an output. Runnables compose via LCEL (.pipe()) to form chains, and every Runnable supports .invoke(), .stream(), .batch() uniformly.
Core principles:
- Composability via LCEL -- Chains are built by piping Runnables:
prompt.pipe(model).pipe(parser). Each step is independently testable and replaceable. Legacy chain classes (LLMChain,ConversationChain) are deprecated. - Provider-agnostic models -- Chat models (
ChatOpenAI,ChatAnthropic,ChatGoogleGenerativeAI) share a common interface. Swap providers by changing one import and model name. UseinitChatModel()for runtime provider selection. - Type-safe structured output --
model.withStructuredOutput(zodSchema)constrains LLM responses to your schema. No manual JSON parsing. - Split package architecture --
@langchain/coreholds abstractions, provider packages (@langchain/openai,@langchain/anthropic) hold implementations,langchainholds higher-level composables. All must share the same@langchain/coreversion. - Observability built in -- Set
LANGCHAIN_TRACING_V2=trueand every chain/agent/tool call is traced to LangSmith automatically.
When to use LangChain:
- You need to compose multi-step LLM workflows (prompt -> model -> parser -> next step)
- You want to swap LLM providers without rewriting business logic
- You need agent-style tool calling with automatic routing
- You need RAG with document loading, chunking, embedding, and retrieval
- You want built-in tracing and evaluation via LangSmith
When NOT to use:
- Single-provider, single-call use cases -- the provider SDK is simpler and has less overhead
- You want full control over HTTP requests -- LangChain abstracts the transport layer
- Extremely latency-sensitive applications where the abstraction overhead matters
<patterns>
Core Patterns
Pattern 1: Chat Model Initialization
Initialize chat models from any provider. They all share the same interface.
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
model: "gpt-4.1",
temperature: 0,
});
const response = await model.invoke("Explain TypeScript generics.");
console.log(response.text);
Why good: Explicit model name, temperature set for determinism, .text accessor for content
// BAD: Hardcoded API key, no model specified
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({ apiKey: "sk-1234..." });
Why bad: Hardcoded API key is a security risk, missing model name uses unpredictable defaults
Provider Switching
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({ model: "claude-sonnet-4-5-20250929" });
// Or use initChatModel for runtime provider selection
import { initChatModel } from "langchain";
const model = await initChatModel("openai:gpt-4.1", { temperature: 0 });
See: examples/core.md for full provider examples and configuration options
Pattern 2: LCEL Chain Composition
Compose chains using .pipe(). Every component is a Runnable.
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
const prompt = ChatPromptTemplate.fromTemplate(
"Summarize this in one sentence: {text}",
);
const model = new ChatOpenAI({ model: "gpt-4.1" });
const parser = new StringOutputParser();
const chain = prompt.pipe(model).pipe(parser);
const result = await chain.invoke({ text: "LangChain is a framework..." });
// result is a plain string
*Why good: