mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
98 lines
3.9 KiB
C#
98 lines
3.9 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
// Translation Chain Workflow Agent — demonstrates how to compose multiple AI agents
|
|
// into a sequential workflow pipeline. Three translation agents are connected:
|
|
// English → French → Spanish → English, showing how agents can be orchestrated
|
|
// as workflow executors in a hosted agent.
|
|
|
|
using Azure.AI.Projects;
|
|
using Azure.Core;
|
|
using Azure.Identity;
|
|
using DotNetEnv;
|
|
using Microsoft.Agents.AI;
|
|
using Microsoft.Agents.AI.Foundry.Hosting;
|
|
using Microsoft.Agents.AI.Workflows;
|
|
using Microsoft.Extensions.AI;
|
|
|
|
// Load .env file if present (for local development)
|
|
Env.TraversePath().Load();
|
|
|
|
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
|
|
?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
|
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o";
|
|
|
|
// Use a chained credential: try a temporary dev token first (for local Docker debugging),
|
|
// then fall back to DefaultAzureCredential (for local dev via dotnet run / managed identity in production).
|
|
TokenCredential credential = new ChainedTokenCredential(
|
|
new DevTemporaryTokenCredential(),
|
|
new DefaultAzureCredential());
|
|
|
|
// Create a chat client from the Foundry project
|
|
IChatClient chatClient = new AIProjectClient(new Uri(endpoint), credential)
|
|
.GetProjectOpenAIClient()
|
|
.GetChatClient(deploymentName)
|
|
.AsIChatClient();
|
|
|
|
// Create translation agents
|
|
AIAgent frenchAgent = chatClient.AsAIAgent("You are a translation assistant that translates the provided text to French.");
|
|
AIAgent spanishAgent = chatClient.AsAIAgent("You are a translation assistant that translates the provided text to Spanish.");
|
|
AIAgent englishAgent = chatClient.AsAIAgent("You are a translation assistant that translates the provided text to English.");
|
|
|
|
// Build the sequential workflow: French → Spanish → English
|
|
AIAgent agent = new WorkflowBuilder(frenchAgent)
|
|
.AddEdge(frenchAgent, spanishAgent)
|
|
.AddEdge(spanishAgent, englishAgent)
|
|
.Build()
|
|
.AsAIAgent(
|
|
name: Environment.GetEnvironmentVariable("AGENT_NAME") ?? "hosted-workflows");
|
|
|
|
// Host the workflow agent as a Foundry Hosted Agent using the Responses API.
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
builder.Services.AddFoundryResponses(agent);
|
|
|
|
var app = builder.Build();
|
|
app.MapFoundryResponses();
|
|
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.MapFoundryResponses("openai/v1");
|
|
}
|
|
|
|
app.Run();
|
|
|
|
/// <summary>
|
|
/// A <see cref="TokenCredential"/> for local Docker debugging only.
|
|
/// Reads a pre-fetched bearer token from the <c>AZURE_BEARER_TOKEN</c> environment variable
|
|
/// once at startup. This should NOT be used in production.
|
|
///
|
|
/// Generate a token on your host and pass it to the container:
|
|
/// export AZURE_BEARER_TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv)
|
|
/// docker run -e AZURE_BEARER_TOKEN=$AZURE_BEARER_TOKEN ...
|
|
/// </summary>
|
|
internal sealed class DevTemporaryTokenCredential : TokenCredential
|
|
{
|
|
private const string EnvironmentVariable = "AZURE_BEARER_TOKEN";
|
|
private readonly string? _token;
|
|
|
|
public DevTemporaryTokenCredential()
|
|
{
|
|
this._token = Environment.GetEnvironmentVariable(EnvironmentVariable);
|
|
}
|
|
|
|
public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
|
|
=> this.GetAccessToken();
|
|
|
|
public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
|
|
=> new(this.GetAccessToken());
|
|
|
|
private AccessToken GetAccessToken()
|
|
{
|
|
if (string.IsNullOrEmpty(this._token) || this._token == "DefaultAzureCredential")
|
|
{
|
|
throw new CredentialUnavailableException($"{EnvironmentVariable} environment variable is not set.");
|
|
}
|
|
|
|
return new AccessToken(this._token, DateTimeOffset.UtcNow.AddHours(1));
|
|
}
|
|
}
|