Semantic Kernel Chat History Created: 19 Jan 2026 Updated: 19 Jan 2026

Enhancing Prompts with Kernel Arguments

In the world of LLM development, a static prompt is rarely enough. Real-world applications require dynamic context—data that changes based on user input, database records, or application state. In Semantic Kernel, this is achieved through Kernel Arguments.

Kernel Arguments act as a bridge between your application data and your prompt templates, allowing you to inject variables into your instructions seamlessly.

The Power of Dynamic Templates

By using the {{$variableName}} syntax within a string, you create a template. Instead of hardcoding values, you define a structure that Semantic Kernel can "render" at runtime. This approach offers several benefits:

  1. Personalization: Adapt responses based on user profiles.
  2. Reusability: Use the same prompt structure for different data sets.
  3. Separation of Concerns: Keep your prompt logic distinct from your C# logic.

Implementation: The Health & Fitness Assistant

The following code demonstrates how to use KernelArguments to personalize a nutrition assistant. It captures user goals (calories, diet type, and fitness objective) and injects them into both the System Prompt and specific User Queries.

using System.ComponentModel;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var apiKey = Environment.GetEnvironmentVariable("OPEN_AI_KEY");

if (string.IsNullOrEmpty(apiKey))
{
Console.WriteLine("Please set the OPEN_AI_KEY environment variable.");
return;
}

var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(
modelId: "gpt-4o",
apiKey: apiKey)
.Build();

var executionSettings = new OpenAIPromptExecutionSettings
{
Temperature = 0.1,
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};

var chat = kernel.GetRequiredService<IChatCompletionService>();

Console.WriteLine("=== Health & Fitness Assistant ===");
Console.WriteLine("First, let's set up your profile for personalized nutrition advice.\n");

Console.Write("Enter your daily calorie goal (e.g., 2000): ");
var calorieGoal = Console.ReadLine() ?? "2000";

Console.Write("Enter your diet type (e.g., balanced, low-carb, high-protein): ");
var dietType = Console.ReadLine() ?? "balanced";

Console.Write("Enter your fitness goal (e.g., weight loss, muscle gain, maintenance): ");
var fitnessGoal = Console.ReadLine() ?? "maintenance";

// 1. Defining Kernel Arguments
var kernelArguments = new KernelArguments
{
["calorieGoal"] = calorieGoal,
["dietType"] = dietType,
["fitnessGoal"] = fitnessGoal
};

// 2. Defining a Template with {{$variable}} syntax
var systemPromptTemplate = """
You are a professional health and fitness assistant specializing in nutrition analysis.
User Profile:
- Daily Calorie Goal: {{$calorieGoal}} calories
- Diet Type: {{$dietType}}
- Fitness Goal: {{$fitnessGoal}}
When analyzing meals, provide:
1. Estimated calorie count
2. Macronutrients breakdown (protein, carbs, fats)
3. Health rating (1-10) based on user's {{$dietType}} diet
4. Brief recommendations aligned with {{$fitnessGoal}} goal
Keep responses concise and practical.
""";

// 3. Rendering the prompt using the kernel and arguments
var renderedSystemPrompt = await kernel.InvokePromptAsync(systemPromptTemplate, kernelArguments);

List<ChatMessageContent> messages =
[
new(AuthorRole.System, renderedSystemPrompt.ToString()),
new(AuthorRole.User, "I want to track my daily calorie intake. What's my total so far?"),
new(AuthorRole.Assistant,
"Currently, I don't have any meals logged. Please share a photo of your meal or describe what you've eaten today."),
];

var history = new ChatHistory(messages);

Console.WriteLine("\n=== Profile Setup Complete ===");
Console.WriteLine($"Calorie Goal: {calorieGoal} | Diet: {dietType} | Goal: {fitnessGoal}");
Console.WriteLine("\nCommands:");
Console.WriteLine(" - Type 'meal' to analyze a sample meal photo");
Console.WriteLine(" - Ask about nutrition, calories, or fitness tips");
Console.WriteLine(" - Type 'exit' or press Enter to quit.\n");

while (true)
{
Console.Write(" User >>> ");
var prompt = Console.ReadLine();
if (string.IsNullOrEmpty(prompt) || prompt.ToLower() == "exit") break;

if (prompt.ToLower() == "meal")
{
var mealAnalysisPromptTemplate = """
Can you analyze this meal image?
Consider my profile:
- My daily calorie goal is {{$calorieGoal}} calories
- I'm following a {{$dietType}} diet
- My fitness goal is {{$fitnessGoal}}
Please tell me:
1. Estimated calories and if it fits my goal
2. Macronutrients breakdown
3. How well it aligns with my {{$dietType}} diet (1-10)
4. Specific recommendations for my {{$fitnessGoal}} goal
""";
// Re-rendering a specific prompt for meal analysis
var renderedMealPrompt = await kernel.InvokePromptAsync(mealAnalysisPromptTemplate, kernelArguments);
history.AddMessage(AuthorRole.User,
[
new TextContent(renderedMealPrompt.ToString()),
new ImageContent(new Uri("https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=800"))
]);

Console.WriteLine("\n[Analyzing meal photo with your profile...]");
}
else
{
history.AddUserMessage(prompt);
}

Console.Write(" Bot >>> ");
string fullMessage = string.Empty;
await foreach (var token in chat.GetStreamingChatMessageContentsAsync(history, executionSettings, kernel))
{
Console.Write(token.Content);
fullMessage += token.Content;
}

Console.WriteLine("\n");

history.AddAssistantMessage(fullMessage);
}

Console.WriteLine("\n=== Chat History Summary ===");
foreach (var chatMessage in history)
{
Console.WriteLine($"\n{chatMessage.Role}:");

if (chatMessage.Items.Count > 1)
{
foreach (var item in chatMessage.Items)
{
if (item is TextContent textContent)
{
Console.WriteLine($" [Text] {textContent.Text}");
}
else if (item is ImageContent imageContent)
{
Console.WriteLine($" [Image] {imageContent.Uri}");
}
}
}
else
{
Console.WriteLine($" {chatMessage.Content}");
}
}

Key Takeaways

  1. KernelArguments as a Dictionary: The KernelArguments object is essentially a specialized dictionary that the template engine looks into to resolve placeholder tokens.
  2. InvokePromptAsync: This method is the engine that combines the string template with the KernelArguments to produce the final text sent to the LLM.
  3. Consistency Across Turns: Notice how the same kernelArguments object is used for both the system profile and the specific meal analysis prompt. This ensures the AI never loses sight of the user's core goals.
  4. Multi-modal Integration: Dynamic prompts work perfectly alongside other content types, such as ImageContent, allowing for rich, context-aware visual analysis.
Share this lesson: