LangChain.js
repository·main·Indexed 12 days ago
https://github.com/langchain-ai/langchainjsAn agent engineering platform and framework for building LLM-powered applications in JavaScript and TypeScript. It provides a standard interface for models, embeddings, tools, and vector stores to create complex AI workflows. The framework supports multiple runtimes including Node.js, Bun, and Cloudflare Workers, and includes tools for model profile generation and standardized integration testing.
What's inside LangChain.js
- LangChain.js is a library designed to help developers build applications powered by Large Language Models (LLMs). Its core value lies in composability: the ability to combine LLMs with other sources of computation or knowledge to create powerful, complex applications.
Supported Google services in LangChain
mainThe common Google package supports Gemini models through both LLM and Chat classes. This applies to both the Google AI Studio-based versions and the Google Cloud Vertex AI versions of the models.
Supported features include:
- Gemini models (LLM and Chat)
- Function/Tool support
Explore the LangChain ecosystem
mainLangChain is part of a larger ecosystem of tools designed for different stages of agent development:
- Deep Agents (JS): A higher-level package built on LangChain for agents with built-in capabilities like planning, subagents, and file system usage.
- LangGraph.js: A low-level agent orchestration framework for building agents that handle complex tasks, offering customizable architecture, long-term memory, and human-in-the-loop workflows.
- LangSmith: A unified developer platform for building, testing, and monitoring LLM applications. It is used for debugging, evaluating agent trajectories, and gaining production visibility.
- LangSmith Deployment: A purpose-built platform for deploying and scaling agents with long-running, stateful workflows.
- Integrations: A vast library of chat & embedding models, tools, toolkits, and vector stores.
Handle Zod schema limitations for Gemini tools
mainWhen using tools with Gemini models through Vertex AI, certain Zod schema features are unsupported and will cause errors. Follow these patterns to ensure compatibility:
Unsupported: Discriminated Unions
.discriminatedUnion()is not supported. Solution: Use a flat object with an enum and optional fields.// ❌ Unsupported z.discriminatedUnion("type", [ z.object({ type: z.literal("a"), value: z.string() }), z.object({ type: z.literal("b"), value: z.number() }), ]); // ✅ Supported z.object({ type: z.enum(["a", "b"]), stringValue: z.string().optional(), numberValue: z.number().optional(), });Unsupported: Union Types
z.union()is not supported. Solution: Use separate optional fields within a single object.// ❌ Unsupported z.union([z.string(), z.number()]); // ✅ Supported z.object({ stringValue: z.string().optional(), numberValue: z.number().optional(), });Unsupported: Positive Refinement
.positive()is automatically converted to.min(0.01). Solution: Use.min()directly to avoid ambiguity.// ⚠️ Automatically converted z.number().positive(); // ✅ Preferred z.number().min(0.01);Manage environment variables in tests with `env`
mainThe
@langchain/test-helpers/envmodule provides utilities for managingprocess.envduring testing, specifically designed for Jest. It allows you to set, preserve, or delete environment variables while ensuring changes are isolated to individual tests and automatically cleaned up usingbeforeEachandafterEachhooks.import { env } from "@langchain/test-helpers/env";How Tool Output Mapping works in MCP Adapters
mainMCP tools return arrays of content blocks (text, image, audio, or embedded resources).
@langchain/mcp-adaptersmaps these into LangChainToolMessageobjects using two primary configuration settings:useStandardContentBlocks: Determines the internal structure of the content blocks.- When
true(recommended), outputs are converted to standardized types likeStandardTextBlock,StandardImageBlock,StandardAudioBlock, andStandardFileBlock(compatible with@langchain/core0.3.48+). - When
false, outputs use older formats likeMessageContentTextorMessageContentImageUrl.
- When
outputHandling: Determines visibility to the LLM.ToolMessage.content: Data sent here is included in the LLM's input context.ToolMessage.artifact: Data sent here is not included in the LLM context. This is useful for large outputs (like dataframes) or multimodal data that the specific LLM provider cannot handle directly.
Default Behavior: MCP
resourceblocks are routed toartifact, while all other types are routed tocontent.Configure searchParameters in ChatXAI
mainYou can control Live Search behavior globally by passing
searchParametersto theChatXAIconstructor, or per-request by passing them to the.invoke()method.Note on Naming: When using
tools.xaiLiveSearch(), use camelCase field names (e.g.,maxSearchResults,fromDate,allowedWebsites). These are automatically mapped to the underlying API'ssnake_caserequirements.// Global configuration via constructor const model = new ChatXAI({ model: "grok-3-fast", searchParameters: { mode: "auto", // "auto" | "on" | "off" max_search_results: 5, from_date: "2024-01-01", // ISO date string return_citations: true, }, }); // Per-request override const result = await model.invoke("Find recent news about SpaceX", { searchParameters: { mode: "on", max_search_results: 10, sources: [ { type: "web", allowed_websites: ["spacex.com", "nasa.gov"], }, ], }, });Understand the role of @langchain/core
main@langchain/coreprovides the base abstractions and schemas that power the LangChain ecosystem. It defines the interfaces for key components such as:- Language models
- Chat models
- Vectorstores
- Retrievers
- Runnables
- Document loaders
- Embedding models
Because these abstractions are standardized, any provider-specific package (like
@langchain/openai) can implement these interfaces, allowing them to be used interchangeably within LangChain chains and workflows.Use tools with ChatGoogle
mainThe
ChatGoogleclass supports two types of tool usage:- Standard LangChain tool calling: The common interface used across most LangChain providers.
- Gemini-specific "Specialty Tools": Includes features like Code Execution and Grounding.
Relationship between LangChain.js and LangChain Python
mainLangChain.js is designed to integrate seamlessly with the LangChain Python package.
Key compatibility features include:
- Serialization: All major objects (prompts, LLMs, chains, etc.) are designed to be serialized and shared across different languages.
- LangChainHub: You can use the LangChainHub to access serialized versions of prompts, chains, and agents that are compatible with both the JS and Python ecosystems.
When to use @langchain/classic vs langchain v1.0
mainUse
@langchain/classicif:- You have existing code using legacy chains (e.g.,
LLMChain,ConversationalRetrievalQAChain,RetrievalQAChain). - You use the Indexing API (
RecordManager). - You depend on
@langchain/communityintegrations previously re-exported from the mainlangchainpackage. - You are maintaining an existing application and are not yet ready to migrate to the
createAgentAPI.
Use
langchainv1.0 for new projects because:- It provides the
createAgentAPI for cleaner, more powerful agent building with middleware support. - It offers better performance and a more focused, less complex API surface.
- It is the primary focus for active development and new features.
- You have existing code using legacy chains (e.g.,
Customize tool calls with Tool Hooks
mainUse
beforeToolCallandafterToolCallhooks inMultiServerMCPClientto intercept and modify tool arguments, headers, or results.import { MultiServerMCPClient } from "@langchain/mcp-adapters"; const client = new MultiServerMCPClient({ mcpServers: { math: { transport: "stdio", command: "npx", args: ["-y", "@modelcontextprotocol/server-math"], }, }, // Modify args or headers before the tool is called beforeToolCall: ({ serverName, name, args }) => { const nextArgs = { ...(args as Record<string, unknown>), injected: true }; return { args: nextArgs, headers: { "X-Request-ID": crypto.randomUUID() }, }; }, // Modify the result after the tool has executed afterToolCall: (res) => { // Return a 2-tuple [content, artifact] if (res.name === "someTool") return { result: ["modified-output", []] }; // Or return the original result return { result: res.result }; }, }); const tools = await client.getTools(); const t = tools.find((tool) => tool.name.includes("add")); const out = await t?.invoke({ a: 1, b: 2 });