[MAF的工具-03]服务端托管运行的一系列Hosted工具
虽然我们在很多情况下都在强调LangChain在设计上要优于MAF,但是不可否认,MAF在一些方法也有其独到之处,其中就包括针对服务端托管并运行工具的支持。也就是说,我们不仅仅可以利用AIFunctionFactory创建在Agent端本地执行的AIFunction,或者利用McpClientTool来远程调用MCP服务提供的工具外,还可以使用一系列预定义在服务端托管并运行工具。这些工具的一般以Hosted为前缀,由于它们的作用仅仅是告诉托管服务Agent种注册了此服务,所以这些工具都没有具体的实现,仅仅是一个标记而已,我们不要妄图从定义这些工具类的代码中去寻找它们的实现逻辑。
1. HostedWebSearchTool
顾名思义,HostedWebSearchTool是一个托管在服务端的Web搜索工具,它的作用是告诉托管服务Agent种注册了此服务。我们可以利用HostedWebSearchTool来调用托管服务Agent种注册的Web搜索工具。HostedWebSearchTool的定义如下,其携带的有效信息基本上只有工具名称(web_search)。
public class HostedWebSearchTool : AITool
{
public override string Name => "web_search";
public override IReadOnlyDictionary<string, object?> AdditionalProperties { get; }
public HostedWebSearchTool();
public HostedWebSearchTool(IReadOnlyDictionary<string, object?>? additionalProperties);
}
在如下这个演示程序中,我们针对指定的Microsoft Foundry项目创建了一个AIProjectClient实例,并利用它创建了一个托管服务Agent。在创建Agent时,我们将HostedWebSearchTool作为工具注册到Agent中。然后我们调用Agent的RunAsync方法来执行一个搜索任务,要求它帮我们搜索2026年世界杯战况如何?。
using Azure.AI.Projects;
using Azure.Identity;
using DotNetEnv;
using Microsoft.Extensions.AI;
Env.Load();
var projectUrl = Environment.GetEnvironmentVariable("PROJECT_URL")!;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
var model = Environment.GetEnvironmentVariable("MODEL")!;
var agent = new AIProjectClient(new Uri(projectUrl),new AzureCliCredential())
.AsAIAgent(
model: model,
instructions: "You are a helpful assistant." ,
tools: [new HostedWebSearchTool()]
);
var response = await agent.RunAsync("2026年世界杯战况如何?");
Console.WriteLine(response);
输出:
截至 2026 年 7 月 11 日,2026 美加墨世界杯已经进入半决赛阶段。 ([fifa.com](https://www.fifa.com/en/tournaments/mens/worldcup/canadamexicousa2026/standings))
目前已确定的四强球队包括:
- 法国
- 摩洛哥
- 西班牙
- 比利时 ([deccanchronicle.com](https://www.deccanchronicle.com/fifa-world-cup-2026/fifa-world-cup-2026-quarterfinals-full-schedule-qualified-teams-and-fixtures-1969250))
淘汰赛关键结果:
- 法国 2:0 摩洛哥(半决赛)
- 西班牙 vs 比利时 的另一场半决赛正在进行中,当前比分一度为 1:1。 ([fifa.com](https://www.fifa.com/en/tournaments/mens/worldcup/canadamexicousa2026/standings))
此前八强阶段的主要结果包括:
- 法国淘汰巴拉圭
- 摩洛哥淘汰加拿大
- 西班牙淘汰葡萄牙
- 比利时淘汰美国 ([fifa.com](https://www.fifa.com/en/tournaments/mens/worldcup/canadamexicousa2026/standings))
本届世界杯是历史上首次扩军到 48 支球队,共有 104 场比赛,由美国、加拿大、墨西哥联合举办。决赛将在美国新泽西州的大都会人寿体育场举行,时间是 2026 年 7 月 19 日。 ([fifa.com](https://www.fifa.com/en/tournaments/mens/worldcup/canadamexicousa2026/articles/match-schedule-fixtures-results-teams-stadiums?os=av.&ref=app))
如果你愿意,我也可以继续给你:
- 最新射手榜
- 中国球迷最关注球队表现
- 阿根廷 / 巴西 / 英格兰等强队战况
- 完整淘汰赛对阵图
- 今日比赛时间表
2. HostedCodeInterpreterTool
HostedCodeInterpreterTool这个工具用于LLM服务商(如 OpenAI、Azure AI)在云端沙箱中运行代码的能力。作为一个标记类的工具,其本身不包含任何代码解释和执行的逻辑,其本质是一个向AI服务的示意信号。当我们在Agent中注册此工具时,即代表授权LLM在处理当前任务时,可以自由编写并自主运行所需的代码(通常为Python),以解决复杂计算或数据分析问题。如下面的代码所示,HostedCodeInterpreterTool将工具命名为code_interpreter。
public class HostedCodeInterpreterTool : AITool
{
public override string Name => "code_interpreter";
public override IReadOnlyDictionary<string, object?> AdditionalProperties { get; }
public IList<AIContent>? Inputs { get; set; }
public HostedCodeInterpreterTool();
public HostedCodeInterpreterTool(IReadOnlyDictionary<string, object?>? additionalProperties);
}
除了在初始化时利用参数additionalProperties来设置附加属性外,我们还可以通过Inputs属性来指定输入内容。我们可以利用它以AIContent列表的形式为代码解析器提供输入数据。这是该工具最关键的属性。代码解释器往往需要读取文件(例如让AI分析一个Excel表格或CSV数据)。支持的AIContent类型包括:
- HostedFileContent: 指向已经上传到云端服务商那里的文件ID);
- DataContent:直接传递二进制数据(并非所AI平台都支持直接传二进制流,不支持的会被
IChatClient自动忽略)。
在如下的演示程序中,我们针对指定的Microsoft Foundry项目创建了一个AIProjectClient实例,并利用它创建了一个托管服务Agent。在创建Agent时,我们将HostedCodeInterpreterTool作为工具注册到Agent中。然后我们调用Agent的RunAsync方法来执行一个数据分析任务。
using Azure.AI.Projects;
using Azure.Identity;
using DotNetEnv;
using Microsoft.Extensions.AI;
Env.Load();
var projectUrl = Environment.GetEnvironmentVariable("PROJECT_URL")!;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
var model = Environment.GetEnvironmentVariable("MODEL")!;
var instructions = """
你是一个资深的数据分析师。请通过编写和运行Python代码来解决用户的问题。
如果遇到数据缺失,请先编写代码进行合理的清洗(例如用均值填充)。。
""";
var agent = new AIProjectClient(new Uri(projectUrl), new AzureCliCredential())
.AsAIAgent(
model: model,
instructions: instructions,
tools: [new HostedCodeInterpreterTool()]
);
var complex_query = ("""
如下这个CSV格式的表格存储了2025年上半年PC和Phone的月度销售数据。
请帮我完成以下任务:
- 1. 检查数据,如果某月的销售数据有缺失,请用该列的平均值填充;
- 2. 分别计算PC和Phone的季度销售额和半年总销售额;
```csv
Month, PC, Phone
1,20000.0,12000.0
2,25000.0,15000.0
3,23000.0,
4,27000.0,22000.0
5,,19000.0
6,32000.0,26000.0
```
""");
var response = await agent.RunAsync(complex_query);
Console.WriteLine(response);
具体来说,我们将一个不完整CSV格式的表格作为输入数据传递给HostedCodeInterpreterTool,并要求Agent帮我们完成以下任务:
- 检查数据,如果某月的销售数据有缺失,请用该列的平均值填充;
- 分别计算PC和Phone的季度销售额和半年总销售额。
从如下的输出结果可以看出,LLM在云端沙箱中成功运行了Python代码,并完成了数据清洗和统计计算的任务。
已完成数据检查、缺失值填充以及季度和半年销售额统计。
缺失值处理结果:
- Phone 第3月缺失,用 Phone 列平均值 18800.0 填充
- PC 第5月缺失,用 PC 列平均值 25400.0 填充
清洗后的数据:
| Month | PC | Phone |
|---|---:|---:|
| 1 | 20000.0 | 12000.0 |
| 2 | 25000.0 | 15000.0 |
| 3 | 23000.0 | 18800.0 |
| 4 | 27000.0 | 22000.0 |
| 5 | 25400.0 | 19000.0 |
| 6 | 32000.0 | 26000.0 |
销售汇总结果:
| 产品 | Q1 | Q2 | Half Year Total |
|---|---:|---:|---:|
| PC | 68000.0 | 84400.0 | 152400.0 |
| Phone | 45800.0 | 67000.0 | 112800.0 |
3. HostedFileSearchTool
HostedFileSearchTool用来告诉支持RAG功能的AI服务:我允许你检索我指定的文件、知识库或向量数据库,用来回答用户的问题”。当LLM面对需要特定知识库才能回答的问题时,如果Agent注册了此工具,LLM服务商(如OpenAI)就会在它们自家的服务器端启动检索机制,找出相关的文件片段喂给大模型。
public class HostedFileSearchTool : AITool
{
public override string Name => "file_search";
public override IReadOnlyDictionary<string, object?> AdditionalProperties { get; }
public IList<AIContent>? Inputs { get; set; }
public int? MaximumResultCount { get; set; }
public HostedFileSearchTool();
public HostedFileSearchTool(IReadOnlyDictionary<string, object?>? additionalProperties);
}
除了表示工具名称的Name属性(返回file_search)和附加属性AdditionalProperties外,HostedFileSearchTool还提供了两个重要的属性:
- Inputs:指定大模型可以去哪里搜索。这是一个非常灵活的设计,支持多种云端知识源:
- HostedFileContent:指向已上传到云端的特定文件 ID;
- HostedVectorStoreContent:指向云端已经建好的向量存储的ID;
- DataContent:直接随请求上传的原始二进制数据;
- MaximumResultCount:一个可选的整数,用来指定检索结果的最大数量。
如下程序演示了一个典型的RAG应用场景。如代码片段所示,我们根据指定的Microsoft Foundry项目创建了一个AIProjectClient实例,并利用它提供的OpenAIFileClient上传了一则描述吴宜泽2026斯诺克世界赛夺冠的新闻稿。然后我们利用这个文件创建了一个向量存储,并根据向量存储的ID创建了HostedVectorStoreContent对象。我们利用这个HostedVectorStoreContent对象创建了一个HostedFileSearchTool对象,并将它注册到根据AIProjectClient对象构建的Agent中。
using Azure.AI.Projects;
using Azure.Identity;
using DotNetEnv;
using Microsoft.Extensions.AI;
using OpenAI.Files;
using OpenAI.VectorStores;
using System.Text;
Env.Load();
var projectUrl = Environment.GetEnvironmentVariable("PROJECT_URL")!;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
var model = Environment.GetEnvironmentVariable("MODEL")!;
var aiProjectClient = new AIProjectClient(new Uri(projectUrl), new AzureCliCredential());
var openAIClient = aiProjectClient.GetProjectOpenAIClient();
var fileClient = openAIClient.GetOpenAIFileClient();
var news = """
北京时间2026年5月5日,英国谢菲尔德克鲁斯堡剧院,决胜局最后一颗黑球落袋后,00后中国球员吴宜泽挥拳庆祝。18:17,吴宜泽击败肖恩·墨菲,拿下2026年斯诺克世锦赛冠军。
社交平台上,**吴宜泽夺冠**迅速登上热搜,不少球迷将这场胜利形容为**中国斯诺克新的接力时刻**。这是继2025年赵心童夺冠之后,中国选手再次问鼎这项赛事最高荣誉。这也是在经历2023年前后相关禁赛与争议事件后,中国球员重新回到世界顶级竞争序列的重要节点。
相比十多年前,丁俊晖在斯诺克领域的单点突破,中国近几年开始稳定涌现世界级斯诺克选手。从个体突破到群体崛起,这项运动在中国已经进入新的发展阶段。
""";
var uploadResult = await fileClient.UploadFileAsync(
BinaryData.FromBytes(Encoding.UTF8.GetBytes(news)),
"news.md",
FileUploadPurpose.Assistants);
var storeClient = openAIClient.GetVectorStoreClient();
var storeResult = await storeClient.CreateVectorStoreAsync(options: new VectorStoreCreationOptions()
{
Name = "document-knowledge-base",
FileIds = { uploadResult.Value.Id }
});
var vectorStoreId = storeResult.Value.Id;
while (true)
{
var vectorStore = await storeClient.GetVectorStoreAsync(vectorStoreId);
if (vectorStore.Value.Status == VectorStoreStatus.Completed)
{
break;
}
await Task.Delay(1000);
}
var agent = aiProjectClient
.AsAIAgent(
model: model,
instructions: "You are a helpful assistant.",
tools: [new HostedFileSearchTool(){ Inputs = [new HostedVectorStoreContent(storeResult.Value.Id)] }]
);
var response = await agent.RunAsync("2026年斯诺克世锦赛冠军是谁?");
Console.WriteLine(response);
最后我们调用Agent的RunAsync方法来执行一个RAG任务,要求它帮我们回答2026年斯诺克世锦赛冠军是谁?。如下是输出结果:
2026年斯诺克世锦赛冠军是中国球员吴宜泽。他在决赛中以18比17击败肖恩·墨菲夺冠。
4. HostedMcpServerTool
HostedMcpServerTool的作用非常明确,就是为LLM的托管方挂载一个MCP服务器。作为一个声明型标记工具,HostedMcpServerTool自己不运行 MCP 协议,而是作为一张委托协议书,把远程MCP的地址告诉LLP托管方,由它在云端服务直接发起HTTP/SSE请求去连接该MCP服务器,彻底解放本地算力与带宽。
public class HostedMcpServerTool : AITool
{
public override string Name => "mcp";
public override IReadOnlyDictionary<string, object?> AdditionalProperties { get; }
public string ServerName { get; }
public string ServerAddress { get; }
public string? ServerDescription { get; set; }
public IList<string>? AllowedTools { get; set; }
public HostedMcpServerToolApprovalMode? ApprovalMode { get; set; }
public IDictionary<string, string>? Headers { get; set; }
public HostedMcpServerTool(string serverName, string serverAddress);
public HostedMcpServerTool(string serverName, string serverAddress, IReadOnlyDictionary<string, object?>? additionalProperties);
public HostedMcpServerTool(string serverName, Uri serverAddress);
public HostedMcpServerTool(string serverName, Uri serverAddress, IReadOnlyDictionary<string, object?>? additionalProperties);
}
HostedMcpServerTool相关属性说明如下:
- ServerName:MCP Server名称;
- ServerAddress:MCP Server地址;
- ServerDescription:MCP Server描述信息;
- AllowedTools:允许使用的工具列表。一个远程MCP Server可能自带了非常多工具。为了防止滥用,你可以通过此属性精确白名单指定只允许调用其中的某几个工具。若为
null则全量开放; - ApprovalMode:针对工具执行决定的审批模式;
- Headers:请求头信息字典。可以把
Authorization: Bearer <Token>或自定义API Key塞进这里。云端LLM服务在替你请求该MCP时,会自动带上这些请求头。
ApprovalMode属性是HostedMcpServerTool的一个重要属性,它决定了托管服务Agent在调用远程MCP Server时,是否需要对工具执行进行审批。ApprovalMode有三种模式:
- AlwaysRequire:总是需要审批。每次调用远程MCP Server的工具时,都会触发审批流程;
- NeverRequire:从不需要审批。每次调用远程MCP Server的工具时,都会直接执行,无需审批;
- RequireSpecific:只对指定的工具需要审批。你可以通过
AlwaysRequireApprovalToolNames和NeverRequireApprovalToolNames属性来指定哪些工具需要审批,哪些工具不需要审批。
public class HostedMcpServerToolApprovalMode
{
public static HostedMcpServerToolAlwaysRequireApprovalMode AlwaysRequire { get; }
public static HostedMcpServerToolNeverRequireApprovalMode NeverRequire { get; }
public static HostedMcpServerToolRequireSpecificApprovalMode RequireSpecific(
IList<string>? alwaysRequireApprovalToolNames,
IList<string>? neverRequireApprovalToolNames);
}
public HostedMcpServerToolAlwaysRequireApprovalMode(){}
public HostedMcpServerToolNeverRequireApprovalMode(){}
public sealed class HostedMcpServerToolRequireSpecificApprovalMode : HostedMcpServerToolApprovalMode
{
public IList<string>? AlwaysRequireApprovalToolNames { get; set; }
public IList<string>? NeverRequireApprovalToolNames { get; set; }
public HostedMcpServerToolRequireSpecificApprovalMode(
IList<string>? alwaysRequireApprovalToolNames,
IList<string>? neverRequireApprovalToolNames);
}
如果没有对ApprovalMode进行设置,意味着该属性默认值为null,此时采用怎样的审批模式取决于LLM服务商的默认策略。不同的LLM服务商可能会有不同的默认策略,有些可能默认总是需要审批,有些可能默认从不需要审批。在如下的演示程序中,我们利用创建的HostedMcpServerTool挂载了一个指向https://mcp.deepwiki.com/mcp地址的MCP Server。这是由知名AI公司Cognition Labs官方推出的远程、完全免费且免认证的公共MCP服务器。它的核心功能是让AI助手具备秒级阅读、检索和理解任何GitHub公开开源项目文档与架构的能力。
using Azure.AI.Projects;
using Azure.Identity;
using DotNetEnv;
using Microsoft.Extensions.AI;
Env.Load();
var projectUrl = Environment.GetEnvironmentVariable("PROJECT_URL")!;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
var model = Environment.GetEnvironmentVariable("MODEL")!;
var tool = new HostedMcpServerTool(
serverName: "deepwiki",
serverAddress: "https://mcp.deepwiki.com/mcp")
{
ApprovalMode = HostedMcpServerToolApprovalMode.NeverRequire
};
var agent = new AIProjectClient(new Uri(projectUrl), new AzureCliCredential())
.AsAIAgent(
model: model,
instructions: "You are a helpful assistant.",
tools: [tool]);
var sesson = await agent.CreateSessionAsync();
var response = await agent.RunAsync("简单介绍一下microsoft/agent-framework这个github repository。",sesson);
Console.WriteLine(response);
我们调用Agent的RunAsync方法来执行一个任务,要求它帮我们简单介绍一下microsoft/agent-framework这个GitHub仓库。Agent会调用远程MCP Server来获取相关信息,并最终返回如下的输出:
microsoft/agent-framework 是微软开源的一个 AI Agent 开发框架,目标是帮助开发者构建“可编排、多智能体、可部署”的 AI 应用。它同时支持 .NET 和 Python,定位有点类似于一个企业级 Agent Runtime + Workflow 平台。
这个项目的核心特点主要有几个方向:
- Agent 抽象
提供统一的 Agent 接口,可以接入 OpenAI、Azure OpenAI、Azure AI Foundry 等模型服务。Agent 不只是简单聊天,还能管理上下文、状态、工具调用和多轮会话。
- Workflow / Orchestration(编排)
这是它比较强调的能力。框架支持:
- 多 Agent 协作
- 顺序 / 并行执行
- Handoff(任务转交)
- Group Chat
- Human-in-the-loop(人工审批)
- Checkpoint(断点恢复)
本质上是在做 AI 工作流引擎,而不只是一个 prompt 封装库。
- Tool & MCP 支持
支持 Function Calling、Hosted Tools,以及 MCP(Model Context Protocol)。也就是说 Agent 可以调用外部工具、数据库、API,甚至和其他 MCP Server 集成。
- Memory 与状态管理
内置 Session、Chat History、Context Provider 等机制,适合做长期对话或企业 Copilot 类应用。
- 企业级能力
项目里明显带有微软企业产品风格,包括:
- Observability(监控)
- Middleware
- Data Governance
- Azure Functions / ASP.NET Core 部署
- 容器化部署
从架构上看,它更像:
“Semantic Kernel + LangGraph + 企业工作流引擎”的结合体。
适合的场景包括:
- 企业内部 Copilot
- 多 Agent 自动化系统
- AI 工作流平台
- AI 客服 / 办公助手
- 需要审批和状态管理的 Agent 系统
如果你之前接触过:
- LangChain
- LangGraph
- AutoGen
- Semantic Kernel
那么 Agent Framework 可以理解为微软正在推动的新一代统一 Agent 基础设施,而且明显更偏“生产级”和“Azure 生态”。
仓库地址:
https://github.com/microsoft/agent-framework
如果你愿意,我还可以进一步帮你介绍:
- 它和 AutoGen / Semantic Kernel 的关系
- 整体架构设计
- 一个简单 demo 的运行流程
- 它相比 LangGraph 的差异
- Python 与 .NET 两套实现的区别
5. HostedToolSearchTool
HostedToolSearchTool是发给LLM的工具检索卡。当你的应用拥有成百上千个工具时,它告诉LLM不要一口气吞下所有工具的定义,而是让它在需要时按需搜索并加载特定工具。在复杂的Agent系统或大型企业应用中,我们可能会向大模型提供几十甚至几百个自定义工具。如果每次对话都把这几百个工具的JSON Schema(名称、描述、参数列表)塞进提示词里,会导致:
- Token成本飙升:即使用户只是说一句你好,也会白白消耗几万个输入Tokens;
- 大模型注意力分散:工具描述过多会导致大模型产生长上下文迷失,甚至误调用不相关的工具。
通过加入HostedToolSearchTool,不会直接发送完整的工具定义给LLM,而是只向AI提供一个概览或告诉它你可以去搜索工具。当大模型发现解决问题需要某个特定能力时,它会调用工具函数tool_search检索到具体工具定义后,再动态加载并调用它。HostedToolSearchTool的定义如下,其携带的有效信息基本上只有工具名称(tool_search),以及可选的附加属性。
public class HostedToolSearchTool : AITool
{
public override string Name => "tool_search";
public override IReadOnlyDictionary<string, object?> AdditionalProperties { get; }
public IList<string>? DeferredTools { get; set; }
public string? Namespace { get; set; }
public string? NamespaceDescription { get; set; }
public HostedToolSearchTool();
public HostedToolSearchTool(IReadOnlyDictionary<string, object?>? additionalProperties);
}
三个额外的属性说明如下:
- DeferredTools:一个字符串列表,指定哪些工具是延迟加载的。也就是说,这些工具不会在初始对话中直接发送给大模型,而是需要在运行时按需检索和加载;
- Namespace:一个可选的字符串,用于指定工具的命名空间;
- NamespaceDescription:一个可选的字符串,用于描述命名空间的用途或功能。
通过下面演示程序创建的Agent注册了两个工具:工具函数GetWeather用于返回指定城市的天气信息,而HostedToolSearchTool则用于按需检索工具。Agent在处理用户请求时,如果需要获取天气信息,它会调用HostedToolSearchTool来检索GetWeather工具,并使用它来获取所需的天气数据。
using Azure.AI.Projects;
using Azure.Identity;
using DotNetEnv;
using Microsoft.Extensions.AI;
using OpenAI.Chat;
using OpenAI.Responses;
using System.ClientModel.Primitives;
using System.ComponentModel;
using System.Text.Encodings.Web;
using System.Text.Json;
Env.Load();
var projectUrl = Environment.GetEnvironmentVariable("PROJECT_URL")!;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
var model = Environment.GetEnvironmentVariable("MODEL")!;
var GetWeather = AIFunctionFactory.Create(
method: ([Description("The city")] string city) => $"晴,气温25摄氏度。",
name: "GetWeather",
description: "获取所在城市天气信息"
);
var agent = new AIProjectClient(new Uri(projectUrl), new AzureCliCredential())
.AsAIAgent(
model: "gpt-5.4-mini",
instructions: "你是一个天气信息的只能助手。",
tools: [
new HostedToolSearchTool{
Namespace = "weather",
NamespaceDescription = "提供获取工具获取天气相关信息",
DeferredTools = [GetWeather.Name]
},
GetWeather
]);
var response = await agent.RunAsync("根据目前北京天气提供一些着装建议");
var rawContents = response.Messages
.SelectMany(m => m.Contents)
.Where(c => c.RawRepresentation is not null)
.Select(c => ModelReaderWriter.Write(c.RawRepresentation!, ModelReaderWriterOptions.Json).ToString())
.ToList();
var options = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var index = 1;
foreach (var rawJson in rawContents)
{
Console.WriteLine($"{new string('-',20)}Content {index++}{new string('-', 20)}");
using JsonDocument document = JsonDocument.Parse(rawJson);
string formattedJson = JsonSerializer.Serialize(document, options);
Console.WriteLine(formattedJson);
}
通过输入任务根据目前北京天气提供一些着装建议调用Agent,并得到对应的响应结果后,我们将所有响应消息的原始内容(RawRepresentation)提取出来,并将其格式化为易读的JSON格式进行输出:
--------------------Content 1--------------------
{
"type": "tool_search_call",
"id": "tsc_0c88c1d3088ccf9d006a524c4c35c881909cde7dc284ac7c3f",
"response_id": "resp_0c88c1d3088ccf9d006a524c4be03481908a9102e6419958a3",
"status": "completed",
"arguments": {
"paths": [
"weather"
]
},
"call_id": null,
"execution": "server"
}
--------------------Content 2--------------------
{
"type": "tool_search_output",
"id": "tso_0c88c1d3088ccf9d006a524c4c45c88190aab3ebb382f74ad8",
"response_id": "resp_0c88c1d3088ccf9d006a524c4be03481908a9102e6419958a3",
"status": "completed",
"call_id": null,
"execution": "server",
"tools": [
{
"type": "namespace",
"description": "提供获取工具获取天气相关信息",
"name": "weather",
"tools": [
{
"type": "function",
"defer_loading": true,
"description": "获取所在城市天气信息",
"name": "GetWeather",
"parameters": {
"type": "object",
"required": [
"city"
],
"properties": {
"city": {
"description": "The city",
"type": "string"
}
},
"additionalProperties": false
},
"strict": false
}
]
}
]
}
--------------------Content 3--------------------
{
"type": "function_call",
"id": "fc_0c88c1d3088ccf9d006a524c4c80188190b54f2fbfe21af954",
"status": "completed",
"call_id": "call_dHaO8YOHTrlDCoqogex7gPjB",
"name": "GetWeather",
"arguments": "{\"city\":\"北京\"}",
"response_id": "resp_0c88c1d3088ccf9d006a524c4be03481908a9102e6419958a3",
"namespace": "weather"
}
--------------------Content 4--------------------
{
"type": "output_text",
"text": "北京现在天气是晴,气温约 25℃。 \n着装建议:\n\n- 上身:短袖 T 恤、薄衬衫都合适\n- 下身:长裤或轻薄休闲裤即可\n- 外搭:如果早晚要出门,可以带一件薄外套\n- 鞋子:透气运动鞋、休闲鞋比较舒服\n- 其他:阳光较强的话,建议带墨镜和防晒用品\n\n如果你要出门时间较长,我也可以继续帮你按“上班/通勤/运动/约会”场景细化搭配。",
"annotations": [],
"logprobs": []
}
从上面的输出接口可以看出任务处理的整个流程:
- 由于Agent注册了
HostedToolSearchTool,并且将GetWeather工具标记为延迟加载(DeferredTools),所以最终调用LLM的提示词中并没有直接包含GetWeather工具的定义。所以LLM会调用工具tool_search来检索工具定义,而作为检索的查询文本来源于我们在HostedToolSearchTool中指定的Namespace属性("paths": ["weather"]); - 检索的工具列表会作为
tool_search执行结果的一部分,其中就包括我们注册在Agent中的GetWeather工具; - LLM在获取到
GetWeather工具的定义后,会根据用户的请求(北京天气)调用GetWeather工具,并将参数传递给它; - 最终,
GetWeather工具返回了北京的天气信息,LLM根据返回的天气信息生成了着装建议,并将其作为最终的输出文本返回给用户。
更多推荐


所有评论(0)