mrkeyoor.com_
Sat 19 Sept 23:52 UTC
npmAI / MLupdated 19 Sept 2026

@langchain/core review

@langchain/core 1.2.9 defines the shared contracts used by LangChain.js integrations: messages, prompt templates, tools, output parsers, retrievers, callbacks, tracing, and the Runnable interface for invoke, batch, stream, retry, and fallback behavior. Provider packages supply the actual chat models and embeddings. Version 1.2.9 fixes Google and Vertex message conversion so tool calls appear as tool_call content blocks without empty text blocks. The preceding 1.2.8 release added retry classifications that stop deterministic failures such as bad credentials, unknown models, aborted calls, and oversized payloads from consuming every retry layer.

Verdict

@langchain/core 1.2.9 installed in 4.2 seconds and left 48 MB across 17 packages in our sandbox, while a root namespace browser build tree-shook to 0.2 KB gzipped. Install it when LangChain interoperability is the requirement; a direct provider SDK is easier to audit when one model client and a few calls are enough.

We installed it

Lab card: what happened when we installed @langchain/coreScreenshot of @langchain/core documentation
Install✓ · 4.2s17 packages on disk · 48 MB
ImportESM import works · require() works · ESM package with exports map
Browser0.2 KBgzipped (0.3 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @langchain/core install cleanly?

Yes. In a fresh container with an empty cache, npm install @langchain/core finished in 4 seconds, leaving 17 packages and 48 MB on disk. npm audit reported no known vulnerabilities.

How much does @langchain/core add to a browser bundle?

0.2 KB gzipped (0.3 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does @langchain/core work with both ESM and CommonJS?

Yes. Both import '@langchain/core' and require('@langchain/core') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does @langchain/core include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@langchain/core or ai: which should you use?

ai: Use it for TypeScript streaming, tool calls, and framework UI helpers with a smaller orchestration model. @langchain/core 1.2.9 installed in 4.2 seconds and left 48 MB across 17 packages in our sandbox, while a root namespace browser build tree-shook to 0.2 KB gzipped.

When should you not use @langchain/core?

One provider SDK and a few direct calls cover the product. The official provider client has fewer abstractions and less version coupling.

API stability3/5The 1.x package has settled on messages, prompts, tools, output parsers, and Runnable methods such as invoke, batch, stream, withRetry, and withFallbacks. Patch releases still alter operational behavior: 1.2.8 changed when retry middleware stops, and 1.2.9 changed Google and Vertex content-block conversion. Cross-version object checks received fixes in 1.2.6, which is evidence that duplicate or mixed core versions remain a practical compatibility concern.
Docs4/5The current JavaScript docs explain models, messages, tools, agents, structured output, streaming, middleware, retrieval, runtime environments, and LangSmith tracing, with separate integration pages for providers. The package exports bundled declarations for each public subpath. Search results still surface pre-1.0 imports and deprecated stream or history APIs, so examples need a version check against the 1.2.9 exports and changelog before copying.
Maintenance5/5Version 1.2.9 was published on August 20, 2026, and the monorepo was pushed on August 25. The unarchived repository has 18,135 stars and GitHub reports 539 open issues and pull requests across its many packages. Recent core patches address retry storms, duplicate-version instanceof behavior, message serialization, stream aggregation, tracing callbacks, gateway routing, and provider content conversion, showing active work on production failure modes.
Ecosystem5/5The npm endpoint counted 5,612,479 downloads in the latest week. LangChain provider packages, LangGraph, and LangSmith share core's Runnable, message, tool, callback, and tracing types. The exports map contains dedicated paths for prompts, tools, messages, documents, retrievers, vector stores, output parsers, caches, and testing. That reach makes core useful inside LangChain, but it also couples integrations to the same evolving contracts.

Use it if

  • Several LangChain provider packages need one shared message, tool, prompt, and Runnable contract.
  • You are implementing a model, retriever, tool, or callback that should plug into LangChain.js.
  • Provider swapping matters enough to keep application code behind BaseChatModel and standard messages.
  • Chains need the same invoke, stream, batch, retry, fallback, and tracing controls.
Skip it if

Setup reality

We installed @langchain/core 1.2.9 in 4.2 seconds in a clean Node 22 container. The result was 17 packages and 48 MB on disk. npm audit reported 0 known vulnerabilities. Core has 7 direct dependencies, no peers, and 13,536 KB unpacked. It is ESM with an exports map, bundled TypeScript declarations, and working require() and ESM import paths.

Install a provider package separately because core does not call a model by itself. API credentials belong to that provider's environment variables or constructor config. Deep imports such as @langchain/core/messages, /prompts, /tools, and /runnables are public export paths and keep intent clear. Node 20 is the declared floor. Browser and edge support depends on the exact subpaths and provider package, so test the deployed runtime rather than assuming every integration follows core.

Our namespace browser build measured 0.3 KB minified and 0.2 KB gzipped. That figure reflects the root import's tree-shaken surface, not the cost of prompts, tokenization, LangSmith, or a provider client used by a real application. Inspect the production entry points you actually import. Version 1.2.9's tool-call conversion fix also means serialized message and cross-provider handoff tests should compare contentBlocks along with message.content.

Runnable batch work is concurrent unless maxConcurrency bounds it, and provider rate limits still apply. Retries can nest across model, tool, and outer workflow layers. Version 1.2.8 marks known deterministic errors as non-retryable and stops on the first such mark; third-party errors remain unclassified and retain prior retry behavior. Pass AbortSignal through config for cancellation, keep tracing credentials optional by environment, and pin compatible LangChain package ranges so one lockfile does not mix behavior from separate 1.x patch lines.

Patterns

Build a message prompt format-chat-prompt

import { ChatPromptTemplate } from '@langchain/core/prompts';

const prompt = ChatPromptTemplate.fromMessages([
  ['system', 'Answer only from the supplied context.'],
  ['human', 'Context: {context}\nQuestion: {question}'],
]);
const value = await prompt.invoke({ context, question });

Single braces declare template variables. Use doubled braces when the output must contain a literal brace.

Pipe a prompt into a model and parser compose-runnable-chain

import { StringOutputParser } from '@langchain/core/output_parsers';

const chain = prompt
  .pipe(model)
  .pipe(new StringOutputParser());

const answer = await chain.invoke({ context, question });

The provider model comes from another package. StringOutputParser turns message chunks into text and discards non-text structure.

Consume text chunks stream-runnable

const stream = await chain.stream({ context, question });
for await (const text of stream) {
  process.stdout.write(text);
}

A final StringOutputParser makes each chunk a string. Without it, chat models emit AIMessageChunk objects.

Invoke a model with typed messages construct-messages

import { HumanMessage, SystemMessage } from '@langchain/core/messages';

const response = await model.invoke([
  new SystemMessage('Reply in one sentence.'),
  new HumanMessage('What does an LRU cache evict?'),
]);

response.content may be text or an array of content blocks. Version 1.2.9 also surfaces tool calls through contentBlocks for Google and Vertex conversions.

Create a schema-checked tool define-tool

import { tool } from '@langchain/core/tools';
import { z } from 'zod';

const lookupOrder = tool(
  async ({ id }) => database.orders.find(id),
  {
    name: 'lookup_order',
    description: 'Read one order by ID',
    schema: z.object({ id: z.string() }),
  },
);

Defining or binding a tool does not execute it. An agent loop or application handler must run each returned tool call.

Turn a function into a Runnable wrap-business-function

import { RunnableLambda } from '@langchain/core/runnables';

const normalize = RunnableLambda.from(async (text: string) => text.trim());
const normalized = await normalize.invoke('  value  ');

RunnableLambda adds invoke, batch, stream, and composition around the function; it does not make CPU work parallel.

Execute two branches for one input run-parallel-branches

import { RunnableMap } from '@langchain/core/runnables';

const branches = RunnableMap.from({
  summary: summaryChain,
  labels: labelChain,
});
const result = await branches.invoke({ input: text });

Branches start concurrently, so both can consume provider quota at the same time and can fail independently.

Limit concurrent batch calls bound-batch-concurrency

const results = await chain.batch(
  inputs.map((input) => ({ input })),
  { maxConcurrency: 2 },
);

Results preserve input order. maxConcurrency=2 limits in-flight Runnable work but does not implement provider-specific rate scheduling.

Retry then switch models retry-with-fallback

const callable = primary
  .withRetry({ stopAfterAttempt: 3 })
  .withFallbacks([backup]);

const response = await callable.invoke(messages);

Version 1.2.8 stops known non-retryable errors on the first attempt. Unclassified third-party errors can still spend the full retry budget.

Abort an in-flight Runnable cancel-invocation

const controller = new AbortController();
const pending = chain.invoke(input, { signal: controller.signal });
controller.abort();
await pending;

The promise rejects after cancellation only if each Runnable and provider integration forwards the AbortSignal.

Ask a model for typed data parse-structured-output

import { z } from 'zod';

const schema = z.object({
  sentiment: z.enum(['positive', 'negative', 'neutral']),
  confidence: z.number().min(0).max(1),
});
const classifier = model.withStructuredOutput(schema);
const result = await classifier.invoke(review);

withStructuredOutput relies on the provider's tool-calling or JSON mechanism. Support and failure behavior differ across model integrations.

Mark a custom failure as final classify-retry-error

import { stampRetryable } from '@langchain/core/errors';

try {
  await validateAccount();
} catch (error) {
  throw stampRetryable(error, false);
}

Version 1.2.8 lets retry middleware stop on an explicit false mark while preserving the original error class and instanceof behavior.

Alternatives

PackageRegistryPick it when
ainpmUse it for TypeScript streaming, tool calls, and framework UI helpers with a smaller orchestration model.
openainpmUse the direct SDK when OpenAI-compatible endpoints are the only model boundary.
llamaindexnpmUse it when document ingestion, indexes, and retrieval engines are the central abstractions.

More ai / ml guides

openai · mcp · huggingface-hub · @modelcontextprotocol/sdk · scikit-learn · tiktoken · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.