Overview
Prompt chaining (sometimes called the Pipeline pattern) is a powerful strategy for handling complex tasks with large language models (LLMs). Instead of relying on a single, monolithic prompt, prompt chaining breaks down a problem into a sequence of smaller, focused steps. Each step is addressed individually, and the output from one prompt is passed as input to the next. This modular approach improves reliability, makes debugging easier, and enables integration with external tools and APIs.
Why Prompt Chaining?
Reduces cognitive load: Each step is simpler and less ambiguous, lowering the chance of errors and hallucinations.
Improves reliability: Sequential decomposition allows for validation and correction at each stage.
Enables tool integration: Each step can interact with external systems, APIs, or databases.
Foundation for agentic systems: Enables multi-step reasoning, planning, and decision-making.
Pattern Example (Three Steps)
Summarize raw material with tight instructions.
Extract structured data (JSON) from the summary.
Compose human-ready content using the structured output.
Assigning a distinct role to each step (e.g., Market Analyst, Trend Analyst, Documentation Writer) helps focus the model and improves output quality.

C# Code Sample: Agent Framework Sequential Chain
Prerequisites
.NET 8+
Azure OpenAI resource & deployed model (e.g., gpt-4o-mini)
Sign in with az login or use an API key credential
NuGet packages (preview):
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Agents.AI.OpenAI --prerelease
using System;
using System.Text.Json;
using Azure.Identity;
using Azure.AI.OpenAI;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.OpenAI;
class Program
{
static async System.Threading.Tasks.Task Main()
{
var endpoint = new Uri("https://<your-azure-openai>.openai.azure.com/");
var modelId = "<your-deployment-or-model-id>";
var client = new AzureOpenAIClient(endpoint, new AzureCliCredential());
AIAgent agent = client
.GetChatClient(modelId)
.CreateAIAgent(instructions:
"You are a disciplined assistant. Follow the user's step-specific instructions exactly.");
var source = @"The new laptop model features a 3.5 GHz octa-core CPU, 16GB RAM, and a 1TB NVMe SSD.
It targets power users, claims 12-hour battery life, and includes Wi-Fi 7.";
string summary = await agent.RunAsync(
"ROLE: Market Analyst.\n" +
"TASK: Summarize the key findings in <=120 words. Stay factual and concise.\n" +
"TEXT:\n" + source);
if (string.IsNullOrWhiteSpace(summary))
throw new InvalidOperationException("Step 1 produced an empty summary.");
string trendsRaw = await agent.RunAsync(
"ROLE: Trend Analyst.\n" +
"TASK: Return ONLY strict JSON. Extract 3 trends with 'name' and 'supportingData'.\n" +
"SCHEMA: { \"trends\": [{\"name\": string, \"supportingData\": string}] }\n" +
"INPUT:\n" + summary);
JsonDocument trendsDoc;
try
{
trendsDoc = JsonDocument.Parse(trendsRaw);
_ = trendsDoc.RootElement.GetProperty("trends");
}
catch (Exception ex)
{
trendsRaw = await agent.RunAsync(
"The previous output was not valid JSON per schema.\n" +
"Return ONLY strict JSON with shape:\n" +
"{ \"trends\": [{\"name\": string, \"supportingData\": string}] }\n" +
"INPUT:\n" + summary);
trendsDoc = JsonDocument.Parse(trendsRaw);
}
var trendsJson = trendsDoc.RootElement.GetProperty("trends").ToString();
string email = await agent.RunAsync(
"ROLE: Expert Documentation Writer.\n" +
"TASK: Draft a concise email (<=150 words) to the marketing team.\n" +
"Include: short intro, bullet list with trend names + supporting data, single CTA line.\n" +
"CONTEXT:\n" +
$"Summary:\n{summary}\n" +
$"Trends (JSON):\n{trendsJson}");
Console.WriteLine("\n--- Summary ---\n" + summary);
Console.WriteLine("\n--- Trends (JSON) ---\n" + trendsRaw);
Console.WriteLine("\n--- Email ---\n" + email);
}
}