智能体工具包

代理支撑框架是将语言模型变成真正能够执行任务的代理的支撑框架。 模型本身只能生成文本。 要让代理调用工具、处理多步骤任务、记住已完成的工作并持续运行直到任务完成,你需要一个围绕模型构建的运行时 — 这个运行时就是工具包。

驱动框架负责驱动代理:它运行调用模型并执行模型请求调用的工具的循环流程,管理对话历史和上下文,确保模型不超出其限制,在采取行动前应用审批和安全策略,并推动代理持续朝着完成任务的方向前进。 编码助手和自主智能体都建立在某种形式的工具包之上 — 它是包裹在模型外的引擎。

代理框架提供现成的工具,因此无需自行构建此基架。 这是一个固执己见、开箱即用的智能体,它将聊天客户端与完整的智能体管道(函数调用、上下文管理、精选的工具和提供程序集)包装在一起,针对研究、编码、数据分析和通用任务自动化等长时间运行的自主工作进行了优化。

你仍提供自己的聊天客户端,并且仅配置要更改的部分。 其他所有内容都有一个合理的默认值,你可以禁用或自定义。

在内部,智能体框架工具包是基于聊天客户端的智能体(Python 中为 Agent,C# 中为 ChatClientAgent),并添加了智能体框架功能集。 所有这些功能也可用作 Agent Framework 中的独立功能。

智能体框架工具包的构成

智能体框架工具包将以下功能捆绑到单个智能体中。 默认情况下,每个选项都处于启用状态(除非标记为可选),可以单独禁用或自定义。

能力 Description
函数调用 具有可配置迭代限制的自动工具调用循环。
每次服务调用的历史记录持久化 每次单独的模型调用后,聊天记录都会被持久化保存,从而支持故障恢复以及在运行过程中进行检查。
压缩 上下文窗口压缩可防止长时间的工具调用循环溢出上下文窗口。 提供令牌预算(或自定义策略)时生效。
待办事项提供程序 智能体用于跟踪多步骤计划的持久待办事项列表。
代理模式提供程序 计划/执行/自定义模式跟踪,用于构建智能体的工作方式。
文件内存提供程序 基于文件的会话内存,用于存储跨轮次持久化的笔记和项目。
文件访问提供程序 限定在工作目录内的读写文件工具。
工具审批 “不再询问”的常设审批规则,加上针对安全、无人值守执行的启发式自动审批。
OpenTelemetry 遵循生成式 AI 语义规范的内置可观测性。
Web 搜索 默认情况下添加的托管 Web 搜索工具。
技能提供程序(可选) 发现并从文件系统逐步加载代理技能
后台代理(可选) 将并行工作委托给后台子代理。
Shell 环境(可选) Shell 命令执行以及对操作系统/Shell/工作目录的探测。
循环(可选) 重新调用代理,直到满足完成条件。

创建工具包智能体

工具包通过 HarnessAgent 命名空间(Microsoft.Agents.AI 包)中的 Microsoft.Agents.AI.Harness 类公开。 最简单的创建方法是从任何 IChatClient 使用 AsHarnessAgent 扩展方法:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

// chatClient is any IChatClient implementation (Foundry, Azure OpenAI, OpenAI, Anthropic, ...).
AIAgent agent = chatClient.AsHarnessAgent();

AgentResponse response = await agent.RunAsync("Plan a weekend trip to Seattle.");
Console.WriteLine(response.Text);

还可以直接构造代理:

AIAgent agent = new HarnessAgent(chatClient);

提供一个HarnessAgentOptions,用于提供说明和工具。 运行时级别的指令 (HarnessAgentOptions.HarnessInstructions) 描述一般操作准则,而任务特定的指令则放在 ChatOptions.InstructionsHarnessAgent 附带默认的工具包级别指令 (HarnessAgent.DefaultInstructions),但你可以通过 HarnessAgentOptions.HarnessInstructions 覆盖它们。

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    Name = "research-agent",
    ChatOptions = new ChatOptions
    {
        Instructions = "You are a research assistant focused on academic sources.",
        Tools = [AIFunctionFactory.Create(GetStockPrice)],
    },
});

启用压缩

压缩可防止长时间的工具调用循环溢出上下文窗口。 当不使用推理服务存储的聊天历史记录时,默认的 InMemoryChatHistoryProvider 也会提供相同的压缩提供程序,以便会话存储的聊天历史记录也被压缩。 提供最大上下文窗口大小和最大输出大小以启用默认的词元预算感知策略:

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    MaxContextWindowTokens = 128_000,
    MaxOutputTokens = 16_384,
});

若要使用自己的策略,请设置 HarnessAgentOptions.CompactionStrategy;以关闭压缩,设置 DisableCompaction = true

自定义和禁用功能

每个默认功能在 HarnessAgentOptions 上都有对应的禁用标志,因此你可以保留所需的管道并丢弃其余部分:

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    HarnessInstructions = "Custom operating guidelines here.",
    DisableTodoProvider = true,      // No todo list
    DisableAgentModeProvider = true, // No plan/execute modes
    DisableWebSearch = true,         // No hosted web search tool
    DisableFileMemory = true,        // No file-based session memory
});

其他标志包括DisableFileAccessDisableAgentSkillsProviderDisableToolAutoApprovalDisableOpenTelemetry。 您还可以通过 AIContextProviders 添加自己的上下文提供程序,并通过 AgentSkillsSource 将技能提供程序指向自定义位置。

循环直到完成

默认情况下,工具包每次调用运行一次。 提供一个或多个 LoopEvaluator 实例,以自动重新调用该代理,直到评估者判定其已完成(例如,当出现完成标记、某个谓词条件得到满足,或 AI 裁判批准时):

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    LoopEvaluators = [new CompletionMarkerLoopEvaluator("DONE")],
});

循环被用作最外层的 Agent 装饰器,因此每次迭代都是一次完整、独立完成,且经过工具批准并被追踪记录的 Agent 运行过程。

Shell 和后台智能体

若要让代理运行 shell 命令,请传递一个 ShellExecutor。 这会添加一个需要审批的 Shell 执行工具,以及一个将操作系统、Shell 和工作目录信息注入上下文的提供程序:

using Microsoft.Agents.AI.Tools.Shell;

// A shell confined to a working directory. Commands require approval by default;
// the deny-list is a UX pre-filter, not a security boundary.
await using var shell = new LocalShellExecutor(new LocalShellExecutorOptions
{
    WorkingDirectory = workingDir,
    ConfineWorkingDirectory = true,
    Policy = new ShellPolicy(denyList: [@"\brm\s+-rf\b", @"\bsudo\b"]),
});

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    ShellExecutor = shell,
});

要启用并行委托,请传递一组后台智能体。 代理可以分派子任务以并发执行:

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    BackgroundAgents = [webSearchAgent, codeAgent],
});

创建工具包智能体

工具包通过 create_harness_agent 工厂函数公开,该函数从聊天客户端组装一个完全配置的 Agent。 最简单的形式只需要一个客户端:

from agent_framework import create_harness_agent
from agent_framework.openai import OpenAIChatClient

agent = create_harness_agent(
    OpenAIChatClient(model="gpt-4o"),
)

session = agent.create_session()
response = await agent.run("Plan a weekend trip to Seattle.", session=session)
print(response.text)

运行时级别的指令描述一般操作准则,而任务特定的指令则放在 agent_instructions。 工具包附带默认的工具包级别指令 (DEFAULT_HARNESS_INSTRUCTIONS),你可以通过 harness_instructions 覆盖它们。 你也可以传递额外的工具:

agent = create_harness_agent(
    client=client,
    name="research-agent",
    agent_instructions="You are a research assistant focused on academic sources.",
    tools=get_stock_price,
)

启用压缩

压缩可防止长时间的工具调用循环溢出上下文窗口。 提供模型的最大上下文窗口大小和最大输出大小,以启用默认令牌预算感知策略:

agent = create_harness_agent(
    client=client,
    max_context_window_tokens=128_000,
    max_output_tokens=16_384,
)

如果未提供令牌参数和自定义策略,则会自动禁用压缩。 若要使用自己的策略,请传入 before_compaction_strategy 和/或 after_compaction_strategy;若要显式关闭压缩功能,请设置 disable_compaction=True

自定义和禁用功能

每个默认功能都有相应的 disable_* 关键字参数,因此可以保留所需的部分并删除其余部分:

agent = create_harness_agent(
    client=client,
    harness_instructions="Custom operating guidelines here.",
    disable_todo=True,         # No todo list
    disable_mode=True,         # No plan/execute modes
    disable_web_search=True,   # No hosted web search tool
    disable_file_memory=True,  # No file-based session memory
)

其他标志包括 disable_file_accessdisable_tool_auto_approvaldisable_compaction。 你可以通过 skills_paths 将技能发现指向自定义位置,并通过 context_providers 添加自己的提供程序。

循环直到完成

默认情况下,工具包每次调用运行一次。 传递一个 loop_should_continue 谓词以自动重新调用智能体,直到谓词判定其完成。 使用 loop_next_message 来控制每次后续迭代的提示词,并使用 loop_max_iterations 来限制传递次数:

from agent_framework import create_harness_agent, todos_remaining

agent = create_harness_agent(
    client=client,
    loop_should_continue=todos_remaining(),
    loop_max_iterations=10,
)

调用该谓词时会传入关键字参数(iterationlast_resultsessionagent 等);todos_remaining 会在该代理的待办事项列表中仍有未完成项时重新运行该代理。 若要自己编写,请接受这些关键字参数,例如 lambda *, last_result, **kwargs: "DONE" not in last_result.text

Shell 和后台智能体

若要让代理运行 shell 命令,请传递一个 shell_executor (例如 LocalShellTool ,来自 agent-framework-tools)。 这会添加一个需要审批的 Shell 执行工具,以及一个探测操作系统和 Shell 环境的提供程序。 调用方负责执行器的生命周期:

from agent_framework_tools.shell import LocalShellTool, ShellPolicy

# A shell confined to a working directory. Commands require approval by default;
# the deny-list is a UX pre-filter, not a security boundary.
async with LocalShellTool(
    workdir="./working",
    confine_workdir=True,
    policy=ShellPolicy(denylist=[r"\brm\s+-rf\b", r"\bsudo\b"]),
) as shell:
    agent = create_harness_agent(
        client=client,
        shell_executor=shell,
    )

要启用并行委托,请传递一系列后台智能体。 代理可以分派子任务以并发执行:

agent = create_harness_agent(
    client=client,
    background_agents=[web_search_agent, code_agent],
)

注释

针对代理 harness 的 Go 语言支持即将推出。 有关最新状态,请参阅 Agent Framework Go 存储库

规划和执行工作流

智能体模式提供程序支持一种两阶段工作风格,与待办事项列表天然契合:

  1. 计划模式 - 交互式。 代理会提出澄清问题、起草待办事项列表和计划,并在完成重大工作之前获得批准。
  2. 执行模式 - 自治。 智能体独立处理待办事项,并随时报告进度。

虽然模式提供程序附带计划和执行模式作为默认模式,但如果需要,这些模式可以替换为其他模式和自定义说明。

示例终端用户体验

工具包为你提供了一个功能强大的智能体,但未规定人们如何与之交互。 为了端到端演示工具包,我们包含一个示例终端 UX — 一个交互式控制台 (TUI),用于流式传输智能体输出、显示其待办事项列表和当前模式、呈现工具审批提示,并支持斜杠命令,如 /todos/mode/exit

Important

这些控制台项目是 示例,不是随附框架的一部分。 它们被设计为自包含的,因此你可以按原样运行以探索工具包,或将其复制到自己的项目中作为构建自己终端体验的起点。

.NET示例控制台是Harness.Shared.Console项目。 其入口点是 HarnessConsole.RunAgentAsync,接受你的智能体、占位符提示和可选的 HarnessConsoleOptions(观察者、斜杠命令处理程序、模式颜色):

using Harness.Shared.Console;

await HarnessConsole.RunAgentAsync(agent, userPrompt: "Ask me anything to get started.");

使用你自己的观察者、工具格式化程序和命令处理程序对其进行自定义 — 或将其分叉作为你自己终端体验的基础。 请参阅.NET 测试框架示例

Python 示例控制台是位于工具包示例旁边的 console 包。 其入口点是 run_agent_async,它运行基于 Textual 的应用:

from console import run_agent_async

await run_agent_async(agent)

它围绕观察器、UI 组件和斜杠命令构建,这些都可通过 ConsoleObserverToolCallFormatterCommandHandler 基类进行扩展(依赖于 textualrich)。 直接使用它,或复制一份并以其为基础打造你自己的终端体验。 请参阅Python harness 示例

后续步骤

深入了解