1. 项目背景与核心概念解析
在.NET生态中构建智能体应用正成为企业级开发的新趋势。AgentFramework作为微软官方推出的智能体开发框架,其核心设计理念是将复杂业务能力封装为可复用的Agent Skill模块。这个"小龙虾mini版"项目演示了如何通过集成Shell命令执行能力,快速扩展智能体的操作系统交互功能。
Agent Skill的本质是遵循"渐进式披露"原则的功能包:
- 每个Skill包含自描述的SKILL.md文件
- 可选配套的脚本、资源目录
- 通过标准接口与主智能体交互
这种架构的优势在于:
- 领域知识封装:将Shell操作这类专业能力与主业务逻辑解耦
- 安全隔离:危险命令检查、输出截断等防护措施可集中实现
- 动态加载:按需调用技能,避免不必要的资源占用
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础配置
2.1 开发环境要求
- .NET 6+ SDK
- Visual Studio 2022或Rider
- 可选:Azure OpenAI服务账号(若需结合大模型能力)
2.2 项目结构初始化
创建标准的ASP.NET Core项目后,需添加以下关键目录:
code复制Skills/
└── system-ops/
├── SKILL.md
├── scripts/
│ └── disk_clean.ps1
└── references/
└── COMMON_CMDS.md
2.3 核心依赖安装
通过NuGet添加关键包:
bash复制dotnet add package Microsoft.Agents.AI --version 1.0.0-preview
dotnet add package Azure.AI.OpenAI --version 1.0.0-beta.12
3. Shell Skill实现详解
3.1 SKILL.md文件规范
markdown复制name: system-ops
description: 提供系统运维相关Shell命令执行能力。包括磁盘清理、进程管理等常见操作。
license: MIT
metadata:
author: NetCoreKevin
version: "1.0"
---
## 可用命令
1. 磁盘空间检查:
```shell
df -h
- 清理临时文件:
shell复制
pwsh -File ./scripts/disk_clean.ps1
安全提示:所有命令执行均通过安全沙箱,禁止直接执行rm等危险操作
code复制
### 3.2 ShellTools安全实现
```csharp
// 危险命令模式匹配增强版
private static readonly Regex DangerousPatterns = new Regex(
@"(rm\s+-[rf]+\s+/)|(sudo\s)|(shutdown)|(reboot)|(:\s*\(\s*\)\s*\{)|(mkfs\.)|(dd\s+if=)",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
[Description("执行跨平台Shell命令")]
public static async Task<string> RunShellAsync(
string command,
string? workingDirectory = null,
CancellationToken cancellationToken = default)
{
// 安全检查
if (DangerousPatterns.IsMatch(command))
{
throw new SecurityException("检测到潜在危险命令");
}
// 进程启动配置
var processInfo = new ProcessStartInfo
{
FileName = OperatingSystem.IsWindows() ? "cmd" : "bash",
Arguments = OperatingSystem.IsWindows()
? $"/c \"{command.Replace("\"", "\\\"")}\""
: $"-c \"{command.Replace("\"", "\\\"")}\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
};
// 异步执行与超时控制
using var process = Process.Start(processInfo);
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
using var linkedCts = CancellationTokenSo
