Sequential Execution Patterns
Sequential execution is the foundation of prompt chains. Understanding when and how to use sequential patterns helps you build efficient, reliable workflows.
When to Use Sequential Execution
Sequential execution is appropriate when:
- Steps have dependencies: Each step needs the output of the previous step
- Order matters: The sequence affects the final result
- Context accumulates: Later steps build on earlier context
- Validation is needed: You must verify each step before proceeding
Basic Sequential Pattern
The simplest chain: one step after another.
async function sequentialChain(input) {
const step1Result = await extractData(input);
const step2Result = await analyzeData(step1Result);
const step3Result = await generateReport(step2Result);
return step3Result;
}
Input → Step 1 → Step 2 → Step 3 → Output
Pipeline Pattern
Each step transforms data for the next:
Loading Prompt Playground...
Accumulator Pattern
Build up results across steps:
async function accumulatorChain(input) {
const state = { original: input, results: [] };
// Step 1: Extract themes
const themes = await extractThemes(input);
state.results.push({ step: 'themes', data: themes });
// Step 2: Analyze each theme (uses accumulated context)
for (const theme of themes) {
const analysis = await analyzeTheme(theme, state.results);
state.results.push({ step: 'analysis', theme: theme.name, data: analysis });
}
// Step 3: Synthesize (uses all accumulated results)
const synthesis = await synthesize(state.results);
state.results.push({ step: 'synthesis', data: synthesis });
return state;
}
Reducer Pattern
Combine multiple inputs into one output through sequential reduction:
Loading Prompt Playground...
Validation Chain Pattern
Check each step's output before proceeding:
async function validatedSequence(input) {
// Step 1: Extract
const extracted = await extractStep(input);
if (!validateExtraction(extracted)) {
throw new Error('Extraction validation failed');
}
// Step 2: Transform
const transformed = await transformStep(extracted);
if (!validateTransformation(transformed)) {
throw new Error('Transformation validation failed');
}
// Step 3: Enrich
const enriched = await enrichStep(transformed);
if (!validateEnrichment(enriched)) {
throw new Error('Enrichment validation failed');
}
return enriched;
}
Context Passing Strategies
Full Context Forward
Pass all previous results to each step:
async function fullContextChain(input) {
const context = { input };
context.step1 = await step1(context);
context.step2 = await step2(context);
context.step3 = await step3(context);
return context.step3.result;
}
Selective Context
Pass only what each step needs:
async function selectiveContextChain(input) {
const step1Result = await step1(input);
const step2Result = await step2({
// Only pass what step2 needs
entities: step1Result.entities,
metadata: step1Result.metadata
});
const step3Result = await step3({
// Only pass what step3 needs
summary: step2Result.summary,
originalInput: input // Sometimes need original
});
return step3Result;
}
Context Summarization
Compress context as it accumulates:
Loading Prompt Playground...
Handling Sequential Failures
Stop on First Error
async function stopOnError(steps, input) {
let current = input;
for (const step of steps) {
try {
current = await step(current);
} catch (error) {
return {
success: false,
failedAt: step.name,
error: error.message,
partialResult: current
};
}
}
return { success: true, result: current };
}
Continue on Non-Critical Errors
async function continueOnNonCritical(steps, input) {
let current = input;
const errors = [];
for (const step of steps) {
try {
current = await step(current);
} catch (error) {
if (step.critical) {
throw error; // Stop for critical errors
}
errors.push({ step: step.name, error: error.message });
// Continue with previous result
}
}
return { result: current, warnings: errors };
}
Performance Considerations
Minimize Round Trips
Less efficient: Many small steps
const words = await countWords(text);
const sentences = await countSentences(text);
const paragraphs = await countParagraphs(text);
More efficient: Combined step
const stats = await getTextStatistics(text);
// Returns { words, sentences, paragraphs }
Avoid Unnecessary Processing
async function smartSequence(input) {
const analysis = await quickAnalysis(input);
// Skip expensive step if not needed
if (analysis.complexity === 'low') {
return simpleProcess(input);
}
return fullProcess(input);
}
Exercise: Design a Sequential Chain
Design a complete sequential chain for this scenario:
Loading Prompt Playground...
Key Takeaways
- Sequential execution is appropriate when steps have dependencies
- Use the pipeline pattern for data transformations
- Use the accumulator pattern to build up results
- Use the reducer pattern to combine multiple inputs
- Validate between steps to catch errors early
- Pass only necessary context to manage token usage
- Compress context when it grows too large
- Handle failures appropriately based on step criticality
- Combine steps when possible to minimize latency
Next, we'll explore parallel execution patterns for independent steps.

