代理工具(有时称为 AI 工具)是运行时基架,可将语言模型转换为可执行工作的代理。 它驱动模型和工具调用,管理聊天状态和上下文,应用审批策略,并可以让代理通过多步骤任务进行。
代理框架为研究、编码、数据分析和其他长时间运行的工作提供一个采用预设配置且开箱即用的工具套件。 提供聊天客户端并仅自定义应用程序所需的功能。
Architecture
Harness 由现有的 Agent Framework 构建模块组合而成,而不是定义一个独立的代理运行时:
- 聊天客户端 - 将代理连接到模型。
- 聊天管道 - 添加函数调用、消息注入、按服务调用历史记录持久性和可选压缩。
- 代理和上下文提供程序— 添加会话范围的指令、工具、内存、待办事项状态、操作模式和可选功能。
- 中间件和修饰器 — 添加审批处理、可观测性和可选的有界循环。
- 应用程序用户体验 — 流式传输响应、显示进度,并收集工具批准等输入。
生成的对象仍然是正常的 Agent Framework 代理:.NET 中派生自 AIAgent 的 HarnessAgent、Python 中由 create_harness_agent 返回的 Agent,或 Go 中用 *agent.Agent 配置的由提供程序支持的 harness.AgentConfig。 其会话使用与其他代理相同的 会话 和 上下文提供程序 抽象。
Harness 功能矩阵
| Capability | 工具套件行为 | 权威指南 |
|---|---|---|
| 函数调用 | 支持针对每个请求配置迭代次数上限。 Go 提供程序的构造函数控制着工具调用循环。 | 函数工具 |
| 每次服务调用的历史记录持久化 | 在一次工具调用运行中,每次模型调用后都会持久保存历史记录。 | 会话 |
| 压 实 | 在.NET和Python中提供令牌限制或自定义策略时启用。 Go 需要显式 provider 组合。 | 压缩 |
| 待办事项跟踪 | 默认启用。 | 规划和待办事项 |
| 代理模式 | 默认情况下启用计划和执行模式。 | 规划和待办事项 |
| 文件内存和文件访问 | 会话文件记忆功能默认启用;共享文件访问需手动启用。 | 上下文提供程序 |
| 工具审批 | 默认情况下会启用永久审批和自动审批规则。 | 工具审批 |
| OpenTelemetry | 代理可观测性默认处于启用状态。 | 可观察性 |
| Web 搜索 | 在所选聊天客户端支持的情况下默认添加。 | Web 搜索 |
| 智能体技能 | 默认情况下,在 .NET 和 Go 中启用;在 Python 中通过提供程序或路径选择加入。 | 代理技能 |
| 后台代理 | 可选并行委派到.NET和Python中命名的子代理。 没有打包的 Go 后台代理服务提供程序。 | 后台代理 |
| Shell 执行 | 由命令行程序包组合而成;Python 工厂可以自动进行配置。 | Shell 工具 |
| 循环 | 由评估器或谓词驱动的可选有界重复调用。 | 代理循环 |
后台代理委托与提供程序管理的 后台响应 是分开的。 后台代理会针对委托的任务运行子代理;后台响应使用延续令牌轮询或恢复一次提供程序请求。
Tip
有关帮助编写 Python harness 应用程序的编码代理指南,请安装 agent-framework-builder-python。
这个外部编码智能体技能独立于矩阵中列出的运行时智能体技能。
创建工具套件代理
Microsoft.Agents.AI.Harness 包在 Microsoft.Agents.AI 命名空间中公开了 HarnessAgent。 使用AsHarnessAgent从任何IChatClient创建工具套件代理,或直接构造HarnessAgent:
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
AIAgent agent = chatClient.AsHarnessAgent();
AgentResponse response = await agent.RunAsync("Plan a weekend trip to Seattle.");
Console.WriteLine(response.Text);
使用HarnessAgentOptions设置工具套件级操作指南、代理特定指令和功能选项:
AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
Name = "research-agent",
HarnessInstructions = "Use tools deliberately and report verified results.",
ChatOptions = new ChatOptions
{
Instructions = "You are a research assistant focused on academic sources.",
},
MaxContextWindowTokens = 128_000,
MaxOutputTokens = 16_384,
});
HarnessAgent.DefaultInstructions 提供默认的线束指南。
HarnessInstructions 出现在之前 ChatOptions.Instructions。
自定义合成
默认功能具有目标选项,包括DisableTodoProvider、、DisableAgentModeProviderDisableFileMemory、DisableAgentSkillsProviderDisableWebSearch、DisableToolAutoApproval、和DisableOpenTelemetryDisableCompaction。
使用 AIContextProviders 添加自定义上下文提供程序。 使用FileAccessStore选择启用文件访问,使用BackgroundAgents选择启用后台委托,并使用LoopEvaluators选择启用循环。
创建工具套件代理
create_harness_agent工厂返回一个完全配置的Agent:
from agent_framework import create_harness_agent
from agent_framework.openai import OpenAIChatClient
agent = create_harness_agent(
client=OpenAIChatClient(model="gpt-4o"),
)
session = agent.create_session()
response = await agent.run("Plan a weekend trip to Seattle.", session=session)
print(response.text)
分别设置工具套件级指令和代理特定指令:
agent = create_harness_agent(
client=client,
name="research-agent",
harness_instructions="Use tools deliberately and report verified results.",
agent_instructions="You are a research assistant focused on academic sources.",
max_context_window_tokens=128_000,
max_output_tokens=16_384,
)
DEFAULT_HARNESS_INSTRUCTIONS 提供默认的线束指南。
harness_instructions 出现在之前 agent_instructions。
自定义合成
使用诸如 disable_todo、disable_mode、disable_file_memory、disable_web_search、disable_tool_auto_approval 和 disable_compaction 等选项来禁用默认设置。
将内置提供程序替换为 todo_provider 或 mode_provider,并使用 context_providers 添加提供程序。 技能需通过 skills_provider 或 skills_paths 选择启用;文件访问、后台代理、Shell 工具和循环也都需要选择启用。
默认情况下,文件访问使用提供的存储作为一个共享工作区。 若要按活动会话 ID 隔离文件,请启用会话范围的文件访问:
from agent_framework import FileSystemAgentFileStore, create_harness_agent
file_store = FileSystemAgentFileStore("agent-files")
agent = create_harness_agent(
client=client,
file_access_store=file_store,
file_access_session_scoped=True,
)
若要在选定的会话之间有意进行共享,请直接构造 FileAccessProvider(store=file_store, scope="tenant-1"),并通过 context_providers 将其添加进去。 作用域是一个映射到由提供程序管理的文件夹的不透明的键,而不是路径。 当活动会话 ID 和显式作用域都不可用时,作用域访问失败,而不是使用共享存储根。
当一个代理有多个文件访问提供程序时使用 tool_name_prefix 。 前缀生成名称,例如 workspace_file_access_read,并防止工具名称冲突。 对于带有前缀的提供程序,请使用提供程序特定的批准规则工厂,以便每个规则都与该提供程序的已生成名称匹配:
from agent_framework import FileAccessProvider, create_harness_agent
workspace = FileAccessProvider(
store=file_store,
tool_name_prefix="workspace",
)
agent = create_harness_agent(
client=client,
context_providers=[workspace],
auto_approval_rules=[workspace.get_read_only_tools_auto_approval_rule()],
)
get_all_tools_auto_approval_rule() 为读取和写入工具创建等效的规则。 除非存储边界和工具输入受信任,否则保持写入审批处于启用状态。
启用文件访问后,使用 file_access_grep 查找从 1 开始计数的行号,使用 file_access_read_lines 检查包含首尾行的范围,并使用 file_access_replace_lines 编辑整行。
file_access_read_lines 为每个行加上其数字和一个选项卡的前缀;将行文本作为 expected_line传递时省略该前缀。 预期文本可防止因过期或不匹配的行号而编辑到错误的行。
file_access_grep 使用不区分大小写的正则表达式,接受最多 256 个字符的模式,并将 10 秒的预算应用于整个搜索。 无效或过长的模式,以及超出预算的搜索,都会返回错误。 在重试之前缩小目录或模式。
重要
file_access_grep 返回与其行终止符匹配的行文本。 自定义的 AgentFileStore.search() 实现必须返回从 1 开始的行号,且这些行号对应的行必须与 read() 针对 AgentFileStore.split_lines() 返回的文本所对应的行相同。
注释
create_harness_agent 已发布。 后台代理、文件访问和循环仍然是实验性的,shell 工具来自预发行 agent-framework-tools 包。
Go agent/harness 包为普通基于提供程序的智能体集成了中间件、上下文提供程序和历史记录默认值。 调用 harness.AgentConfig(harness.Config{}, agent.Config{...})、处理其错误,并将返回的配置传递给提供程序构造函数。 它不引入单独的代理类型或工具执行循环。
创建工具套件代理
复合示例配置了由 Foundry 提供支持的 Harness 代理:
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/microsoft/agent-framework-go/agent"
"github.com/microsoft/agent-framework-go/agent/harness"
"github.com/microsoft/agent-framework-go/examples/internal/demo"
"github.com/microsoft/agent-framework-go/message"
"github.com/microsoft/agent-framework-go/provider/foundryprovider"
)
workingDirectory, err := os.Getwd()
if err != nil {
return fmt.Errorf("get working directory: %w", err)
}
cfg, err := harness.AgentConfig(harness.Config{WorkingDirectory: workingDirectory}, agent.Config{
Name: "HarnessAssistant",
Middlewares: []agent.Middleware{logger},
})
if err != nil {
return err
}
a := foundryprovider.NewAgent(
demo.FoundryProjectEndpoint,
demo.FoundryTokenCredential(),
foundryprovider.ModelDeployment(demo.FoundryModel),
foundryprovider.AgentConfig{
Config: cfg,
DisableStoreOutput: true,
Instructions: "Help with software engineering tasks. Use memory and todos to track the current session's work.",
},
)
自定义合成
帮助程序提供以下默认值:
| 组分 | Go harness 默认值 |
|---|---|
| 规划 | 会话支持的待办事项工具和计划/执行模式,从计划模式开始 |
| 文件内存 | 位于 agent-file-memory 下的持久文件,每个会话都有一个独立的工作文件夹 |
| 技能 | 从工作目录进行基于文件的发现,不包括内存子树 |
| Web 搜索 | 托管的 Web 搜索声明,除非调用方已提供一个 |
| Approval | 适用于需要审批的工具的“待定审批”和“自动审批”中间件 |
| History | 具有按服务调用进行持久化的内存中历史记录 |
| 消息注入 | 每个智能体一个 agent.MessageInjector |
| 跟踪 | 智能体、工具及受支持的模型调用检测功能 |
使用 harness.Config 禁用组件或覆盖其配置。 当所选服务或部署不支持托管的 Web 搜索时,禁用托管的 Web 搜索。 基于文件的技能脚本需要显式配置的脚本运行程序。
帮助程序保留调用方工具、中间件、上下文提供程序和显式配置的历史记录提供程序。 在部署 Foundry 模型时,如果本地历史记录拥有对话控制权,请使用 DisableStoreOutput: true。
Go 帮助程序不会添加压缩、循环和 shell 工具。 根据需要显式配置它们。 其他 SDK 中描述的打包后台代理委托提供程序在 Go 中不可用。
有关设置,请参阅 创建 Go harness 代理;有关默认值和覆盖项,请参阅 Go harness 配置指南。
示例终端用户体验
Harness 不规定应用程序接口。 存储库包含示例终端应用程序,这些应用程序可以流式传输输出、显示待办事项和当前模式、呈现工具审批提示,并提供/todos、/mode和 /exit等命令。
重要
这些控制台项目是示例,而不是随附的框架组件。 将它们用作可运行的示例,或用作你自己的终端体验的起点。
.NET 示例入口点为 HarnessConsole.RunAgentAsync:
using Harness.Shared.Console;
await HarnessConsole.RunAgentAsync(
agent,
userPrompt: "Ask me anything to get started.");
使用观察程序、工具格式化程序、命令处理程序和HarnessConsoleOptions自定义该示例。 请参阅 .NET Harness 示例。
Python 示例在工具套件示例旁使用基于 Textual 的console包:
from console import run_agent_async
await run_agent_async(agent)
使用观察器、格式化器、命令和用户界面组件来自定义示例。 请参阅 Python Harness 示例。
Go 存储库中包含一个带有审批处理功能的复合测试框架示例,以及一个独立的交互式聊天 CLI 演示。 聊天 CLI 使用纯代理;它与 C# 或 Python Harness 控制台不等效。