Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
40 changes: 40 additions & 0 deletions dotnet/samples/01-get-started/01_HelloAgent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft. All rights reserved.

// Step 1: Your First Agent
// The simplest possible agent — send a message, get a response.
// Uses Azure AI Foundry Responses API as the default provider.
//
// For more on agents, see: ../02-agents/README.md
// For docs: https://learn.microsoft.com/agent-framework/get-started/your-first-agent

using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;

// <create_agent>
string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT")
?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
name: "Assistant",
model: deploymentName,
instructions: "You are a helpful assistant.");
// </create_agent>

// <run_agent>
Console.WriteLine(await agent.RunAsync("What is the capital of France?"));
// </run_agent>

// <run_agent_streaming>
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me a fun fact about Paris."))
{
Console.Write(update);
}
Console.WriteLine();
// </run_agent_streaming>

// Cleanup
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
51 changes: 51 additions & 0 deletions dotnet/samples/01-get-started/02_AddTools.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Microsoft. All rights reserved.

// Step 2: Add Tools
// Give your agent the ability to call functions (tools) to retrieve external data.
// This sample adds a weather function tool and demonstrates automatic tool invocation.
//
// For tools deep dive, see: ../02-agents/tools/
// For docs: https://learn.microsoft.com/agent-framework/agents/tools

using System.ComponentModel;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT")
?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

// <define_tool>
[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
=> $"The weather in {location} is cloudy with a high of 15°C.";
// </define_tool>

// <create_agent_with_tools>
AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());

AITool tool = AIFunctionFactory.Create(GetWeather);
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
name: "WeatherAssistant",
model: deploymentName,
instructions: "You are a helpful assistant that can get weather information.",
tools: [tool]);
// </create_agent_with_tools>

// <invoke_with_tools>
AgentSession session = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", session));
// </invoke_with_tools>

// Streaming with tools
session = await agent.CreateSessionAsync();
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("What is the weather like in Amsterdam?", session))
{
Console.Write(update);
}
Console.WriteLine();

// Cleanup
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
42 changes: 42 additions & 0 deletions dotnet/samples/01-get-started/03_MultiTurn.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft. All rights reserved.

// Step 3: Multi-Turn Conversations
// Maintain conversation context across multiple exchanges with the agent.
// The session object preserves conversation state between calls.
//
// For more on conversations, see: ../02-agents/conversations/
// For docs: https://learn.microsoft.com/agent-framework/agents/conversations

using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;

string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT")
?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());

ChatClientAgent agent = await aiProjectClient.CreateAIAgentAsync(
name: "JokerAgent",
options: new AgentVersionCreationOptions(
new PromptAgentDefinition(model: deploymentName)
{
Instructions = "You are good at telling jokes."
}));

// <multi_turn>
// Create a conversation for tracking in Foundry UI
ProjectConversationsClient conversationsClient = aiProjectClient.GetProjectOpenAIClient().GetProjectConversationsClient();
ProjectConversation conversation = await conversationsClient.CreateProjectConversationAsync();

AgentSession session = await agent.CreateSessionAsync(conversation.Id);

Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session));
Console.WriteLine(await agent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", session));
// </multi_turn>

// Cleanup
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
await conversationsClient.DeleteConversationAsync(conversation.Id);
55 changes: 55 additions & 0 deletions dotnet/samples/01-get-started/04_Memory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft. All rights reserved.

// Step 4: Memory
// Add persistent memory so the agent can remember information across sessions.
// Uses ChatHistoryMemoryProvider with an in-memory vector store to recall prior conversations.
//
// For more on conversations, see: ../02-agents/conversations/
// For docs: https://learn.microsoft.com/agent-framework/agents/memory

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;
using OpenAI.Chat;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var embeddingDeploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME") ?? "text-embedding-3-large";

// <setup_memory>
// Create a vector store for storing chat messages (replace with a persistent store in production).
VectorStore vectorStore = new InMemoryVectorStore(new InMemoryVectorStoreOptions()
{
EmbeddingGenerator = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetEmbeddingClient(embeddingDeploymentName)
.AsIEmbeddingGenerator()
});

AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetChatClient(deploymentName)
.AsAIAgent(new ChatClientAgentOptions
{
ChatOptions = new() { Instructions = "You are good at telling jokes." },
Name = "Joker",
AIContextProviderFactory = (ctx, ct) => new ValueTask<AIContextProvider>(new ChatHistoryMemoryProvider(
vectorStore,
collectionName: "chathistory",
vectorDimensions: 3072,
storageScope: new() { UserId = "UID1", SessionId = Guid.NewGuid().ToString() },
searchScope: new() { UserId = "UID1" }))
});
// </setup_memory>

// <use_memory>
// Session 1: Tell the agent what you like
AgentSession session1 = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("I like jokes about Pirates. Tell me a joke about a pirate.", session1));

// Session 2: The agent remembers your preferences from session 1
AgentSession session2 = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("Tell me a joke that I might like.", session2));
// </use_memory>
45 changes: 45 additions & 0 deletions dotnet/samples/01-get-started/05_FirstWorkflow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft. All rights reserved.

// Step 5: Your First Workflow
// Chain processing steps together in a sequential workflow.
// Executors are processing units connected by edges that define data flow.
//
// For more on workflows, see: ../03-workflows/
// For docs: https://learn.microsoft.com/agent-framework/workflows/overview

using Microsoft.Agents.AI.Workflows;

// <define_executors>
// First executor: converts input text to uppercase
Func<string, string> uppercaseFunc = s => s.ToUpperInvariant();
var uppercase = uppercaseFunc.BindAsExecutor("UppercaseExecutor");

// Second executor: reverses the text
var reverse = new ReverseTextExecutor();
// </define_executors>

// <build_workflow>
WorkflowBuilder builder = new(uppercase);
builder.AddEdge(uppercase, reverse).WithOutputFrom(reverse);
var workflow = builder.Build();
// </build_workflow>

// <run_workflow>
await using Run run = await InProcessExecution.RunAsync(workflow, "Hello, World!");
foreach (WorkflowEvent evt in run.NewEvents)
{
if (evt is ExecutorCompletedEvent executorComplete)
{
Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
}
}
// </run_workflow>

/// <summary>
/// Executor that reverses the input text.
/// </summary>
internal sealed class ReverseTextExecutor() : Executor<string, string>("ReverseTextExecutor")
{
public override ValueTask<string> HandleAsync(string message, IWorkflowContext context, CancellationToken cancellationToken = default)
=> ValueTask.FromResult(string.Concat(message.Reverse()));
}
40 changes: 40 additions & 0 deletions dotnet/samples/01-get-started/06_HostYourAgent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft. All rights reserved.

// Step 6: Host Your Agent
// Expose an agent over the A2A (Agent-to-Agent) protocol so other agents can call it.
// This sample shows how to consume an A2A agent's skills as function tools.
//
// For more on hosting, see: ../04-hosting/
// For docs: https://learn.microsoft.com/agent-framework/hosting/a2a

using A2A;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI.Chat;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var a2aAgentHost = Environment.GetEnvironmentVariable("A2A_AGENT_HOST")
?? throw new InvalidOperationException("A2A_AGENT_HOST is not set.");

// <discover_a2a_agent>
// Discover and connect to a remote A2A agent
A2ACardResolver agentCardResolver = new(new Uri(a2aAgentHost));
AgentCard agentCard = await agentCardResolver.GetAgentCardAsync();
AIAgent a2aAgent = agentCard.AsAIAgent();
// </discover_a2a_agent>

// <use_a2a_agent>
// Create a local agent that can use the remote agent's skills as tools
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetChatClient(deploymentName)
.AsAIAgent(
instructions: "You are a helpful assistant that helps people with travel planning.",
tools: [.. a2aAgent.AsAIFunctions(agentCard)]);

Console.WriteLine(await agent.RunAsync(
"Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport'"));
// </use_a2a_agent>
24 changes: 24 additions & 0 deletions dotnet/samples/01-get-started/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Get Started with Agent Framework (.NET)

Progressive samples that build up from a simple agent to a hosted application.

| # | Sample | What You'll Learn | Go Deeper |
|---|--------|-------------------|-----------|
| 1 | [Hello Agent](./01_HelloAgent.cs) | Create and run a minimal agent | [Agents Overview](../02-agents/) |
| 2 | [Add Tools](./02_AddTools.cs) | Give your agent function tools | [Tools Deep Dive](../02-agents/tools/) |
| 3 | [Multi-Turn](./03_MultiTurn.cs) | Maintain conversation context | [Conversations](../02-agents/conversations/) |
| 4 | [Memory](./04_Memory.cs) | Add persistent memory/context | [Conversations](../02-agents/conversations/) |
| 5 | [First Workflow](./05_FirstWorkflow.cs) | Chain steps in a workflow | [Workflows](../03-workflows/) |
| 6 | [Host Your Agent](./06_HostYourAgent.cs) | Expose agent via A2A protocol | [Hosting](../04-hosting/) |

## Prerequisites

```bash
dotnet add package Microsoft.Agents.AI
```

## Running

```bash
dotnet run 01_HelloAgent.cs
```
59 changes: 59 additions & 0 deletions dotnet/samples/02-agents/BackgroundResponses.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft. All rights reserved.

// Background Responses
// Use background responses for long-running agent tasks with polling and resumption.
// Supports both non-streaming (polling) and streaming (with interruption recovery).
//
// For docs: https://learn.microsoft.com/agent-framework/agents/background-responses

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI.Responses;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetResponsesClient(deploymentName)
.AsAIAgent();

// <background_polling>
AgentRunOptions options = new() { AllowBackgroundResponses = true };
AgentSession session = await agent.CreateSessionAsync();

AgentResponse response = await agent.RunAsync("Write a very long novel about otters in space.", session, options);

// Poll until the response is complete.
while (response.ContinuationToken is { } token)
{
await Task.Delay(TimeSpan.FromSeconds(2));
options.ContinuationToken = token;
response = await agent.RunAsync(session, options);
}

Console.WriteLine(response.Text);
// </background_polling>

// <background_streaming>
options = new() { AllowBackgroundResponses = true };
session = await agent.CreateSessionAsync();

AgentResponseUpdate? lastUpdate = null;
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Write a very long novel about otters in space.", session, options))
{
Console.Write(update.Text);
lastUpdate = update;

// Simulate connection loss
if (update.Text.Length > 0) break;
}

// Resume from interruption point
options.ContinuationToken = lastUpdate?.ContinuationToken;
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(session, options))
{
Console.Write(update.Text);
}
// </background_streaming>
Loading
Loading