diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 0000000..ab66b16
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,35 @@
+# GitHub Copilot Instructions
+
+## Repository Layout Rules
+
+### Root-level files
+The root of this repository must contain **only**:
+- `README.md` — the main repository readme
+- `LICENSE` — the license file
+
+All other documentation, planning documents, and policy files must be placed in the `docs/` folder at the root of the repository.
+
+### docs/ folder
+The `docs/` folder at the root of the repository is the single location for:
+- Planning documents (e.g., modernization plans, roadmaps)
+- Policy files (e.g., CODE_OF_CONDUCT.md, SECURITY.md, SUPPORT.md)
+- Any other repository-wide documentation that is not a `README.md` or `LICENSE`
+
+**This rule does NOT apply to documentation that belongs to individual samples.**
+Each sample folder (e.g., `02.CreateYourFirstAgent/`, `07.Workflow/`, `09.Cases/`) may contain its own `README.md` and any documentation files specific to that sample.
+
+### Sample folders
+Each numbered chapter folder and its sub-folders may freely contain:
+- `README.md`
+- Sample-specific documentation and assets (images, diagrams, etc.)
+- Code files and project files
+
+### Summary
+
+| Location | Allowed files |
+|---|---|
+| Repo root | `README.md`, `LICENSE` only |
+| `docs/` | All repo-wide docs, plans, and policy files |
+| Any sample/chapter folder | `README.md`, sample-specific docs, code |
+
+When creating new planning documents, policy files, or repository-wide documentation, always place them in `docs/` — never at the repo root.
diff --git a/.gitignore b/.gitignore
index 71d95bd..30f5007 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@
*.userosscache
*.sln.docstates
*.env
+# Note: .NET user-secrets (dotnet user-secrets set ...) are stored outside the
+# repository in your OS user profile and are never committed to git.
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
diff --git a/00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/dotnet-agent-framework-travelagent.csproj b/00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/dotnet-agent-framework-travelagent.csproj
deleted file mode 100644
index 7b3d90f..0000000
--- a/00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/dotnet-agent-framework-travelagent.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- Exe
- net10.0
- dotnet_agent_framework_travelagent
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/00.ForBeginners/02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent/Program.cs b/00.ForBeginners/02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent/Program.cs
deleted file mode 100644
index a641bf5..0000000
--- a/00.ForBeginners/02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent/Program.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.ClientModel;
-using Microsoft.Extensions.AI;
-using Microsoft.Agents.AI;
-using OpenAI;
-using DotNetEnv;
-
-// Load environment variables from .env file
-Env.Load("../../../../.env");
-
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
- ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
- ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
-
-// Configure OpenAI client for GitHub Models
-var openAIOptions = new OpenAIClientOptions()
-{
- Endpoint = new Uri(github_endpoint)
-};
-
-// Agent Tool: Random Destination Generator
-[Description("Provides a random vacation destination.")]
-static string GetRandomDestination()
-{
- var destinations = new List
- {
- "Paris, France",
- "Tokyo, Japan",
- "New York City, USA",
- "Sydney, Australia",
- "Rome, Italy",
- "Barcelona, Spain",
- "Cape Town, South Africa",
- "Rio de Janeiro, Brazil",
- "Bangkok, Thailand",
- "Vancouver, Canada"
- };
- var random = new Random();
- int index = random.Next(destinations.Count);
- return destinations[index];
-}
-
-// Create AI Agent with basic instructions and tool
-AIAgent agent = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions)
- .GetChatClient(github_model_id)
- .AsIChatClient()
- .AsAIAgent(
- name: "BasicAgent",
- instructions: "You are a basic AI Agent that can answer questions and suggest random travel destinations.",
- tools: [AIFunctionFactory.Create((Func)GetRandomDestination)]
- );
-
-// Run agent with standard response
-Console.WriteLine("=== Basic Agent Response ===");
-Console.WriteLine(await agent.RunAsync("Suggest a vacation destination."));
-
-// Run agent with streaming response
-Console.WriteLine("\n=== Streaming Response ===");
-await foreach (var update in agent.RunStreamingAsync("Suggest a vacation destination."))
-{
- Console.Write(update);
-}
-Console.WriteLine();
diff --git a/00.ForBeginners/02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent/dotnet-agent-framework-basicagent.csproj b/00.ForBeginners/02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent/dotnet-agent-framework-basicagent.csproj
deleted file mode 100644
index fe9a539..0000000
--- a/00.ForBeginners/02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent/dotnet-agent-framework-basicagent.csproj
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- Exe
- net10.0
- dotnet_agent_framework_basicagent
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/00.ForBeginners/03-agentic-design-patterns/code_samples/dotnet-agent-framework-basicagent/dotnet-agent-framework-basicagent.csproj b/00.ForBeginners/03-agentic-design-patterns/code_samples/dotnet-agent-framework-basicagent/dotnet-agent-framework-basicagent.csproj
deleted file mode 100644
index fe9a539..0000000
--- a/00.ForBeginners/03-agentic-design-patterns/code_samples/dotnet-agent-framework-basicagent/dotnet-agent-framework-basicagent.csproj
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- Exe
- net10.0
- dotnet_agent_framework_basicagent
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/Program.cs b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/Program.cs
index dfe898b..12cf890 100644
--- a/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/Program.cs
+++ b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/Program.cs
@@ -1,13 +1,12 @@
-using System;
+using System;
using System.ComponentModel;
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
// Tool: Random Destination Generator
[Description("Provides a random vacation destination.")]
@@ -31,11 +30,15 @@ static string GetRandomDestination()
return destinations[index];
}
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
// Configure OpenAI client for GitHub Models
diff --git a/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/README.md b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/README.md
new file mode 100644
index 0000000..13446b0
--- /dev/null
+++ b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/README.md
@@ -0,0 +1,32 @@
+# Tool Use (.NET)
+
+Shows how to build a stateful agent conversation using `AgentSession`. A travel-planning agent uses a custom tool to suggest destinations across multiple sequential turns, demonstrating how session context is preserved between calls.
+
+## What it shows
+- Creating and managing an `AgentSession` for multi-turn conversations
+- Registering and invoking a C# function as an agent tool
+- How the agent autonomously decides when to call a tool based on user input
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/app.cs b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/app.cs
new file mode 100644
index 0000000..5107acf
--- /dev/null
+++ b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/app.cs
@@ -0,0 +1,74 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId c2c7f177-4a84-4250-9357-98122c3f2feb
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.ComponentModel;
+using System.ClientModel;
+using Microsoft.Extensions.AI;
+using Microsoft.Agents.AI;
+using OpenAI;
+using Microsoft.Extensions.Configuration;
+
+// Load environment variables from .env file
+
+// Tool: Random Destination Generator
+[Description("Provides a random vacation destination.")]
+static string GetRandomDestination()
+{
+ var destinations = new List
+ {
+ "Paris, France",
+ "Tokyo, Japan",
+ "New York City, USA",
+ "Sydney, Australia",
+ "Rome, Italy",
+ "Barcelona, Spain",
+ "Cape Town, South Africa",
+ "Rio de Janeiro, Brazil",
+ "Bangkok, Thailand",
+ "Vancouver, Canada"
+ };
+ var random = new Random();
+ int index = random.Next(destinations.Count);
+ return destinations[index];
+}
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
+ ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
+ ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+// Configure OpenAI client for GitHub Models
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint = new Uri(github_endpoint)
+};
+var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
+
+// Create AI Agent with tool integration
+AIAgent agent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ instructions: "You are a helpful AI Agent that can help plan vacations for customers at random destinations.",
+ tools: [AIFunctionFactory.Create((Func)GetRandomDestination)]
+);
+
+// Create conversation thread for context
+AgentSession session = await agent.CreateSessionAsync();
+
+// Run agent with tool invocation
+Console.WriteLine(await agent.RunAsync("Plan me a day trip", session));
+
+// Follow-up request to demonstrate tool re-invocation
+Console.WriteLine(await agent.RunAsync("I don't like that destination. Plan me another vacation.", session));
diff --git a/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/dotnet-agent-framework-ghmodels-tool.csproj b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/dotnet-agent-framework-ghmodels-tool.csproj
index 6e13ec3..cbdaff4 100644
--- a/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/dotnet-agent-framework-ghmodels-tool.csproj
+++ b/00.ForBeginners/04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/dotnet-agent-framework-ghmodels-tool.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,19 +6,25 @@
dotnet_agent_framework_ghmodels_toolenableenable
+ c2c7f177-4a84-4250-9357-98122c3f2feb
-
-
-
+
+
-
-
+
+
+
+
+
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/Program.cs b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/Program.cs
index 2ca52e2..0c84819 100644
--- a/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/Program.cs
+++ b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/Program.cs
@@ -1,4 +1,4 @@
-using System.ClientModel;
+using System.ClientModel;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
@@ -6,13 +6,15 @@
using OpenAI;
using OpenAI.Files;
using OpenAI.VectorStores;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-Env.Load("/Users/lokinfey/Desktop/AOAI/Foundry/Agent-Framework-Samples/.env");
-
-var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
-var deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
// Create an AI Project client and get an OpenAI client that works with the foundry service.
AIProjectClient aiProjectClient = new(
diff --git a/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/README.md b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/README.md
new file mode 100644
index 0000000..ebd4689
--- /dev/null
+++ b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/README.md
@@ -0,0 +1,34 @@
+# Agentic RAG — File Search with Azure AI Foundry (.NET)
+
+Uploads a document to Azure AI Foundry, creates a vector store from it, and attaches a `HostedFileSearchTool` to the agent. The agent answers questions using only the uploaded document's content.
+
+## What it shows
+- Uploading files to Azure AI Foundry and creating a vector store
+- Attaching `HostedFileSearchTool` for retrieval-augmented generation (RAG)
+- Grounding an agent's responses strictly in the uploaded document
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+dotnet user-secrets set "AZURE_AI_MODEL_DEPLOYMENT_NAME" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+> The sample uploads `../document.md` (located in the `05-agentic-rag/code_samples/` folder) to Foundry at startup.
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/app.cs b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/app.cs
new file mode 100644
index 0000000..88d1306
--- /dev/null
+++ b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/app.cs
@@ -0,0 +1,69 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 4e72b0fc-2c2e-4371-9d75-0912883af3f6
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System.ClientModel;
+using Azure.AI.Projects;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using OpenAI;
+using OpenAI.Files;
+using OpenAI.VectorStores;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
+
+// Create an AI Project client and get an OpenAI client that works with the foundry service.
+AIProjectClient aiProjectClient = new(
+ new Uri(endpoint),
+ new AzureCliCredential());
+OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
+
+// Upload the file that contains the data to be used for RAG to the Foundry service.
+OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
+ClientResult uploadResult = await fileClient.UploadFileAsync(
+ filePath: "../document.md",
+ purpose: FileUploadPurpose.Assistants);
+
+#pragma warning disable OPENAI001
+VectorStoreClient vectorStoreClient = openAIClient.GetVectorStoreClient();
+ClientResult vectorStoreCreate = await vectorStoreClient.CreateVectorStoreAsync(options: new VectorStoreCreationOptions()
+{
+ Name = "document-knowledge-base",
+ FileIds = { uploadResult.Value.Id }
+});
+#pragma warning restore OPENAI001
+
+var fileSearchTool = new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreCreate.Value.Id)] };
+
+AIAgent agent = await aiProjectClient
+ .CreateAIAgentAsync(
+ model: deploymentName,
+ name: "dotNETRAGAgent",
+ instructions: @"You are an AI assistant designed to answer user questions using only the information retrieved from the provided document(s).
+ If a user's question cannot be answered using the retrieved context, you must clearly respond:
+ 'I'm sorry, but the uploaded document does not contain the necessary information to answer that question.'
+ Do not answer from general knowledge or reasoning. Do not make assumptions or generate hypothetical explanations.
+ For questions that do have relevant content in the document, respond accurately and cite the document explicitly.",
+ tools: [fileSearchTool]);
+
+AgentSession session = await agent.CreateSessionAsync();
+
+Console.WriteLine(await agent.RunAsync("Can you explain Contoso's travel insurance coverage?", session));
diff --git a/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj
index 767aa18..cdb65b0 100644
--- a/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj
+++ b/00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,21 +7,27 @@
Trueenableenable
+ 4e72b0fc-2c2e-4371-9d75-0912883af3f6
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Models/Plan.cs b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Models/Plan.cs
similarity index 100%
rename from 00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Models/Plan.cs
rename to 00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Models/Plan.cs
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Models/TravelPlan.cs b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Models/TravelPlan.cs
similarity index 100%
rename from 00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Models/TravelPlan.cs
rename to 00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Models/TravelPlan.cs
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Program.cs b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Program.cs
similarity index 83%
rename from 00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Program.cs
rename to 00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Program.cs
index 36d6358..ead18e3 100644
--- a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/Program.cs
+++ b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/Program.cs
@@ -1,21 +1,24 @@
-using System;
+using System;
using System.ClientModel;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
// Configure OpenAI client for GitHub Models
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/README.md b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/README.md
new file mode 100644
index 0000000..c43a4e7
--- /dev/null
+++ b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/README.md
@@ -0,0 +1,32 @@
+# Planning Design (.NET)
+
+Demonstrates the planning agentic design pattern. A planner agent receives a high-level travel request and produces a structured `TravelPlan` JSON object that breaks the task into specialised sub-agent assignments (flights, hotels, activities, etc.).
+
+## What it shows
+- Structured JSON output via `ChatResponseFormatJson` and `AIJsonUtilities.CreateJsonSchema`
+- Using an agent as an orchestrator / router that decomposes tasks for specialist agents
+- Configuring `ChatClientAgentOptions` with a response format schema
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/app.cs b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/app.cs
new file mode 100644
index 0000000..ff9afff
--- /dev/null
+++ b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/app.cs
@@ -0,0 +1,87 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 3bbd10f1-79a7-498e-9aba-1c26488635ae
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.ClientModel;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Microsoft.Extensions.AI;
+using Microsoft.Agents.AI;
+using OpenAI;
+using Microsoft.Extensions.Configuration;
+
+// Load environment variables from .env file
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
+ ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
+ ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+// Configure OpenAI client for GitHub Models
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint = new Uri(github_endpoint)
+};
+var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
+
+// Planning agent configuration
+const string AGENT_NAME = "TravelPlanAgent";
+const string AGENT_INSTRUCTIONS = @"You are an planner agent.
+ Your job is to decide which agents to run based on the user's request.
+ Below are the available agents specialised in different tasks:
+ - FlightBooking: For booking flights and providing flight information
+ - HotelBooking: For booking hotels and providing hotel information
+ - CarRental: For booking cars and providing car rental information
+ - ActivitiesBooking: For booking activities and providing activity information
+ - DestinationInfo: For providing information about destinations
+ - DefaultAgent: For handling general request";
+
+ChatClientAgentOptions agentOptions = new()
+{
+ Name = AGENT_NAME,
+ Description = AGENT_INSTRUCTIONS,
+ ChatOptions = new()
+ {
+ ResponseFormat = ChatResponseFormatJson.ForJsonSchema(
+ schema: AIJsonUtilities.CreateJsonSchema(typeof(TravelPlan)),
+ schemaName: "TravelPlan",
+ schemaDescription: "Travel Plan with main_task and subtasks")
+ }
+};
+
+AIAgent agent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(agentOptions);
+
+Console.WriteLine(await agent.RunAsync("Create a travel plan for a family of 4, with 2 kids, from Singapore to Melbourne"));
+
+// Model classes inlined from Models/Plan.cs and Models/TravelPlan.cs
+
+public class Plan
+{
+ [JsonPropertyName("assigned_agent")]
+ public string? Assigned_agent { get; set; }
+
+ [JsonPropertyName("task_details")]
+ public string? Task_details { get; set; }
+}
+
+public class TravelPlan
+{
+ [JsonPropertyName("main_task")]
+ public string? Main_task { get; set; }
+
+ [JsonPropertyName("subtasks")]
+ public IList Subtasks { get; set; } = [];
+}
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/dotnet-agent-framework-ghmodel-planningdesign.csproj b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/dotnet-agent-framework-ghmodel-planningdesign.csproj
new file mode 100644
index 0000000..13be066
--- /dev/null
+++ b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/dotnet-agent-framework-ghmodel-planningdesign.csproj
@@ -0,0 +1,30 @@
+
+
+
+ Exe
+ net10.0
+ dotnet_agent_framework_ghmodel_planningdesign
+ enable
+ enable
+ 3bbd10f1-79a7-498e-9aba-1c26488635ae
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/dotnet-agent-framrwork-ghmodel-planningdesign.csproj b/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/dotnet-agent-framrwork-ghmodel-planningdesign.csproj
deleted file mode 100644
index 831dccf..0000000
--- a/00.ForBeginners/07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign/dotnet-agent-framrwork-ghmodel-planningdesign.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- Exe
- net10.0
- dotnet_agent_framrwork_ghmodel_planningdesign
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/00.ForBeginners/08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents/Program.cs b/00.ForBeginners/08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents/Program.cs
deleted file mode 100644
index 0560289..0000000
--- a/00.ForBeginners/08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents/Program.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using System;
-using System.ClientModel;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using Microsoft.Extensions.AI;
-using Microsoft.Agents.AI;
-using Microsoft.Agents.AI.Workflows;
-using OpenAI;
-using DotNetEnv;
-
-// Load environment variables from .env file
-Env.Load("../../../../.env");
-
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
- ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
- ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
-
-// Configure OpenAI client for GitHub Models
-var openAIOptions = new OpenAIClientOptions()
-{
- Endpoint = new Uri(github_endpoint)
-};
-var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
-
-// Define Concierge Agent (Quality Reviewer)
-const string REVIEWER_NAME = "Concierge";
-const string REVIEWER_INSTRUCTIONS = @"""
- You are an are hotel concierge who has opinions about providing the most local and authentic experiences for travelers.
- The goal is to determine if the front desk travel agent has recommended the best non-touristy experience for a traveler.
- If so, state that it is approved.
- If not, provide insight on how to refine the recommendation without using a specific example.
- """;
-
-// Define Front Desk Agent (Travel Specialist)
-const string FRONTDESK_NAME = "FrontDesk";
-const string FRONTDESK_INSTRUCTIONS = @"""
- You are a Front Desk Travel Agent with ten years of experience and are known for brevity as you deal with many customers.
- The goal is to provide the best activities and locations for a traveler to visit.
- Only provide a single recommendation per response.
- You're laser focused on the goal at hand.
- Don't waste time with chit chat.
- Consider suggestions when refining an idea.
- """;
-
-// Configure agent options
-ChatClientAgentOptions frontdeskAgentOptions = new()
-{
- Name = FRONTDESK_NAME,
- Description = FRONTDESK_INSTRUCTIONS
-};
-
-ChatClientAgentOptions reviewerAgentOptions = new()
-{
- Name = REVIEWER_NAME,
- Description = REVIEWER_INSTRUCTIONS
-};
-
-// Create agent instances
-AIAgent reviewerAgent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(reviewerAgentOptions);
-AIAgent frontdeskAgent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(frontdeskAgentOptions);
-
-// Build the multi-agent workflow
-var workflow = new WorkflowBuilder(frontdeskAgent)
- .AddEdge(frontdeskAgent, reviewerAgent)
- .Build();
-
-// Start the streaming workflow execution
-StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, "I would like to go to Paris."));
-
-// Send message to start workflow
-await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
-
-// Process streaming workflow events
-string strResult = "";
-await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
-{
- if (evt is AgentResponseUpdateEvent executorComplete)
- {
- strResult += executorComplete.Data;
- Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
- }
-}
-
-// Display final aggregated result
-Console.WriteLine("\n=== Final Result ===");
-Console.WriteLine(strResult);
diff --git a/00.ForBeginners/08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents/dotnet-agent-framework-ghmodel-workflow-multi-agents.csproj b/00.ForBeginners/08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents/dotnet-agent-framework-ghmodel-workflow-multi-agents.csproj
deleted file mode 100644
index fbed7db..0000000
--- a/00.ForBeginners/08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents/dotnet-agent-framework-ghmodel-workflow-multi-agents.csproj
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- Exe
- net10.0
- dotnet_agent_framework_ghmodel_workflow_multi_agents
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/00.ForBeginners/README.md b/00.ForBeginners/README.md
index eae8fd6..6dfed33 100644
--- a/00.ForBeginners/README.md
+++ b/00.ForBeginners/README.md
@@ -13,35 +13,35 @@ Learn the foundational concepts of AI agents and get started with your first Mic
**Code Samples:**
- **Python:** [`python-agent-framework-travelagent.ipynb`](./01-intro-to-ai-agents/code_samples/python-agent-framework-travelagent.ipynb)
-- **.NET:** [`dotnet-agent-framework-travelagent.ipynb`](./01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent.ipynb)
+- **.NET:** [`dotnet-travelagent-ghmodel/`](../02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/)
### 02. Explore Agentic Frameworks
Dive deeper into the Microsoft Agent Framework architecture and understand different implementation patterns.
**Code Samples:**
- **Python:** [`python-agent-framework-basicagent.ipynb`](./02-explore-agentic-frameworks/code_samples/python-agent-framework-basicagent.ipynb)
-- **.NET:** [`dotnet-agent-framework-basicagent.ipynb`](./02-explore-agentic-frameworks/code_samples/dotnet-agent-framework-basicagent.ipynb)
+- **.NET:** [`02-dotnet-agent-framework-ghmodel/`](../03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/)
### 03. Agentic Design Patterns
Explore common design patterns and best practices for building robust AI agents with GitHub Models integration.
**Code Samples:**
- **Python:** [`python-agent-framework-ghmodel-basicagent.ipynb`](./03-agentic-design-patterns/code_samples/python-agent-framework-ghmodel-basicagent.ipynb)
-- **.NET:** [`dotnet-agent-framework-ghmodel-basicagent.ipynb`](./03-agentic-design-patterns/code_samples/dotnet-agent-framework-ghmodel-basicagent.ipynb)
+- **.NET:** [`02-dotnet-agent-framework-ghmodel/`](../03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/)
### 04. Tool Use and Integration
Learn how to enhance your agents with external tools and capabilities using GitHub Models.
**Code Samples:**
- **Python:** [`python-agent-framework-ghmodel-tools.ipynb`](./04-tool-use/code_samples/python-agent-framework-ghmodel-tools.ipynb)
-- **.NET:** [`dotnet-agent-framework-ghmodels-tool.ipynb`](./04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool.ipynb)
+- **.NET:** [`dotnet-agent-framework-ghmodels-tool/`](./04-tool-use/code_samples/dotnet-agent-framework-ghmodels-tool/)
### 05. Agentic RAG (Retrieval-Augmented Generation)
Implement knowledge-enhanced agents using Azure AI Foundry's file search capabilities.
**Code Samples:**
- **Python:** [`python-agent-framework-aifoundry-file-search.ipynb`](./05-agentic-rag/code_samples/python-agent-framework-aifoundry-file-search.ipynb)
-- **.NET:** [`dotnet-agent-framework-aifoundry-file-search.ipynb`](./05-agentic-rag/code_samples/dotnet-agent-framework-aifoundry-file-search.ipynb)
+- **.NET:** [`dotnet-agent-framework-msfoundry-file-search/`](./05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/)
**Supporting Files:**
- [`document.md`](./05-agentic-rag/code_samples/document.md) - Sample document for RAG demonstrations
@@ -51,14 +51,14 @@ Explore advanced planning capabilities and design patterns with GitHub Models in
**Code Samples:**
- **Python:** [`python-agent-framrwork-ghmodel-planningdesign.ipynb`](./07-planning-design/code_samples/python-agent-framrwork-ghmodel-planningdesign.ipynb)
-- **.NET:** [`dotnet-agent-framrwork-ghmodel-planningdesign.ipynb`](./07-planning-design/code_samples/dotnet-agent-framrwork-ghmodel-planningdesign.ipynb)
+- **.NET:** [`dotnet-agent-framework-ghmodel-planningdesign`](./07-planning-design/code_samples/dotnet-agent-framework-ghmodel-planningdesign/)
### 08. Multi-Agent Systems
Build collaborative multi-agent workflows using GitHub Models for complex problem-solving scenarios.
**Code Samples:**
- **Python:** [`python-agent-framework-ghmodel-workflow-multi-agents.ipynb`](./08-multi-agent/code_samples/python-agent-framework-ghmodel-workflow-multi-agents.ipynb)
-- **.NET:** [`dotnet-agent-framework-ghmodel-workflow-multi-agents.ipynb`](./08-multi-agent/code_samples/dotnet-agent-framework-ghmodel-workflow-multi-agents.ipynb)
+- **.NET:** [`01.dotnet-agent-framework-workflow-ghmodel-basic/`](../07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/)
### 09. Metacognition
*Coming Soon* - Advanced metacognitive capabilities for self-aware agents.
diff --git a/01.AgentFoundation/README.md b/01.AgentFoundation/README.md
index d6856a0..d857f89 100644
--- a/01.AgentFoundation/README.md
+++ b/01.AgentFoundation/README.md
@@ -39,4 +39,37 @@ This framework is the spiritual successor and consolidation of learnings from pi
The Microsoft Agent Framework is designed to be the foundational layer for the next generation of intelligent, autonomous systems, making agent development more accessible and powerful than ever before.
+## Code Samples
+
+### .NET
+
+| Sample | Description |
+|--------|-------------|
+| [dotnet-agent-foundation](./code_samples/dotNET/dotnet-agent-foundation/) | Annotated "anatomy of an agent" walkthrough covering all four building blocks: `IChatClient`, `AIAgent`, Tools, and `AgentSession` (multi-turn). Backed by GitHub Models. |
+
+#### Prerequisites
+
+- .NET 10 SDK
+- [GitHub Personal Access Token](https://github.com/settings/tokens) with no special scopes (for GitHub Models)
+
+#### Setup
+
+```bash
+cd 01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation
+
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+#### Run
+
+```bash
+# Option 1 — file-based (no project required):
+dotnet run app.cs
+
+# Option 2 — project-based:
+dotnet run
+```
+
diff --git a/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/Program.cs b/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/Program.cs
new file mode 100644
index 0000000..04aa4da
--- /dev/null
+++ b/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/Program.cs
@@ -0,0 +1,170 @@
+// ============================================================
+// ANATOMY OF A MICROSOFT AGENT FRAMEWORK AGENT
+// This sample walks through every building block of an agent,
+// annotated step-by-step.
+// ============================================================
+
+using System.ClientModel;
+using System.ComponentModel;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+using OpenAI;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var githubEndpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var githubModel = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var githubToken = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+// ============================================================
+// BUILDING BLOCK 1 — IChatClient
+// ============================================================
+// An IChatClient is the raw connection to the language model.
+// It speaks the chat-completion protocol (send messages, get a reply).
+// The Microsoft Agent Framework wraps any IChatClient into an AIAgent.
+// Here we create one backed by GitHub Models (OpenAI-compatible endpoint).
+// ============================================================
+
+var openAIOptions = new OpenAIClientOptions { Endpoint = new Uri(githubEndpoint) };
+IChatClient chatClient = new OpenAIClient(new ApiKeyCredential(githubToken), openAIOptions)
+ .GetChatClient(githubModel)
+ .AsIChatClient(); // converts OpenAI ChatClient → Microsoft.Extensions.AI IChatClient
+
+// ============================================================
+// BUILDING BLOCK 2 — AIAgent
+// ============================================================
+// AIAgent is the core abstraction in the Microsoft Agent Framework.
+// It adds on top of IChatClient:
+// • A name — identifies the agent in logs and multi-agent workflows
+// • Instructions — the system prompt, shapes the agent's behavior
+// • Tools — .NET functions the model can call autonomously
+// ============================================================
+
+AIAgent agent = chatClient.AsAIAgent(
+ name: "FactBot",
+ instructions: """
+ You are a concise fact assistant that answers questions about world capitals
+ and major landmarks. Reply in 2-3 sentences maximum. If asked for a
+ random city, call the GetRandomCity tool first.
+ """
+);
+
+Console.WriteLine("=== BUILDING BLOCK 2: Basic AIAgent ===");
+Console.WriteLine("Agent created. Name: FactBot");
+Console.WriteLine();
+
+// ============================================================
+// EXECUTION PATTERN 1 — RunAsync (single-turn)
+// ============================================================
+// RunAsync sends a single user message and returns the complete
+// response as a string. No conversation state is kept.
+// ============================================================
+
+Console.WriteLine("=== EXECUTION PATTERN 1: RunAsync (single-turn) ===");
+var response = await agent.RunAsync("What is the capital of Japan, and what is it known for?");
+Console.WriteLine(response);
+Console.WriteLine();
+
+// ============================================================
+// EXECUTION PATTERN 2 — RunStreamingAsync (single-turn, streaming)
+// ============================================================
+// RunStreamingAsync yields text tokens as they are produced by
+// the model. Use this when you want to display output progressively,
+// e.g., in a UI or CLI that should feel responsive.
+// ============================================================
+
+Console.WriteLine("=== EXECUTION PATTERN 2: RunStreamingAsync (streaming) ===");
+await foreach (var token in agent.RunStreamingAsync("What is the Eiffel Tower?"))
+{
+ Console.Write(token);
+}
+Console.WriteLine();
+Console.WriteLine();
+
+// ============================================================
+// BUILDING BLOCK 3 — Tools
+// ============================================================
+// Tools are ordinary .NET methods the agent can call automatically.
+// Two conventions make a method a tool:
+// 1. [Description("...")] attribute — passed to the model as the
+// tool's description so it knows when and how to call it.
+// 2. AIFunctionFactory.Create(func) — wraps the method into an
+// AIFunction that the agent framework can register and invoke.
+// The model decides when to call a tool; the framework handles the
+// actual invocation and sends the result back to the model.
+// ============================================================
+
+[Description("Returns a random world capital city to use as a topic.")]
+static string GetRandomCity()
+{
+ string[] cities = ["Tokyo", "Paris", "Cairo", "Sydney", "Rio de Janeiro", "Toronto", "Berlin"];
+ return cities[Random.Shared.Next(cities.Length)];
+}
+
+AIAgent agentWithTools = chatClient.AsAIAgent(
+ name: "FactBotWithTools",
+ instructions: """
+ You are a concise fact assistant. When asked for a random city or topic,
+ call GetRandomCity first, then provide 2-3 interesting facts about it.
+ """,
+ tools: [AIFunctionFactory.Create((Func)GetRandomCity)]
+);
+
+Console.WriteLine("=== BUILDING BLOCK 3: Agent with Tools ===");
+var toolResponse = await agentWithTools.RunAsync("Give me facts about a random city.");
+Console.WriteLine(toolResponse);
+Console.WriteLine();
+
+// ============================================================
+// BUILDING BLOCK 4 — AgentSession (multi-turn conversation)
+// ============================================================
+// An AgentSession holds the conversation history for one thread.
+// Passing the same session to successive RunAsync calls means the
+// model sees all prior messages, enabling follow-up questions and
+// context-aware replies.
+//
+// Without a session, each RunAsync is stateless — the model has
+// no memory of previous messages.
+// ============================================================
+
+Console.WriteLine("=== BUILDING BLOCK 4: AgentSession (multi-turn) ===");
+
+AgentSession session = await agentWithTools.CreateSessionAsync();
+
+var turn1 = await agentWithTools.RunAsync("Tell me about a random city.", session);
+Console.WriteLine($"Turn 1: {turn1}");
+Console.WriteLine();
+
+// The agent remembers which city it just mentioned — no need to repeat it.
+var turn2 = await agentWithTools.RunAsync("What is the local cuisine like there?", session);
+Console.WriteLine($"Turn 2: {turn2}");
+Console.WriteLine();
+
+var turn3 = await agentWithTools.RunAsync("And what time zone is it in?", session);
+Console.WriteLine($"Turn 3: {turn3}");
+Console.WriteLine();
+
+// ============================================================
+// SUMMARY
+// ============================================================
+// The four building blocks compose a full agent:
+//
+// IChatClient — connection to the model
+// ↓
+// AIAgent — adds name, instructions, tools
+// ↓
+// Tools — .NET functions the model can call
+// ↓
+// AgentSession — maintains conversation history (multi-turn)
+//
+// From here, the next step is to explore multiple agents working
+// together in a Workflow (see 07.Workflow) or different providers
+// (see 03.ExploreAgentFramework).
+// ============================================================
+
+Console.WriteLine("=== Summary ===");
+Console.WriteLine("The four building blocks: IChatClient → AIAgent → Tools → AgentSession");
diff --git a/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/app.cs b/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/app.cs
new file mode 100644
index 0000000..be421b2
--- /dev/null
+++ b/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/app.cs
@@ -0,0 +1,180 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId e9f0a1b2-c3d4-5e6f-7890-abcdef012345
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+// ============================================================
+// ANATOMY OF A MICROSOFT AGENT FRAMEWORK AGENT
+// This sample walks through every building block of an agent,
+// annotated step-by-step.
+// ============================================================
+
+using System.ClientModel;
+using System.ComponentModel;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+using OpenAI;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var githubEndpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var githubModel = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var githubToken = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+// ============================================================
+// BUILDING BLOCK 1 — IChatClient
+// ============================================================
+// An IChatClient is the raw connection to the language model.
+// It speaks the chat-completion protocol (send messages, get a reply).
+// The Microsoft Agent Framework wraps any IChatClient into an AIAgent.
+// Here we create one backed by GitHub Models (OpenAI-compatible endpoint).
+// ============================================================
+
+var openAIOptions = new OpenAIClientOptions { Endpoint = new Uri(githubEndpoint) };
+IChatClient chatClient = new OpenAIClient(new ApiKeyCredential(githubToken), openAIOptions)
+ .GetChatClient(githubModel)
+ .AsIChatClient(); // converts OpenAI ChatClient → Microsoft.Extensions.AI IChatClient
+
+// ============================================================
+// BUILDING BLOCK 2 — AIAgent
+// ============================================================
+// AIAgent is the core abstraction in the Microsoft Agent Framework.
+// It adds on top of IChatClient:
+// • A name — identifies the agent in logs and multi-agent workflows
+// • Instructions — the system prompt, shapes the agent's behavior
+// • Tools — .NET functions the model can call autonomously
+// ============================================================
+
+AIAgent agent = chatClient.AsAIAgent(
+ name: "FactBot",
+ instructions: """
+ You are a concise fact assistant that answers questions about world capitals
+ and major landmarks. Reply in 2-3 sentences maximum. If asked for a
+ random city, call the GetRandomCity tool first.
+ """
+);
+
+Console.WriteLine("=== BUILDING BLOCK 2: Basic AIAgent ===");
+Console.WriteLine("Agent created. Name: FactBot");
+Console.WriteLine();
+
+// ============================================================
+// EXECUTION PATTERN 1 — RunAsync (single-turn)
+// ============================================================
+// RunAsync sends a single user message and returns the complete
+// response as a string. No conversation state is kept.
+// ============================================================
+
+Console.WriteLine("=== EXECUTION PATTERN 1: RunAsync (single-turn) ===");
+var response = await agent.RunAsync("What is the capital of Japan, and what is it known for?");
+Console.WriteLine(response);
+Console.WriteLine();
+
+// ============================================================
+// EXECUTION PATTERN 2 — RunStreamingAsync (single-turn, streaming)
+// ============================================================
+// RunStreamingAsync yields text tokens as they are produced by
+// the model. Use this when you want to display output progressively,
+// e.g., in a UI or CLI that should feel responsive.
+// ============================================================
+
+Console.WriteLine("=== EXECUTION PATTERN 2: RunStreamingAsync (streaming) ===");
+await foreach (var token in agent.RunStreamingAsync("What is the Eiffel Tower?"))
+{
+ Console.Write(token);
+}
+Console.WriteLine();
+Console.WriteLine();
+
+// ============================================================
+// BUILDING BLOCK 3 — Tools
+// ============================================================
+// Tools are ordinary .NET methods the agent can call automatically.
+// Two conventions make a method a tool:
+// 1. [Description("...")] attribute — passed to the model as the
+// tool's description so it knows when and how to call it.
+// 2. AIFunctionFactory.Create(func) — wraps the method into an
+// AIFunction that the agent framework can register and invoke.
+// The model decides when to call a tool; the framework handles the
+// actual invocation and sends the result back to the model.
+// ============================================================
+
+[Description("Returns a random world capital city to use as a topic.")]
+static string GetRandomCity()
+{
+ string[] cities = ["Tokyo", "Paris", "Cairo", "Sydney", "Rio de Janeiro", "Toronto", "Berlin"];
+ return cities[Random.Shared.Next(cities.Length)];
+}
+
+AIAgent agentWithTools = chatClient.AsAIAgent(
+ name: "FactBotWithTools",
+ instructions: """
+ You are a concise fact assistant. When asked for a random city or topic,
+ call GetRandomCity first, then provide 2-3 interesting facts about it.
+ """,
+ tools: [AIFunctionFactory.Create((Func)GetRandomCity)]
+);
+
+Console.WriteLine("=== BUILDING BLOCK 3: Agent with Tools ===");
+var toolResponse = await agentWithTools.RunAsync("Give me facts about a random city.");
+Console.WriteLine(toolResponse);
+Console.WriteLine();
+
+// ============================================================
+// BUILDING BLOCK 4 — AgentSession (multi-turn conversation)
+// ============================================================
+// An AgentSession holds the conversation history for one thread.
+// Passing the same session to successive RunAsync calls means the
+// model sees all prior messages, enabling follow-up questions and
+// context-aware replies.
+//
+// Without a session, each RunAsync is stateless — the model has
+// no memory of previous messages.
+// ============================================================
+
+Console.WriteLine("=== BUILDING BLOCK 4: AgentSession (multi-turn) ===");
+
+AgentSession session = await agentWithTools.CreateSessionAsync();
+
+var turn1 = await agentWithTools.RunAsync("Tell me about a random city.", session);
+Console.WriteLine($"Turn 1: {turn1}");
+Console.WriteLine();
+
+// The agent remembers which city it just mentioned — no need to repeat it.
+var turn2 = await agentWithTools.RunAsync("What is the local cuisine like there?", session);
+Console.WriteLine($"Turn 2: {turn2}");
+Console.WriteLine();
+
+var turn3 = await agentWithTools.RunAsync("And what time zone is it in?", session);
+Console.WriteLine($"Turn 3: {turn3}");
+Console.WriteLine();
+
+// ============================================================
+// SUMMARY
+// ============================================================
+// The four building blocks compose a full agent:
+//
+// IChatClient — connection to the model
+// ↓
+// AIAgent — adds name, instructions, tools
+// ↓
+// Tools — .NET functions the model can call
+// ↓
+// AgentSession — maintains conversation history (multi-turn)
+//
+// From here, the next step is to explore multiple agents working
+// together in a Workflow (see 07.Workflow) or different providers
+// (see 03.ExploreAgentFramework).
+// ============================================================
+
+Console.WriteLine("=== Summary ===");
+Console.WriteLine("The four building blocks: IChatClient → AIAgent → Tools → AgentSession");
diff --git a/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/dotnet-agent-foundation.csproj b/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/dotnet-agent-foundation.csproj
new file mode 100644
index 0000000..439e183
--- /dev/null
+++ b/01.AgentFoundation/code_samples/dotNET/dotnet-agent-foundation/dotnet-agent-foundation.csproj
@@ -0,0 +1,33 @@
+
+
+
+ Exe
+ net10.0
+ dotnet_agent_foundation
+ enable
+ enable
+ e9f0a1b2-c3d4-5e6f-7890-abcdef012345
+ $(NoWarn);CA1812;OPENAI001;MEAI001
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/Program.cs b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/Program.cs
index 9982074..f0b8600 100644
--- a/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/Program.cs
+++ b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/Program.cs
@@ -1,19 +1,22 @@
-using System;
+using System;
using System.ComponentModel;
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
?? throw new InvalidOperationException("GITHUB_ENDPOINT is required");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
?? throw new InvalidOperationException("GITHUB_TOKEN is required");
// Configure OpenAI client for GitHub Models
diff --git a/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/README.md b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/README.md
new file mode 100644
index 0000000..305f322
--- /dev/null
+++ b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/README.md
@@ -0,0 +1,34 @@
+# Travel Agent — Create Your First Agent (.NET)
+
+> **Maintainer note:** This sample is structurally identical to [`00.ForBeginners/01-intro-to-ai-agents/…/dotnet-agent-framework-travelagent`](../../../../00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/). Consider differentiating them conceptually (e.g., expand this one with session memory, multi-turn conversation, or a richer tool set) or consolidating into a single canonical sample.
+
+A hands-on "Hello World" for the Microsoft Agent Framework. Builds a travel-planning agent backed by **GitHub Models**, attaches a destination-picker tool, and exercises both awaited and streaming invocation styles.
+
+## What it shows
+- Wiring `OpenAIClient` → `GetChatClient` → `AsIChatClient` → `AsAIAgent` pipeline
+- Providing a named tool via `AIFunctionFactory.Create`
+- `RunAsync` (single response) and `RunStreamingAsync` (token streaming)
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/Program.cs b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/app.cs
similarity index 69%
rename from 00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/Program.cs
rename to 02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/app.cs
index 70686f0..8e1d1d7 100644
--- a/00.ForBeginners/01-intro-to-ai-agents/code_samples/dotnet-agent-framework-travelagent/Program.cs
+++ b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/app.cs
@@ -1,19 +1,32 @@
-using System;
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 72ce6d02-83a5-4d22-8e78-1bd196957158
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
using System.ComponentModel;
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
?? throw new InvalidOperationException("GITHUB_ENDPOINT is required");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
?? throw new InvalidOperationException("GITHUB_TOKEN is required");
// Configure OpenAI client for GitHub Models
diff --git a/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/dotnet-travelagent-ghmodel.csproj b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/dotnet-travelagent-ghmodel.csproj
index 89a07d4..376fa3b 100644
--- a/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/dotnet-travelagent-ghmodel.csproj
+++ b/02.CreateYourFirstAgent/code_samples/dotNET/dotnet-travelagent-ghmodel/dotnet-travelagent-ghmodel.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,18 +6,24 @@
dotnet_travelagent_ghmodelenableenable
+ 72ce6d02-83a5-4d22-8e78-1bd196957158
-
-
-
+
+
-
-
+
+
+
+
+
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/02-dotnet-agent-framework-ghmodel.csproj b/03.ExploerAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/02-dotnet-agent-framework-ghmodel.csproj
deleted file mode 100644
index 31335b7..0000000
--- a/03.ExploerAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/02-dotnet-agent-framework-ghmodel.csproj
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- Exe
- net10.0
- _02_dotnet_agent_framework_ghmodel
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/04-dotnet-agent-framework-foundrylocal.csproj b/03.ExploerAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/04-dotnet-agent-framework-foundrylocal.csproj
deleted file mode 100644
index 901bd66..0000000
--- a/03.ExploerAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/04-dotnet-agent-framework-foundrylocal.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- Exe
- net10.0
- _04_dotnet_agent_framework_foundrylocal
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/03.ExploerAgentFramework/README.md b/03.ExploreAgentFramework/README.md
similarity index 97%
rename from 03.ExploerAgentFramework/README.md
rename to 03.ExploreAgentFramework/README.md
index 1a6d57b..54f9316 100644
--- a/03.ExploerAgentFramework/README.md
+++ b/03.ExploreAgentFramework/README.md
@@ -1,342 +1,342 @@
-# Using the Agent Framework to Connect Different AI Solutions
-
-The Agent Framework provides a unified interface for interacting with various AI models and services. This tutorial demonstrates how to connect to four different AI solutions—Azure OpenAI Service, GitHub Models, Azure AI Foundry, and Foundry Local—using the framework's implementations in both .NET (C\#) and Python.
-
-## Configuration and Setup
-
-Before running any of the examples, you need to configure your environment variables. The framework uses these variables to connect to the different AI endpoints. Create a `.env` file in the root of your project and populate it with the necessary credentials and endpoints.
-
-[cite\_start]You can use the `.env.examples` file as a template[cite: 1]:
-
-```env
-# For GitHub Models
-GITHUB_TOKEN="Your GitHub Models Token"
-GITHUB_ENDPOINT="Your GitHub Models Endpoint"
-GITHUB_MODEL_ID="Your GitHub Model ID"
-
-# For Azure OpenAI Service
-AZURE_OPENAI_ENDPOINT="Your Azure OpenAI Endpoint"
-AZURE_OPENAI_CHAT_DEPLOYMENT_NAME ="Your Azure OpenAI Model Deployment Name"
-
-# For Foundry Local
-FOUNDRYLOCAL_ENDPOINT="http://localhost:5272/v1"
-FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME="Your Local Model Name (e.g., Qwen3-0.6b-cpu)"
-
-# For Azure AI Foundry (Azure AI Studio)
-AZURE_AI_PROJECT_ENDPOINT ="Your Azure AI Foundry Project Endpoint"
-AZURE_AI_MODEL_DEPLOYMENT_NAME ="Your Azure AI Foundry Project Deployment Name"
-```
-
------
-
-## 1\. Connecting to Azure OpenAI Service
-
-This section shows how to use the Agent Framework to connect to models deployed in Azure OpenAI Service.
-
-### Connection Architecture
-
-The framework uses a dedicated `AzureOpenAIClient` to handle authentication and communication with the Azure OpenAI endpoint.
-
-```mermaid
-graph TD
- A[Your Application] --> B{Agent Framework};
- B --> C[AzureOpenAIClient];
- C --> D[Azure OpenAI Service Endpoint];
-```
-
-### .NET / C\# Implementation
-
-The .NET example uses the `Azure.AI.OpenAI` and `Microsoft.Agents.AI` libraries to create a client and run the agent.
-
-1. **Dependencies**: NuGet packages like `Azure.AI.OpenAI`, `Azure.Identity`, and the local `Microsoft.Agents.AI.dll` are required.
-2. **Client Initialization**: The code initializes an `AzureOpenAIClient`, providing the service endpoint and credentials (e.g., `AzureCliCredential`).
-3. **Agent Creation**: The `CreateAIAgent` extension method is called on the chat client to get an agent instance with system instructions.
-4. **Execution**: The agent is run using `RunAsync` or `RunStreamingAsync`.
-
-**Key Code Snippet:**
-
-```csharp
-// Load endpoint and model ID from environment variables
-var aoai_endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
-var aoai_model_id = Environment.GetEnvironmentVariable("AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME");
-
-// Create the agent
-AIAgent agent = new AzureOpenAIClient(
- new Uri(aoai_endpoint),
- new AzureCliCredential())
- .GetChatClient(aoai_model_id)
- .CreateAIAgent("You are a helpful assistant.");
-
-// Run the agent and get a response
-Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework."));
-```
-
-### Python Implementation
-
-The Python example uses the `agent_framework.azure` library to achieve the same result.
-
-1. **Dependencies**: The key libraries are `agent_framework` and `azure-identity`.
-2. **Agent Creation**: The `AzureOpenAIChatClient` is instantiated with a credential object. The `create_agent` method is then called to configure the agent with its instructions.
-3. **Execution**: The `agent.run_stream()` method is used to invoke the agent and stream the response.
-
-**Key Code Snippet:**
-
-```python
-from azure.identity import AzureCliCredential
-from agent_framework.azure import AzureOpenAIChatClient
-
-# Create an agent with Azure CLI credentials
-agent = AzureOpenAIChatClient(credential=AzureCliCredential()).create_agent(
- instructions="You are a helpful weather agent."
-)
-
-query = "Write a haiku about Agent Framework."
-
-# Stream the agent's response
-async for chunk in agent.run_stream(query):
- if chunk.text:
- print(chunk.text, end="", flush=True)
-```
-
------
-
-## 2\. Connecting to GitHub Models
-
-GitHub Models provides an OpenAI-compatible API endpoint. This allows the Agent Framework to use its standard `OpenAIClient` to connect.
-
-### Connection Architecture
-
-The connection is made to the GitHub Models endpoint, which behaves like an OpenAI API.
-
-```mermaid
-graph TD
- A[Your Application] --> B{Agent Framework};
- B --> C[OpenAIClient];
- C --> D[GitHub Models Endpoint];
-```
-
-### .NET / C\# Implementation
-
-The approach is similar to connecting to any OpenAI-compatible service.
-
-1. **Dependencies**: This uses the `Microsoft.Extensions.AI.OpenAI` package and local Agent Framework assemblies.
-2. **Client Initialization**: An `OpenAIClient` is created. The `OpenAIClientOptions` are configured with the GitHub Models endpoint URL, and an `ApiKeyCredential` is used to pass the GitHub token.
-3. **Agent Creation**: The `CreateAIAgent` method is used to instantiate the agent with its system prompt.
-
-**Key Code Snippet:**
-
-```csharp
-// Load connection details from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID");
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN");
-
-// Configure client options with the endpoint
-var openAIOptions = new OpenAIClientOptions()
-{
- Endpoint= new Uri(github_endpoint)
-};
-
-// Create the agent with an API key credential
-AIAgent agent = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions)
- .GetChatClient(github_model_id)
- .CreateAIAgent(instructions:"You are a helpful assistant.");
-
-// Run the agent
-Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework."));
-```
-
-### Python Implementation
-
-The Python example uses the `OpenAIChatClient` from the framework.
-
-1. **Dependencies**: The `agent_framework.openai` and `python-dotenv` libraries are used.
-2. **Client Initialization**: The `OpenAIChatClient` is initialized with the `base_url` pointing to the GitHub endpoint and the `api_key` set to the GitHub token.
-3. **Execution**: A list of `ChatMessage` objects is created and passed to the `client.get_response` method to get a completion.
-
-**Key Code Snippet:**
-
-```python
-import os
-from dotenv import load_dotenv
-from agent_framework import ChatMessage, Role
-from agent_framework.openai import OpenAIChatClient
-
-load_dotenv()
-
-# Initialize the client with GitHub endpoint and token
-client = OpenAIChatClient(
- base_url=os.environ.get("GITHUB_ENDPOINT"),
- api_key=os.environ.get("GITHUB_TOKEN"),
- ai_model_id=os.environ.get("GITHUB_MODEL_ID")
-)
-
-# Prepare the messages and get a response
-messages = [
- ChatMessage(role=Role.SYSTEM, text="You are a helpful assistant."),
- ChatMessage(role=Role.USER, text="Write a haiku about Agent Framework.")
- ]
-response = await client.get_response(messages)
-print(response.messages[0].text)
-```
-
------
-
-## 3\. Connecting to Azure AI Foundry (Azure AI Studio)
-
-Azure AI Foundry allows you to create and manage persistent agents. The Agent Framework provides a client to interact with these stateful agents.
-
-### Connection Architecture
-
-The framework communicates with the Azure AI Project endpoint to interact with specific, persistent agents by name or ID.
-
-```mermaid
-graph TD
- A[Your Application] --> B{Agent Framework};
- B --> C[PersistentAgentsClient];
- C --> D[Azure AI Project Endpoint];
-```
-
-### .NET / C\# Implementation
-
-This example uses the `Azure.AI.Agents.Persistent` client library.
-
-1. **Dependencies**: The primary dependency is the `Azure.AI.Agents.Persistent` NuGet package.
-2. **Client Initialization**: A `PersistentAgentsClient` is created using the Azure AI Project endpoint and a credential.
-3. **Agent Creation/Retrieval**: The code first creates a new persistent agent with `CreateAgentAsync`. The resulting agent metadata is then used to get a runnable `AIAgent` instance with `GetAIAgentAsync`.
-4. **Execution**: Agents in AI Foundry are stateful and operate on threads. A new thread is created with `agent.GetNewThread()`, and the `RunAsync` method is called with both the prompt and the thread.
-
-**Key Code Snippet:**
-
-```csharp
-// Load endpoint and model ID from environment variables
-var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT");
-var azure_foundry_model_id = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME");
-
-// Create the client
-var persistentAgentsClient = new PersistentAgentsClient(azure_foundry_endpoint, new AzureCliCredential());
-
-// Create a new persistent agent
-var agentMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
- model: azure_foundry_model_id,
- name: "Agent-Framework",
- instructions: "You are an AI assistant that helps people find information.");
-
-// Get the agent instance and a new thread for conversation
-AIAgent agent = await persistentAgentsClient.GetAIAgentAsync(agentMetadata.Value.Id);
-AgentThread thread = agent.GetNewThread();
-
-// Run the agent within the context of the thread
-Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework", thread));
-```
-
-### Python Implementation
-
-The Python example uses `AzureAIAgentClient` to interact with persistent agents.
-
-1. **Dependencies**: `agent_framework.azure` and `azure-identity` are required.
-2. **Client Initialization**: The `AzureAIAgentClient` is initialized with an async credential.
-3. **Agent and Thread Management**: Inside an `async with` block, `client.create_agent` defines a persistent agent. A new conversational context is created with `agent.get_new_thread()`.
-4. **Execution**: `agent.run` is called with the query and the thread object.
-
-**Key Code Snippet:**
-
-```python
-from azure.identity.aio import AzureCliCredential
-from agent_framework.azure import AzureAIAgentClient
-
-async with AzureCliCredential() as credential, AzureAIAgentClient(async_credential=credential) as client:
- # Create a persistent agent
- agent = client.create_agent(
- name="AgentDemo",
- instructions="You are a helpful assistant."
- )
-
- # Start a new conversation thread
- thread = agent.get_new_thread()
- query = "Write a haiku about Agent Framework."
-
- # Get the agent's response
- result = await agent.run(query, thread=thread)
- print(f"Agent: {result}\\n")
-```
-
------
-
-## 4\. Connecting to Foundry Local
-
-Foundry Local serves AI models via a local, OpenAI-compatible API. This makes it easy to test agents with local models without needing cloud resources.
-
-### Connection Architecture
-
-The connection pattern is identical to that of GitHub Models, but the endpoint is a local server address.
-
-```mermaid
-graph TD
- A[Your Application] --> B{Agent Framework};
- B --> C[OpenAIClient];
- C --> D[Foundry Local Endpoint (e.g., http://localhost:5272/v1)];
-```
-
-### .NET / C\# Implementation
-
-The code is nearly identical to the GitHub Models example, with changes only to the endpoint, model ID, and API key.
-
-1. **Client Initialization**: The `OpenAIClient` is configured to point to the `FOUNDRYLOCAL_ENDPOINT` (e.g., `http://localhost:5272/v1`).
-2. **Authentication**: Since Foundry Local does not require authentication by default, a dummy API key like `"nokey"` is used.
-
-**Key Code Snippet:**
-
-```csharp
-// Get local endpoint and model ID
-var foundrylocal_endpoint = Environment.GetEnvironmentVariable("FOUNDRYLOCAL_ENDPOINT");
-var foundrylocal_model_id = Environment.GetEnvironmentVariable("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME");
-
-// Configure options to point to the local server
-var openAIOptions = new OpenAIClientOptions()
-{
- Endpoint= new Uri(foundrylocal_endpoint)
-};
-
-// Create the agent with a dummy API key
-AIAgent agent = new OpenAIClient(new ApiKeyCredential("nokey"), openAIOptions)
- .GetChatClient(foundrylocal_model_id)
- .CreateAIAgent(instructions:"You are a helpful assistant.");
-
-// Run the agent
-Console.WriteLine(await agent.RunAsync("Can you introduce yourself?"));
-```
-
-### Python Implementation
-
-The Python code is also very similar to the GitHub example, differing only in the client's connection parameters.
-
-1. **Client Initialization**: The `OpenAIChatClient` is initialized with the `base_url` set to the `FOUNDRYLOCAL_ENDPOINT` from the environment variables.
-2. **Authentication**: The `api_key` is set to `"nokey"`.
-
-**Key Code Snippet:**
-
-```python
-import os
-from dotenv import load_dotenv
-from agent_framework import ChatMessage, Role
-from agent_framework.openai import OpenAIChatClient
-
-load_dotenv()
-
-# Initialize client for Foundry Local
-client = OpenAIChatClient(
- base_url=os.environ.get("FOUNDRYLOCAL_ENDPOINT"),
- api_key="nokey",
- ai_model_id=os.environ.get("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME")
-)
-
-# Prepare messages and execute
-messages = [
- ChatMessage(role=Role.SYSTEM, text="You are a helpful assistant."),
- ChatMessage(role=Role.USER, text="Can you introduce yourself?")
- ]
-
-response = await client.get_response(messages)
-print(response.messages[0].text)
+# Using the Agent Framework to Connect Different AI Solutions
+
+The Agent Framework provides a unified interface for interacting with various AI models and services. This tutorial demonstrates how to connect to four different AI solutions—Azure OpenAI Service, GitHub Models, Azure AI Foundry, and Foundry Local—using the framework's implementations in both .NET (C\#) and Python.
+
+## Configuration and Setup
+
+Before running any of the examples, you need to configure your environment variables. The framework uses these variables to connect to the different AI endpoints. Create a `.env` file in the root of your project and populate it with the necessary credentials and endpoints.
+
+[cite\_start]You can use the `.env.examples` file as a template[cite: 1]:
+
+```env
+# For GitHub Models
+GITHUB_TOKEN="Your GitHub Models Token"
+GITHUB_ENDPOINT="Your GitHub Models Endpoint"
+GITHUB_MODEL_ID="Your GitHub Model ID"
+
+# For Azure OpenAI Service
+AZURE_OPENAI_ENDPOINT="Your Azure OpenAI Endpoint"
+AZURE_OPENAI_CHAT_DEPLOYMENT_NAME ="Your Azure OpenAI Model Deployment Name"
+
+# For Foundry Local
+FOUNDRYLOCAL_ENDPOINT="http://localhost:5272/v1"
+FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME="Your Local Model Name (e.g., Qwen3-0.6b-cpu)"
+
+# For Azure AI Foundry (Azure AI Studio)
+AZURE_AI_PROJECT_ENDPOINT ="Your Azure AI Foundry Project Endpoint"
+AZURE_AI_MODEL_DEPLOYMENT_NAME ="Your Azure AI Foundry Project Deployment Name"
+```
+
+-----
+
+## 1\. Connecting to Azure OpenAI Service
+
+This section shows how to use the Agent Framework to connect to models deployed in Azure OpenAI Service.
+
+### Connection Architecture
+
+The framework uses a dedicated `AzureOpenAIClient` to handle authentication and communication with the Azure OpenAI endpoint.
+
+```mermaid
+graph TD
+ A[Your Application] --> B{Agent Framework};
+ B --> C[AzureOpenAIClient];
+ C --> D[Azure OpenAI Service Endpoint];
+```
+
+### .NET / C\# Implementation
+
+The .NET example uses the `Azure.AI.OpenAI` and `Microsoft.Agents.AI` libraries to create a client and run the agent.
+
+1. **Dependencies**: NuGet packages like `Azure.AI.OpenAI`, `Azure.Identity`, and the local `Microsoft.Agents.AI.dll` are required.
+2. **Client Initialization**: The code initializes an `AzureOpenAIClient`, providing the service endpoint and credentials (e.g., `AzureCliCredential`).
+3. **Agent Creation**: The `CreateAIAgent` extension method is called on the chat client to get an agent instance with system instructions.
+4. **Execution**: The agent is run using `RunAsync` or `RunStreamingAsync`.
+
+**Key Code Snippet:**
+
+```csharp
+// Load endpoint and model ID from environment variables
+var aoai_endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT");
+var aoai_model_id = Environment.GetEnvironmentVariable("AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME");
+
+// Create the agent
+AIAgent agent = new AzureOpenAIClient(
+ new Uri(aoai_endpoint),
+ new AzureCliCredential())
+ .GetChatClient(aoai_model_id)
+ .CreateAIAgent("You are a helpful assistant.");
+
+// Run the agent and get a response
+Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework."));
+```
+
+### Python Implementation
+
+The Python example uses the `agent_framework.azure` library to achieve the same result.
+
+1. **Dependencies**: The key libraries are `agent_framework` and `azure-identity`.
+2. **Agent Creation**: The `AzureOpenAIChatClient` is instantiated with a credential object. The `create_agent` method is then called to configure the agent with its instructions.
+3. **Execution**: The `agent.run_stream()` method is used to invoke the agent and stream the response.
+
+**Key Code Snippet:**
+
+```python
+from azure.identity import AzureCliCredential
+from agent_framework.azure import AzureOpenAIChatClient
+
+# Create an agent with Azure CLI credentials
+agent = AzureOpenAIChatClient(credential=AzureCliCredential()).create_agent(
+ instructions="You are a helpful weather agent."
+)
+
+query = "Write a haiku about Agent Framework."
+
+# Stream the agent's response
+async for chunk in agent.run_stream(query):
+ if chunk.text:
+ print(chunk.text, end="", flush=True)
+```
+
+-----
+
+## 2\. Connecting to GitHub Models
+
+GitHub Models provides an OpenAI-compatible API endpoint. This allows the Agent Framework to use its standard `OpenAIClient` to connect.
+
+### Connection Architecture
+
+The connection is made to the GitHub Models endpoint, which behaves like an OpenAI API.
+
+```mermaid
+graph TD
+ A[Your Application] --> B{Agent Framework};
+ B --> C[OpenAIClient];
+ C --> D[GitHub Models Endpoint];
+```
+
+### .NET / C\# Implementation
+
+The approach is similar to connecting to any OpenAI-compatible service.
+
+1. **Dependencies**: This uses the `Microsoft.Extensions.AI.OpenAI` package and local Agent Framework assemblies.
+2. **Client Initialization**: An `OpenAIClient` is created. The `OpenAIClientOptions` are configured with the GitHub Models endpoint URL, and an `ApiKeyCredential` is used to pass the GitHub token.
+3. **Agent Creation**: The `CreateAIAgent` method is used to instantiate the agent with its system prompt.
+
+**Key Code Snippet:**
+
+```csharp
+// Load connection details from environment variables
+var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT");
+var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID");
+var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN");
+
+// Configure client options with the endpoint
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint= new Uri(github_endpoint)
+};
+
+// Create the agent with an API key credential
+AIAgent agent = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions)
+ .GetChatClient(github_model_id)
+ .CreateAIAgent(instructions:"You are a helpful assistant.");
+
+// Run the agent
+Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework."));
+```
+
+### Python Implementation
+
+The Python example uses the `OpenAIChatClient` from the framework.
+
+1. **Dependencies**: The `agent_framework.openai` and `python-dotenv` libraries are used.
+2. **Client Initialization**: The `OpenAIChatClient` is initialized with the `base_url` pointing to the GitHub endpoint and the `api_key` set to the GitHub token.
+3. **Execution**: A list of `ChatMessage` objects is created and passed to the `client.get_response` method to get a completion.
+
+**Key Code Snippet:**
+
+```python
+import os
+from dotenv import load_dotenv
+from agent_framework import ChatMessage, Role
+from agent_framework.openai import OpenAIChatClient
+
+load_dotenv()
+
+# Initialize the client with GitHub endpoint and token
+client = OpenAIChatClient(
+ base_url=os.environ.get("GITHUB_ENDPOINT"),
+ api_key=os.environ.get("GITHUB_TOKEN"),
+ ai_model_id=os.environ.get("GITHUB_MODEL_ID")
+)
+
+# Prepare the messages and get a response
+messages = [
+ ChatMessage(role=Role.SYSTEM, text="You are a helpful assistant."),
+ ChatMessage(role=Role.USER, text="Write a haiku about Agent Framework.")
+ ]
+response = await client.get_response(messages)
+print(response.messages[0].text)
+```
+
+-----
+
+## 3\. Connecting to Azure AI Foundry (Azure AI Studio)
+
+Azure AI Foundry allows you to create and manage persistent agents. The Agent Framework provides a client to interact with these stateful agents.
+
+### Connection Architecture
+
+The framework communicates with the Azure AI Project endpoint to interact with specific, persistent agents by name or ID.
+
+```mermaid
+graph TD
+ A[Your Application] --> B{Agent Framework};
+ B --> C[PersistentAgentsClient];
+ C --> D[Azure AI Project Endpoint];
+```
+
+### .NET / C\# Implementation
+
+This example uses the `Azure.AI.Agents.Persistent` client library.
+
+1. **Dependencies**: The primary dependency is the `Azure.AI.Agents.Persistent` NuGet package.
+2. **Client Initialization**: A `PersistentAgentsClient` is created using the Azure AI Project endpoint and a credential.
+3. **Agent Creation/Retrieval**: The code first creates a new persistent agent with `CreateAgentAsync`. The resulting agent metadata is then used to get a runnable `AIAgent` instance with `GetAIAgentAsync`.
+4. **Execution**: Agents in AI Foundry are stateful and operate on threads. A new thread is created with `agent.GetNewThread()`, and the `RunAsync` method is called with both the prompt and the thread.
+
+**Key Code Snippet:**
+
+```csharp
+// Load endpoint and model ID from environment variables
+var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT");
+var azure_foundry_model_id = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME");
+
+// Create the client
+var persistentAgentsClient = new PersistentAgentsClient(azure_foundry_endpoint, new AzureCliCredential());
+
+// Create a new persistent agent
+var agentMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
+ model: azure_foundry_model_id,
+ name: "Agent-Framework",
+ instructions: "You are an AI assistant that helps people find information.");
+
+// Get the agent instance and a new thread for conversation
+AIAgent agent = await persistentAgentsClient.GetAIAgentAsync(agentMetadata.Value.Id);
+AgentThread thread = agent.GetNewThread();
+
+// Run the agent within the context of the thread
+Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework", thread));
+```
+
+### Python Implementation
+
+The Python example uses `AzureAIAgentClient` to interact with persistent agents.
+
+1. **Dependencies**: `agent_framework.azure` and `azure-identity` are required.
+2. **Client Initialization**: The `AzureAIAgentClient` is initialized with an async credential.
+3. **Agent and Thread Management**: Inside an `async with` block, `client.create_agent` defines a persistent agent. A new conversational context is created with `agent.get_new_thread()`.
+4. **Execution**: `agent.run` is called with the query and the thread object.
+
+**Key Code Snippet:**
+
+```python
+from azure.identity.aio import AzureCliCredential
+from agent_framework.azure import AzureAIAgentClient
+
+async with AzureCliCredential() as credential, AzureAIAgentClient(async_credential=credential) as client:
+ # Create a persistent agent
+ agent = client.create_agent(
+ name="AgentDemo",
+ instructions="You are a helpful assistant."
+ )
+
+ # Start a new conversation thread
+ thread = agent.get_new_thread()
+ query = "Write a haiku about Agent Framework."
+
+ # Get the agent's response
+ result = await agent.run(query, thread=thread)
+ print(f"Agent: {result}\\n")
+```
+
+-----
+
+## 4\. Connecting to Foundry Local
+
+Foundry Local serves AI models via a local, OpenAI-compatible API. This makes it easy to test agents with local models without needing cloud resources.
+
+### Connection Architecture
+
+The connection pattern is identical to that of GitHub Models, but the endpoint is a local server address.
+
+```mermaid
+graph TD
+ A[Your Application] --> B{Agent Framework};
+ B --> C[OpenAIClient];
+ C --> D[Foundry Local Endpoint (e.g., http://localhost:5272/v1)];
+```
+
+### .NET / C\# Implementation
+
+The code is nearly identical to the GitHub Models example, with changes only to the endpoint, model ID, and API key.
+
+1. **Client Initialization**: The `OpenAIClient` is configured to point to the `FOUNDRYLOCAL_ENDPOINT` (e.g., `http://localhost:5272/v1`).
+2. **Authentication**: Since Foundry Local does not require authentication by default, a dummy API key like `"nokey"` is used.
+
+**Key Code Snippet:**
+
+```csharp
+// Get local endpoint and model ID
+var foundrylocal_endpoint = Environment.GetEnvironmentVariable("FOUNDRYLOCAL_ENDPOINT");
+var foundrylocal_model_id = Environment.GetEnvironmentVariable("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME");
+
+// Configure options to point to the local server
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint= new Uri(foundrylocal_endpoint)
+};
+
+// Create the agent with a dummy API key
+AIAgent agent = new OpenAIClient(new ApiKeyCredential("nokey"), openAIOptions)
+ .GetChatClient(foundrylocal_model_id)
+ .CreateAIAgent(instructions:"You are a helpful assistant.");
+
+// Run the agent
+Console.WriteLine(await agent.RunAsync("Can you introduce yourself?"));
+```
+
+### Python Implementation
+
+The Python code is also very similar to the GitHub example, differing only in the client's connection parameters.
+
+1. **Client Initialization**: The `OpenAIChatClient` is initialized with the `base_url` set to the `FOUNDRYLOCAL_ENDPOINT` from the environment variables.
+2. **Authentication**: The `api_key` is set to `"nokey"`.
+
+**Key Code Snippet:**
+
+```python
+import os
+from dotenv import load_dotenv
+from agent_framework import ChatMessage, Role
+from agent_framework.openai import OpenAIChatClient
+
+load_dotenv()
+
+# Initialize client for Foundry Local
+client = OpenAIChatClient(
+ base_url=os.environ.get("FOUNDRYLOCAL_ENDPOINT"),
+ api_key="nokey",
+ ai_model_id=os.environ.get("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME")
+)
+
+# Prepare messages and execute
+messages = [
+ ChatMessage(role=Role.SYSTEM, text="You are a helpful assistant."),
+ ChatMessage(role=Role.USER, text="Can you introduce yourself?")
+ ]
+
+response = await client.get_response(messages)
+print(response.messages[0].text)
```
\ No newline at end of file
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/01-dotnet-agent-framework-aoai.csproj b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/01-dotnet-agent-framework-aoai.csproj
similarity index 50%
rename from 03.ExploerAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/01-dotnet-agent-framework-aoai.csproj
rename to 03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/01-dotnet-agent-framework-aoai.csproj
index 3ee98a1..3213ed5 100644
--- a/03.ExploerAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/01-dotnet-agent-framework-aoai.csproj
+++ b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/01-dotnet-agent-framework-aoai.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,19 +6,23 @@
_01_dotnet_agent_framework_aoaienableenable
+ 2e421ed5-5bee-47c3-9608-7d42f9dfed00
-
-
+
-
-
-
+
+
+
+
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/Program.cs b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/Program.cs
similarity index 61%
rename from 03.ExploerAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/Program.cs
rename to 03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/Program.cs
index 6669222..46c5803 100644
--- a/03.ExploerAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/Program.cs
+++ b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/Program.cs
@@ -1,13 +1,16 @@
-using Azure.AI.OpenAI;
+using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI.Chat;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
-Env.Load("/Users/lokinfey/Desktop/AOAI/Foundry/Agent-Framework-Samples/.env");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-var aoai_endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
-var aoai_model_id = Environment.GetEnvironmentVariable("AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME") ?? "gpt-4.1-mini";
+var aoai_endpoint = config["AZURE_OPENAI_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
+var aoai_model_id = config["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"] ?? "gpt-4.1-mini";
Console.WriteLine($"Using Azure OpenAI Endpoint: {aoai_endpoint}");
Console.WriteLine($"Using Azure OpenAI Model Deployment: {aoai_model_id}");
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/README.md b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/README.md
new file mode 100644
index 0000000..4deee9d
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/README.md
@@ -0,0 +1,32 @@
+# Agent Framework — Azure OpenAI Provider (.NET)
+
+Shows how to create an `AIAgent` using **Azure OpenAI** as the backing provider, authenticating with `AzureCliCredential`.
+
+## What it shows
+- Constructing an `AIAgent` from `AzureOpenAIClient` (no OpenAI API key required)
+- Passwordless authentication via Azure CLI (`az login`)
+- Standard and streaming responses against an Azure-hosted deployment
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An Azure OpenAI resource with a deployed model
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_OPENAI_ENDPOINT" ""
+dotnet user-secrets set "AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME" "gpt-4.1-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/app.cs b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/app.cs
new file mode 100644
index 0000000..4758c2f
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/01-dotnet-agent-framework-aoai/app.cs
@@ -0,0 +1,39 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 2e421ed5-5bee-47c3-9608-7d42f9dfed00
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using Azure.AI.OpenAI;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using OpenAI.Chat;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var aoai_endpoint = config["AZURE_OPENAI_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
+var aoai_model_id = config["AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME"] ?? "gpt-4.1-mini";
+
+Console.WriteLine($"Using Azure OpenAI Endpoint: {aoai_endpoint}");
+Console.WriteLine($"Using Azure OpenAI Model Deployment: {aoai_model_id}");
+
+AIAgent agent = new AzureOpenAIClient(
+ new Uri(aoai_endpoint),
+ new AzureCliCredential())
+ .GetChatClient(aoai_model_id)
+ .AsAIAgent(instructions: "You are a helpful assistant.", name: "MAFDemoAgent");
+
+
+Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework."));
+
+await foreach (var update in agent.RunStreamingAsync("Write a haiku about Agent Framework."))
+{
+ Console.Write(update);
+}
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/02-dotnet-agent-framework-ghmodel.csproj b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/02-dotnet-agent-framework-ghmodel.csproj
new file mode 100644
index 0000000..e32d83d
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/02-dotnet-agent-framework-ghmodel.csproj
@@ -0,0 +1,29 @@
+
+
+
+ Exe
+ net10.0
+ _02_dotnet_agent_framework_ghmodel
+ enable
+ enable
+ 897b8bea-86e0-456a-a321-9a96d36c8d67
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/Program.cs b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/Program.cs
similarity index 75%
rename from 03.ExploerAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/Program.cs
rename to 03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/Program.cs
index f470491..87c8e0a 100644
--- a/03.ExploerAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/Program.cs
+++ b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/Program.cs
@@ -1,18 +1,21 @@
-using System;
+using System;
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
-// Get configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
// Configure OpenAI client for GitHub Models
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/README.md b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/README.md
new file mode 100644
index 0000000..996941d
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/README.md
@@ -0,0 +1,32 @@
+# Agent Framework — GitHub Models Provider (.NET)
+
+Minimal sample showing `AIAgent` creation with **GitHub Models** as the provider. Demonstrates that switching providers only requires changing the `IChatClient` — the agent API stays the same.
+
+## What it shows
+- Creating an `AIAgent` from `OpenAIClient` pointed at `models.inference.ai.azure.com`
+- Provider-agnostic `RunAsync` / `RunStreamingAsync` invocation
+- How `AsIChatClient()` adapts the OpenAI SDK chat client to `Microsoft.Extensions.AI`
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/00.ForBeginners/03-agentic-design-patterns/code_samples/dotnet-agent-framework-basicagent/Program.cs b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/app.cs
similarity index 69%
rename from 00.ForBeginners/03-agentic-design-patterns/code_samples/dotnet-agent-framework-basicagent/Program.cs
rename to 03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/app.cs
index a641bf5..e09d6b0 100644
--- a/00.ForBeginners/03-agentic-design-patterns/code_samples/dotnet-agent-framework-basicagent/Program.cs
+++ b/03.ExploreAgentFramework/code_samples/dotNET/02-dotnet-agent-framework-ghmodel/app.cs
@@ -1,19 +1,32 @@
-using System;
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 897b8bea-86e0-456a-a321-9a96d36c8d67
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
using System.ComponentModel;
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
-// Get GitHub Models configuration from environment variables
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"]
?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"]
?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
// Configure OpenAI client for GitHub Models
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/03-dotnet-agent-framework-msfoundry.csproj b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/03-dotnet-agent-framework-msfoundry.csproj
similarity index 58%
rename from 03.ExploerAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/03-dotnet-agent-framework-msfoundry.csproj
rename to 03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/03-dotnet-agent-framework-msfoundry.csproj
index 1ca6836..f74a6fe 100644
--- a/03.ExploerAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/03-dotnet-agent-framework-msfoundry.csproj
+++ b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/03-dotnet-agent-framework-msfoundry.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,20 +7,26 @@
Trueenableenable
+ 06e4bd3a-9846-4330-98e5-7e0431118217
-
-
+
+
+
+
+
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/Program.cs b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/Program.cs
similarity index 79%
rename from 03.ExploerAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/Program.cs
rename to 03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/Program.cs
index 46ab1cd..930a2ac 100644
--- a/03.ExploerAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/Program.cs
+++ b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/Program.cs
@@ -1,15 +1,17 @@
-using Azure.AI.Projects;
+using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-Env.Load("/Users/lokinfey/Desktop/AOAI/Foundry/Agent-Framework-Samples/.env");
-
-var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
-var deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
// Create an AI Project client and get an OpenAI client that works with the foundry service.
AIProjectClient aiProjectClient = new(
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/README.md b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/README.md
new file mode 100644
index 0000000..973b866
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/README.md
@@ -0,0 +1,32 @@
+# Agent Framework — Azure AI Foundry Provider (.NET)
+
+Creates a managed agent on **Azure AI Foundry** via `AIProjectClient.CreateAIAgentAsync` using `AgentVersionCreationOptions` / `PromptAgentDefinition`. The agent is versioned and reusable across sessions.
+
+## What it shows
+- Using `AIProjectClient` to create and retrieve versioned agents in Foundry
+- `AgentVersionCreationOptions` with `PromptAgentDefinition` for declarative agent setup
+- Invoking a Foundry-hosted agent with `RunAsync`
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a deployed model
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+dotnet user-secrets set "AZURE_AI_MODEL_DEPLOYMENT_NAME" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/app.cs b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/app.cs
new file mode 100644
index 0000000..d705e75
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/03-dotnet-agent-framework-msfoundry/app.cs
@@ -0,0 +1,46 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 06e4bd3a-9846-4330-98e5-7e0431118217
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using Azure.AI.Projects;
+using Azure.AI.Projects.OpenAI;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
+
+// Create an AI Project client and get an OpenAI client that works with the foundry service.
+AIProjectClient aiProjectClient = new(
+ new Uri(endpoint),
+ new AzureCliCredential());
+
+
+AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
+ name: "Agent-Framework",
+ creationOptions: new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: deploymentName)
+ {
+ Instructions = "You are good at telling jokes."
+ })
+);
+
+
+Console.WriteLine(await agent.RunAsync("Write a haiku about Agent Framework"));
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/04-dotnet-agent-framework-foundrylocal.csproj b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/04-dotnet-agent-framework-foundrylocal.csproj
new file mode 100644
index 0000000..36f91d0
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/04-dotnet-agent-framework-foundrylocal.csproj
@@ -0,0 +1,29 @@
+
+
+
+ Exe
+ net10.0
+ _04_dotnet_agent_framework_foundrylocal
+ enable
+ enable
+ 54f947d6-b3f4-4d15-9772-afd04450d9d3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/03.ExploerAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/Program.cs b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/Program.cs
similarity index 79%
rename from 03.ExploerAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/Program.cs
rename to 03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/Program.cs
index 6ad2319..01d0d9f 100644
--- a/03.ExploerAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/Program.cs
+++ b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/Program.cs
@@ -1,17 +1,20 @@
-using System;
+using System;
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using OpenAI;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables from .env file
-Env.Load("../../../../.env");
-// Get Foundry Local configuration from environment variables
-var foundryLocalEndpoint = Environment.GetEnvironmentVariable("FOUNDRYLOCAL_ENDPOINT")
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var foundryLocalEndpoint = config["FOUNDRYLOCAL_ENDPOINT"]
?? throw new InvalidOperationException("FOUNDRYLOCAL_ENDPOINT is not set.");
-var foundryLocalModelId = Environment.GetEnvironmentVariable("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME")
+var foundryLocalModelId = config["FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME"]
?? throw new InvalidOperationException("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME is not set.");
Console.WriteLine($"Endpoint: {foundryLocalEndpoint}");
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/README.md b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/README.md
new file mode 100644
index 0000000..023538d
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/README.md
@@ -0,0 +1,33 @@
+# Agent Framework — Foundry Local Provider (.NET)
+
+Runs an `AIAgent` entirely on-device using **Foundry Local** — no cloud endpoint or API key required (an empty `"nokey"` credential is accepted). Demonstrates that the same agent API works with locally-hosted models.
+
+## What it shows
+- Connecting to a local Foundry endpoint with `OpenAIClient`
+- Running an agent without any cloud dependency
+- Standard and streaming responses from a local model
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- [Foundry Local](https://github.com/microsoft/foundry-local) installed and running with a downloaded model
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "FOUNDRYLOCAL_ENDPOINT" "http://localhost:5272/v1"
+dotnet user-secrets set "FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME" ""
+```
+
+> Run `foundry model list` to view downloaded model aliases.
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/app.cs b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/app.cs
new file mode 100644
index 0000000..03468b9
--- /dev/null
+++ b/03.ExploreAgentFramework/code_samples/dotNET/04-dotnet-agent-framework-foundrylocal/app.cs
@@ -0,0 +1,57 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 54f947d6-b3f4-4d15-9772-afd04450d9d3
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.ClientModel;
+using Microsoft.Extensions.AI;
+using Microsoft.Agents.AI;
+using OpenAI;
+using Microsoft.Extensions.Configuration;
+
+// Load environment variables from .env file
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var foundryLocalEndpoint = config["FOUNDRYLOCAL_ENDPOINT"]
+ ?? throw new InvalidOperationException("FOUNDRYLOCAL_ENDPOINT is not set.");
+var foundryLocalModelId = config["FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME"]
+ ?? throw new InvalidOperationException("FOUNDRYLOCAL_MODEL_DEPLOYMENT_NAME is not set.");
+
+Console.WriteLine($"Endpoint: {foundryLocalEndpoint}");
+Console.WriteLine($"Model: {foundryLocalModelId}");
+
+// Configure OpenAI client for Foundry Local (no API key required)
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint = new Uri(foundryLocalEndpoint)
+};
+
+var openAIClient = new OpenAIClient(new ApiKeyCredential("nokey"), openAIOptions);
+
+// Create AI Agent
+AIAgent agent = openAIClient
+ .GetChatClient(foundryLocalModelId)
+ .AsIChatClient()
+ .AsAIAgent(instructions: "You are a helpful assistant.", name: "FoundryLocalAgent");
+
+// Run agent
+Console.WriteLine("\n=== Response ===");
+Console.WriteLine(await agent.RunAsync("Can you introduce yourself?"));
+
+// Run agent with streaming response
+Console.WriteLine("\n=== Streaming Response ===");
+await foreach (var update in agent.RunStreamingAsync("What can you help me with?"))
+{
+ Console.Write(update);
+}
+Console.WriteLine();
diff --git a/03.ExploerAgentFramework/code_samples/python/01-python-agent-framework-aoai.ipynb b/03.ExploreAgentFramework/code_samples/python/01-python-agent-framework-aoai.ipynb
similarity index 100%
rename from 03.ExploerAgentFramework/code_samples/python/01-python-agent-framework-aoai.ipynb
rename to 03.ExploreAgentFramework/code_samples/python/01-python-agent-framework-aoai.ipynb
diff --git a/03.ExploerAgentFramework/code_samples/python/02-python-agent-framrwork-ghmodel.ipynb b/03.ExploreAgentFramework/code_samples/python/02-python-agent-framrwork-ghmodel.ipynb
similarity index 100%
rename from 03.ExploerAgentFramework/code_samples/python/02-python-agent-framrwork-ghmodel.ipynb
rename to 03.ExploreAgentFramework/code_samples/python/02-python-agent-framrwork-ghmodel.ipynb
diff --git a/03.ExploerAgentFramework/code_samples/python/03-python-agent-framework-msfoundry.ipynb b/03.ExploreAgentFramework/code_samples/python/03-python-agent-framework-msfoundry.ipynb
similarity index 100%
rename from 03.ExploerAgentFramework/code_samples/python/03-python-agent-framework-msfoundry.ipynb
rename to 03.ExploreAgentFramework/code_samples/python/03-python-agent-framework-msfoundry.ipynb
diff --git a/03.ExploerAgentFramework/code_samples/python/04-python-agent-framework-foundrylocal.ipynb b/03.ExploreAgentFramework/code_samples/python/04-python-agent-framework-foundrylocal.ipynb
similarity index 100%
rename from 03.ExploerAgentFramework/code_samples/python/04-python-agent-framework-foundrylocal.ipynb
rename to 03.ExploreAgentFramework/code_samples/python/04-python-agent-framework-foundrylocal.ipynb
diff --git a/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/01-dotnet-agent-framework-msfoundry-vision.csproj b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/01-dotnet-agent-framework-msfoundry-vision.csproj
index 9013eb6..b373366 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/01-dotnet-agent-framework-msfoundry-vision.csproj
+++ b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/01-dotnet-agent-framework-msfoundry-vision.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,21 +7,26 @@
Trueenableenable
+ 874a6202-85a7-4082-9b3f-7587cd525178
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/Program.cs b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/Program.cs
index 3a8d57e..bdc35a8 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/Program.cs
+++ b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/Program.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
using System.IO;
using Azure.AI.Projects;
@@ -6,12 +6,14 @@
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
- using DotNetEnv;
+using Microsoft.Extensions.Configuration;
- Env.Load("../../../../../.env");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-
-var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
var azure_foundry_model_id = "gpt-4o";
var imgPath ="../../../files/home.png";
diff --git a/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/README.md b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/README.md
new file mode 100644
index 0000000..47cd75c
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/README.md
@@ -0,0 +1,33 @@
+# Vision Tool — Azure AI Foundry (.NET)
+
+Demonstrates multimodal input: an image of a room is sent to the agent, which analyses the visible furniture and provides purchase recommendations. Uses `DataContent` to attach image bytes to a `ChatMessage`.
+
+## What it shows
+- Sending images to an agent via `DataContent` (base-64 encoded bytes) in a `ChatMessage`
+- Creating a Foundry-hosted agent configured for multimodal (`gpt-4o`) inference
+- Maintaining a session (`AgentSession`) across a multi-turn visual conversation
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a `gpt-4o` deployment
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+```
+
+> The model is hardcoded to `gpt-4o` because vision requires a multimodal model. The image used is `../../../files/home.png` (relative to the project folder).
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/app.cs b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/app.cs
new file mode 100644
index 0000000..d7837e7
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/01-dotnet-agent-framework-msfoundry-vision/app.cs
@@ -0,0 +1,70 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 874a6202-85a7-4082-9b3f-7587cd525178
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.Linq;
+using System.IO;
+using Azure.AI.Projects;
+using Azure.AI.Projects.OpenAI;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var azure_foundry_model_id = "gpt-4o";
+
+var imgPath = "../../../files/home.png";
+
+const string AgentName = "Vision-Agent";
+const string AgentInstructions = "You are my furniture sales consultant, you can find different furniture elements from the pictures and give me a purchase suggestion";
+
+
+async Task OpenImageBytesAsync(string path)
+{
+ return await File.ReadAllBytesAsync(path);
+}
+
+var imageBytes = await OpenImageBytesAsync(imgPath);
+
+AIProjectClient aiProjectClient = new(
+ new Uri(azure_foundry_endpoint),
+ new AzureCliCredential());
+
+
+AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
+ name: AgentName,
+ creationOptions: new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: azure_foundry_model_id)
+ {
+ Instructions = AgentInstructions
+ })
+);
+
+
+ChatMessage userMessage = new ChatMessage(ChatRole.User, [
+ new TextContent("Can you identify the furniture items in this image and suggest which ones would fit well in a modern living room?"), new DataContent(imageBytes, "image/png")
+]);
+
+
+
+AgentSession session = await agent.CreateSessionAsync();
+
+
+Console.WriteLine(await agent.RunAsync(userMessage, session));
diff --git a/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/02-dotnet-agent-framework-msfoundry-code-interpreter.csproj b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/02-dotnet-agent-framework-msfoundry-code-interpreter.csproj
index b509cd2..67cbf2e 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/02-dotnet-agent-framework-msfoundry-code-interpreter.csproj
+++ b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/02-dotnet-agent-framework-msfoundry-code-interpreter.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,21 +7,27 @@
Trueenableenable
+ 739b43fa-eee0-4252-82f4-618910423167$(NoWarn);CA1812;OPENAI001;MEAI001
-
-
+
+
+
+
+
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/Program.cs b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/Program.cs
index c0831d6..97f3693 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/Program.cs
+++ b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/Program.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
using System.IO;
using System.Text;
@@ -9,13 +9,14 @@
using Microsoft.Extensions.AI;
using OpenAI.Assistants;
using OpenAI.Responses;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
- Env.Load("../../../../../.env");
-
-
-var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
var azure_foundry_model_id = "gpt-4.1-mini";
const string AgentName = "Code-Agent-Framework";
diff --git a/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/README.md b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/README.md
new file mode 100644
index 0000000..2900239
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/README.md
@@ -0,0 +1,33 @@
+# Code Interpreter Tool — Azure AI Foundry (.NET)
+
+Attaches the hosted **Code Interpreter** tool to a Foundry agent, which lets it write and execute Python code server-side to answer computational questions. The sample captures and displays both the generated code and the execution output.
+
+## What it shows
+- Enabling `ResponseTool.CreateCodeInterpreterTool` on a Foundry agent
+- Reading `CodeInterpreterToolCallContent` and `CodeInterpreterToolResultContent` from the response
+- How the agent autonomously writes and runs code to solve problems (Fibonacci sequence)
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a deployed model
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+```
+
+> The model is hardcoded to `gpt-4.1-mini`.
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/app.cs b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/app.cs
new file mode 100644
index 0000000..c7c9434
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/02-dotnet-agent-framework-msfoundry-code-interpreter/app.cs
@@ -0,0 +1,90 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 739b43fa-eee0-4252-82f4-618910423167
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Text;
+using Azure.AI.Projects;
+using Azure.AI.Projects.OpenAI;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using OpenAI.Assistants;
+using OpenAI.Responses;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var azure_foundry_model_id = "gpt-4.1-mini";
+
+const string AgentName = "Code-Agent-Framework";
+const string AgentInstructions = "You are an AI assistant that helps people find information.";
+
+AIProjectClient aiProjectClient = new(
+ new Uri(azure_foundry_endpoint),
+ new AzureCliCredential());
+
+AIAgent codingAgent = await aiProjectClient.CreateAIAgentAsync(
+ name: AgentName,
+ creationOptions: new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: azure_foundry_model_id)
+ {
+ Instructions = AgentInstructions,
+ Tools = {
+ ResponseTool.CreateCodeInterpreterTool(
+ new CodeInterpreterToolContainer(
+ CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration(fileIds: [])
+ )
+ ),
+ }
+ })
+);
+
+AgentResponse response = await codingAgent.RunAsync("Use code to determine the values in the Fibonacci sequence that that are less then the value of 101?");
+
+// Get the CodeInterpreterToolCallContent
+CodeInterpreterToolCallContent? toolCallContent = response.Messages.SelectMany(m => m.Contents).OfType().FirstOrDefault();
+if (toolCallContent?.Inputs is not null)
+{
+ DataContent? codeInput = toolCallContent.Inputs.OfType().FirstOrDefault();
+ if (codeInput?.HasTopLevelMediaType("text") ?? false)
+ {
+ Console.WriteLine($"Code Input: {Encoding.UTF8.GetString(codeInput.Data.ToArray()) ?? "Not available"}");
+ }
+}
+
+// Get the CodeInterpreterToolResultContent
+CodeInterpreterToolResultContent? toolResultContent = response.Messages.SelectMany(m => m.Contents).OfType().FirstOrDefault();
+if (toolResultContent?.Outputs is not null && toolResultContent.Outputs.OfType().FirstOrDefault() is { } resultOutput)
+{
+ Console.WriteLine($"Code Tool Result: {resultOutput.Text}");
+}
+
+// Getting any annotations generated by the tool
+foreach (AIAnnotation annotation in response.Messages.SelectMany(m => m.Contents).SelectMany(C => C.Annotations ?? []))
+{
+ if (annotation.RawRepresentation is TextAnnotationUpdate citationAnnotation)
+ {
+ Console.WriteLine($$"""
+ File Id: {{citationAnnotation.OutputFileId}}
+ Text to Replace: {{citationAnnotation.TextToReplace}}
+ Filename: {{Path.GetFileName(citationAnnotation.TextToReplace)}}
+ """);
+ }
+}
diff --git a/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/03-dotnet-agent-framework-msfoundry-binggrounding.csproj b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/03-dotnet-agent-framework-msfoundry-binggrounding.csproj
index 3d6aad2..aa0555c 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/03-dotnet-agent-framework-msfoundry-binggrounding.csproj
+++ b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/03-dotnet-agent-framework-msfoundry-binggrounding.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,21 +7,27 @@
Trueenableenable
+ ee9707f4-4391-43ca-bdd5-38f721eb32a9$(NoWarn);CA1812;OPENAI001;MEAI001
-
-
+
+
+
+
+
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/Program.cs b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/Program.cs
index 3f0f96c..3a129fe 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/Program.cs
+++ b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/Program.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Linq;
using System.IO;
using System.Text;
@@ -9,16 +9,17 @@
using Microsoft.Extensions.AI;
using OpenAI.Assistants;
using OpenAI.Responses;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// using OpenAI.Assistants;
// using OpenAI.Responses;
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
- Env.Load("../../../../../.env");
-
-
-var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
var azure_foundry_model_id = "gpt-4.1-mini";
const string AgentName = "Bing-Agent-Framework";
@@ -31,7 +32,7 @@
new AzureCliCredential());
-var connectionName = Environment.GetEnvironmentVariable("BING_CONNECTION_NAME");
+var connectionName = config["BING_CONNECTION_NAME"];
Console.WriteLine($"Using Bing Connection: {connectionName}");
diff --git a/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/README.md b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/README.md
new file mode 100644
index 0000000..e7bb8ad
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/README.md
@@ -0,0 +1,33 @@
+# Bing Grounding Tool — Azure AI Foundry (.NET)
+
+Connects an Azure AI Foundry agent to a **Bing Grounding** connection so it can search the live web and cite sources in answers. Demonstrates how to attach a `BingGroundingAgentTool` to a Foundry-hosted agent.
+
+## What it shows
+- Looking up an `AIProjectConnection` by name and wrapping it in `BingGroundingAgentTool`
+- Attaching real-time web search capability to a Foundry agent
+- Responses that reference live Bing search results
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a deployed model
+- A **Bing Search** connection configured in your AI Foundry hub
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+dotnet user-secrets set "BING_CONNECTION_NAME" ""
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/app.cs b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/app.cs
new file mode 100644
index 0000000..edb8279
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/03-dotnet-agent-framework-msfoundry-binggrounding/app.cs
@@ -0,0 +1,73 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId ee9707f4-4391-43ca-bdd5-38f721eb32a9
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.Linq;
+using System.IO;
+using System.Text;
+using Azure.AI.Projects;
+using Azure.AI.Projects.OpenAI;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using OpenAI.Assistants;
+using OpenAI.Responses;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var azure_foundry_model_id = "gpt-4.1-mini";
+
+const string AgentName = "Bing-Agent-Framework";
+const string AgentInstructions = @"You are a helpful assistant that can search the web for current information.
+ Use the Bing search tool to find up-to-date information and provide accurate, well-sourced answers.
+ Always cite your sources when possible.";
+
+AIProjectClient aiProjectClient = new(
+ new Uri(azure_foundry_endpoint),
+ new AzureCliCredential());
+
+
+var connectionName = config["BING_CONNECTION_NAME"];
+
+Console.WriteLine($"Using Bing Connection: {connectionName}");
+
+AIProjectConnection bingConnectionName = aiProjectClient.Connections.GetConnection(connectionName: connectionName);
+
+BingGroundingAgentTool bingGroundingAgentTool = new(new BingGroundingSearchToolOptions(
+ searchConfigurations: [new BingGroundingSearchConfiguration(projectConnectionId: bingConnectionName.Id)]
+ )
+);
+
+
+AIAgent bingAgent = await aiProjectClient.CreateAIAgentAsync(
+ name: AgentName,
+ creationOptions: new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: azure_foundry_model_id)
+ {
+ Instructions = AgentInstructions,
+ Tools = {
+ bingGroundingAgentTool,
+ }
+ })
+);
+
+AgentResponse response = await bingAgent.RunAsync("What is today's date and weather in Guangzhou?");
+
+Console.WriteLine("Response:");
+Console.WriteLine(response);
diff --git a/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/04-dotnet-agent-framework-msfoundry-file-search.csproj b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/04-dotnet-agent-framework-msfoundry-file-search.csproj
index 15165b4..21c9a64 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/04-dotnet-agent-framework-msfoundry-file-search.csproj
+++ b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/04-dotnet-agent-framework-msfoundry-file-search.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,21 +7,27 @@
Trueenableenable
+ 8324968c-859a-4090-8afa-336940d7cf66
-
-
+
+
+
+
+
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/Program.cs b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/Program.cs
index 16787af..d85b315 100644
--- a/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/Program.cs
+++ b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/Program.cs
@@ -1,4 +1,17 @@
-// See https://aka.ms/new-console-template for more information
+// ============================================================
+// 04 — FILE SEARCH TOOL
+// This sample shows how HostedFileSearchTool plugs into an
+// AIAgent using the exact same pattern as the other hosted
+// tools in this chapter (Code Interpreter, Bing Search):
+//
+// 1. Prepare the tool — upload a file + create a vector store
+// 2. Create the tool — new HostedFileSearchTool(vectorStoreId)
+// 3. Register the tool — pass it in the tools: [] parameter
+//
+// The agent framework handles calling the tool automatically.
+// For a full RAG pipeline walkthrough, see 06.RAGs.
+// ============================================================
+
using System.ClientModel;
using Azure.AI.Projects;
using Azure.Identity;
@@ -7,46 +20,54 @@
using OpenAI;
using OpenAI.Files;
using OpenAI.VectorStores;
-using DotNetEnv;
-
+using Microsoft.Extensions.Configuration;
-Env.Load("/Users/lokinfey/Desktop/AOAI/Foundry/Agent-Framework-Samples/.env");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
-var deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
-// Create an AI Project client and get an OpenAI client that works with the foundry service.
-AIProjectClient aiProjectClient = new(
- new Uri(endpoint),
- new AzureCliCredential());
-OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
+// Step 1 — Prepare the tool: upload the knowledge file and index it into a vector store.
+// The vector store is the searchable index that backs the File Search tool.
+AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
+OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
-// Upload the file that contains the data to be used for RAG to the Foundry service.
-OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
-ClientResult uploadResult = await fileClient.UploadFileAsync(
+OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
+var uploadResult = await fileClient.UploadFileAsync(
filePath: "../../../files/demo.md",
purpose: FileUploadPurpose.Assistants);
#pragma warning disable OPENAI001
VectorStoreClient vectorStoreClient = openAIClient.GetVectorStoreClient();
-ClientResult vectorStoreCreate = await vectorStoreClient.CreateVectorStoreAsync(options: new VectorStoreCreationOptions()
-{
- Name = "rag-document-knowledge-base",
- FileIds = { uploadResult.Value.Id }
-});
+var vectorStoreResult = await vectorStoreClient.CreateVectorStoreAsync(
+ options: new VectorStoreCreationOptions()
+ {
+ Name = "file-search-tool-demo",
+ FileIds = { uploadResult.Value.Id }
+ });
#pragma warning restore OPENAI001
-var fileSearchTool = new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreCreate.Value.Id)] };
-
-AIAgent agent = await aiProjectClient
- .CreateAIAgentAsync(
- model: deploymentName,
- name: "dotNETRAGAgent",
- instructions: @"You are an AI assistant that helps people find information in a set of documents. Use the File Search tool to look up relevant information from the files when needed to answer user questions. If you don't know the answer, just say you don't know. Do not make up answers.",
- tools: [fileSearchTool]);
+// Step 2 — Create the tool.
+// HostedFileSearchTool follows the same pattern as HostedCodeInterpreterTool
+// and HostedWebSearchTool shown in earlier samples in this chapter.
+var fileSearchTool = new HostedFileSearchTool()
+{
+ Inputs = [new HostedVectorStoreContent(vectorStoreResult.Value.Id)]
+};
+// Step 3 — Register the tool with the agent.
+// The agent framework decides when to invoke the tool based on the user's query.
+AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
+ model: deploymentName,
+ name: "FileSearchToolAgent",
+ instructions: "You are a helpful assistant. Use the File Search tool to find information in the uploaded documents. If you can't find the answer, say so clearly.",
+ tools: [fileSearchTool]);
AgentSession session = await agent.CreateSessionAsync();
-Console.WriteLine(await agent.RunAsync("What's graphrag?", session));
+Console.WriteLine("=== File Search Tool Demo ===");
+Console.WriteLine(await agent.RunAsync("What is GraphRAG and what is it used for?", session));
diff --git a/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/README.md b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/README.md
new file mode 100644
index 0000000..f3b6a3c
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/README.md
@@ -0,0 +1,34 @@
+# File Search Tool — Azure AI Foundry (.NET)
+
+Uploads a Markdown document to Azure AI Foundry, indexes it in a vector store, and attaches `HostedFileSearchTool` to the agent. The agent answers questions grounded exclusively in the uploaded file content.
+
+## What it shows
+- Uploading files to Foundry with `OpenAIFileClient.UploadFileAsync`
+- Creating a vector store and linking it via `HostedVectorStoreContent`
+- Using `HostedFileSearchTool` for retrieval-augmented generation (RAG)
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a deployed model
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+dotnet user-secrets set "AZURE_AI_MODEL_DEPLOYMENT_NAME" "gpt-4o-mini"
+```
+
+> The sample uploads `../../../files/demo.md` (located in the `04.Tools/code_samples/` folder).
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/app.cs b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/app.cs
new file mode 100644
index 0000000..f6aff84
--- /dev/null
+++ b/04.Tools/code_samples/dotNET/msfoundry/04-dotnet-agent-framework-msfoundry-file-search/app.cs
@@ -0,0 +1,100 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 8324968c-859a-4090-8afa-336940d7cf66
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 8324968c-859a-4090-8afa-336940d7cf66
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+// ============================================================
+// 04 — FILE SEARCH TOOL
+// This sample shows how HostedFileSearchTool plugs into an
+// AIAgent using the exact same pattern as the other hosted
+// tools in this chapter (Code Interpreter, Bing Search):
+//
+// 1. Prepare the tool — upload a file + create a vector store
+// 2. Create the tool — new HostedFileSearchTool(vectorStoreId)
+// 3. Register the tool — pass it in the tools: [] parameter
+//
+// The agent framework handles calling the tool automatically.
+// For a full RAG pipeline walkthrough, see 06.RAGs.
+// ============================================================
+
+using System.ClientModel;
+using Azure.AI.Projects;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using OpenAI;
+using OpenAI.Files;
+using OpenAI.VectorStores;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
+
+// Step 1 — Prepare the tool: upload the knowledge file and index it into a vector store.
+// The vector store is the searchable index that backs the File Search tool.
+AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
+OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
+
+OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
+var uploadResult = await fileClient.UploadFileAsync(
+ filePath: "../../../files/demo.md",
+ purpose: FileUploadPurpose.Assistants);
+
+#pragma warning disable OPENAI001
+VectorStoreClient vectorStoreClient = openAIClient.GetVectorStoreClient();
+var vectorStoreResult = await vectorStoreClient.CreateVectorStoreAsync(
+ options: new VectorStoreCreationOptions()
+ {
+ Name = "file-search-tool-demo",
+ FileIds = { uploadResult.Value.Id }
+ });
+#pragma warning restore OPENAI001
+
+// Step 2 — Create the tool.
+// HostedFileSearchTool follows the same pattern as HostedCodeInterpreterTool
+// and HostedWebSearchTool shown in earlier samples in this chapter.
+var fileSearchTool = new HostedFileSearchTool()
+{
+ Inputs = [new HostedVectorStoreContent(vectorStoreResult.Value.Id)]
+};
+
+// Step 3 — Register the tool with the agent.
+// The agent framework decides when to invoke the tool based on the user's query.
+AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
+ model: deploymentName,
+ name: "FileSearchToolAgent",
+ instructions: "You are a helpful assistant. Use the File Search tool to find information in the uploaded documents. If you can't find the answer, say so clearly.",
+ tools: [fileSearchTool]);
+
+AgentSession session = await agent.CreateSessionAsync();
+
+Console.WriteLine("=== File Search Tool Demo ===");
+Console.WriteLine(await agent.RunAsync("What is GraphRAG and what is it used for?", session));
diff --git a/05.Providers/README.md b/05.Providers/README.md
index cf1eef6..38cdba1 100644
--- a/05.Providers/README.md
+++ b/05.Providers/README.md
@@ -177,3 +177,53 @@ For example, a "Travel Planner" agent could delegate tasks by calling a "Flight
* **Specialized Expertise:** A generalist agent can consult a specialist agent for deep knowledge in a specific area (e.g., a "General Support" agent calling a "Billing Expert" agent).
* **Collaborative Problem-Solving:** Multiple agents can work together, sharing information and intermediate results to solve a problem that would be too complex for a single agent.
+
+### A2A Example
+
+#### .NET Example
+
+This sample demonstrates the A2A pattern using GitHub Models. A **ResearchAgent** specialist is wrapped as a callable tool for an **OrchestratorAgent**, which delegates research queries to it at runtime.
+
+The key mechanism is `AIFunctionFactory.Create`, which turns any .NET delegate — including another agent's `RunAsync` — into an `AIFunction` the model can invoke as a tool call.
+
+```csharp
+// Wrap ResearchAgent as a callable tool for another agent
+Func> researchFunc =
+ async (query) => (await researchAgent.RunAsync(query)).ToString();
+
+var researchTool = AIFunctionFactory.Create(
+ (Func>)researchFunc,
+ name: "ResearchTopic",
+ description: "Delegates a research query to the ResearchAgent specialist.");
+
+// OrchestratorAgent treats ResearchAgent as a provider
+AIAgent orchestratorAgent = chatClient.AsAIAgent(
+ name: "OrchestratorAgent",
+ instructions: "For every question, call ResearchTopic first, then compose a friendly answer.",
+ tools: [researchTool]);
+
+var answer = await orchestratorAgent.RunAsync("What should I know about visiting Tokyo?");
+Console.WriteLine(answer);
+```
+
+Full sample: [02-dotnet-agent-framework-ghmodel-a2a](./code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/)
+
+**Setup**
+
+```bash
+cd 05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a
+
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+**Run**
+
+```bash
+dotnet run app.cs # file-based
+# or
+dotnet run # project-based
+```
+
+> **Compare with 07.Workflow:** In a Workflow, agents are wired into a fixed pipeline and messages pass through in sequence. In A2A, the orchestrator decides at runtime whether and when to call the specialist — it is a dynamic tool call, not a predetermined edge in a graph.
diff --git a/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/AgentMCP.Console.csproj b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/AgentMCP.Console.csproj
index 90f03b6..ca25b69 100644
--- a/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/AgentMCP.Console.csproj
+++ b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/AgentMCP.Console.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,23 +6,28 @@
Trueenableenable
+ d0e13627-3df1-4b64-aec6-0fb17f50a14d
-
-
+
-
-
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/Program.cs b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/Program.cs
index cf795d9..78c1396 100644
--- a/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/Program.cs
+++ b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/Program.cs
@@ -1,4 +1,4 @@
-#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
+#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
using System;
using System.Linq;
@@ -7,13 +7,15 @@
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
-using DotNetEnv;
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-Env.Load("../../../../../.env");
-
-var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
-var azure_foundry_model_id = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4.1-mini";
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
+var azure_foundry_model_id = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4.1-mini";
var persistentAgentsClient = new PersistentAgentsClient(azure_foundry_endpoint, new AzureCliCredential());
@@ -42,7 +44,7 @@
// var threadWithRequiredApproval = await agentWithRequiredApproval.GetNewThreadAsync();
var sessionWithRequiredApproval = await agentWithRequiredApproval.CreateSessionAsync();
var response = await agentWithRequiredApproval.RunAsync("Please summarize the Azure AI Agent documentation related to MCP Tool calling?", sessionWithRequiredApproval);
-var userInputRequests = response.UserInputRequests.ToList();
+var userInputRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
while (userInputRequests.Count > 0)
{
@@ -65,7 +67,7 @@
// Pass the user input responses back to the agent for further processing.
response = await agentWithRequiredApproval.RunAsync(userInputResponses, sessionWithRequiredApproval);
- userInputRequests = response.UserInputRequests.ToList();
+ userInputRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
}
Console.WriteLine($"\nAgent: {response}");
diff --git a/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/README.md b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/README.md
new file mode 100644
index 0000000..1d33fbb
--- /dev/null
+++ b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/README.md
@@ -0,0 +1,34 @@
+# MCP Tool with Approval Flow — Azure AI Foundry (.NET)
+
+Connects a Foundry agent to a remote **Model Context Protocol (MCP)** server (`microsoft_learn`) and requires explicit user approval before each tool call. Demonstrates how to implement a human-in-the-loop approval gate for MCP-based tool invocations.
+
+## What it shows
+- Attaching a `HostedMcpServerTool` to a Foundry agent with `ApprovalMode.AlwaysRequire`
+- Processing `McpServerToolApprovalRequestContent` messages in the response loop
+- Submitting user approval decisions back to the agent with `McpServerToolApprovalResponseContent`
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a deployed model
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+dotnet user-secrets set "AZURE_AI_MODEL_DEPLOYMENT_NAME" "gpt-4.1-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+When the agent wants to call an MCP tool, it will prompt you to enter `Y` to approve before the call is made.
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/app.cs b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/app.cs
new file mode 100644
index 0000000..964b002
--- /dev/null
+++ b/05.Providers/code_samples/dotNET/01-dotnet-agent-framework-aifoundry-mcp/AgentMCP.Console/app.cs
@@ -0,0 +1,86 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId d0e13627-3df1-4b64-aec6-0fb17f50a14d
+#:property EnablePreviewFeatures true
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package ModelContextProtocol@0.6.0-preview.1
+#:package System.Linq.Async@7.0.0
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI.Persistent@1.0.0-preview.260219.1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
+
+using System;
+using System.Linq;
+
+using Azure.AI.Agents.Persistent;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var azure_foundry_endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
+var azure_foundry_model_id = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4.1-mini";
+
+
+var persistentAgentsClient = new PersistentAgentsClient(azure_foundry_endpoint, new AzureCliCredential());
+var mcpToolWithApproval = new HostedMcpServerTool(
+ serverName: "microsoft_learn",
+ serverAddress: "https://learn.microsoft.com/api/mcp")
+{
+ AllowedTools = ["microsoft_docs_search"],
+ ApprovalMode = HostedMcpServerToolApprovalMode.AlwaysRequire
+};
+
+// Create an agent based on Azure OpenAI Responses as the backend.
+AIAgent agentWithRequiredApproval = await persistentAgentsClient.CreateAIAgentAsync(
+ model: azure_foundry_model_id,
+ options: new()
+ {
+ Name = "MicrosoftLearnAgentWithApproval",
+ ChatOptions = new()
+ {
+ Instructions = "You answer questions by searching the Microsoft Learn content only.",
+ Tools = [mcpToolWithApproval]
+ },
+ });
+
+// You can then invoke the agent like any other AIAgent.
+var sessionWithRequiredApproval = await agentWithRequiredApproval.CreateSessionAsync();
+var response = await agentWithRequiredApproval.RunAsync("Please summarize the Azure AI Agent documentation related to MCP Tool calling?", sessionWithRequiredApproval);
+var userInputRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+
+while (userInputRequests.Count > 0)
+{
+ // Ask the user to approve each MCP call request.
+ var userInputResponses = userInputRequests
+ .OfType()
+ .Select(approvalRequest =>
+ {
+ Console.WriteLine($"""
+ The agent would like to invoke the following MCP Tool, please reply Y to approve.
+ ServerName: {approvalRequest.ToolCall.ServerName}
+ Name: {approvalRequest.ToolCall.ToolName}
+ Arguments: {string.Join(", ", approvalRequest.ToolCall.Arguments?.Select(x => $"{x.Key}: {x.Value}") ?? [])}
+ """);
+ return new ChatMessage(ChatRole.User, [approvalRequest.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]);
+ })
+ .ToList();
+
+ // Pass the user input responses back to the agent for further processing.
+ response = await agentWithRequiredApproval.RunAsync(userInputResponses, sessionWithRequiredApproval);
+
+ userInputRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+}
+
+Console.WriteLine($"\nAgent: {response}");
diff --git a/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/02-dotnet-agent-framework-ghmodel-a2a.csproj b/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/02-dotnet-agent-framework-ghmodel-a2a.csproj
new file mode 100644
index 0000000..5b2fcb6
--- /dev/null
+++ b/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/02-dotnet-agent-framework-ghmodel-a2a.csproj
@@ -0,0 +1,25 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+ f1e2d3c4-b5a6-7890-cdef-012345678901
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/Program.cs b/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/Program.cs
new file mode 100644
index 0000000..fa77df0
--- /dev/null
+++ b/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/Program.cs
@@ -0,0 +1,110 @@
+// ============================================================
+// AGENT-TO-AGENT (A2A) PATTERN
+//
+// In A2A, one agent treats another agent as a callable provider —
+// a specialist it can delegate to on demand.
+//
+// This sample shows two agents:
+// • ResearchAgent — a specialist that returns concise facts
+// • OrchestratorAgent — wraps ResearchAgent as a tool and calls
+// it automatically when it needs research to answer the user
+//
+// The key mechanism:
+// AIFunctionFactory.Create(researchFunc, ...) — wraps the
+// ResearchAgent's RunAsync as an AIFunction tool that the
+// orchestrator can invoke just like any other tool.
+//
+// Compare with 07.Workflow where agents are wired into a fixed
+// pipeline. Here the orchestrator decides at runtime whether and
+// when to call the specialist agent.
+// ============================================================
+
+using System.ClientModel;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+using OpenAI;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var githubEndpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var githubModel = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var githubToken = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+var openAIOptions = new OpenAIClientOptions { Endpoint = new Uri(githubEndpoint) };
+IChatClient chatClient = new OpenAIClient(new ApiKeyCredential(githubToken), openAIOptions)
+ .GetChatClient(githubModel)
+ .AsIChatClient();
+
+// -----------------------------------------------
+// Agent 1 — ResearchAgent (the specialist provider)
+// Focused, terse instructions: return facts only,
+// no elaboration. This keeps the delegation output
+// clean and easy for the orchestrator to re-use.
+// -----------------------------------------------
+AIAgent researchAgent = chatClient.AsAIAgent(
+ name: "ResearchAgent",
+ instructions: """
+ You are a concise research specialist. When given a topic or question,
+ respond with exactly 3-5 factual bullet points and nothing else.
+ No introductions, no conclusions, no extra commentary.
+ """);
+
+// -----------------------------------------------
+// A2A Bridge — wrap the ResearchAgent as a tool
+//
+// AIFunctionFactory.Create turns any .NET delegate into an AIFunction
+// that a language model can call. By wrapping ResearchAgent.RunAsync
+// here, the OrchestratorAgent can invoke it as a tool call — the
+// same mechanism used for APIs and database queries.
+//
+// From the orchestrator's perspective, ResearchAgent is just another
+// provider it can query; it does not know or care that the provider
+// is itself an AI agent.
+// -----------------------------------------------
+Func> researchFunc =
+ async (query) => (await researchAgent.RunAsync(query)).ToString();
+
+var researchTool = AIFunctionFactory.Create(
+ (Func>)researchFunc,
+ name: "ResearchTopic",
+ description: "Delegates a research query to the ResearchAgent specialist. " +
+ "Returns 3-5 concise factual bullet points about the topic.");
+
+// -----------------------------------------------
+// Agent 2 — OrchestratorAgent (the coordinator)
+// The orchestrator knows it has a ResearchTopic tool
+// and is instructed to use it before drafting an answer.
+// It never does the research itself.
+// -----------------------------------------------
+AIAgent orchestratorAgent = chatClient.AsAIAgent(
+ name: "OrchestratorAgent",
+ instructions: """
+ You are a travel guide assistant. For every destination question:
+ 1. ALWAYS call ResearchTopic first to get factual details.
+ 2. Use the returned facts to build a 2-3 sentence travel tip.
+ 3. Keep the tone friendly and engaging.
+ Never answer from your own knowledge without calling ResearchTopic.
+ """,
+ tools: [researchTool]);
+
+// -----------------------------------------------
+// Run — the orchestrator transparently calls the
+// ResearchAgent behind the scenes for each question.
+// -----------------------------------------------
+Console.WriteLine("=== Agent-to-Agent (A2A) Demo ===");
+Console.WriteLine();
+
+// Turn 1 — orchestrator will call ResearchAgent for Tokyo facts
+Console.WriteLine("Q: What should I know about visiting Tokyo?");
+var answer1 = await orchestratorAgent.RunAsync("What should I know about visiting Tokyo?");
+Console.WriteLine($"A: {answer1}");
+Console.WriteLine();
+
+// Turn 2 — orchestrator calls ResearchAgent again for a different topic
+Console.WriteLine("Q: Give me a travel tip for Cape Town.");
+var answer2 = await orchestratorAgent.RunAsync("Give me a travel tip for Cape Town.");
+Console.WriteLine($"A: {answer2}");
diff --git a/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/app.cs b/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/app.cs
new file mode 100644
index 0000000..af1cab1
--- /dev/null
+++ b/05.Providers/code_samples/dotNET/02-dotnet-agent-framework-ghmodel-a2a/app.cs
@@ -0,0 +1,120 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId f1e2d3c4-b5a6-7890-cdef-012345678901
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+// ============================================================
+// AGENT-TO-AGENT (A2A) PATTERN
+//
+// In A2A, one agent treats another agent as a callable provider —
+// a specialist it can delegate to on demand.
+//
+// This sample shows two agents:
+// • ResearchAgent — a specialist that returns concise facts
+// • OrchestratorAgent — wraps ResearchAgent as a tool and calls
+// it automatically when it needs research to answer the user
+//
+// The key mechanism:
+// AIFunctionFactory.Create(researchFunc, ...) — wraps the
+// ResearchAgent's RunAsync as an AIFunction tool that the
+// orchestrator can invoke just like any other tool.
+//
+// Compare with 07.Workflow where agents are wired into a fixed
+// pipeline. Here the orchestrator decides at runtime whether and
+// when to call the specialist agent.
+// ============================================================
+
+using System.ClientModel;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
+using OpenAI;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var githubEndpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var githubModel = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var githubToken = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+var openAIOptions = new OpenAIClientOptions { Endpoint = new Uri(githubEndpoint) };
+IChatClient chatClient = new OpenAIClient(new ApiKeyCredential(githubToken), openAIOptions)
+ .GetChatClient(githubModel)
+ .AsIChatClient();
+
+// -----------------------------------------------
+// Agent 1 — ResearchAgent (the specialist provider)
+// Focused, terse instructions: return facts only,
+// no elaboration. This keeps the delegation output
+// clean and easy for the orchestrator to re-use.
+// -----------------------------------------------
+AIAgent researchAgent = chatClient.AsAIAgent(
+ name: "ResearchAgent",
+ instructions: """
+ You are a concise research specialist. When given a topic or question,
+ respond with exactly 3-5 factual bullet points and nothing else.
+ No introductions, no conclusions, no extra commentary.
+ """);
+
+// -----------------------------------------------
+// A2A Bridge — wrap the ResearchAgent as a tool
+//
+// AIFunctionFactory.Create turns any .NET delegate into an AIFunction
+// that a language model can call. By wrapping ResearchAgent.RunAsync
+// here, the OrchestratorAgent can invoke it as a tool call — the
+// same mechanism used for APIs and database queries.
+//
+// From the orchestrator's perspective, ResearchAgent is just another
+// provider it can query; it does not know or care that the provider
+// is itself an AI agent.
+// -----------------------------------------------
+Func> researchFunc =
+ async (query) => (await researchAgent.RunAsync(query)).ToString();
+
+var researchTool = AIFunctionFactory.Create(
+ (Func>)researchFunc,
+ name: "ResearchTopic",
+ description: "Delegates a research query to the ResearchAgent specialist. " +
+ "Returns 3-5 concise factual bullet points about the topic.");
+
+// -----------------------------------------------
+// Agent 2 — OrchestratorAgent (the coordinator)
+// The orchestrator knows it has a ResearchTopic tool
+// and is instructed to use it before drafting an answer.
+// It never does the research itself.
+// -----------------------------------------------
+AIAgent orchestratorAgent = chatClient.AsAIAgent(
+ name: "OrchestratorAgent",
+ instructions: """
+ You are a travel guide assistant. For every destination question:
+ 1. ALWAYS call ResearchTopic first to get factual details.
+ 2. Use the returned facts to build a 2-3 sentence travel tip.
+ 3. Keep the tone friendly and engaging.
+ Never answer from your own knowledge without calling ResearchTopic.
+ """,
+ tools: [researchTool]);
+
+// -----------------------------------------------
+// Run — the orchestrator transparently calls the
+// ResearchAgent behind the scenes for each question.
+// -----------------------------------------------
+Console.WriteLine("=== Agent-to-Agent (A2A) Demo ===");
+Console.WriteLine();
+
+// Turn 1 — orchestrator will call ResearchAgent for Tokyo facts
+Console.WriteLine("Q: What should I know about visiting Tokyo?");
+var answer1 = await orchestratorAgent.RunAsync("What should I know about visiting Tokyo?");
+Console.WriteLine($"A: {answer1}");
+Console.WriteLine();
+
+// Turn 2 — orchestrator calls ResearchAgent again for a different topic
+Console.WriteLine("Q: Give me a travel tip for Cape Town.");
+var answer2 = await orchestratorAgent.RunAsync("Give me a travel tip for Cape Town.");
+Console.WriteLine($"A: {answer2}");
diff --git a/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/Program.cs b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/Program.cs
index b4fef2e..89197da 100644
--- a/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/Program.cs
+++ b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/Program.cs
@@ -1,4 +1,23 @@
-using System.ClientModel;
+// ============================================================
+// RETRIEVAL-AUGMENTED GENERATION (RAG) PIPELINE
+//
+// RAG grounds an LLM in your own documents so it can answer
+// questions about private data it was not trained on.
+//
+// This sample walks through all five steps:
+//
+// Step 1: Upload — send your document(s) to Azure AI Foundry
+// Step 2: Index — create a vector store (searchable index)
+// Step 3: Configure — build a HostedFileSearchTool linked to the store
+// Step 4: Create — define the agent with strict "document-only" instructions
+// Step 5: Query — run multi-turn Q&A; the agent cites its sources
+//
+// Unlike the tool introduction in 04.Tools, the focus here is on
+// building a grounded, citation-accurate assistant that refuses to
+// answer from general knowledge.
+// ============================================================
+
+using System.ClientModel;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
@@ -6,49 +25,107 @@
using OpenAI;
using OpenAI.Files;
using OpenAI.VectorStores;
-using DotNetEnv;
-
+using Microsoft.Extensions.Configuration;
-Env.Load("/Users/lokinfey/Desktop/AOAI/Foundry/Agent-Framework-Samples/.env");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
-var deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
-// Create an AI Project client and get an OpenAI client that works with the foundry service.
-AIProjectClient aiProjectClient = new(
- new Uri(endpoint),
- new AzureCliCredential());
-OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
+AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
+OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
-// Upload the file that contains the data to be used for RAG to the Foundry service.
-OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
-ClientResult uploadResult = await fileClient.UploadFileAsync(
+// -----------------------------------------------
+// Step 1 — Upload
+// Upload the knowledge document to Azure AI Foundry.
+// The file is stored server-side and assigned a unique ID.
+// -----------------------------------------------
+Console.WriteLine("[Step 1] Uploading knowledge document...");
+OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
+var uploadResult = await fileClient.UploadFileAsync(
filePath: "../../files/demo.md",
purpose: FileUploadPurpose.Assistants);
+Console.WriteLine($" File uploaded: {uploadResult.Value.Id}");
+// -----------------------------------------------
+// Step 2 — Index
+// Create a vector store from the uploaded file.
+// The vector store converts the document into embeddings so the
+// agent can perform semantic (meaning-based) search at query time.
+// -----------------------------------------------
+Console.WriteLine("[Step 2] Creating vector store (semantic index)...");
#pragma warning disable OPENAI001
VectorStoreClient vectorStoreClient = openAIClient.GetVectorStoreClient();
-ClientResult vectorStoreCreate = await vectorStoreClient.CreateVectorStoreAsync(options: new VectorStoreCreationOptions()
-{
- Name = "document-knowledge-base",
- FileIds = { uploadResult.Value.Id }
-});
+var vectorStoreResult = await vectorStoreClient.CreateVectorStoreAsync(
+ options: new VectorStoreCreationOptions()
+ {
+ Name = "rag-knowledge-base",
+ FileIds = { uploadResult.Value.Id }
+ });
#pragma warning restore OPENAI001
+Console.WriteLine($" Vector store created: {vectorStoreResult.Value.Id}");
+
+// -----------------------------------------------
+// Step 3 — Configure
+// Attach the vector store to a HostedFileSearchTool.
+// The tool is the bridge between the agent and the index.
+// -----------------------------------------------
+Console.WriteLine("[Step 3] Configuring HostedFileSearchTool...");
+var fileSearchTool = new HostedFileSearchTool()
+{
+ Inputs = [new HostedVectorStoreContent(vectorStoreResult.Value.Id)]
+};
+
+// -----------------------------------------------
+// Step 4 — Create the RAG agent
+// The system prompt is intentionally strict:
+// • Answer ONLY from the retrieved document context.
+// • Never use general knowledge or make assumptions.
+// • Cite the source document for every factual claim.
+// • Admit clearly when the document does not cover the question.
+// This prevents hallucinations and keeps answers grounded.
+// -----------------------------------------------
+Console.WriteLine("[Step 4] Creating RAG agent...");
+AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
+ model: deploymentName,
+ name: "DocumentRAGAgent",
+ instructions: """
+ You are a document-grounded assistant. Answer user questions using ONLY
+ the information retrieved from the provided file(s).
-var fileSearchTool = new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreCreate.Value.Id)] };
+ Rules:
+ - Cite the source document for every factual statement.
+ - If the document does not contain the answer, respond:
+ "The uploaded document does not contain information to answer that question."
+ - Never answer from general knowledge, training data, or assumptions.
+ - Keep answers concise and accurate.
+ """,
+ tools: [fileSearchTool]);
-AIAgent agent = await aiProjectClient
- .CreateAIAgentAsync(
- model: deploymentName,
- name: "dotNETRAGAgent",
- instructions: @"You are an AI assistant designed to answer user questions using only the information retrieved from the provided document(s).
- If a user's question cannot be answered using the retrieved context, you must clearly respond:
- 'I'm sorry, but the uploaded document does not contain the necessary information to answer that question.'
- Do not answer from general knowledge or reasoning. Do not make assumptions or generate hypothetical explanations.
- For questions that do have relevant content in the document, respond accurately and cite the document explicitly.",
- tools: [fileSearchTool]);
+// -----------------------------------------------
+// Step 5 — Query (multi-turn)
+// An AgentSession holds the conversation history so follow-up
+// questions can refer back to earlier answers.
+// -----------------------------------------------
+Console.WriteLine("[Step 5] Starting multi-turn RAG session...");
+Console.WriteLine();
AgentSession session = await agent.CreateSessionAsync();
-Console.WriteLine(await agent.RunAsync("What's GraphRAG?", session));
+// Turn 1 — Retrieve a core concept
+Console.WriteLine("Q1: What is GraphRAG?");
+Console.WriteLine(await agent.RunAsync("What is GraphRAG?", session));
+Console.WriteLine();
+
+// Turn 2 — Drill into use cases (tests multi-turn context)
+Console.WriteLine("Q2: What are its main use cases?");
+Console.WriteLine(await agent.RunAsync("What are its main use cases?", session));
+Console.WriteLine();
+
+// Turn 3 — Verify document boundaries (tests refusal on out-of-scope questions)
+Console.WriteLine("Q3: How does it compare to Elasticsearch?");
+Console.WriteLine(await agent.RunAsync("How does it compare to Elasticsearch?", session));
diff --git a/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/README.md b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/README.md
new file mode 100644
index 0000000..cd8e1de
--- /dev/null
+++ b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/README.md
@@ -0,0 +1,36 @@
+# RAG — File Search with Azure AI Foundry (.NET)
+
+> **Maintainer note:** This sample shares the same agent pattern as [`00.ForBeginners/05-agentic-rag/…/dotnet-agent-framework-msfoundry-file-search`](../../../../00.ForBeginners/05-agentic-rag/code_samples/dotnet-agent-framework-msfoundry-file-search/). The two differ only in the uploaded document (`demo.md` here vs. `document.md` there) and the seed question. Consider converging them on a single document or expanding this chapter-level sample with additional RAG patterns (e.g., hybrid search, metadata filters).
+
+Uploads a Markdown knowledge-base document to Azure AI Foundry and uses `HostedFileSearchTool` to build a retrieval-augmented generation (RAG) pipeline. The agent answers questions using only the indexed document.
+
+## What it shows
+- End-to-end RAG pattern: file upload → vector store creation → `HostedFileSearchTool` attachment → grounded Q&A
+- Strict grounding instructions that prevent the agent from using general knowledge
+- `AgentSession` for multi-turn document Q&A
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- An [Azure AI Foundry](https://ai.azure.com) project with a deployed model
+- Azure CLI logged in (`az login`)
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "AZURE_AI_PROJECT_ENDPOINT" ""
+dotnet user-secrets set "AZURE_AI_MODEL_DEPLOYMENT_NAME" "gpt-4o-mini"
+```
+
+> The sample uploads `../../files/demo.md` (located in the `06.RAGs/code_samples/` folder).
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/app.cs b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/app.cs
new file mode 100644
index 0000000..23e0b84
--- /dev/null
+++ b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/app.cs
@@ -0,0 +1,144 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 92469d2f-b467-4911-9cbc-dafa21cc55dd
+#:property EnablePreviewFeatures true
+#:package Azure.AI.OpenAI@2.1.0
+#:package Azure.Identity@1.17.1
+#:package Azure.AI.Projects@1.2.0-beta.5
+#:package Azure.AI.Projects.OpenAI@1.0.0-beta.5
+#:package Azure.AI.Agents.Persistent@1.2.0-beta.8
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.AzureAI@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+// ============================================================
+// RETRIEVAL-AUGMENTED GENERATION (RAG) PIPELINE
+//
+// RAG grounds an LLM in your own documents so it can answer
+// questions about private data it was not trained on.
+//
+// This sample walks through all five steps:
+//
+// Step 1: Upload — send your document(s) to Azure AI Foundry
+// Step 2: Index — create a vector store (searchable index)
+// Step 3: Configure — build a HostedFileSearchTool linked to the store
+// Step 4: Create — define the agent with strict "document-only" instructions
+// Step 5: Query — run multi-turn Q&A; the agent cites its sources
+//
+// Unlike the tool introduction in 04.Tools, the focus here is on
+// building a grounded, citation-accurate assistant that refuses to
+// answer from general knowledge.
+// ============================================================
+
+using System.ClientModel;
+using Azure.AI.Projects;
+using Azure.Identity;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using OpenAI;
+using OpenAI.Files;
+using OpenAI.VectorStores;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
+
+AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
+OpenAIClient openAIClient = aiProjectClient.GetProjectOpenAIClient();
+
+// -----------------------------------------------
+// Step 1 — Upload
+// Upload the knowledge document to Azure AI Foundry.
+// The file is stored server-side and assigned a unique ID.
+// -----------------------------------------------
+Console.WriteLine("[Step 1] Uploading knowledge document...");
+OpenAIFileClient fileClient = openAIClient.GetOpenAIFileClient();
+var uploadResult = await fileClient.UploadFileAsync(
+ filePath: "../../files/demo.md",
+ purpose: FileUploadPurpose.Assistants);
+Console.WriteLine($" File uploaded: {uploadResult.Value.Id}");
+
+// -----------------------------------------------
+// Step 2 — Index
+// Create a vector store from the uploaded file.
+// The vector store converts the document into embeddings so the
+// agent can perform semantic (meaning-based) search at query time.
+// -----------------------------------------------
+Console.WriteLine("[Step 2] Creating vector store (semantic index)...");
+#pragma warning disable OPENAI001
+VectorStoreClient vectorStoreClient = openAIClient.GetVectorStoreClient();
+var vectorStoreResult = await vectorStoreClient.CreateVectorStoreAsync(
+ options: new VectorStoreCreationOptions()
+ {
+ Name = "rag-knowledge-base",
+ FileIds = { uploadResult.Value.Id }
+ });
+#pragma warning restore OPENAI001
+Console.WriteLine($" Vector store created: {vectorStoreResult.Value.Id}");
+
+// -----------------------------------------------
+// Step 3 — Configure
+// Attach the vector store to a HostedFileSearchTool.
+// The tool is the bridge between the agent and the index.
+// -----------------------------------------------
+Console.WriteLine("[Step 3] Configuring HostedFileSearchTool...");
+var fileSearchTool = new HostedFileSearchTool()
+{
+ Inputs = [new HostedVectorStoreContent(vectorStoreResult.Value.Id)]
+};
+
+// -----------------------------------------------
+// Step 4 — Create the RAG agent
+// The system prompt is intentionally strict:
+// • Answer ONLY from the retrieved document context.
+// • Never use general knowledge or make assumptions.
+// • Cite the source document for every factual claim.
+// • Admit clearly when the document does not cover the question.
+// This prevents hallucinations and keeps answers grounded.
+// -----------------------------------------------
+Console.WriteLine("[Step 4] Creating RAG agent...");
+AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
+ model: deploymentName,
+ name: "DocumentRAGAgent",
+ instructions: """
+ You are a document-grounded assistant. Answer user questions using ONLY
+ the information retrieved from the provided file(s).
+
+ Rules:
+ - Cite the source document for every factual statement.
+ - If the document does not contain the answer, respond:
+ "The uploaded document does not contain information to answer that question."
+ - Never answer from general knowledge, training data, or assumptions.
+ - Keep answers concise and accurate.
+ """,
+ tools: [fileSearchTool]);
+
+// -----------------------------------------------
+// Step 5 — Query (multi-turn)
+// An AgentSession holds the conversation history so follow-up
+// questions can refer back to earlier answers.
+// -----------------------------------------------
+Console.WriteLine("[Step 5] Starting multi-turn RAG session...");
+Console.WriteLine();
+
+AgentSession session = await agent.CreateSessionAsync();
+
+// Turn 1 — Retrieve a core concept
+Console.WriteLine("Q1: What is GraphRAG?");
+Console.WriteLine(await agent.RunAsync("What is GraphRAG?", session));
+Console.WriteLine();
+
+// Turn 2 — Drill into use cases (tests multi-turn context)
+Console.WriteLine("Q2: What are its main use cases?");
+Console.WriteLine(await agent.RunAsync("What are its main use cases?", session));
+Console.WriteLine();
+
+// Turn 3 — Verify document boundaries (tests refusal on out-of-scope questions)
+Console.WriteLine("Q3: How does it compare to Elasticsearch?");
+Console.WriteLine(await agent.RunAsync("How does it compare to Elasticsearch?", session));
diff --git a/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj
index 767aa18..a3d6106 100644
--- a/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj
+++ b/06.RAGs/code_samples/dotNET/dotnet-agent-framework-msfoundry-file-search/dotnet-agent-framework-msfoundry-file-search.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,21 +7,27 @@
Trueenableenable
+ 92469d2f-b467-4911-9cbc-dafa21cc55dd
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/01.dotnet-agent-framework-workflow-ghmodel-basic.csproj b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/01.dotnet-agent-framework-workflow-ghmodel-basic.csproj
index c654404..e4adc32 100644
--- a/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/01.dotnet-agent-framework-workflow-ghmodel-basic.csproj
+++ b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/01.dotnet-agent-framework-workflow-ghmodel-basic.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,17 +6,24 @@
_01.dotnet_agent_framework_workflow_ghmodel_basicenableenable
+ c2f12400-7f7c-41bd-a2c5-188e7dbb4e13
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/Program.cs b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/Program.cs
index 685b451..f7cbc30 100644
--- a/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/Program.cs
+++ b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/Program.cs
@@ -1,19 +1,23 @@
-using System;
+using System;
using System.ComponentModel;
using System.ClientModel;
using OpenAI;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
// Load environment variables
-Env.Load("../../../../.env");
// Get GitHub configuration
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT") ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
-var github_model_id = Environment.GetEnvironmentVariable("GITHUB_MODEL_ID") ?? "gpt-4o-mini";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
// Configure OpenAI client
var openAIOptions = new OpenAIClientOptions()
@@ -59,7 +63,7 @@ Consider suggestions when refining an idea.
]);
// Execute workflow
-StreamingRun run = await InProcessExecution.StreamAsync(workflow, userMessage);
+await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, userMessage);
// Process workflow events
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
diff --git a/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/README.md b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/README.md
new file mode 100644
index 0000000..f01124b
--- /dev/null
+++ b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/README.md
@@ -0,0 +1,32 @@
+# Basic Workflow — Two-Agent Review Loop (.NET)
+
+Builds a two-agent workflow using `WorkflowBuilder`: a **FrontDesk** travel agent proposes activity recommendations and a **Concierge** reviewer accepts or requests refinements. The agents take turns until the concierge approves.
+
+## What it shows
+- Building a directed agent graph with `WorkflowBuilder.AddEdge`
+- Running a workflow with `InProcessExecution.RunStreamingAsync`
+- Consuming `WorkflowEvent` / `AgentResponseUpdateEvent` updates in a streaming loop
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+dotnet user-secrets set "GITHUB_MODEL_ID" "gpt-4o-mini"
+```
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/app.cs b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/app.cs
new file mode 100644
index 0000000..6622902
--- /dev/null
+++ b/07.Workflow/code_samples/dotNET/01.dotnet-agent-framework-workflow-ghmodel-basic/app.cs
@@ -0,0 +1,108 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId c2f12400-7f7c-41bd-a2c5-188e7dbb4e13
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Agents.AI.Workflows@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.ComponentModel;
+using System.ClientModel;
+using OpenAI;
+using Microsoft.Extensions.AI;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.Workflows;
+using Microsoft.Extensions.Configuration;
+
+// Load environment variables
+
+// Get GitHub configuration
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_model_id = config["GITHUB_MODEL_ID"] ?? "gpt-4o-mini";
+var github_token = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+// Configure OpenAI client
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint = new Uri(github_endpoint)
+};
+
+var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
+
+// Define agent configurations
+const string ReviewerAgentName = "Concierge";
+const string ReviewerAgentInstructions = @"
+ You are an are hotel concierge who has opinions about providing the most local and authentic experiences for travelers.
+ The goal is to determine if the front desk travel agent has recommended the best non-touristy experience for a traveler.
+ If so, state that it is approved.
+ If not, provide insight on how to refine the recommendation without using a specific example.
+ ";
+
+const string FrontDeskAgentName = "FrontDesk";
+const string FrontDeskAgentInstructions = @"
+ You are a Front Desk Travel Agent with ten years of experience and are known for brevity as you deal with many customers.
+ The goal is to provide the best activities and locations for a traveler to visit.
+ Only provide a single recommendation per response.
+ You're laser focused on the goal at hand.
+ Don't waste time with chit chat.
+ Consider suggestions when refining an idea.
+ ";
+
+// Create AI agents
+AIAgent reviewerAgent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: ReviewerAgentName, instructions: ReviewerAgentInstructions);
+AIAgent frontDeskAgent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: FrontDeskAgentName, instructions: FrontDeskAgentInstructions);
+
+// Build workflow
+var workflow = new WorkflowBuilder(frontDeskAgent)
+ .AddEdge(frontDeskAgent, reviewerAgent)
+ .Build();
+
+// Create user message
+ChatMessage userMessage = new ChatMessage(ChatRole.User, [
+ new TextContent("I would like to go to Paris.")
+]);
+
+// Execute workflow
+await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, userMessage);
+
+// Process workflow events
+await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
+
+string messageData = "";
+
+await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
+{
+ if (evt is AgentResponseUpdateEvent executorComplete)
+ {
+ messageData += executorComplete.Data;
+ Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
+ }
+}
+
+Console.WriteLine("\n=== Final Output ===");
+Console.WriteLine(messageData);
+
+// Mermaid
+Console.WriteLine("\nMermaid string: \n=======");
+var mermaid = workflow.ToMermaidString();
+Console.WriteLine(mermaid);
+Console.WriteLine("=======");
+
+// DOT - Save to file instead of stdout to avoid pipe issues
+var dotString = workflow.ToDotString();
+var dotFilePath = "workflow.dot";
+File.WriteAllText(dotFilePath, dotString);
+Console.WriteLine($"\nDOT graph saved to: {dotFilePath}");
+Console.WriteLine("To generate image: dot -Tsvg workflow.dot -o workflow.svg");
+Console.WriteLine(" dot -Tpng workflow.dot -o workflow.png");
diff --git a/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/02.dotnet-agent-framework-workflow-ghmodel-sequential.csproj b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/02.dotnet-agent-framework-workflow-ghmodel-sequential.csproj
index 0e453f8..2329f2f 100644
--- a/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/02.dotnet-agent-framework-workflow-ghmodel-sequential.csproj
+++ b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/02.dotnet-agent-framework-workflow-ghmodel-sequential.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,17 +6,24 @@
_02.dotnet_agent_framework_workflow_ghmodel_sequentialenableenable
+ b0f6cf92-970e-48d5-94e4-58e1561d4fff
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/Program.cs b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/Program.cs
index 5602300..4df304c 100644
--- a/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/Program.cs
+++ b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/Program.cs
@@ -1,18 +1,20 @@
-using System;
+using System;
using System.ComponentModel;
using System.ClientModel;
using OpenAI;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
-// Load environment variables
-Env.Load("../../../../.env");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT") ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_endpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
var github_model_id = "gpt-4o";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+var github_token = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
var imgPath = "../../imgs/home.png";
@@ -78,7 +80,7 @@ async Task OpenImageBytesAsync(string path)
]);
// Execute workflow
-StreamingRun run = await InProcessExecution.StreamAsync(workflow, userMessage);
+StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, userMessage);
// Process streaming results
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
diff --git a/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/README.md b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/README.md
new file mode 100644
index 0000000..eec40c5
--- /dev/null
+++ b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/README.md
@@ -0,0 +1,33 @@
+# Sequential Workflow — Image-to-Quote Pipeline (.NET)
+
+Constructs a three-stage sequential workflow: a **Sales Agent** identifies furniture from a room image, a **Price Agent** estimates costs, and a **Quote Agent** produces a formatted Markdown purchase quote. Demonstrates multimodal input fed into a linear agent chain.
+
+## What it shows
+- A multi-stage sequential pipeline with `WorkflowBuilder`
+- Passing image bytes (`DataContent`) as initial workflow input
+- Each agent receiving the previous agent's output as context
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token with access to `gpt-4o`
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+```
+
+> The model is hardcoded to `gpt-4o`. The image used is `../../imgs/home.png` (relative to the project folder).
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/app.cs b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/app.cs
new file mode 100644
index 0000000..ad57e83
--- /dev/null
+++ b/07.Workflow/code_samples/dotNET/02.dotnet-agent-framework-workflow-ghmodel-sequential/app.cs
@@ -0,0 +1,122 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId b0f6cf92-970e-48d5-94e4-58e1561d4fff
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Agents.AI.Workflows@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.ComponentModel;
+using System.ClientModel;
+using OpenAI;
+using Microsoft.Extensions.AI;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.Workflows;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_model_id = "gpt-4o";
+var github_token = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+var imgPath = "../../imgs/home.png";
+
+// Configure OpenAI client
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint = new Uri(github_endpoint)
+};
+
+var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
+
+// Define agent names and instructions
+const string SalesAgentName = "Sales-Agent";
+const string SalesAgentInstructions = "You are my furniture sales consultant, you can find different furniture elements from the pictures and give me a purchase suggestion";
+
+const string PriceAgentName = "Price-Agent";
+const string PriceAgentInstructions = @"You are a furniture pricing specialist and budget consultant. Your responsibilities include:
+ 1. Analyze furniture items and provide realistic price ranges based on quality, brand, and market standards
+ 2. Break down pricing by individual furniture pieces
+ 3. Provide budget-friendly alternatives and premium options
+ 4. Consider different price tiers (budget, mid-range, premium)
+ 5. Include estimated total costs for room setups
+ 6. Suggest where to find the best deals and shopping recommendations
+ 7. Factor in additional costs like delivery, assembly, and accessories
+ 8. Provide seasonal pricing insights and best times to buy
+ Always format your response with clear price breakdowns and explanations for the pricing rationale.";
+
+const string QuoteAgentName = "Quote-Agent";
+const string QuoteAgentInstructions = @"You are a assistant that create a quote for furniture purchase.
+ 1. Create a well-structured quote document that includes:
+ 2. A title page with the document title, date, and client name
+ 3. An introduction summarizing the purpose of the document
+ 4. A summary section with total estimated costs and recommendations
+ 5. Use clear headings, bullet points, and tables for easy readability
+ 6. All quotes are presented in markdown form";
+
+// Read image bytes
+async Task OpenImageBytesAsync(string path)
+{
+ return await File.ReadAllBytesAsync(path);
+}
+
+var imageBytes = await OpenImageBytesAsync(imgPath);
+
+// Create AI agents
+AIAgent salesagent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: SalesAgentName, instructions: SalesAgentInstructions);
+AIAgent priceagent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: PriceAgentName, instructions: PriceAgentInstructions);
+AIAgent quoteagent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: QuoteAgentName, instructions: QuoteAgentInstructions);
+
+// Build sequential workflow
+var workflow = new WorkflowBuilder(salesagent)
+ .AddEdge(salesagent, priceagent)
+ .AddEdge(priceagent, quoteagent)
+ .Build();
+
+// Create user message with image
+ChatMessage userMessage = new ChatMessage(ChatRole.User, [
+ new DataContent(imageBytes, "image/png"),
+ new TextContent("Please find the relevant furniture according to the image and give the corresponding price for each piece of furniture.Finally Output generates a quotation")
+]);
+
+// Execute workflow
+StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, userMessage);
+
+// Process streaming results
+await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
+string id = "";
+string messageData = "";
+await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
+{
+ if (evt is AgentResponseUpdateEvent executorComplete)
+ {
+ messageData += executorComplete.Data;
+ Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
+ }
+}
+
+Console.WriteLine(messageData);
+// Mermaid
+Console.WriteLine("\nMermaid string: \n=======");
+var mermaid = workflow.ToMermaidString();
+Console.WriteLine(mermaid);
+Console.WriteLine("=======");
+
+// DOT - Save to file instead of stdout to avoid pipe issues
+var dotString = workflow.ToDotString();
+var dotFilePath = "workflow.dot";
+File.WriteAllText(dotFilePath, dotString);
+Console.WriteLine($"\nDOT graph saved to: {dotFilePath}");
+Console.WriteLine("To generate image: dot -Tsvg workflow.dot -o workflow.svg");
+Console.WriteLine(" dot -Tpng workflow.dot -o workflow.png");
diff --git a/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/03.dotnet-agent-framework-workflow-ghmodel-concurrent.csproj b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/03.dotnet-agent-framework-workflow-ghmodel-concurrent.csproj
index 7055382..11a6b5d 100644
--- a/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/03.dotnet-agent-framework-workflow-ghmodel-concurrent.csproj
+++ b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/03.dotnet-agent-framework-workflow-ghmodel-concurrent.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -6,17 +6,24 @@
_03.dotnet_agent_framework_workflow_ghmodel_concurrentenableenable
+ 248d296e-d7c2-464b-8ace-5e2c3b1cbdc9
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/Program.cs b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/Program.cs
index 747fb5e..dcac5ff 100644
--- a/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/Program.cs
+++ b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/Program.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.ComponentModel;
using System.ClientModel;
using OpenAI;
@@ -6,14 +6,16 @@
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Reflection;
-using DotNetEnv;
+using Microsoft.Extensions.Configuration;
-// Load environment variables
-Env.Load("../../../../.env");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT") ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_endpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
var github_model_id = "gpt-4o";
-var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+var github_token = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
// Configure OpenAI client
var openAIOptions = new OpenAIClientOptions()
@@ -43,13 +45,13 @@
// Build concurrent workflow with FanOut/FanIn pattern
var workflow = new WorkflowBuilder(startExecutor)
.AddFanOutEdge(startExecutor, targets: [researcherAgent, plannerAgent])
- .AddFanInEdge(sources: [researcherAgent, plannerAgent], aggregationExecutor)
+ .AddFanInBarrierEdge(sources: [researcherAgent, plannerAgent], aggregationExecutor)
.WithOutputFrom(aggregationExecutor)
.Build();
string messageData = "";
// Execute workflow
-StreamingRun run = await InProcessExecution.StreamAsync(workflow, "Plan a trip to Seattle in December");
+await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, "Plan a trip to Seattle in December");
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
{
if (evt is AgentResponseUpdateEvent executorComplete)
diff --git a/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/README.md b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/README.md
new file mode 100644
index 0000000..223b552
--- /dev/null
+++ b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/README.md
@@ -0,0 +1,35 @@
+# Concurrent Workflow — Fan-Out / Fan-In Pattern (.NET)
+
+Demonstrates a parallel (fan-out) workflow: a **Researcher** and a **Planner** agent run concurrently on the same input, and a `ConcurrentAggregationExecutor` merges their outputs before producing a final combined travel plan.
+
+## What it shows
+- `WorkflowBuilder.AddFanOutEdge` to dispatch to multiple agents simultaneously
+- `AddFanInBarrierEdge` with `ConcurrentAggregationExecutor` to merge parallel outputs
+- `ConcurrentStartExecutor` as the workflow entry point
+
+> **Note:** `ReflectingExecutor` and `IMessageHandler` used in this sample are marked obsolete. They will be replaced with `[MessageHandler]`-attributed partial classes in a future version.
+
+## Prerequisites
+- [.NET 10 SDK](https://dot.net)
+- A [GitHub Models](https://github.com/marketplace/models) personal access token with access to `gpt-4o`
+
+## Configure secrets
+
+```bash
+dotnet user-secrets set "GITHUB_TOKEN" ""
+dotnet user-secrets set "GITHUB_ENDPOINT" "https://models.inference.ai.azure.com"
+```
+
+> The model is hardcoded to `gpt-4o`.
+
+## Run
+
+```bash
+dotnet run
+```
+
+## Run with file-based approach (.NET 10)
+
+```bash
+dotnet run app.cs
+```
diff --git a/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/app.cs b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/app.cs
new file mode 100644
index 0000000..d23109d
--- /dev/null
+++ b/07.Workflow/code_samples/dotNET/03.dotnet-agent-framework-workflow-ghmodel-concurrent/app.cs
@@ -0,0 +1,131 @@
+// File-based run: dotnet run app.cs
+#:property UserSecretsId 248d296e-d7c2-464b-8ace-5e2c3b1cbdc9
+#:package Microsoft.Extensions.AI@10.3.0
+#:package Microsoft.Extensions.AI.OpenAI@10.3.0
+#:package OpenAI@2.8.0
+#:package Microsoft.Agents.AI@1.0.0-rc1
+#:package Microsoft.Agents.AI.OpenAI@1.0.0-rc1
+#:package Microsoft.Agents.AI.Workflows@1.0.0-rc1
+#:package Microsoft.Extensions.Configuration.UserSecrets@10.0.0
+#:package Microsoft.Extensions.Configuration.EnvironmentVariables@10.0.0
+
+using System;
+using System.ComponentModel;
+using System.ClientModel;
+using OpenAI;
+using Microsoft.Extensions.AI;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.Workflows;
+using Microsoft.Agents.AI.Workflows.Reflection;
+using Microsoft.Extensions.Configuration;
+
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
+
+var github_endpoint = config["GITHUB_ENDPOINT"] ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
+var github_model_id = "gpt-4o";
+var github_token = config["GITHUB_TOKEN"] ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
+
+// Configure OpenAI client
+var openAIOptions = new OpenAIClientOptions()
+{
+ Endpoint = new Uri(github_endpoint)
+};
+
+var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
+
+// Define agent names and instructions
+const string ResearcherAgentName = "Researcher-Agent";
+const string ResearcherAgentInstructions = "You are my travel researcher, working with me to analyze the destination, list relevant attractions, and make detailed plans for each attraction.";
+
+const string PlanAgentName = "Plan-Agent";
+const string PlanAgentInstructions = "You are my travel planner, working with me to create a detailed travel plan based on the researcher's findings.";
+
+// Create AI agents
+AIAgent researcherAgent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: ResearcherAgentName, instructions: ResearcherAgentInstructions);
+AIAgent plannerAgent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
+ name: PlanAgentName, instructions: PlanAgentInstructions);
+
+// Create concurrent executors
+var startExecutor = new ConcurrentStartExecutor();
+var aggregationExecutor = new ConcurrentAggregationExecutor();
+
+// Build concurrent workflow with FanOut/FanIn pattern
+var workflow = new WorkflowBuilder(startExecutor)
+ .AddFanOutEdge(startExecutor, targets: [researcherAgent, plannerAgent])
+ .AddFanInBarrierEdge(sources: [researcherAgent, plannerAgent], aggregationExecutor)
+ .WithOutputFrom(aggregationExecutor)
+ .Build();
+
+string messageData = "";
+// Execute workflow
+await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, "Plan a trip to Seattle in December");
+await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
+{
+ if (evt is AgentResponseUpdateEvent executorComplete)
+ {
+ messageData += executorComplete.Data;
+ Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
+ }
+}
+
+Console.WriteLine(messageData);
+
+
+// Mermaid
+Console.WriteLine("\nMermaid string: \n=======");
+var mermaid = workflow.ToMermaidString();
+Console.WriteLine(mermaid);
+Console.WriteLine("=======");
+
+// DOT - Save to file instead of stdout to avoid pipe issues
+var dotString = workflow.ToDotString();
+var dotFilePath = "workflow.dot";
+File.WriteAllText(dotFilePath, dotString);
+Console.WriteLine($"\nDOT graph saved to: {dotFilePath}");
+Console.WriteLine("To generate image: dot -Tsvg workflow.dot -o workflow.svg");
+Console.WriteLine(" dot -Tpng workflow.dot -o workflow.png");
+
+///
+/// Executor that starts the concurrent processing by broadcasting messages to all agents.
+///
+public class ConcurrentStartExecutor() :
+ ReflectingExecutor("ConcurrentStartExecutor"),
+ IMessageHandler
+{
+ ///
+ /// Starts the concurrent processing by sending messages to the agents.
+ ///
+ public async ValueTask HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default)
+ {
+ await context.SendMessageAsync(new ChatMessage(ChatRole.User, message));
+ await context.SendMessageAsync(new TurnToken(emitEvents: true));
+ }
+}
+
+///
+/// Executor that aggregates the results from the concurrent agents.
+///
+public class ConcurrentAggregationExecutor() :
+ ReflectingExecutor("ConcurrentAggregationExecutor"),
+ IMessageHandler
+{
+ private readonly List _messages = [];
+
+ ///
+ /// Handles incoming messages from the agents and aggregates their responses.
+ ///
+ public async ValueTask HandleAsync(ChatMessage message, IWorkflowContext context, CancellationToken cancellationToken = default)
+ {
+ this._messages.Add(message);
+
+ if (this._messages.Count == 2)
+ {
+ var formattedMessages = string.Join(Environment.NewLine, this._messages.Select(m => $"{m.AuthorName}: {m.Text}"));
+ await context.YieldOutputAsync(formattedMessages);
+ }
+ }
+}
diff --git a/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/04.dotnet-agent-framework-workflow-msfoundry-condition.csproj b/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/04.dotnet-agent-framework-workflow-msfoundry-condition.csproj
index aca35d0..8425d2d 100644
--- a/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/04.dotnet-agent-framework-workflow-msfoundry-condition.csproj
+++ b/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/04.dotnet-agent-framework-workflow-msfoundry-condition.csproj
@@ -1,4 +1,4 @@
-
+Exe
@@ -7,23 +7,29 @@
Trueenableenable
+ 861df000-8a3f-4d7f-a4ba-b14286e638a2$(NoWarn);CA1812;OPENAI001;MEAI001
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-
+
+
+
+
\ No newline at end of file
diff --git a/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/Program.cs b/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/Program.cs
index c2d1e23..7eb6307 100644
--- a/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/Program.cs
+++ b/07.Workflow/code_samples/dotNET/04.dotnet-agent-framework-workflow-msfoundry-condition/Program.cs
@@ -1,351 +1,116 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.IO;
-using System.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using Azure.Identity;
using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
+using Azure.Identity;
using Microsoft.Agents.AI;
-using Microsoft.Extensions.AI;
using Microsoft.Agents.AI.Workflows;
-using Microsoft.Agents.AI.Workflows.Reflection;
-using OpenAI.Assistants;
-using OpenAI.Responses;
-using DotNetEnv;
-using Azure.AI.Agents.Persistent;
-
-// Load environment variables
-Env.Load("../../../../.env");
-
-var azure_foundry_endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
-var azure_foundry_model_id = "gpt-4.1-mini";
-var bing_conn_id = Environment.GetEnvironmentVariable("BING_CONNECTION_ID") ?? throw new InvalidOperationException("BING_CONNECTION_ID is not set.");
-
-// Agent instructions
-const string EvangelistInstructions = @"
-You are a technology evangelist create a first draft for a technical tutorials.
-1. Each knowledge point in the outline must include a link. Follow the link to access the content related to the knowledge point in the outline. Expand on that content.
-2. Each knowledge point must be explained in detail.
-3. Rewrite the content according to the entry requirements, including the title, outline, and corresponding content. It is not necessary to follow the outline in full order.
-4. The content must be more than 200 words.
-4. Output draft as Markdown format. set 'draft_content' to the draft content.
-5. return result as JSON with fields 'draft_content' (string).";
-
-const string ContentReviewerInstructions = @"
-You are a content reviewer and need to check whether the tutorial's draft content meets the following requirements:
-
-1. The draft content less than 200 words, set 'review_result' to 'No' and 'reason' to 'Content is too short'. If the draft content is more than 200 words, set 'review_result' to 'Yes' and 'reason' to 'The content is good'.
-2. set 'draft_content' to the original draft content.
-3. return result as JSON with fields 'review_result' ('Yes' or 'No' ) and 'reason' (string) and 'draft_content' (string).";
-
-const string PublisherInstructions = @"
-You are the content publisher ,run code to save the tutorial's draft content as a Markdown file. Saved file's name is marked with current date and time, such as yearmonthdayhourminsec. Note that if it is 1-9, you need to add 0, such as 20240101123045.md.
-";
-
-string OUTLINE_Content = @"
-# Introduce AI Agent
-
-## What's AI Agent
-
-https://github.com/microsoft/ai-agents-for-beginners/tree/main/01-intro-to-ai-agents
-
-***Note*** Don's create any sample code
-
-## Introduce Azure AI Foundry Agent Service
-
-https://learn.microsoft.com/en-us/azure/ai-foundry/agents/overview
-
-***Note*** Don's create any sample code
-
-## Microsoft Agent Framework
-
-https://github.com/microsoft/agent-framework/tree/main/docs/docs-templates
-
-***Note*** Don's create any sample code
-";
-
-
-AIProjectClient aiProjectClient = new(
- new Uri(azure_foundry_endpoint),
- new AzureCliCredential());
-
-
-
-var connectionName = Environment.GetEnvironmentVariable("BING_CONNECTION_NAME");
-
-Console.WriteLine($"Using Bing Connection: {connectionName}");
-
-AIProjectConnection bingConnectionName = aiProjectClient.Connections.GetConnection(connectionName: connectionName);
-
-
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Configuration;
-// Console.WriteLine($"Using Bing Connection ID: {bing_conn_id}");
+var config = new ConfigurationBuilder()
+ .AddUserSecrets()
+ .AddEnvironmentVariables()
+ .Build();
-// Configure Bing Grounding Tool
-BingGroundingAgentTool bingGroundingAgentTool = new(new BingGroundingSearchToolOptions(
- searchConfigurations: [new Azure.AI.Projects.OpenAI.BingGroundingSearchConfiguration(projectConnectionId: bingConnectionName.Id)]
- )
-);
+var endpoint = config["AZURE_AI_PROJECT_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
+var deploymentName = config["AZURE_AI_MODEL_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";
+// Create an Azure AI Foundry project client
+AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
-AIAgent evangelistagent = await aiProjectClient.CreateAIAgentAsync(
- name: "dotNETEvangelist",
+// Create four specialist agents as Azure AI Foundry persistent agents
+AIAgent writerAgent = await aiProjectClient.CreateAIAgentAsync(
+ name: "Writer-Agent",
creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: azure_foundry_model_id)
+ new PromptAgentDefinition(model: deploymentName)
{
- Instructions = EvangelistInstructions,
- Tools = {
- bingGroundingAgentTool,
- }
- })
-);
-
-// var conttent_ResponseFormat = ChatResponseFormat.ForJsonSchema(AIJsonUtilities.CreateJsonSchema(typeof(ContentResult)), "ContentResult", "Content Result with DraftContent");
-
-// var content_option = new ChatOptions{
-// ResponseFormat = conttent_ResponseFormat
-// };
-
-AIAgent contentRevieweragent = await aiProjectClient.CreateAIAgentAsync(
- name: "dotNETContentReviewer",
+ Instructions = """
+ You are a creative travel content writer.
+ When given a destination, write a concise, engaging 2-3 sentence paragraph about it.
+ Focus on what makes it unique and appealing to visitors.
+ """
+ }));
+
+AIAgent reviewerAgent = await aiProjectClient.CreateAIAgentAsync(
+ name: "Reviewer-Agent",
creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: azure_foundry_model_id)
+ new PromptAgentDefinition(model: deploymentName)
{
- Instructions = ContentReviewerInstructions,
- })
-
-);
-
-AIAgent publisheragent = await aiProjectClient.CreateAIAgentAsync(
- name: "dotNETPublisher",
+ Instructions = """
+ You are a strict travel content quality reviewer.
+ Review the content and decide whether it is ready to publish.
+ Your first word MUST be either "APPROVED" or "REVISE" followed by your feedback.
+ Example: "APPROVED: Great descriptions, ready to publish."
+ Example: "REVISE: Missing specific landmarks and local details."
+ """
+ }));
+
+AIAgent editorAgent = await aiProjectClient.CreateAIAgentAsync(
+ name: "Editor-Agent",
creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: azure_foundry_model_id)
+ new PromptAgentDefinition(model: deploymentName)
{
- Instructions = PublisherInstructions,
- Tools = {
- ResponseTool.CreateCodeInterpreterTool(
- new CodeInterpreterToolContainer(
- CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration(fileIds: [])
- )
- ),
- },
- })
-);
-
-
-
-// Create the three specialized agents
-// var evangelistMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
-// model: azure_foundry_model_id,
-// name: "dotNETEvangelist",
-// instructions: EvangelistInstructions,
-// tools: [bingGroundingTool]
-// );
-
-// var contentReviewerMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
-// model: azure_foundry_model_id,
-// name: "dotNETContentReviewer",
-// instructions: ContentReviewerInstructions
-// );
-
-// var publisherMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
-// model: azure_foundry_model_id,
-// name: "dotNETPublisher",
-// instructions: PublisherInstructions,
-// tools: [new CodeInterpreterToolDefinition()]
-// );
-
-
-// AIAgent publisheragent = await agentsClient.GetAIAgentAsync(publisher_agentId);
-
-// Create the three specialized agents
-// var evangelistMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
-// model: azure_foundry_model_id,
-// name: "Evangelist",
-// instructions: EvangelistInstructions,
-// tools: [bingGroundingTool]
-// );
-
-// var contentReviewerMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
-// model: azure_foundry_model_id,
-// name: "ContentReviewer",
-// instructions: ContentReviewerInstructions
-// );
-
-// var publisherMetadata = await persistentAgentsClient.Administration.CreateAgentAsync(
-// model: azure_foundry_model_id,
-// name: "Publisher",
-// instructions: PublisherInstructions,
-// tools: [new CodeInterpreterToolDefinition()]
-// );
-
-// string evangelist_agentId = evangelistMetadata.Value.Id;
-// string contentReviewer_agentId = contentReviewerMetadata.Value.Id;
-// string publisher_agentId = publisherMetadata.Value.Id;
-
-// // Get AI Agents
-// AIAgent evangelistagent = await persistentAgentsClient.GetAIAgentAsync(evangelist_agentId, new()
-// {
-// // ResponseFormat = ChatResponseFormat.ForJsonSchema(AIJsonUtilities.CreateJsonSchema(typeof(ContentResult)), "ContentResult", "Content Result with DraftContent"),
-// });
-
-// AIAgent contentRevieweragent = await persistentAgentsClient.GetAIAgentAsync(contentReviewer_agentId, new()
-// {
-// ResponseFormat = ChatResponseFormat.ForJsonSchema(AIJsonUtilities.CreateJsonSchema(typeof(ReviewResult)), "ReviewResult", "Review Result From DraftContent")
-// });
-
-// AIAgent publisheragent = await persistentAgentsClient.GetAIAgentAsync(publisher_agentId);
-
-// Create executors
-var draftExecutor = new DraftExecutor(evangelistagent);
-var contentReviewerExecutor = new ContentReviewExecutor(contentRevieweragent);
-var publishExecutor = new PublishExecutor(publisheragent);
-var sendReviewerExecutor = new SendReviewExecutor();
-
-// Build workflow with conditional logic
-var workflow = new WorkflowBuilder(draftExecutor)
- .AddEdge(draftExecutor, contentReviewerExecutor)
- .AddEdge(contentReviewerExecutor, publishExecutor, condition: GetCondition(expectedResult: "Yes"))
- .AddEdge(contentReviewerExecutor, sendReviewerExecutor, condition: GetCondition(expectedResult: "No"))
- .WithOutputFrom(publishExecutor, sendReviewerExecutor)
+ Instructions = """
+ You are a travel content editor.
+ You receive content flagged for revision. Improve it by adding specific landmarks,
+ local cuisine highlights, and vivid sensory details. Return only the improved paragraph.
+ """
+ }));
+
+AIAgent publisherAgent = await aiProjectClient.CreateAIAgentAsync(
+ name: "Publisher-Agent",
+ creationOptions: new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: deploymentName)
+ {
+ Instructions = """
+ You are a travel content publisher.
+ Format the final content with a bold heading and return the polished result.
+ """
+ }));
+
+// Condition predicates that inspect the reviewer agent's ChatMessage output
+static bool IsApproved(ChatMessage? msg) =>
+ msg?.Text?.Contains("APPROVED", StringComparison.OrdinalIgnoreCase) == true;
+
+static bool NeedsRevision(ChatMessage? msg) =>
+ msg?.Text?.Contains("REVISE", StringComparison.OrdinalIgnoreCase) == true;
+
+// Build the conditional workflow:
+//
+// writerAgent → reviewerAgent
+// ↓ [APPROVED] ──────────────── publisherAgent
+// ↓ [REVISE] → editorAgent → publisherAgent
+//
+var workflow = new WorkflowBuilder(writerAgent)
+ .AddEdge(writerAgent, reviewerAgent)
+ .AddEdge(reviewerAgent, publisherAgent, IsApproved, label: "approved")
+ .AddEdge(reviewerAgent, editorAgent, NeedsRevision, label: "needs revision")
+ .AddEdge(editorAgent, publisherAgent)
.Build();
-// Prepare prompt
-string prompt = @"You need to write a draft based on the following outline and the content provided in the link corresponding to the outline.
-After draft create , the reviewer check it , if it meets the requirements, it will be submitted to the publisher and save it as a Markdown file,
-otherwise need to rewrite draft until it meets the requirements.
-The provided outline content and related links is as follows:" + OUTLINE_Content;
+Console.WriteLine("=== Conditional Content Workflow — Azure AI Foundry ===\n");
-Console.WriteLine("Starting workflow...");
-
-// Execute workflow
-var chat = new ChatMessage(ChatRole.User, prompt);
-await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, chat);
-
-// Process workflow events
+// Execute the workflow with a travel destination as input
+await using StreamingRun run = await InProcessExecution.RunStreamingAsync(
+ workflow,
+ new ChatMessage(ChatRole.User, "Write travel content about Tokyo, Japan."));
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
{
- if (evt is WorkflowOutputEvent outputEvent)
+ if (evt is AgentResponseUpdateEvent update)
{
- Console.WriteLine($"{outputEvent}");
+ Console.Write($"[{update.ExecutorId}] {update.Data}");
}
}
+Console.WriteLine("\n");
-// Mermaid
-Console.WriteLine("\nMermaid string: \n=======");
-var mermaid = workflow.ToMermaidString();
-Console.WriteLine(mermaid);
-Console.WriteLine("=======");
+// Visualize the workflow graph
+Console.WriteLine("Workflow Mermaid:\n=======");
+Console.WriteLine(workflow.ToMermaidString());
+Console.WriteLine("=======\n");
-// DOT - Save to file instead of stdout to avoid pipe issues
-var dotString = workflow.ToDotString();
var dotFilePath = "workflow.dot";
-File.WriteAllText(dotFilePath, dotString);
-Console.WriteLine($"\nDOT graph saved to: {dotFilePath}");
-Console.WriteLine("To generate image: dot -Tsvg workflow.dot -o workflow.svg");
-Console.WriteLine(" dot -Tpng workflow.dot -o workflow.png");
-
-// Helper function for conditional routing
-static Func