Loading...
Loading...
LangChain.js patterns for building LLM applications — chat models, LCEL chains, prompt templates, structured output, agents, tools, RAG, streaming, and LangSmith tracing
npx skill4agent add agents-inc/skills ai-orchestration-langchainQuick Guide: Use LangChain.js (v1.x) to build composable LLM applications. Use LCEL () for all chain composition -- never use legacyprompt.pipe(model).pipe(parser). UseLLMChainfor typed responses. UsewithStructuredOutput(zodSchema)(LangGraph-backed) for agentic workflows --createAgent()is legacy. AllAgentExecutorpackages must share the same@langchain/*version or you get cryptic type errors at runtime.@langchain/core
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,, named constants)import type
prompt.pipe(model).pipe(parser)LLMChainConversationChainSequentialChain@langchain/*@langchain/corewithStructuredOutput(zodSchema)createAgent()langchainAgentExecutorcreateToolCallingAgentOPENAI_API_KEYANTHROPIC_API_KEY.pipe()RunnableSequenceChatPromptTemplateMessagesPlaceholderwithStructuredOutput()tool()createAgent()useChatuseCompletionwithStructuredOutputcreateAgent.pipe().invoke().stream().batch()prompt.pipe(model).pipe(parser)LLMChainConversationChainChatOpenAIChatAnthropicChatGoogleGenerativeAIinitChatModel()model.withStructuredOutput(zodSchema)@langchain/core@langchain/openai@langchain/anthropiclangchain@langchain/coreLANGCHAIN_TRACING_V2=trueimport { 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);.text// BAD: Hardcoded API key, no model specified
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({ apiKey: "sk-1234..." });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 });.pipe()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// BAD: Legacy LLMChain (deprecated)
import { LLMChain } from "langchain/chains";
const chain = new LLMChain({ llm: model, prompt });LLMChainRunnableSequence.from()RunnablePassthroughRunnableParallelwithStructuredOutput()import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
const MovieSchema = z.object({
title: z.string().describe("The movie title"),
year: z.number().describe("Release year"),
genres: z.array(z.string()).describe("List of genres"),
});
const structuredModel = new ChatOpenAI({
model: "gpt-4.1",
}).withStructuredOutput(MovieSchema);
const movie = await structuredModel.invoke("Tell me about Inception.");
// movie is typed: { title: string; year: number; genres: string[] }// BAD: Manual JSON parsing from completion text
const response = await model.invoke("Return JSON with title and year...");
const data = JSON.parse(response.text); // Fragile, untyped, can throwtool()snake_caseimport { tool } from "@langchain/core/tools";
import { z } from "zod";
const getWeather = tool(
async ({ location }) => {
// Call real weather API here
return `Weather in ${location}: 22C, sunny`;
},
{
name: "get_weather",
description: "Get current weather for a city",
schema: z.object({
location: z.string().describe("City name, e.g. 'San Francisco'"),
}),
},
);.describe()snake_case// BAD: Using DynamicStructuredTool (verbose, legacy pattern)
import { DynamicStructuredTool } from "@langchain/core/tools";
const tool = new DynamicStructuredTool({
name: "getWeather", // camelCase breaks some providers
description: "...",
schema: z.object({ ... }),
func: async (input) => { ... },
});DynamicStructuredTooltool()createAgent()createAgent()import { createAgent } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const search = tool(async ({ query }) => `Results for: ${query}`, {
name: "search",
description: "Search for information",
schema: z.object({ query: z.string() }),
});
const agent = createAgent({
model: "openai:gpt-4.1",
tools: [search],
systemPrompt: "You are a helpful research assistant.",
});
const stream = await agent.stream({
messages: [{ role: "user", content: "Find info about LangChain" }],
});
for await (const step of stream) {
console.log(step.messages.at(-1));
}createAgent// BAD: Legacy AgentExecutor pattern
import { AgentExecutor, createToolCallingAgent } from "langchain/agents";
const agent = createToolCallingAgent({ llm, tools, prompt });
const executor = new AgentExecutor({ agent, tools });AgentExecutorimport { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "@langchain/classic/vectorstores/memory";
const CHUNK_SIZE = 1000;
const CHUNK_OVERLAP = 200;
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: CHUNK_SIZE,
chunkOverlap: CHUNK_OVERLAP,
});
const chunks = await splitter.splitDocuments(docs);
const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small" });
const vectorStore = new MemoryVectorStore(embeddings);
await vectorStore.addDocuments(chunks);
// Retrieve
const results = await vectorStore.similaritySearch("query", 3);MemoryVectorStore.stream()const chain = prompt.pipe(model).pipe(parser);
const stream = await chain.stream({ text: "Explain quantum computing." });
for await (const chunk of stream) {
process.stdout.write(chunk);
}// BAD: Collecting all output then displaying
const result = await chain.invoke({ text: "..." });
console.log(result); // User waits for full responseLANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_...
LANGCHAIN_PROJECT=my-project
# Recommended for non-serverless environments:
LANGCHAIN_CALLBACKS_BACKGROUND=trueLANGCHAIN_CALLBACKS_BACKGROUND=trueDo you need multi-step LLM workflows (prompt -> model -> parser -> ...)?
+-- YES -> Use LangChain (LCEL chains)
+-- NO -> Do you need to swap between LLM providers?
+-- YES -> Use LangChain (unified chat model interface)
+-- NO -> Do you need RAG or agent tool calling?
+-- YES -> Use LangChain
+-- NO -> Use the provider SDK directly (simpler, fewer deps)Which provider?
+-- OpenAI -> ChatOpenAI from @langchain/openai
+-- Anthropic -> ChatAnthropic from @langchain/anthropic
+-- Google -> ChatGoogleGenerativeAI from @langchain/google-genai
+-- Runtime selection -> initChatModel("provider:model") from langchain
+-- Other -> Check @langchain/communityDoes the model need to autonomously decide when to call tools?
+-- YES -> createAgent() (handles tool-call loops, state management)
+-- NO -> Is it a fixed sequence of steps?
+-- YES -> LCEL chain (prompt.pipe(model).pipe(parser))
+-- NO -> RunnableSequence.from() with branchingAre you writing new code?
+-- YES -> ALWAYS use LCEL (.pipe()) -- never legacy chains
+-- NO -> Is the existing code using LLMChain/ConversationChain?
+-- YES -> Migrate to LCEL when touching the code
+-- NO -> Keep as-is if it worksLLMChainConversationChainSequentialChain@langchain/coreinstanceofwithStructuredOutput()AgentExecutorcreateAgent()getWeatherget_weather.describe()BufferMemoryConversationSummaryMemoryRunnableWithMessageHistoryLANGCHAIN_CALLBACKS_BACKGROUND=truelangchain/@langchain/core/langchain@langchain/core@langchain/core@langchain/corelangchainRunnableLambda.stream()RunnabletransformChatPromptTemplate.fromTemplate()ChatPromptTemplate.fromMessages()MemoryVectorStore@langchain/corenpm install @langchain/coreinstanceofnpm ls @langchain/corewithStructuredOutput()JsonOutputParserChatPromptTemplate.fromMessages()["system", "..."]["human", "..."]systemhumanaideveloperuserassistanttool()@langchain/core/toolstool()langchainlangchaininitChatModel()initChatModel("anthropic:claude-sonnet-4-5-20250929")@langchain/anthropicStateSchemacreateAgentwithStructuredOutput()RecursiveCharacterTextSplitter@langchain/textsplitterslangchain/text_splittercreateAgent()streamMode: "values"All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,, named constants)import type
prompt.pipe(model).pipe(parser)LLMChainConversationChainSequentialChain@langchain/*@langchain/corewithStructuredOutput(zodSchema)createAgent()langchainAgentExecutorcreateToolCallingAgentOPENAI_API_KEYANTHROPIC_API_KEY