这是”用 Microsoft Agent Framework 搭建你自己的 claw”系列的第三篇。上一篇让理财助手学会了安全读写你的数据——它会读取你的投资组合、交易前先跟你确认、记住你觉得重要的事。但它能做的工作还很有限:所有能力都塞在一个 prompt 里、一次只能做一件事、够不到文件访问工具之外来真正重组数据。
这一篇从四个方向把 claw 的能力放大:
- Skills——把领域知识(估值、风险评分)打包成可发现的文件,Agent 按需加载,包括集中管理的 Foundry Skills
- Shell——给 Agent 一个受限的 shell,用来整理和重组文件
- CodeAct——让 Agent 自己写代码、跑代码,算出它查不到的答案
- 后台 Agent——把工作并发派给子 Agent,再汇总结果
按需教学:Skills
把所有指令塞进 system prompt 不具可扩展性——上下文膨胀,焦点稀释。Skills 的解决方式是用 SKILL.md 文件承载每个技能,Agent 只看到技能名称和一行描述,请求匹配时才逐步加载完整内容。
给 claw 配上两个文件型技能:valuation(估值)和 risk-scoring(风险评分)。
在 .NET 里,用 AgentSkillsProviderBuilder 构建自己的 provider:
var skillsProvider = new AgentSkillsProviderBuilder()
.UseFileSkills([skillsDir],
scriptRunner: SubprocessScriptRunner.RunAsync)
.Build();
AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
DisableAgentSkillsProvider = true,
AIContextProviders = [skillsProvider],
});
Python 里类似:
from agent_framework import SkillsProvider
skills_provider = SkillsProvider.from_paths(
skill_paths=[str(skills_dir)],
script_runner=subprocess_script_runner,
)
agent = create_harness_agent(
client=client,
skills_provider=skills_provider,
)
现在说”帮我估算一下 MSFT 的估值”就会让 Agent 加载 valuation 技能、读取指南、跑脚本、给出公允价值估算。而系统 prompt 里一句关于估值和风险的内容都没写。
集中管理的 Foundry Skills
文件型技能随 Agent 一起部署,改了就得重新部署。Foundry Skills 反过来:在 Foundry 项目里发布和更新,Agent 运行时自动获取。
因为需要 Foundry endpoint,所以是选配。.NET 里通过 Foundry 的 MCP 端点实时发现:
if (!string.IsNullOrWhiteSpace(toolboxUrl))
{
var (mcpClient, _) = await FoundrySkills.ConnectAsync(
toolboxUrl, credential);
skillsBuilder.UseMcpSkills(mcpClient);
}
Python 里也是同样思路:连接到 Toolbox MCP endpoint,把 MCPSkillsSource 和本地的 FileSkillsSource 合并:
sources = [FileSkillsSource(str(skills_dir),
script_runner=subprocess_script_runner)]
if toolbox_url:
session = await _connect_foundry_toolbox(stack, toolbox_url)
sources.append(MCPSkillsSource(client=session))
source = sources[0] if len(sources) == 1 \
else AggregatingSkillsSource(sources)
skills_provider = SkillsProvider(DeduplicatingSkillsSource(source))
无论哪种方式,Agent 看到的都是一个统一的技能集。
Skills 不只是领域操作指南——也可以承载 Agent 的行为规则。比如发一个 financial-agent-rules 技能到 Foundry 工具箱,里面写”拒绝回答与理财无关的问题”,由于它的描述声明了”用于所有请求”,Agent 每次都会加载它。发完之后问”法国的首都是什么”,claw 会有礼貌地拒绝并引导你回到理财话题上。
伸手碰文件系统:Shell
文件访问能让 Agent 读写单文件,但重组一个乱糟糟的文件夹——移动、改名、批量操作——正是 shell 的活。比如用户的交易确认文件堆成一团:
working/confirmations/
trade confirmation 1.txt
conf_AAPL.txt
copy of trade 3.txt
SPY sell.txt
Harness 可以把 shell 作为审批门控的 run_shell 工具暴露给 Agent。当然很危险,所以有两层防护:工作目录限制(每条命令都锚定到确认文件库,跑不出去)和拒绝列表(预过滤明显破坏性的命令)。
.NET:
await using var shell = new LocalShellExecutor(
new LocalShellExecutorOptions
{
WorkingDirectory = vaultDir,
ConfineWorkingDirectory = true,
Policy = new ShellPolicy(denyList:
[
@"\brm\s+-rf\b", @"\bsudo\b",
@":\(\)\s*\{", @"\bmkfs\b", @">\s*/dev/sd",
]),
Timeout = TimeSpan.FromSeconds(15),
});
AIAgent agent = chatClient.AsHarnessAgent(
new HarnessAgentOptions { ShellExecutor = shell });
Python:
from agent_framework_tools.shell import LocalShellTool, ShellPolicy
shell = LocalShellTool(
workdir=str(vault_dir),
confine_workdir=True,
policy=ShellPolicy(denylist=[
r"\brm\s+-rf\b", r"\bsudo\b",
r":\(\)\s*\{", r"\bmkfs\b", r">\s*/dev/sd",
]),
timeout=15,
)
拒绝列表是 UX 护栏,不是安全边界。真正的隔离靠的是工作目录限制和审批弹窗。对不信任的输入,可以用 DockerShellExecutor 跑在沙箱里。
现在说”整理一下我的交易确认文件”——Agent 会检查文件夹、提出方案,然后让你逐条审批后把文件按 年/月 目录重组织。
让 Agent 自己算:CodeAct
有些问题不是查出来的,是算出来的。“我的投资组合值多少钱?“这类问题,让模型在脑子里做算术不如让它跑一小段代码。CodeAct 给了 Agent 一个沙箱化的解释器,它可以写代码然后跑。
.NET 里 CodeAct 基于 Hyperlight(微虚拟机,需要硬件虚拟化):
using HyperlightSandbox.Guest.Python;
using Microsoft.Agents.AI.Hyperlight;
var codeAct = new HyperlightCodeActProvider(
HyperlightCodeActProviderOptions.CreateForWasm(
PythonGuestModule.GetModulePath()));
AIAgent agent = chatClient.AsHarnessAgent(
new HarnessAgentOptions
{
AIContextProviders = [skillsProvider, codeAct],
});
Python 里用 Monty,纯跨平台解释器,不需要虚拟化:
from agent_framework_monty import MontyCodeActProvider
context_providers = [
skills_provider,
MontyCodeActProvider(approval_mode="never_require")
]
agent = create_harness_agent(
client=client,
context_providers=context_providers,
)
有了 CodeAct,说”算一下我投资组合的总价值”——Agent 会读持仓,写几行 Python 把股数乘以价格求和,跑代码,报告结果。整个计算过程有迹可循,不是猜的。
并行做事:后台 Agent
“研究一下 MSFT、NVDA 和 SPY”——一个一个查太慢,把所有网络搜索塞进主 Agent 又搞乱上下文。Harness 支持后台 Agent:交给 claw 一批子 Agent,让它把工作委托出去,并发执行,然后收结果。
先搭一个轻量的、只做网络搜索的研究 Agent:
AIAgent research = chatClient.AsAIAgent(
name: "TickerResearchAgent",
description: "Search web for news about a stock ticker.",
instructions: "Research one ticker, return 3-4 bullet points.",
tools: [new HostedWebSearchTool()]);
AIAgent agent = chatClient.AsHarnessAgent(
new HarnessAgentOptions
{
BackgroundAgents = [research],
});
Python 也一样:
research_agent = Agent(
client,
name="TickerResearchAgent",
description="Search web for news about a stock ticker.",
instructions="Research one ticker, return 3-4 bullet points.",
tools=[client.get_web_search_tool()],
)
agent = create_harness_agent(
client=client,
background_agents=[research_agent],
)
这会给主 Agent 一套 background_agents_* 工具:它可以启动每个股票代码的研究任务,让它们并行跑,检查进度,再收集结果——汇总成一份报告。扇出扇入是 Agent 自己的决策,管线是 Harness 处理的。
可以跑起来试试
# .NET
cd dotnet
dotnet run --project samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities
# Python
uv run python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py
然后按顺序试试:
Value MSFT for me.——加载 valuation 技能,跑脚本,给估值How risky is my portfolio?——读 portfolio.csv,加载 risk-scoring 技能/mode plan,然后Tidy up my trade confirmations.——先进入计划模式检查文件夹并提案,审批后用 shell 执行Work out the total value of my portfolio.——写 Python 算结果Research MSFT, NVDA and SPY.——并发派给研究 Agent,汇总What's the capital of France?——配置了 financial-agent-rules Foundry 技能后会礼貌拒绝
独立使用这些构建模块
每种能力都可以脱离 Harness 单独拿起来用:
| 能力 | .NET | Python |
|---|---|---|
| Skills | AgentSkillsProvider — Microsoft.Agents.AI | from agent_framework import SkillsProvider |
| Shell | LocalShellExecutor — Microsoft.Agents.AI.Tools.Shell | from agent_framework_tools.shell import LocalShellTool |
| CodeAct | HyperlightCodeActProvider — Microsoft.Agents.AI.Hyperlight | from agent_framework_monty import MontyCodeActProvider |
| 后台 Agent | BackgroundAgentsProvider — Microsoft.Agents.AI | from agent_framework import BackgroundAgentsProvider |