diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj index c6bab8327e..4aafb7582a 100644 --- a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj +++ b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj @@ -6,16 +6,64 @@ enable enable + + + false + - - - + + + + + + + - + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Dockerfile b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Dockerfile new file mode 100644 index 0000000000..b494ad2254 --- /dev/null +++ b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "AgentWithTextSearchRag.dll"] diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Program.cs b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Program.cs index 65f3a9e98f..94552a8014 100644 --- a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Program.cs +++ b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/Program.cs @@ -4,6 +4,7 @@ // capabilities to an AI agent. The provider runs a search against an external knowledge base // before each model invocation and injects the results into the model context. +using Azure.AI.AgentServer.AgentFramework.Extensions; using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; @@ -23,7 +24,7 @@ TextSearchProviderOptions textSearchOptions = new() AIAgent agent = new AzureOpenAIClient( new Uri(endpoint), - new AzureCliCredential()) + new DefaultAzureCredential()) .GetChatClient(deploymentName) .CreateAIAgent(new ChatClientAgentOptions { @@ -31,16 +32,7 @@ AIAgent agent = new AzureOpenAIClient( AIContextProviderFactory = ctx => new TextSearchProvider(MockSearchAsync, ctx.SerializedState, ctx.JsonSerializerOptions, textSearchOptions) }); -AgentThread thread = agent.GetNewThread(); - -Console.WriteLine(">> Asking about returns\n"); -Console.WriteLine(await agent.RunAsync("Hi! I need help understanding the return policy.", thread)); - -Console.WriteLine("\n>> Asking about shipping\n"); -Console.WriteLine(await agent.RunAsync("How long does standard shipping usually take?", thread)); - -Console.WriteLine("\n>> Asking about product care\n"); -Console.WriteLine(await agent.RunAsync("What is the best way to maintain the TrailRunner tent fabric?", thread)); +await agent.RunAIAgentAsync(); static Task> MockSearchAsync(string query, CancellationToken cancellationToken) { diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/agent.yaml b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/agent.yaml new file mode 100644 index 0000000000..35a8582c1a --- /dev/null +++ b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/agent.yaml @@ -0,0 +1,29 @@ +name: AgentWithTextSearchRag +displayName: "Text Search RAG Agent" +description: > + An AI agent that uses TextSearchProvider for retrieval augmented generation (RAG) capabilities. + The agent runs searches against an external knowledge base before each model invocation and + injects the results into the model context. It can answer questions about Contoso Outdoors + policies and products, including return policies, refunds, shipping options, and product care + instructions such as tent maintenance. +metadata: + authors: + - Microsoft Agent Framework Team + tags: + - example + - Agent Framework +template: + kind: hosted + name: AgentWithTextSearchRag + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: AZURE_OPENAI_ENDPOINT + value: ${AZURE_OPENAI_ENDPOINT} + - name: AZURE_OPENAI_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/dotnet/samples/HostedAgents/AgentWithTextSearchRag/run-requests.http b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/run-requests.http new file mode 100644 index 0000000000..4bfb02d8f8 --- /dev/null +++ b/dotnet/samples/HostedAgents/AgentWithTextSearchRag/run-requests.http @@ -0,0 +1,30 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple string input +POST {{endpoint}} +Content-Type: application/json +{ + "input": "Hi! I need help understanding the return policy." +} + +### Explicit input +POST {{endpoint}} +Content-Type: application/json +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "How long does standard shipping usually take?" + } + ] + } + ] +} diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj b/dotnet/samples/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj index f192c19901..7e70caabda 100644 --- a/dotnet/samples/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj +++ b/dotnet/samples/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj @@ -6,18 +6,64 @@ enable enable + + + false + - - - + + + + + + + - - - + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/Dockerfile b/dotnet/samples/HostedAgents/AgentsInWorkflows/Dockerfile new file mode 100644 index 0000000000..0d3e5757cd --- /dev/null +++ b/dotnet/samples/HostedAgents/AgentsInWorkflows/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "AgentsInWorkflows.dll"] diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/Program.cs b/dotnet/samples/HostedAgents/AgentsInWorkflows/Program.cs index 3e01f6e717..b1d8a922fd 100644 --- a/dotnet/samples/HostedAgents/AgentsInWorkflows/Program.cs +++ b/dotnet/samples/HostedAgents/AgentsInWorkflows/Program.cs @@ -4,6 +4,7 @@ // Three translation agents are connected sequentially to create a translation chain: // English → French → Spanish → English, showing how agents can be composed as workflow executors. +using Azure.AI.AgentServer.AgentFramework.Extensions; using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Agents.AI; @@ -14,7 +15,7 @@ using Microsoft.Extensions.AI; 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"; -IChatClient chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()) +IChatClient chatClient = new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()) .GetChatClient(deploymentName) .AsIChatClient(); @@ -23,26 +24,14 @@ AIAgent frenchAgent = GetTranslationAgent("French", chatClient); AIAgent spanishAgent = GetTranslationAgent("Spanish", chatClient); AIAgent englishAgent = GetTranslationAgent("English", chatClient); -// Build the workflow by adding executors and connecting them -Workflow workflow = new WorkflowBuilder(frenchAgent) +// Build the workflow and turn it into an agent +AIAgent agent = new WorkflowBuilder(frenchAgent) .AddEdge(frenchAgent, spanishAgent) .AddEdge(spanishAgent, englishAgent) -.Build(); + .Build() + .AsAgent(); -// Execute the workflow -await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, new ChatMessage(ChatRole.User, "Hello World!")); - -// Must send the turn token to trigger the agents. -// The agents are wrapped as executors. When they receive messages, -// they will cache the messages and only start processing when they receive a TurnToken. -await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); -await foreach (WorkflowEvent evt in run.WatchStreamAsync()) -{ - if (evt is AgentRunUpdateEvent executorComplete) - { - Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}"); - } -} +await agent.RunAIAgentAsync(); static ChatClientAgent GetTranslationAgent(string targetLanguage, IChatClient chatClient) => new(chatClient, $"You are a translation assistant that translates the provided text to {targetLanguage}."); diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/agent.yaml b/dotnet/samples/HostedAgents/AgentsInWorkflows/agent.yaml new file mode 100644 index 0000000000..bf706f9925 --- /dev/null +++ b/dotnet/samples/HostedAgents/AgentsInWorkflows/agent.yaml @@ -0,0 +1,28 @@ +name: AgentsInWorkflows +displayName: "Translation Chain Workflow Agent" +description: > + A workflow agent that performs sequential translation through multiple languages. + The agent translates text from English to French, then to Spanish, and finally back + to English, leveraging AI-powered translation capabilities in a pipeline workflow. +metadata: + authors: + - Agent Framework Team + tags: + - example + - Microsoft Agent Framework Team + - workflows +template: + kind: hosted + name: AgentsInWorkflows + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: AZURE_OPENAI_ENDPOINT + value: ${AZURE_OPENAI_ENDPOINT} + - name: AZURE_OPENAI_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/dotnet/samples/HostedAgents/AgentsInWorkflows/run-requests.http b/dotnet/samples/HostedAgents/AgentsInWorkflows/run-requests.http new file mode 100644 index 0000000000..5c33700a93 --- /dev/null +++ b/dotnet/samples/HostedAgents/AgentsInWorkflows/run-requests.http @@ -0,0 +1,30 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple string input +POST {{endpoint}} +Content-Type: application/json +{ + "input": "Hello, how are you today?" +} + +### Explicit input +POST {{endpoint}} +Content-Type: application/json +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "Hello, how are you today?" + } + ] + } + ] +}