0
# Runnable System
1
2
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.
3
4
## Capabilities
5
6
### Base Runnable
7
8
Abstract base class providing universal composability interface for all LangChain components.
9
10
```typescript { .api }
11
/**
12
* Abstract base class for all runnable components in LangChain
13
* @template RunInput - Input type for the runnable
14
* @template RunOutput - Output type for the runnable
15
* @template CallOptions - Options type for invocation
16
*/
17
abstract class Runnable<RunInput = any, RunOutput = any, CallOptions extends RunnableConfig = RunnableConfig> {
18
/** Execute the runnable with given input */
19
abstract invoke(input: RunInput, options?: Partial<CallOptions>): Promise<RunOutput>;
20
21
/** Stream the runnable execution, yielding intermediate results */
22
stream(input: RunInput, options?: Partial<CallOptions>): AsyncGenerator<RunOutput>;
23
24
/** Execute the runnable on multiple inputs in parallel */
25
batch(inputs: RunInput[], options?: Partial<CallOptions> & { maxConcurrency?: number }): Promise<RunOutput[]>;
26
27
/** Chain this runnable with another runnable */
28
pipe<NewRunOutput>(coerceable: RunnableLike<RunOutput, NewRunOutput>): Runnable<RunInput, NewRunOutput>;
29
30
/** Create a copy of this runnable with default configuration */
31
withConfig(config: Partial<CallOptions>): Runnable<RunInput, RunOutput, CallOptions>;
32
33
/** Bind arguments to this runnable */
34
bind(kwargs: Partial<CallOptions>): Runnable<RunInput, RunOutput, CallOptions>;
35
36
/** Add retry logic to this runnable */
37
withRetry(fields?: { stopAfterAttempt?: number; waitExponentialBase?: number }): RunnableRetry<RunInput, RunOutput, CallOptions>;
38
39
/** Add fallback runnables in case of failure */
40
withFallbacks(fields: { fallbacks: Runnable<RunInput, RunOutput>[] }): RunnableWithFallbacks<RunInput, RunOutput>;
41
}
42
```
43
44
**Usage Examples:**
45
46
```typescript
47
import { RunnableLambda } from "@langchain/core/runnables";
48
49
// Create a simple runnable
50
const doubler = RunnableLambda.from((x: number) => x * 2);
51
52
// Invoke directly
53
const result = await doubler.invoke(5); // 10
54
55
// Stream (for generators)
56
for await (const chunk of doubler.stream(5)) {
57
console.log(chunk); // 10
58
}
59
60
// Batch process
61
const results = await doubler.batch([1, 2, 3]); // [2, 4, 6]
62
63
// Chain with another runnable
64
const formatter = RunnableLambda.from((x: number) => `Result: ${x}`);
65
const chain = doubler.pipe(formatter);
66
const formatted = await chain.invoke(5); // "Result: 10"
67
```
68
69
### Runnable Sequence
70
71
Chain multiple runnables to execute sequentially, passing output from one to the next.
72
73
```typescript { .api }
74
/**
75
* Chain multiple runnables sequentially
76
* @template RunInput - Input type for the sequence
77
* @template RunOutput - Output type for the sequence
78
*/
79
class RunnableSequence<RunInput = any, RunOutput = any> extends Runnable<RunInput, RunOutput> {
80
/** Array of runnables to execute in sequence */
81
steps: Runnable[];
82
83
constructor(fields: { first: Runnable<RunInput>; middle?: Runnable[]; last: Runnable<any, RunOutput> });
84
85
/** Create sequence from array of runnables */
86
static from<RunInput, RunOutput>(steps: [Runnable<RunInput>, ...Runnable[], Runnable<any, RunOutput>]): RunnableSequence<RunInput, RunOutput>;
87
}
88
```
89
90
**Usage Examples:**
91
92
```typescript
93
import { RunnableSequence, RunnableLambda } from "@langchain/core/runnables";
94
95
// Create sequence manually
96
const step1 = RunnableLambda.from((x: string) => x.toUpperCase());
97
const step2 = RunnableLambda.from((x: string) => `Hello, ${x}!`);
98
const sequence = RunnableSequence.from([step1, step2]);
99
100
const result = await sequence.invoke("world"); // "Hello, WORLD!"
101
102
// Or use pipe method (more common)
103
const chain = step1.pipe(step2);
104
const result2 = await chain.invoke("world"); // "Hello, WORLD!"
105
```
106
107
### Runnable Parallel
108
109
Execute multiple runnables in parallel and collect their results.
110
111
```typescript { .api }
112
/**
113
* Execute multiple runnables in parallel
114
* @template RunInput - Input type for all runnables
115
*/
116
class RunnableParallel<RunInput = any> extends Runnable<RunInput, Record<string, any>> {
117
/** Map of runnable names to runnables */
118
steps: Record<string, Runnable<RunInput>>;
119
120
constructor(fields: Record<string, Runnable<RunInput>>);
121
122
/** Create parallel execution from object of runnables */
123
static from<RunInput>(steps: Record<string, RunnableLike<RunInput>>): RunnableParallel<RunInput>;
124
}
125
```
126
127
**Usage Examples:**
128
129
```typescript
130
import { RunnableParallel, RunnableLambda } from "@langchain/core/runnables";
131
132
const parallel = RunnableParallel.from({
133
upper: RunnableLambda.from((x: string) => x.toUpperCase()),
134
lower: RunnableLambda.from((x: string) => x.toLowerCase()),
135
length: RunnableLambda.from((x: string) => x.length),
136
});
137
138
const result = await parallel.invoke("Hello");
139
// { upper: "HELLO", lower: "hello", length: 5 }
140
```
141
142
### Runnable Lambda
143
144
Wrap a function to make it a runnable component.
145
146
```typescript { .api }
147
/**
148
* Convert a function into a runnable
149
* @template RunInput - Function input type
150
* @template RunOutput - Function output type
151
*/
152
class RunnableLambda<RunInput = any, RunOutput = any> extends Runnable<RunInput, RunOutput> {
153
/** The wrapped function */
154
func: (input: RunInput) => RunOutput | Promise<RunOutput>;
155
156
constructor(fields: { func: (input: RunInput) => RunOutput | Promise<RunOutput> });
157
158
/** Create lambda from function */
159
static from<RunInput, RunOutput>(func: (input: RunInput) => RunOutput | Promise<RunOutput>): RunnableLambda<RunInput, RunOutput>;
160
}
161
```
162
163
### Runnable Passthrough
164
165
Pass input through unchanged, optionally assigning additional fields.
166
167
```typescript { .api }
168
/**
169
* Pass input through unchanged, with optional field assignment
170
* @template RunInput - Input type to pass through
171
*/
172
class RunnablePassthrough<RunInput = any> extends Runnable<RunInput, RunInput> {
173
constructor();
174
175
/** Create passthrough that assigns additional fields */
176
static assign<RunInput extends Record<string, any>>(mapping: Record<string, RunnableLike<RunInput>>): Runnable<RunInput, RunInput>;
177
178
/** Create passthrough that picks specific fields */
179
static pick<RunInput extends Record<string, any>, K extends keyof RunInput>(keys: K | K[]): Runnable<RunInput, Pick<RunInput, K>>;
180
}
181
```
182
183
**Usage Examples:**
184
185
```typescript
186
import { RunnablePassthrough, RunnableLambda } from "@langchain/core/runnables";
187
188
// Simple passthrough
189
const passthrough = new RunnablePassthrough();
190
const result = await passthrough.invoke("hello"); // "hello"
191
192
// Assign additional fields
193
const withExtra = RunnablePassthrough.assign({
194
upper: RunnableLambda.from((x: { text: string }) => x.text.toUpperCase()),
195
length: RunnableLambda.from((x: { text: string }) => x.text.length),
196
});
197
198
const result2 = await withExtra.invoke({ text: "hello" });
199
// { text: "hello", upper: "HELLO", length: 5 }
200
201
// Pick specific fields
202
const picker = RunnablePassthrough.pick(["name", "age"]);
203
const result3 = await picker.invoke({ name: "Alice", age: 30, city: "NYC" });
204
// { name: "Alice", age: 30 }
205
```
206
207
### Runnable Branch
208
209
Conditional execution based on input condition.
210
211
```typescript { .api }
212
/**
213
* Conditional execution of runnables based on input
214
* @template RunInput - Input type for condition evaluation
215
* @template RunOutput - Output type from branches
216
*/
217
class RunnableBranch<RunInput = any, RunOutput = any> extends Runnable<RunInput, RunOutput> {
218
/** Array of condition-runnable pairs plus default */
219
branches: Array<{
220
condition: (input: RunInput) => boolean | Promise<boolean>;
221
runnable: Runnable<RunInput, RunOutput>;
222
}>;
223
default?: Runnable<RunInput, RunOutput>;
224
225
constructor(branches: Array<[
226
(input: RunInput) => boolean | Promise<boolean>,
227
RunnableLike<RunInput, RunOutput>
228
]>, defaultBranch?: RunnableLike<RunInput, RunOutput>);
229
}
230
```
231
232
**Usage Examples:**
233
234
```typescript
235
import { RunnableBranch, RunnableLambda } from "@langchain/core/runnables";
236
237
const branch = new RunnableBranch([
238
[(x: number) => x > 0, RunnableLambda.from((x: number) => `Positive: ${x}`)],
239
[(x: number) => x < 0, RunnableLambda.from((x: number) => `Negative: ${x}`)],
240
], RunnableLambda.from(() => "Zero"));
241
242
const result1 = await branch.invoke(5); // "Positive: 5"
243
const result2 = await branch.invoke(-3); // "Negative: -3"
244
const result3 = await branch.invoke(0); // "Zero"
245
```
246
247
### Runnable Binding
248
249
Runnable with pre-bound configuration or arguments.
250
251
```typescript { .api }
252
/**
253
* Runnable with pre-bound arguments or configuration
254
* @template RunInput - Input type for the bound runnable
255
* @template RunOutput - Output type for the bound runnable
256
* @template CallOptions - Call options type
257
*/
258
class RunnableBinding<RunInput, RunOutput, CallOptions extends RunnableConfig = RunnableConfig> extends Runnable<RunInput, RunOutput, CallOptions> {
259
/** The bound runnable */
260
bound: Runnable<RunInput, RunOutput, CallOptions>;
261
/** Pre-bound configuration */
262
config: Partial<CallOptions>;
263
/** Pre-bound keyword arguments */
264
kwargs: Record<string, unknown>;
265
266
constructor(fields: {
267
bound: Runnable<RunInput, RunOutput, CallOptions>;
268
config?: Partial<CallOptions>;
269
kwargs?: Record<string, unknown>;
270
});
271
}
272
```
273
274
### Runnable Retry
275
276
Add automatic retry logic to any runnable.
277
278
```typescript { .api }
279
/**
280
* Add retry logic to a runnable
281
* @template RunInput - Input type for the runnable
282
* @template RunOutput - Output type for the runnable
283
* @template CallOptions - Call options type
284
*/
285
class RunnableRetry<RunInput, RunOutput, CallOptions extends RunnableConfig = RunnableConfig> extends Runnable<RunInput, RunOutput, CallOptions> {
286
/** The runnable to retry */
287
bound: Runnable<RunInput, RunOutput, CallOptions>;
288
/** Maximum number of attempts */
289
stopAfterAttempt: number;
290
/** Exponential backoff base */
291
waitExponentialBase: number;
292
293
constructor(fields: {
294
bound: Runnable<RunInput, RunOutput, CallOptions>;
295
stopAfterAttempt?: number;
296
waitExponentialBase?: number;
297
});
298
}
299
```
300
301
### Runnable With Fallbacks
302
303
Provide fallback runnables in case of failure.
304
305
```typescript { .api }
306
/**
307
* Runnable with fallback options on failure
308
* @template RunInput - Input type
309
* @template RunOutput - Output type
310
*/
311
class RunnableWithFallbacks<RunInput, RunOutput> extends Runnable<RunInput, RunOutput> {
312
/** Primary runnable to try first */
313
runnable: Runnable<RunInput, RunOutput>;
314
/** Fallback runnables to try on failure */
315
fallbacks: Runnable<RunInput, RunOutput>[];
316
317
constructor(fields: {
318
runnable: Runnable<RunInput, RunOutput>;
319
fallbacks: Runnable<RunInput, RunOutput>[];
320
});
321
}
322
```
323
324
### Runnable Each
325
326
Apply a runnable to each item in an array input.
327
328
```typescript { .api }
329
/**
330
* Apply a runnable to each item in an array
331
* @template RunInput - Type of each array item
332
* @template RunOutput - Type of output for each item
333
*/
334
class RunnableEach<RunInput, RunOutput> extends Runnable<RunInput[], RunOutput[]> {
335
/** The runnable to apply to each item */
336
bound: Runnable<RunInput, RunOutput>;
337
338
constructor(fields: {
339
bound: Runnable<RunInput, RunOutput>;
340
});
341
}
342
```
343
344
**Usage Examples:**
345
346
```typescript
347
import { RunnableEach, RunnableLambda } from "@langchain/core/runnables";
348
349
// Apply transformation to each item in array
350
const transformer = RunnableLambda.from((x: string) => x.toUpperCase());
351
const eachTransformer = new RunnableEach({ bound: transformer });
352
353
const result = await eachTransformer.invoke(["hello", "world"]);
354
// ["HELLO", "WORLD"]
355
```
356
357
### Runnable Assign
358
359
Assign additional fields to input object.
360
361
```typescript { .api }
362
/**
363
* Assign additional fields to input object
364
* @template RunInput - Input object type
365
*/
366
class RunnableAssign<RunInput extends Record<string, any>> extends Runnable<RunInput, RunInput> {
367
/** Mapping of field names to runnables */
368
mapping: Record<string, Runnable<RunInput>>;
369
370
constructor(mapping: Record<string, RunnableLike<RunInput>>);
371
}
372
```
373
374
**Usage Examples:**
375
376
```typescript
377
import { RunnableAssign, RunnableLambda } from "@langchain/core/runnables";
378
379
// Assign computed fields to input
380
const assign = new RunnableAssign({
381
wordCount: RunnableLambda.from((x: { text: string }) => x.text.split(' ').length),
382
uppercase: RunnableLambda.from((x: { text: string }) => x.text.toUpperCase())
383
});
384
385
const result = await assign.invoke({ text: "hello world" });
386
// { text: "hello world", wordCount: 2, uppercase: "HELLO WORLD" }
387
```
388
389
### Runnable Pick
390
391
Select specific fields from input object.
392
393
```typescript { .api }
394
/**
395
* Pick specific fields from input object
396
* @template RunInput - Input object type
397
* @template K - Keys to pick
398
*/
399
class RunnablePick<RunInput extends Record<string, any>, K extends keyof RunInput> extends Runnable<RunInput, Pick<RunInput, K>> {
400
/** Keys to pick from input */
401
keys: K[];
402
403
constructor(keys: K | K[]);
404
}
405
```
406
407
**Usage Examples:**
408
409
```typescript
410
import { RunnablePick } from "@langchain/core/runnables";
411
412
const picker = new RunnablePick(["name", "age"]);
413
414
const result = await picker.invoke({
415
name: "Alice",
416
age: 30,
417
city: "NYC",
418
country: "USA"
419
});
420
// { name: "Alice", age: 30 }
421
```
422
423
### Router Runnable
424
425
Route execution to different runnables based on input routing logic.
426
427
```typescript { .api }
428
/**
429
* Route to different runnables based on routing logic
430
* @template RunInput - Input type
431
* @template RunOutput - Output type
432
*/
433
class RouterRunnable<RunInput, RunOutput> extends Runnable<RunInput, RunOutput> {
434
/** Routing function to determine which runnable to use */
435
router: (input: RunInput) => string | Promise<string>;
436
/** Map of route names to runnables */
437
runnables: Record<string, Runnable<RunInput, RunOutput>>;
438
/** Default runnable if no route matches */
439
defaultRunnable?: Runnable<RunInput, RunOutput>;
440
441
constructor(fields: {
442
router: (input: RunInput) => string | Promise<string>;
443
runnables: Record<string, Runnable<RunInput, RunOutput>>;
444
defaultRunnable?: Runnable<RunInput, RunOutput>;
445
});
446
}
447
```
448
449
**Usage Examples:**
450
451
```typescript
452
import { RouterRunnable, RunnableLambda } from "@langchain/core/runnables";
453
454
const router = new RouterRunnable({
455
router: (input: { type: string; data: any }) => input.type,
456
runnables: {
457
text: RunnableLambda.from((x) => `Processing text: ${x.data}`),
458
number: RunnableLambda.from((x) => `Number is: ${x.data * 2}`),
459
image: RunnableLambda.from((x) => `Image processing: ${x.data.url}`)
460
},
461
defaultRunnable: RunnableLambda.from(() => "Unknown type")
462
});
463
464
const result = await router.invoke({ type: "text", data: "hello" });
465
// "Processing text: hello"
466
```
467
468
### Runnable With Message History
469
470
Add conversation memory to any runnable.
471
472
```typescript { .api }
473
/**
474
* Add conversation memory to a runnable
475
* @template RunInput - Input type
476
* @template RunOutput - Output type
477
*/
478
class RunnableWithMessageHistory<RunInput, RunOutput> extends Runnable<RunInput, RunOutput> {
479
/** The runnable to wrap with memory */
480
runnable: Runnable<RunInput, RunOutput>;
481
/** Function to get message history for a session */
482
getMessageHistory: (sessionId: string) => BaseChatMessageHistory;
483
/** Function to extract input messages from input */
484
inputMessagesKey?: string | ((input: RunInput) => BaseMessage[]);
485
/** Function to extract history messages from input */
486
historyMessagesKey?: string;
487
/** Function to extract output messages from output */
488
outputMessagesKey?: string | ((output: RunOutput) => BaseMessage[]);
489
490
constructor(fields: {
491
runnable: Runnable<RunInput, RunOutput>;
492
getMessageHistory: (sessionId: string) => BaseChatMessageHistory;
493
inputMessagesKey?: string | ((input: RunInput) => BaseMessage[]);
494
historyMessagesKey?: string;
495
outputMessagesKey?: string | ((output: RunOutput) => BaseMessage[]);
496
});
497
}
498
```
499
500
## Types
501
502
```typescript { .api }
503
interface RunnableConfig {
504
/** Callback handlers for observability */
505
callbacks?: Callbacks;
506
/** Tags for categorizing runs */
507
tags?: string[];
508
/** Additional metadata */
509
metadata?: Record<string, unknown>;
510
/** Human-readable name for the run */
511
runName?: string;
512
/** Configurable parameters */
513
configurable?: Record<string, unknown>;
514
/** Run ID for tracking */
515
runId?: string;
516
}
517
518
interface RunnableBatchOptions {
519
/** Maximum number of concurrent executions */
520
maxConcurrency?: number;
521
/** Whether to return exceptions instead of throwing */
522
returnExceptions?: boolean;
523
}
524
525
type RunnableLike<RunInput, RunOutput> =
526
| Runnable<RunInput, RunOutput>
527
| ((input: RunInput) => RunOutput | Promise<RunOutput>)
528
| ((input: RunInput) => AsyncGenerator<RunOutput>);
529
530
interface RunnableInterface<RunInput, RunOutput> {
531
invoke(input: RunInput, options?: RunnableConfig): Promise<RunOutput>;
532
stream(input: RunInput, options?: RunnableConfig): AsyncGenerator<RunOutput>;
533
batch(inputs: RunInput[], options?: RunnableBatchOptions): Promise<RunOutput[]>;
534
}
535
536
interface RunnableConfigurableFields {
537
[key: string]: {
538
annotation?: string;
539
name?: string;
540
description?: string;
541
default?: unknown;
542
isShared?: boolean;
543
};
544
}
545
546
/**
547
* Ensure config object has required defaults
548
*/
549
function ensureConfig(config?: RunnableConfig): RunnableConfig;
550
551
/**
552
* Merge multiple config objects
553
*/
554
function mergeConfigs(...configs: (RunnableConfig | undefined)[]): RunnableConfig;
555
556
/**
557
* Apply patches to a config object
558
*/
559
function patchConfig(config: RunnableConfig, patch: Partial<RunnableConfig>): RunnableConfig;
560
561
/**
562
* Get callback manager for a given config
563
*/
564
function getCallbackManagerForConfig(config?: RunnableConfig): CallbackManager | undefined;
565
```