Microsoft Agent Framework Concept ( Chapter-2) Created: 20 Apr 2026 Updated: 20 Apr 2026

What Are AI Agents? Reasoning, Tools, and Context

An AI agent is a software system that uses a large language model to accomplish an objective. Where a plain chatbot only produces text, an agent decides what to do next, calls external systems to actually do it, and remembers what has happened so far. These three abilities are what separate an agent from a simple prompt–response wrapper around a model.

This article walks through the three pillars that every agent combines — reasoning & decision-making, tool usage, and context awareness — and shows a .NET console demo that illustrates each pillar with a small, dependency-free simulation.

An Agent Is a System That Accomplishes Objectives

The simplest definition: an agent takes a goal in natural language, figures out the steps, executes those steps, and returns a result. The goal can be anything from “summarize this PDF” to “reconcile last month’s invoices.” What makes the system an agent rather than a script is that it does not follow a fixed procedure — it plans the procedure using an LLM.

Internally, an agent runs a loop: look at the current state, decide on the next action, perform it, observe the result, and decide again. The loop ends when the objective is satisfied. Microsoft Agent Framework calls this the default agent runtime execution model.

Pillar 1 — Reasoning & Decision-Making

The “brain” of the agent is the LLM. Given the objective, the conversation so far, and the list of available tools, the model emits a plan: which tool to call next, with which arguments, or whether the objective is already complete. This is the step where the agent chooses what to do.

Typical inputs to reasoning:

  1. System instructions that define scope and style
  2. The user’s objective in natural language
  3. Tool descriptions — name, purpose, parameter schema
  4. Current context — past messages, retrieved knowledge, prior tool results

The model’s output is either a final answer or a structured tool call. When the reasoning produces a tool call, control moves to pillar 2.

Pillar 2 — Tool Usage

A tool is anything the agent can invoke to affect the outside world or fetch fresh information: a C# method, an HTTP API, an MCP server, a database query, a code-execution sandbox. Tools are what let the agent move beyond the model’s training data and take real action.

Common categories of tools:

  1. MCP servers (Model Context Protocol) — a standard way to expose tools to any agent
  2. Code execution — the agent runs code it wrote to answer a question
  3. External APIs — REST, GraphQL, or SDK calls to business systems
  4. Local functions — any method you register with the agent at build time

Tool descriptions live alongside the system prompt, so the model sees every available tool every turn and can pick among them. Good descriptions matter: when too many tools share similar purposes, the model picks poorly. In .NET, a tool is just a function — the framework generates its JSON schema from the method signature.

Pillar 3 — Context Awareness

Reasoning plus tools would already beat a chatbot, but without memory every turn starts from zero. Context awareness is what lets an agent answer follow-up questions, reuse earlier results, and draw on knowledge that does not fit in a single prompt.

The three main sources of context:

  1. Chat history & threads — prior user and assistant messages, managed by the agent session
  2. Vector stores & enterprise data — documents retrieved by semantic similarity (the core of RAG)
  3. Knowledge graphs — structured relationships the agent can traverse for precise lookups

In Microsoft Agent Framework, context providers inject this information automatically before each model call, so the agent always sees the latest relevant slice. Tool results from earlier turns are also folded into the next reasoning step, which is how the agent “learns” within a session.

Why the Three Pillars Work Together

Each pillar on its own is limited. Reasoning without tools can only describe what it would do. Tools without reasoning must be wired together by hand. Context without either is just a search box. Combine all three and the agent becomes something meaningfully new: a system that operates autonomously (chooses its own steps), adaptively (reacts to new information mid-task), and intelligently (grounds decisions in prior state and retrieved knowledge).

That is also why agents introduce nondeterminism that traditional software does not have. The same objective can produce different tool sequences on different runs, which means testing, observability, and guardrails matter more, not less, than for deterministic code.

A .NET Demo of the Three Pillars

The demo below is a small antique-restoration workshop agent. It does not call a real LLM — instead, each pillar is implemented with plain C# so you can trace the behavior step by step. The domain is deliberately unfamiliar so the shape of an agent stands out more than the specifics of any one API.

The demo runs three sequential objectives:

  1. Appraise and restore a Victorian pocket watch
  2. Estimate restoration for an Art Deco jewelry box
  3. Revalue the pocket watch after polishing — this one hits the context cache

Watch how the third objective reuses the prior appraisal instead of calling the price tool fresh.

Full Example

namespace MicrosoftAgentFrameworkLesson.ConsoleApp;

// Domain: an antique-restoration workshop agent.
// Purpose: illustrate the three agent pillars — Reasoning & Decision-Making,
// Tool Usage, and Context Awareness — without calling a real LLM.
// Every "AI" step here is deterministic and hand-written so the concept is visible.
public static class WhatAreAgentsDemo
{
public static Task RunAsync()
{
Console.WriteLine("╔══════════════════════════════════════════════════════════╗");
Console.WriteLine("║ What Are Agents? — Three Pillars (Workshop Simulation) ║");
Console.WriteLine("╚══════════════════════════════════════════════════════════╝\n");

WorkshopAgent agent = new();

// A series of restoration requests that arrive over time.
// The agent accumulates context across them.
string[] objectives =
[
"Appraise and restore a 1890s brass pocket watch with a cracked crystal.",
"Estimate restoration for a 1920s walnut jewelry box with a loose hinge.",
"Revalue the same 1890s pocket watch after polishing."
];

foreach (string objective in objectives)
{
agent.Accomplish(objective);
Console.WriteLine(new string('═', 60));
}

Console.WriteLine("\nThe agent combined reasoning, tools, and context to accomplish each objective.");
return Task.CompletedTask;
}
}

// A deliberately small "agent" implementation whose three methods map directly
// to the three pillars in the diagram: Reason → UseTools → RememberContext.
internal sealed class WorkshopAgent
{
// PILLAR 3 — Context Awareness: durable memory across objectives.
private readonly List<string> _history = [];
private readonly Dictionary<string, decimal> _appraisalCache = new(StringComparer.OrdinalIgnoreCase);

public void Accomplish(string objective)
{
Console.WriteLine($"\n► Objective: {objective}\n");

// PILLAR 1 — Reasoning & Decision-Making:
// The agent inspects the objective and decides which tools are needed.
Plan plan = Reason(objective);
Console.WriteLine(" [Reasoning] Selected plan:");
foreach (string step in plan.Steps)
{
Console.WriteLine($" - {step}");
}
Console.WriteLine();

// PILLAR 2 — Tool Usage:
// Each step invokes a concrete tool (a normal C# function).
decimal totalCost = 0;
string itemKey = plan.ItemKey;

if (plan.NeedsEraLookup)
{
string era = EraLookupTool(itemKey);
Console.WriteLine($" [Tool: EraLookup] \"{itemKey}\" → {era}");
}

if (plan.NeedsMaterialLookup)
{
string material = MaterialLookupTool(itemKey);
Console.WriteLine($" [Tool: MaterialLookup] \"{itemKey}\" → {material}");
}

if (plan.NeedsPriceEstimate)
{
// Context-aware: reuse cached appraisal if we've seen this item before.
if (_appraisalCache.TryGetValue(itemKey, out decimal cached))
{
totalCost = cached * 0.9m; // post-polish revaluation discount
Console.WriteLine($" [Context Hit] prior appraisal for \"{itemKey}\" = {cached:C}");
Console.WriteLine($" [Tool: PriceEstimate] revalued at {totalCost:C} (−10% post-polish)");
}
else
{
totalCost = PriceEstimateTool(itemKey);
_appraisalCache[itemKey] = totalCost;
Console.WriteLine($" [Tool: PriceEstimate] {totalCost:C}");
}
}

// PILLAR 3 — Context Awareness: record what we did so future objectives benefit.
string outcome = $"{itemKey} → {totalCost:C}";
_history.Add(outcome);

Console.WriteLine($"\n [Memory] history now has {_history.Count} past job(s):");
foreach (string h in _history)
{
Console.WriteLine($" • {h}");
}
Console.WriteLine($"\n ✓ Objective accomplished.");
}

// ----- Reasoning -----
// In a real agent an LLM produces the plan. Here, a simple rule-based planner
// stands in so the concept is visible without an API key.
private static Plan Reason(string objective)
{
string lower = objective.ToLowerInvariant();
string itemKey =
lower.Contains("pocket watch") ? "1890s brass pocket watch" :
lower.Contains("jewelry box") ? "1920s walnut jewelry box" :
"unknown artifact";

bool revalue = lower.Contains("revalue") || lower.Contains("after polishing");

List<string> steps = [];
if (!revalue) steps.Add("Identify era");
if (!revalue) steps.Add("Identify material");
steps.Add(revalue ? "Revalue against prior appraisal" : "Estimate restoration price");

return new Plan(
ItemKey: itemKey,
Steps: steps,
NeedsEraLookup: !revalue,
NeedsMaterialLookup: !revalue,
NeedsPriceEstimate: true);
}

// ----- Tools (PILLAR 2) -----
// Each method is a "tool the agent can call" — just a normal function.
private static string EraLookupTool(string item) => item switch
{
"1890s brass pocket watch" => "Late Victorian (1890–1901)",
"1920s walnut jewelry box" => "Art Deco (1920–1935)",
_ => "Unknown era"
};

private static string MaterialLookupTool(string item) => item switch
{
"1890s brass pocket watch" => "Brass case, mineral-glass crystal",
"1920s walnut jewelry box" => "American black walnut, brass hinges",
_ => "Unknown material"
};

private static decimal PriceEstimateTool(string item) => item switch
{
"1890s brass pocket watch" => 240.00m,
"1920s walnut jewelry box" => 180.00m,
_ => 0m
};

private sealed record Plan(
string ItemKey,
List<string> Steps,
bool NeedsEraLookup,
bool NeedsMaterialLookup,
bool NeedsPriceEstimate);
}

From Simulation to Real Agent

To turn this skeleton into a Microsoft Agent Framework agent, three things change:

  1. The Reason method is replaced by a call to an LLM (for example, client.AsAIAgent(...) with Microsoft Foundry, Azure OpenAI, or OpenAI)
  2. The tool methods stay almost unchanged — you register them with the agent and the framework handles schema generation and invocation
  3. The dictionary-based memory is replaced by an agent session (for chat history) and optionally a context provider backed by a vector store or knowledge graph

The overall shape — plan, call tools, remember — is the same. That is the mental model the rest of this tutorial series builds on.

Reference

Microsoft Agent Framework overview — Microsoft Learn

What is Microsoft Foundry Agent Service? — Microsoft Learn

AI agent adoption — Microsoft Learn


Share this lesson: