Core LangChain.js abstractions and schemas for building applications with Large Language Models
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The Runnable system is the core composability framework in LangChain Core, providing a universal interface that enables any component to be chained, streamed, batched, and configured. All major LangChain components implement the Runnable interface.
Abstract base class providing universal composability interface for all LangChain components.
/**
* Abstract base class for all runnable components in LangChain
* @template RunInput - Input type for the runnable
* @template RunOutput - Output type for the runnable
* @template CallOptions - Options type for invocation
*/
abstract class Runnable<RunInput = any, RunOutput = any, CallOptions extends RunnableConfig = RunnableConfig> {
/** Execute the runnable with given input */
abstract invoke(input: RunInput, options?: Partial<CallOptions>): Promise<RunOutput>;
/** Stream the runnable execution, yielding intermediate results */
stream(input: RunInput, options?: Partial<CallOptions>): AsyncGenerator<RunOutput>;
/** Execute the runnable on multiple inputs in parallel */
batch(inputs: RunInput[], options?: Partial<CallOptions> & { maxConcurrency?: number }): Promise<RunOutput[]>;
/** Chain this runnable with another runnable */
pipe<NewRunOutput>(coerceable: RunnableLike<RunOutput, NewRunOutput>): Runnable<RunInput, NewRunOutput>;
/** Create a copy of this runnable with default configuration */
withConfig(config: Partial<CallOptions>): Runnable<RunInput, RunOutput, CallOptions>;
/** Bind arguments to this runnable */
bind(kwargs: Partial<CallOptions>): Runnable<RunInput, RunOutput, CallOptions>;
/** Add retry logic to this runnable */
withRetry(fields?: { stopAfterAttempt?: number; waitExponentialBase?: number }): RunnableRetry<RunInput, RunOutput, CallOptions>;
/** Add fallback runnables in case of failure */
withFallbacks(fields: { fallbacks: Runnable<RunInput, RunOutput>[] }): RunnableWithFallbacks<RunInput, RunOutput>;
}Usage Examples:
import { RunnableLambda } from "@langchain/core/runnables";
// Create a simple runnable
const doubler = RunnableLambda.from((x: number) => x * 2);
// Invoke directly
const result = await doubler.invoke(5); // 10
// Stream (for generators)
for await (const chunk of doubler.stream(5)) {
console.log(chunk); // 10
}
// Batch process
const results = await doubler.batch([1, 2, 3]); // [2, 4, 6]
// Chain with another runnable
const formatter = RunnableLambda.from((x: number) => `Result: ${x}`);
const chain = doubler.pipe(formatter);
const formatted = await chain.invoke(5); // "Result: 10"Chain multiple runnables to execute sequentially, passing output from one to the next.
/**
* Chain multiple runnables sequentially
* @template RunInput - Input type for the sequence
* @template RunOutput - Output type for the sequence
*/
class RunnableSequence<RunInput = any, RunOutput = any> extends Runnable<RunInput, RunOutput> {
/** Array of runnables to execute in sequence */
steps: Runnable[];
constructor(fields: { first: Runnable<RunInput>; middle?: Runnable[]; last: Runnable<any, RunOutput> });
/** Create sequence from array of runnables */
static from<RunInput, RunOutput>(steps: [Runnable<RunInput>, ...Runnable[], Runnable<any, RunOutput>]): RunnableSequence<RunInput, RunOutput>;
}Usage Examples:
import { RunnableSequence, RunnableLambda } from "@langchain/core/runnables";
// Create sequence manually
const step1 = RunnableLambda.from((x: string) => x.toUpperCase());
const step2 = RunnableLambda.from((x: string) => `Hello, ${x}!`);
const sequence = RunnableSequence.from([step1, step2]);
const result = await sequence.invoke("world"); // "Hello, WORLD!"
// Or use pipe method (more common)
const chain = step1.pipe(step2);
const result2 = await chain.invoke("world"); // "Hello, WORLD!"Execute multiple runnables in parallel and collect their results.
/**
* Execute multiple runnables in parallel
* @template RunInput - Input type for all runnables
*/
class RunnableParallel<RunInput = any> extends Runnable<RunInput, Record<string, any>> {
/** Map of runnable names to runnables */
steps: Record<string, Runnable<RunInput>>;
constructor(fields: Record<string, Runnable<RunInput>>);
/** Create parallel execution from object of runnables */
static from<RunInput>(steps: Record<string, RunnableLike<RunInput>>): RunnableParallel<RunInput>;
}Usage Examples:
import { RunnableParallel, RunnableLambda } from "@langchain/core/runnables";
const parallel = RunnableParallel.from({
upper: RunnableLambda.from((x: string) => x.toUpperCase()),
lower: RunnableLambda.from((x: string) => x.toLowerCase()),
length: RunnableLambda.from((x: string) => x.length),
});
const result = await parallel.invoke("Hello");
// { upper: "HELLO", lower: "hello", length: 5 }Wrap a function to make it a runnable component.
/**
* Convert a function into a runnable
* @template RunInput - Function input type
* @template RunOutput - Function output type
*/
class RunnableLambda<RunInput = any, RunOutput = any> extends Runnable<RunInput, RunOutput> {
/** The wrapped function */
func: (input: RunInput) => RunOutput | Promise<RunOutput>;
constructor(fields: { func: (input: RunInput) => RunOutput | Promise<RunOutput> });
/** Create lambda from function */
static from<RunInput, RunOutput>(func: (input: RunInput) => RunOutput | Promise<RunOutput>): RunnableLambda<RunInput, RunOutput>;
}Pass input through unchanged, optionally assigning additional fields.
/**
* Pass input through unchanged, with optional field assignment
* @template RunInput - Input type to pass through
*/
class RunnablePassthrough<RunInput = any> extends Runnable<RunInput, RunInput> {
constructor();
/** Create passthrough that assigns additional fields */
static assign<RunInput extends Record<string, any>>(mapping: Record<string, RunnableLike<RunInput>>): Runnable<RunInput, RunInput>;
/** Create passthrough that picks specific fields */
static pick<RunInput extends Record<string, any>, K extends keyof RunInput>(keys: K | K[]): Runnable<RunInput, Pick<RunInput, K>>;
}Usage Examples:
import { RunnablePassthrough, RunnableLambda } from "@langchain/core/runnables";
// Simple passthrough
const passthrough = new RunnablePassthrough();
const result = await passthrough.invoke("hello"); // "hello"
// Assign additional fields
const withExtra = RunnablePassthrough.assign({
upper: RunnableLambda.from((x: { text: string }) => x.text.toUpperCase()),
length: RunnableLambda.from((x: { text: string }) => x.text.length),
});
const result2 = await withExtra.invoke({ text: "hello" });
// { text: "hello", upper: "HELLO", length: 5 }
// Pick specific fields
const picker = RunnablePassthrough.pick(["name", "age"]);
const result3 = await picker.invoke({ name: "Alice", age: 30, city: "NYC" });
// { name: "Alice", age: 30 }Conditional execution based on input condition.
/**
* Conditional execution of runnables based on input
* @template RunInput - Input type for condition evaluation
* @template RunOutput - Output type from branches
*/
class RunnableBranch<RunInput = any, RunOutput = any> extends Runnable<RunInput, RunOutput> {
/** Array of condition-runnable pairs plus default */
branches: Array<{
condition: (input: RunInput) => boolean | Promise<boolean>;
runnable: Runnable<RunInput, RunOutput>;
}>;
default?: Runnable<RunInput, RunOutput>;
constructor(branches: Array<[
(input: RunInput) => boolean | Promise<boolean>,
RunnableLike<RunInput, RunOutput>
]>, defaultBranch?: RunnableLike<RunInput, RunOutput>);
}Usage Examples:
import { RunnableBranch, RunnableLambda } from "@langchain/core/runnables";
const branch = new RunnableBranch([
[(x: number) => x > 0, RunnableLambda.from((x: number) => `Positive: ${x}`)],
[(x: number) => x < 0, RunnableLambda.from((x: number) => `Negative: ${x}`)],
], RunnableLambda.from(() => "Zero"));
const result1 = await branch.invoke(5); // "Positive: 5"
const result2 = await branch.invoke(-3); // "Negative: -3"
const result3 = await branch.invoke(0); // "Zero"Runnable with pre-bound configuration or arguments.
/**
* Runnable with pre-bound arguments or configuration
* @template RunInput - Input type for the bound runnable
* @template RunOutput - Output type for the bound runnable
* @template CallOptions - Call options type
*/
class RunnableBinding<RunInput, RunOutput, CallOptions extends RunnableConfig = RunnableConfig> extends Runnable<RunInput, RunOutput, CallOptions> {
/** The bound runnable */
bound: Runnable<RunInput, RunOutput, CallOptions>;
/** Pre-bound configuration */
config: Partial<CallOptions>;
/** Pre-bound keyword arguments */
kwargs: Record<string, unknown>;
constructor(fields: {
bound: Runnable<RunInput, RunOutput, CallOptions>;
config?: Partial<CallOptions>;
kwargs?: Record<string, unknown>;
});
}Add automatic retry logic to any runnable.
/**
* Add retry logic to a runnable
* @template RunInput - Input type for the runnable
* @template RunOutput - Output type for the runnable
* @template CallOptions - Call options type
*/
class RunnableRetry<RunInput, RunOutput, CallOptions extends RunnableConfig = RunnableConfig> extends Runnable<RunInput, RunOutput, CallOptions> {
/** The runnable to retry */
bound: Runnable<RunInput, RunOutput, CallOptions>;
/** Maximum number of attempts */
stopAfterAttempt: number;
/** Exponential backoff base */
waitExponentialBase: number;
constructor(fields: {
bound: Runnable<RunInput, RunOutput, CallOptions>;
stopAfterAttempt?: number;
waitExponentialBase?: number;
});
}Provide fallback runnables in case of failure.
/**
* Runnable with fallback options on failure
* @template RunInput - Input type
* @template RunOutput - Output type
*/
class RunnableWithFallbacks<RunInput, RunOutput> extends Runnable<RunInput, RunOutput> {
/** Primary runnable to try first */
runnable: Runnable<RunInput, RunOutput>;
/** Fallback runnables to try on failure */
fallbacks: Runnable<RunInput, RunOutput>[];
constructor(fields: {
runnable: Runnable<RunInput, RunOutput>;
fallbacks: Runnable<RunInput, RunOutput>[];
});
}Apply a runnable to each item in an array input.
/**
* Apply a runnable to each item in an array
* @template RunInput - Type of each array item
* @template RunOutput - Type of output for each item
*/
class RunnableEach<RunInput, RunOutput> extends Runnable<RunInput[], RunOutput[]> {
/** The runnable to apply to each item */
bound: Runnable<RunInput, RunOutput>;
constructor(fields: {
bound: Runnable<RunInput, RunOutput>;
});
}Usage Examples:
import { RunnableEach, RunnableLambda } from "@langchain/core/runnables";
// Apply transformation to each item in array
const transformer = RunnableLambda.from((x: string) => x.toUpperCase());
const eachTransformer = new RunnableEach({ bound: transformer });
const result = await eachTransformer.invoke(["hello", "world"]);
// ["HELLO", "WORLD"]Assign additional fields to input object.
/**
* Assign additional fields to input object
* @template RunInput - Input object type
*/
class RunnableAssign<RunInput extends Record<string, any>> extends Runnable<RunInput, RunInput> {
/** Mapping of field names to runnables */
mapping: Record<string, Runnable<RunInput>>;
constructor(mapping: Record<string, RunnableLike<RunInput>>);
}Usage Examples:
import { RunnableAssign, RunnableLambda } from "@langchain/core/runnables";
// Assign computed fields to input
const assign = new RunnableAssign({
wordCount: RunnableLambda.from((x: { text: string }) => x.text.split(' ').length),
uppercase: RunnableLambda.from((x: { text: string }) => x.text.toUpperCase())
});
const result = await assign.invoke({ text: "hello world" });
// { text: "hello world", wordCount: 2, uppercase: "HELLO WORLD" }Select specific fields from input object.
/**
* Pick specific fields from input object
* @template RunInput - Input object type
* @template K - Keys to pick
*/
class RunnablePick<RunInput extends Record<string, any>, K extends keyof RunInput> extends Runnable<RunInput, Pick<RunInput, K>> {
/** Keys to pick from input */
keys: K[];
constructor(keys: K | K[]);
}Usage Examples:
import { RunnablePick } from "@langchain/core/runnables";
const picker = new RunnablePick(["name", "age"]);
const result = await picker.invoke({
name: "Alice",
age: 30,
city: "NYC",
country: "USA"
});
// { name: "Alice", age: 30 }Route execution to different runnables based on input routing logic.
/**
* Route to different runnables based on routing logic
* @template RunInput - Input type
* @template RunOutput - Output type
*/
class RouterRunnable<RunInput, RunOutput> extends Runnable<RunInput, RunOutput> {
/** Routing function to determine which runnable to use */
router: (input: RunInput) => string | Promise<string>;
/** Map of route names to runnables */
runnables: Record<string, Runnable<RunInput, RunOutput>>;
/** Default runnable if no route matches */
defaultRunnable?: Runnable<RunInput, RunOutput>;
constructor(fields: {
router: (input: RunInput) => string | Promise<string>;
runnables: Record<string, Runnable<RunInput, RunOutput>>;
defaultRunnable?: Runnable<RunInput, RunOutput>;
});
}Usage Examples:
import { RouterRunnable, RunnableLambda } from "@langchain/core/runnables";
const router = new RouterRunnable({
router: (input: { type: string; data: any }) => input.type,
runnables: {
text: RunnableLambda.from((x) => `Processing text: ${x.data}`),
number: RunnableLambda.from((x) => `Number is: ${x.data * 2}`),
image: RunnableLambda.from((x) => `Image processing: ${x.data.url}`)
},
defaultRunnable: RunnableLambda.from(() => "Unknown type")
});
const result = await router.invoke({ type: "text", data: "hello" });
// "Processing text: hello"Add conversation memory to any runnable.
/**
* Add conversation memory to a runnable
* @template RunInput - Input type
* @template RunOutput - Output type
*/
class RunnableWithMessageHistory<RunInput, RunOutput> extends Runnable<RunInput, RunOutput> {
/** The runnable to wrap with memory */
runnable: Runnable<RunInput, RunOutput>;
/** Function to get message history for a session */
getMessageHistory: (sessionId: string) => BaseChatMessageHistory;
/** Function to extract input messages from input */
inputMessagesKey?: string | ((input: RunInput) => BaseMessage[]);
/** Function to extract history messages from input */
historyMessagesKey?: string;
/** Function to extract output messages from output */
outputMessagesKey?: string | ((output: RunOutput) => BaseMessage[]);
constructor(fields: {
runnable: Runnable<RunInput, RunOutput>;
getMessageHistory: (sessionId: string) => BaseChatMessageHistory;
inputMessagesKey?: string | ((input: RunInput) => BaseMessage[]);
historyMessagesKey?: string;
outputMessagesKey?: string | ((output: RunOutput) => BaseMessage[]);
});
}interface RunnableConfig {
/** Callback handlers for observability */
callbacks?: Callbacks;
/** Tags for categorizing runs */
tags?: string[];
/** Additional metadata */
metadata?: Record<string, unknown>;
/** Human-readable name for the run */
runName?: string;
/** Configurable parameters */
configurable?: Record<string, unknown>;
/** Run ID for tracking */
runId?: string;
}
interface RunnableBatchOptions {
/** Maximum number of concurrent executions */
maxConcurrency?: number;
/** Whether to return exceptions instead of throwing */
returnExceptions?: boolean;
}
type RunnableLike<RunInput, RunOutput> =
| Runnable<RunInput, RunOutput>
| ((input: RunInput) => RunOutput | Promise<RunOutput>)
| ((input: RunInput) => AsyncGenerator<RunOutput>);
interface RunnableInterface<RunInput, RunOutput> {
invoke(input: RunInput, options?: RunnableConfig): Promise<RunOutput>;
stream(input: RunInput, options?: RunnableConfig): AsyncGenerator<RunOutput>;
batch(inputs: RunInput[], options?: RunnableBatchOptions): Promise<RunOutput[]>;
}
interface RunnableConfigurableFields {
[key: string]: {
annotation?: string;
name?: string;
description?: string;
default?: unknown;
isShared?: boolean;
};
}
/**
* Ensure config object has required defaults
*/
function ensureConfig(config?: RunnableConfig): RunnableConfig;
/**
* Merge multiple config objects
*/
function mergeConfigs(...configs: (RunnableConfig | undefined)[]): RunnableConfig;
/**
* Apply patches to a config object
*/
function patchConfig(config: RunnableConfig, patch: Partial<RunnableConfig>): RunnableConfig;
/**
* Get callback manager for a given config
*/
function getCallbackManagerForConfig(config?: RunnableConfig): CallbackManager | undefined;