diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 85769f892d..a4a699b780 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -79,6 +79,7 @@
+
diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index e764f4c936..f46ab37c4f 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -25,6 +25,8 @@
+
+
@@ -43,6 +45,7 @@
+
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj
new file mode 100644
index 0000000000..4fa7edf3fc
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net9.0
+ 12
+
+ enable
+ disable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs
new file mode 100644
index 0000000000..df315dbfaa
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/Program.cs
@@ -0,0 +1,102 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample shows all the required steps to create a fully custom agent implementation.
+// In this case the agent doesn't use AI at all, and simply parrots back the user input in upper case.
+// You can however, build a fully custom agent that uses AI in any way you want.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.AI.Agents;
+using SampleApp;
+
+AIAgent agent = new UpperCaseParrotAgent();
+
+// Invoke the agent and output the text result.
+Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
+
+// Invoke the agent with streaming support.
+await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate."))
+{
+ Console.WriteLine(update);
+}
+
+namespace SampleApp
+{
+ // Custom agent that parrot's the user input back in upper case.
+ internal sealed class UpperCaseParrotAgent : AIAgent
+ {
+ public override async Task RunAsync(IReadOnlyCollection messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
+ {
+ // Create a thread if the user didn't supply one.
+ thread ??= this.GetNewThread();
+
+ // Clone the input messages and turn them into response messages with upper case text.
+ List responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
+
+ // Notify the thread of the input and output messages.
+ await NotifyThreadOfNewMessagesAsync(thread, messages, cancellationToken);
+ await NotifyThreadOfNewMessagesAsync(thread, responseMessages, cancellationToken);
+
+ return new AgentRunResponse
+ {
+ AgentId = this.Id,
+ ResponseId = Guid.NewGuid().ToString(),
+ Messages = responseMessages
+ };
+ }
+
+ public override async IAsyncEnumerable RunStreamingAsync(IReadOnlyCollection messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ // Create a thread if the user didn't supply one.
+ thread ??= this.GetNewThread();
+
+ // Clone the input messages and turn them into response messages with upper case text.
+ List responseMessages = CloneAndToUpperCase(messages, this.DisplayName).ToList();
+
+ // Notify the thread of the input and output messages.
+ await NotifyThreadOfNewMessagesAsync(thread, messages, cancellationToken);
+ await NotifyThreadOfNewMessagesAsync(thread, responseMessages, cancellationToken);
+
+ foreach (var message in responseMessages)
+ {
+ yield return new AgentRunResponseUpdate
+ {
+ AgentId = this.Id,
+ AuthorName = this.DisplayName,
+ Role = ChatRole.Assistant,
+ Contents = message.Contents,
+ ResponseId = Guid.NewGuid().ToString(),
+ MessageId = Guid.NewGuid().ToString()
+ };
+ }
+ }
+
+ private static IEnumerable CloneAndToUpperCase(IReadOnlyCollection messages, string agentName) => messages.Select(x =>
+ {
+ // Clone the message and update its author to be the agent.
+ var messageClone = x.Clone();
+ messageClone.Role = ChatRole.Assistant;
+ messageClone.MessageId = Guid.NewGuid().ToString();
+ messageClone.AuthorName = agentName;
+
+ // Clone and convert any text content to upper case.
+ messageClone.Contents = x.Contents.Select(c => c switch
+ {
+ TextContent tc => new TextContent(tc.Text.ToUpperInvariant())
+ {
+ AdditionalProperties = tc.AdditionalProperties,
+ Annotations = tc.Annotations,
+ RawRepresentation = tc.RawRepresentation
+ },
+ _ => c
+ }).ToList();
+
+ return messageClone;
+ });
+ }
+}
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md
new file mode 100644
index 0000000000..97eb3e87d3
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_CustomImplementation/README.md
@@ -0,0 +1,3 @@
+# Prerequisites
+
+This sample has no prerequisites.
\ No newline at end of file
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs
index 94994dd92d..8a2579b1ff 100644
--- a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/Program.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
// This sample shows how to create and use a simple AI agent with ONNX as the backend.
+// WARNING: ONNX doesn't support function calling, so any function tools passed to the agent will be ignored.
using System;
using Microsoft.Extensions.AI.Agents;
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/README.md b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/README.md
index 7bfacf30e9..cb86e0d7c4 100644
--- a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/README.md
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_ONNX/README.md
@@ -1,10 +1,18 @@
# Prerequisites
+WARNING: ONNX doesn't support function calling, so any function tools passed to the agent will be ignored.
+
Before you begin, ensure you have the following prerequisites:
- .NET 8.0 SDK or later
- An ONNX model downloaded to your machine
+You can download an ONNX model from hugging face, using git clone:
+
+```powershell
+git clone https://huggingface.co/microsoft/Phi-4-mini-instruct-onnx
+```
+
Set the following environment variables:
```powershell
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj
new file mode 100644
index 0000000000..44603cc24c
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Agent_With_Ollama.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ net9.0
+ 12
+
+ enable
+ disable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs
new file mode 100644
index 0000000000..9a8b028f5f
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/Program.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// This sample shows how to create and use a simple AI agent with Ollama as the backend.
+
+using System;
+using Microsoft.Extensions.AI.Agents;
+using OllamaSharp;
+
+var endpoint = Environment.GetEnvironmentVariable("OLLAMA_ENDPOINT") ?? throw new InvalidOperationException("OLLAMA_ENDPOINT is not set.");
+var modelName = Environment.GetEnvironmentVariable("OLLAMA_MODEL_NAME") ?? throw new InvalidOperationException("OLLAMA_MODEL_NAME is not set.");
+
+const string JokerName = "Joker";
+const string JokerInstructions = "You are good at telling jokes.";
+
+// Get a chat client for Ollama and use it to construct an AIAgent.
+using OllamaApiClient chatClient = new(new Uri(endpoint), modelName);
+AIAgent agent = new ChatClientAgent(chatClient, JokerInstructions, JokerName);
+
+// Invoke the agent and output the text result.
+Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
diff --git a/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/README.md b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/README.md
new file mode 100644
index 0000000000..be76a75de0
--- /dev/null
+++ b/dotnet/samples/GettingStarted/AgentProviders/Agent_With_Ollama/README.md
@@ -0,0 +1,34 @@
+# Prerequisites
+
+Before you begin, ensure you have the following prerequisites:
+
+- .NET 8.0 SDK or later
+- Docker installed and running on your machine
+- An Ollama model downloaded into Ollama
+
+To download and start Ollama on Docker using CPU, run the following command in your terminal.
+
+```powershell
+docker run -d -v "c:\temp\ollama:/root/.ollama" -p 11434:11434 --name ollama ollama/ollama
+```
+
+To download and start Ollama on Docker using GPU, run the following command in your terminal.
+
+```powershell
+docker run -d --gpus=all -v "c:\temp\ollama:/root/.ollama" -p 11434:11434 --name ollama ollama/ollama
+```
+
+After the container has started, launch a Terminal window for the docker container, e.g. if using docker desktop, choose Open in Terminal from actions.
+
+From this terminal download the required models, e.g. here we are downloading the phi3 model.
+
+```text
+ollama pull gpt-oss
+```
+
+Set the following environment variables:
+
+```powershell
+$env:OLLAMA_ENDPOINT="http://localhost:11434"
+$env:OLLAMA_MODEL_NAME="gpt-oss"
+```
diff --git a/dotnet/samples/GettingStarted/AgentProviders/README.md b/dotnet/samples/GettingStarted/AgentProviders/README.md
index 981e60d9b8..0b5fbf1a74 100644
--- a/dotnet/samples/GettingStarted/AgentProviders/README.md
+++ b/dotnet/samples/GettingStarted/AgentProviders/README.md
@@ -9,6 +9,7 @@ see the [Getting Started Steps](../GettingStartedSteps/README.md) samples.
## Prerequisites
See the README.md for each sample for the prerequisites for that sample.
+
## Samples
|Sample|Description|
@@ -17,6 +18,8 @@ See the README.md for each sample for the prerequisites for that sample.
|[Creating an AIAgent with AzureFoundry](./Agent_With_AzureFoundry/)|This sample demonstrates how to create an Azure Foundry agent and expose it as an AIAgent|
|[Creating an AIAgent with Azure OpenAI ChatCompletion](./Agent_With_AzureOpenAIChatCompletion/)|This sample demonstrates how to create an AIAgent using Azure OpenAI ChatCompletion as the underlying inference service|
|[Creating an AIAgent with Azure OpenAI Responses](./Agent_With_AzureOpenAIResponses/)|This sample demonstrates how to create an AIAgent using Azure OpenAI Responses as the underlying inference service|
+|[Creating an AIAgent with a custom implementation](./Agent_With_CustomImplementation/)|This sample demonstrates how to create an AIAgent with a custom implementation|
+|[Creating an AIAgent with Ollama](./Agent_With_Ollama/)|This sample demonstrates how to create an AIAgent using Ollama as the underlying inference service|
|[Creating an AIAgent with ONNX](./Agent_With_ONNX/)|This sample demonstrates how to create an AIAgent using ONNX as the underlying inference service|
|[Creating an AIAgent with OpenAI ChatCompletion](./Agent_With_OpenAIChatCompletion/)|This sample demonstrates how to create an AIAgent using OpenAI ChatCompletion as the underlying inference service|
|[Creating an AIAgent with OpenAI Responses](./Agent_With_OpenAIResponses/)|This sample demonstrates how to create an AIAgent using OpenAI Responses as the underlying inference service|
diff --git a/dotnet/samples/GettingStarted/README.md b/dotnet/samples/GettingStarted/README.md
index 55cc7f7a97..e95b96c923 100644
--- a/dotnet/samples/GettingStarted/README.md
+++ b/dotnet/samples/GettingStarted/README.md
@@ -7,6 +7,8 @@ of the agent framework.
|Sample|Description|
|---|---|
-|[Agents](./Agents/README.md)|Getting started with agents|
+|[Agents](./Agents/README.md)|Step by step instructions for getting started with agents|
|[Agent Providers](./AgentProviders/README.md)|Getting started with creating agents using various providers|
|[Agent Open Telemetry](./AgentOpenTelemetry/README.md)|Getting started with OpenTelemetry for agents|
+|[Agent With OpenAI exchange types](./AgentWithOpenAI/README.md)|Using OpenAI exchange types with agents|
+|[Workflow](./Workflow/README.md)|Getting started with Workflow|