Breaking down complex tasks into smaller, discrete steps is one of the best ways to improve the quality of LLM outputs. The blog writer workflow example does this by following the same approach a human would take to write a blog post: conducting research, creating an outline, writing a structured draft, and finally editing that draft.
The Blog Writer workflow consists of the following steps:
GenerateTopics
)WebResearch
)CatalogResearch
)WriteOutline
)WriteDraft
)Editorial
)MatchTone
)# Navigate to the example directory
cd examples/blog-writer
# Install dependencies
pnpm install
# Set your API keys
export ANTHROPIC_API_KEY=<your_anthropic_api_key>
export PERPLEXITY_API_KEY=<your_perplexity_api_key>
# Optional: For catalog search
export GENSX_API_KEY=<your_gensx_api_key>
export GENSX_PROJECT=<your_project_name>
export GENSX_ENV=development
# Run the example
pnpm run start
The workflow demonstrates how to break complex content generation into discrete, manageable steps. Each component has a specific role and produces structured output for the next step:
const WriteBlog = gensx.Workflow("WriteBlog", async (props: WriteBlogProps) => {
// Step 1: Conduct research
const research = await Research({
title: props.title,
prompt: props.prompt,
});
// Step 2: Create outline based on research
const outline = await WriteOutline({
title: props.title,
prompt: props.prompt,
research: research,
});
// Step 3: Write draft based on outline and research
const draft = await WriteDraft({
title: props.title,
prompt: props.prompt,
outline: outline.object,
research: research,
targetWordCount: props.wordCount ?? 1500,
});
// Step 4: Editorial pass to make it more engaging
const finalContent = await Editorial({
title: props.title,
prompt: props.prompt,
draft: draft,
targetWordCount: props.wordCount ?? 1500,
});
return { title: props.title, content: finalContent, metadata: {...} };
});
The Research
component processes multiple research topics in parallel using Promise.all
, combining web research with optional catalog search:
const Research = gensx.Component("Research", async (props: ResearchProps) => {
// Generate research topics
const topicsResult = await GenerateTopics({
title: props.title,
prompt: props.prompt,
});
// Conduct web research in parallel
const webResearchPromises = topicsResult.topics.map((topic) =>
WebResearch({ topic }),
);
const webResearch = await Promise.all(webResearchPromises);
return {
topics: topicsResult.topics,
webResearch: webResearch,
};
});
The WebResearch
component uses Perplexity’s Sonar API to get current information with proper citations:
const WebResearch = gensx.Component(
"WebResearch",
async (props: { topic: string }) => {
const result = await generateText({
model: perplexity("sonar-pro"),
prompt: `Research the following topic comprehensively: ${props.topic}
Provide detailed, current information with proper citations.`,
});
return {
topic: props.topic,
content: result.text,
citations: result.response.citations || [],
source: "perplexity",
};
},
);
Components can use tools to gather additional information during generation. The WriteSection
component includes a web research tool for section-specific information:
const webResearchTool = tool({
description: "Conduct additional web research on a specific topic",
parameters: z.object({
topic: z.string().describe("The specific topic to research"),
}),
execute: async ({ topic }: { topic: string }) => {
const result = await WebResearch({ topic });
return {
topic: result.topic,
content: result.content,
citations: result.citations,
source: result.source,
};
},
});
Check out the other examples in the GenSX Github Repo .