Logo
Guide

Basic Usage

Learn how to use the LlamaIndex workflow.

A Workflow in LlamaIndex.TS is an event-driven abstraction used to chain together several events. Workflows are made up of steps, with each step responsible for handling certain event types and emitting new events.

Workflows are designed for any cases that benefit from event-driven programming, not only for LLM and AI tasks.

npm install @llamaindex/workflow

Start from scratch

Let's start from a Hello World workflow.

const :  = { : 0 };
 
const 
const workflow: Workflow<ContextData, string, string>
workflow
= new <, string, string>();

First, we define a workflow with 3 generic types: ContextData, Input, and Output.

In general, ContextData is used to store the shared data between steps, Input is the type of the input event, and Output is the type of the output event.

In you code logic, you should share state between steps via ContextData.

.({
	: [<string>],
	: [<string>]
}, async (, ) => {
	const  = .;
	..++;
	return new (`Hello, ${}!`);
});

In the workflow, we add a step that listens to StartEvent<string> and emits StopEvent<string>.

The step is an async function that takes two arguments: context and event.

context type

PropTypeDefault
data
NonNullable<Data>
-
sendEvent
(event: WorkflowEvent<unknown>) => void
-
requireEvent
<T extends AnyWorkflowEventConstructor>(event: T) => Promise<InstanceType<T>>
-

There are two more properties in HandlerContext:

  • sendEvent: invoke another event in the workflow, other than StartEvent, StopEvent, or the current event. (Or there will have circular reference)
  • requireEvent: wait for a specific event to be emitted.

You can use sendEvent and requireEvent to build complex workflows.

class  extends <string> {}
class  extends <boolean> {}
.({
	: [],
	: []
}, async (...) => {
	// do some analysis
	return new (true);
})
.({
	: [<string>],
	: [<string>]
}, async (, ) => {
	const  = .;
	.(new ('start'));
	..++;
	const {  } = await .();
	return new (`Hello, ${}! Analysis result: ${ ? 'success' : 'fail'}`);
});

For example, you can compile requireEvent with waitUntil in Vercel Functions or Cloudflare Worker

.({
	: [<string>],
	: [<string>]
}, async (, ) => {
	const  = .;
	.(new ('start'));
	..++;
	(.());
	// note that `waitUntil` is not a promise, it will extend the lifetime of the workflow
	// you can wait for some background tasks to finish
	return new (`Hello, ${}!`);
});

Multiple runs

You can run the same workflow multiple times with different inputs.

{
	const  = await .('Alex', );
	.(.); // Hello, Alex!
}
 
{
	const  = await .('World', );
	.(.); // Hello, World!
}

Context is shared between runs, so the counter will be increased.

Ideally, it should be serializable to make sure it can be recovered from HTTP requests or other storage.

Full example

Workflow type

PropTypeDefault
addStep
<const In extends [AnyWorkflowEventConstructor | StartEventConstructor, ...(AnyWorkflowEventConstructor | StopEventConstructor)[]], const Out extends (AnyWorkflowEventConstructor | StopEventConstructor)[]>(parameters: StepParameters<...>, stepFn: (context: HandlerContext<...>, ...events: { [K in keyof In]: InstanceT...
-
hasStep
(stepFn: StepHandler<unknown, [AnyWorkflowEventConstructor | StartEventConstructor<string>], []>) => boolean
-
removeStep
(stepFn: StepHandler<unknown, [AnyWorkflowEventConstructor | StartEventConstructor<string>], []>) => Workflow<ContextData, Start, Stop>
-
run
{ (event: Start | StartEvent<Start>): unknown extends ContextData ? WorkflowContext<Start, Stop, ContextData> : WorkflowContext<...>; <Data extends ContextData>(event: Start | StartEvent<...>, data: Data): WorkflowContext<...>; }
-
recover
(data: ArrayBuffer) => WorkflowContext<Start, Stop, ContextData>
-

WorkflowContext type

PropTypeDefault
strict
() => WorkflowContext<Start, Stop, Data>
-
data
NonNullable<Data>
-
with
<Initial extends Data>(data: Initial) => WorkflowContext<Start, Stop, Initial>
-
then
<TResult1, TResult2 = never>(onfulfilled?: ((value: StopEvent<Stop>) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<...>) | null | undefined) => Promise<...>
-
catch
<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null | undefined) => Promise<StopEvent<Stop> | TResult>
-
finally
(onfinally?: (() => void) | null | undefined) => Promise<never>
-
snapshot
() => ArrayBuffer
-
__@asyncIterator@99
() => AsyncIterableIterator<WorkflowEvent<unknown>>
-
__@toStringTag@101
string
-
Edit on GitHub

Last updated on

On this page