Pipelines
Steps
Transform pipeline data with explicit steps.
Steps are the basic unit of a pipeline. Use them for parsing, normalization, enrichment, formatting, and small application-owned decisions.
1. Transform the Input
type TicketInput = {
customer: string;
subject: string;
body: string;
};
const pipeline = new PipelineBuilder<TicketInput>()
.step((ticket) => ({
...ticket,
customer: ticket.customer.trim(),
subject: ticket.subject.trim(),
}))
.step((ticket) => ({
title: ticket.subject.toLowerCase(),
customer: ticket.customer,
wordCount: ticket.body.trim().split(/\s+/).length,
}))
.build();
const result = await pipeline.run({
customer: " Acme Co. ",
subject: " Checkout is failing ",
body: "Enterprise checkout fails after payment retries.",
});The first step receives the run(...) input.
2. Return a New Shape
const pipeline = new PipelineBuilder<number>()
.step((dollars) => Math.round(dollars * 100))
.step((cents) => ({
cents,
formatted: `$${(cents / 100).toFixed(2)}`,
}))
.build();
const price = await pipeline.run(12.5);Each next step receives the value returned by the previous step. In this example, the first step returns cents as a number, then the second step returns an object.
3. Use Async Steps
const pipeline = new PipelineBuilder<{ email: string; subject: string }>()
.step(async (input) => ({
user: await users.findByEmail(input.email),
subject: input.subject,
}))
.step(({ user, subject }) => ({
userId: user.id,
plan: user.plan,
subject,
}))
.build();Async steps are awaited before the next stage runs.
4. Keep Steps Small
Prefer several simple steps over one large function:
const pipeline = new PipelineBuilder<string>()
.step(parseInboundEmail)
.step(normalizeTicketFields)
.step(loadCustomerContext)
.build();Small steps are easier to test and easier to replace with agent, extractor, or retrieval stages later.
