Skip to main content

Command Palette

Search for a command to run...

AI Agentic Design Pattern - Prompt Chaining

in C# with Microsoft Agent Framework

Updated
3 min read
AI Agentic Design Pattern - Prompt Chaining
K

A highly skilled Cloud Solutions Architect with 20+ years of experience in software application development across diverse industries. Offering expertise in Cloud Computing and Artificial Intelligence. Passionate about designing and implementing innovative cloud-based solutions, migrating applications to the cloud, and integrating third-party platforms. Dedicated to collaborating with other developers and contributing to open-source projects to enhance software application functionality and performance

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)

  1. Summarize raw material with tight instructions.

  2. Extract structured data (JSON) from the summary.

  3. 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>"; // e.g., gpt-4o-mini
        var client = new AzureOpenAIClient(endpoint, new AzureCliCredential());

        // General-purpose agent; constrain behavior per step via instructions
        AIAgent agent = client
            .GetChatClient(modelId)
            .CreateAIAgent(instructions:
                "You are a disciplined assistant. Follow the user's step-specific instructions exactly.");

        // Step 1: Summarize
        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.");

        // Step 2: Extract trends as structured JSON
        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)
        {
            // Corrective re-prompt
            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();

        // Step 3: Compose email
        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);
    }
}