WPF/C#:使用Microsoft Agent Framework框架創建一個帶有審批功能的終端Agent
前言
最近新出了一個Microsoft Agent Framework框架,我感覺還挺有意思的,就通過它的那個Using function tools with human in the loop approvals例子,做了一個終端助手Agent。我覺得使用這個作為學習人在環上這個例子蠻合適的,因為對于需要執行敏感操作(如系統命令)的場景,人工審批機制顯得尤為重要。本文以Rouyan為例,說明如何使用Microsoft Agent Framework創建一個能夠執行終端命令并具備人工審批功能的WPF應用。
在詳細介紹之前,先來看看它的效果。
1、比如獲取當前時間
會先彈出一個人工審批窗口:

然后你點擊同意了才會執行:

如果你拒絕了就是這樣:

實際上你可以利用終端做很多事情,我再舉一個例子。
2、新建一個文件,寫入你好:

選擇同意,結果如圖所示:


在介紹如何具體實現之前,先來介紹一下Microsoft Agent Framework。
Microsoft Agent Framework介紹
GitHub上的簡介是:“一個用于構建、編排和部署AI代理及多代理工作流程的框架,支持Python和.NET。”
GitHub地址:https://github.com/microsoft/agent-framework

Microsoft Agent Framework 是一個開源開發工具包,用于為 .NET 和 Python 構建 AI 代理和多代理工作流。它整合并擴展了 Semantic Kernel 和 AutoGen 項目的思想,融合了兩者的優點,并新增了多項功能。該框架由同一團隊開發,將成為未來構建 AI 代理的統一基礎。
Agent Framework 提供了兩大主要功能類別:
AI 代理:單個代理利用大語言模型(LLM)處理用戶輸入,調用工具和 MCP 服務器執行操作,并生成響應。代理支持的模型提供商包括 Azure OpenAI、OpenAI 和 Azure AI。
工作流:基于圖形的工作流,用于連接多個代理和功能,以執行復雜的多步驟任務。工作流支持基于類型的路由、嵌套、檢查點以及適用于人工干預場景的請求/響應模式。
該框架還提供了基礎構建模塊,包括模型客戶端(聊天補全和響應)、用于狀態管理的代理線程、用于代理記憶的上下文提供程序、用于攔截代理操作的中間件,以及用于工具集成的MCP客戶端。這些組件共同為您提供靈活性和強大功能,以構建交互性強、穩健且安全的AI應用程序。

具體實現
1、安裝Nuget包:

2、編寫運行腳本的函數
[Description("Execute a Windows cmd.exe script and return its output.")]
static string ExecuteCmd([Description("The script content to run via 'cmd.exe /c'.")] string script)
{
try
{
var psi = new ProcessStartInfo("cmd.exe", "/c " + script)
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using (var process = new Process())
{
process.StartInfo = psi;
process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();
if (!string.IsNullOrWhiteSpace(error))
{
return $"錯誤: {error.Trim()}";
}
return output.Trim();
}
}
catch (Exception ex)
{
return $"執行失敗: {ex.Message}";
}
}
3、配置AI Agent
文檔中只寫了Azure中怎么使用,兼容OpenAI格式的可以這樣寫:
// 配置AI Agent
DotEnv.Load();
var envVars = DotEnv.Read();
var apiKey = envVars["OPENAI_API_KEY"];
var model = envVars["OPENAI_CHAT_MODEL"];
var baseUrl = new Uri(envVars["OPENAI_BASE_URL"]);
ApiKeyCredential apiKeyCredential = new ApiKeyCredential(apiKey);
OpenAIClientOptions openAIClientOptions = new OpenAIClientOptions();
openAIClientOptions.Endpoint = baseUrl;
AIAgent agent = new OpenAIClient(apiKeyCredential, openAIClientOptions)
.GetChatClient(model)
.CreateAIAgent(instructions: "你是一個樂于助人的助手,可以執行命令行腳本。請使用中文回答。", tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(ExecuteCmd))]);
這里有一個新東西就是ApprovalRequiredAIFunction。
這說明如果調用這個函數需要經過人工審批。
4、審批流程
// Call the agent and check if there are any user input requests to handle.
AgentThread thread = agent.GetNewThread();
var response = await agent.RunAsync(InputText, thread);
var userInputRequests = response.UserInputRequests.ToList();
我們先來看看這個是什么,運行起來打個斷點看看:

這就是一個Agent想要執行的函數,那么現在來看看如何審批:
while (userInputRequests.Count > 0)
{
var userInputResponses = new List<ChatMessage>();
foreach (var functionApprovalRequest in userInputRequests.OfType<FunctionApprovalRequestContent>())
{
var scriptContent = functionApprovalRequest.FunctionCall.Arguments?["script"]?.ToString() ?? "未知腳本";
var functionName = functionApprovalRequest.FunctionCall.Name;
var dialogVm = new HumanApprovalDialogViewModel
{
Title = "命令執行審批",
Message = $"是否同意執行以下命令?\n\n函數名稱: {functionName}\n腳本內容: {scriptContent}"
};
bool? result = _windowManager.ShowDialog(dialogVm);
bool approved = result == true;
userInputResponses.Add(new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]));
}
// Pass the user input responses back to the agent for further processing.
response = await agent.RunAsync(userInputResponses, thread);
userInputRequests = response.UserInputRequests.ToList();
}
根據這個地方userInputResponses.Add(new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]));中的approved傳入的是true還是false表示用戶是同意還是拒絕。
然后發送請求獲取新的回復,直到沒有需要人工審批的函數為止。
5、流式響應
最后再獲取一個流式響應:
await foreach (var update in agent.RunStreamingAsync("輸出最終答案", thread))
{
OutputText += update.Text;
}
最后
以上就是本期的全部內容,希望對你有所幫助。
全部代碼已上傳至GitHub,地址:https://github.com/Ming-jiayou/Rouyan。
終端助手的代碼主要在src/Rouyan/Pages/ViewModel/TerminalAgentViewModel.cs中。

浙公網安備 33010602011771號