免费文章 · 05 理解工具、工作流与 Agent
让 AI 通过工具获取信息和执行操作
上一节,我们讨论了怎样根据任务特点组合模型与工作步骤,并结合效果与成本,选择合适的工作方式。接下来,我们要让这些安排真正连接到外部系统:从应用中读取当前资料,再把生成的内容保存为以后能够继续读取、修改的草稿。
比如,我们要求 AI“参考最新资料,写完后保存”。但模型该通过什么工具取得资料?草稿应该保存到哪里?操作完成后,又怎样取得实际结果?这些问题不仅涉及工具怎样调用,也涉及我们应该为 AI 提供什么样的工具。
这一节,我们先理解模型与程序怎样通过工具协作,再从实际任务出发,学习如何设计职责清楚、粒度合适的工具,并让它们返回后续工作需要的信息。随着工具增多,我们还会学习怎样组织和提供这些能力,最后通过真实调用记录,检查工具设计是否真正满足任务需要。
工具怎样连接模型与外部系统
当资料保存在外部应用中,模型要使用最新内容,就需要有办法读取它;如果还要保存生成的草稿,也需要有执行写入的能力。工具就是模型与外部系统之间的连接。
例如,模型提出读取当前作品要求的请求,工具程序取得资料,再由运行环境将结果提供给模型;保存草稿时,则通过工具把标题和正文写入指定章节。工具既能让模型取得当前需要的信息,也能执行改变外部系统状态的操作。
工具可以由应用自行实现,也可以使用平台提供的搜索、计算或浏览等能力。无论工具来自哪里,都需要让模型知道有哪些操作可以使用、需要提供什么参数,以及执行结果怎样返回。
一次工具调用是怎样完成的
我们常说“AI 调用了保存工具”,但实际完成一次调用,需要模型与运行环境共同配合。以应用自行提供的工具为例,可以分为四个环节:
- 应用提供工具定义。 名称和说明告诉模型工具能做什么、什么时候适合使用;参数结构说明需要提供哪些字段及其类型。实际执行程序仍在应用一侧。
- 模型生成调用请求。 模型根据当前任务选择工具,填写参数,返回结构化的调用请求。
- 运行环境执行操作。 应用接收请求,将参数交给对应的工具程序,由程序检查输入和业务条件,再执行读取或写入。
- 执行结果返回模型。 运行环境将读取内容、保存回执或错误信息提供给模型,供它继续工作。
图中,蓝色箭头表示调用请求,绿色箭头表示执行结果。真正的正文写入发生在右侧工具程序中。模型负责提出请求,运行环境负责执行和回传。
在常见的工具调用协议中,每次请求都有对应的调用标识,用于关联请求与返回结果。这样,即使同一个工具连续调用多次,或者多个请求并行完成,也能准确区分每份结果来自哪次调用。
一次模型返回也可能包含多个工具调用。彼此独立的读取可以并行执行;如果下一步依赖前一次的结果,就需要等结果返回后,再确定接下来的操作。
从任务倒推需要哪些工具
了解工具怎样工作后,接下来就要决定:我们究竟应该为 AI 提供哪些工具?
应用内部可能已经有大量接口,但这些接口通常按数据和功能模块组织,而 AI 面对的是具体任务。如果直接把所有接口交给模型,原本可以由程序完成的查找、拼接和整理,也可能变成模型需要逐步处理的工作。
因此,设计工具时,我们可以从任务倒推:需要哪些外部能力?每个工具应该负责多大范围的工作?又需要返回什么结果?
找出任务需要的外部能力
先看任务要完成什么,以及哪些工作需要借助外部系统。模型可以根据已有资料组织情节、撰写正文,但读取应用中的最新记录、查询章节状态和持久保存草稿,都需要相应的程序支持。
以“完成第一章并保存为待审草稿”为例,我们可以整理出四项需要:
任务中的需要 | 对应工具 | 职责 |
|---|---|---|
取得当前要求、设定和大纲 |
| 提供写作依据 |
读取指定章节 |
| 取得正文与修订信息 |
了解已有章节 |
| 返回章节目录与状态 |
保存待审草稿 |
| 按业务条件写入指定章节 |
这样,工具的设计就有了明确依据。我们需要的是完成任务所必需的能力,而不是先凑齐一套增删改查接口。 本次没有删除作品或正式采用稿件的要求,就不必额外开放这些操作。
确定工具的职责与粒度
知道需要哪些能力后,还要决定一次调用负责多少工作。
如果工具拆得太细,模型就需要完成更多调用和中间处理;如果封装得太多,又可能把原本需要分别判断的操作绑在一起。我们可以根据实际任务,在三种设计方式之间选择:
设计方式 | 工具示例 | 主要特点 |
|---|---|---|
基础操作 |
| 灵活,但模型需要自行处理文件路径和业务约定 |
业务动作 |
| 对象和职责明确,程序可以落实相应规则 |
组合能力 |
| 把多个相关操作封装在一个工具中,一次返回整理好的结果 |
那么,什么时候值得把多个操作合成一个工具?
关键要看中间是否还需要模型作出判断。例如,按照指定章号取得要求、目录和已有正文,如果这些资料总是一起使用,就可以考虑让程序统一整理,再交给模型写作。这样能减少机械的读取与拼接。
但如果任务只是修改一段对白,直接读取对应章节可能更合适,没有必要每次都取得整套写作资料。工具应该封装多少工作,要由实际使用需要决定。
另外,组合工具时还要考虑操作后果。保存草稿与正式采用虽然都涉及章节状态,却需要不同的确认条件。比如,本次只授权 AI 保存待审草稿,正式采用仍由人决定,因此不应把两个动作合并成一次自动执行。
让模型理解工具的用途和结果
划分好工具的职责,接下来还要让模型知道什么时候使用、怎样使用。模型主要依据工具的名称、说明和参数结构选择调用,因此,这些信息需要准确表达工具的用途与要求。
名称、说明和参数怎样配合
名称帮助模型辨认动作,说明交代适用情形和使用边界,参数结构则约定调用时需要提供什么。三者共同回答:这个工具能完成什么、什么时候应该使用、需要哪些输入。
例如,“管理作品”很难区分读取、保存还是删除;“将指定章节保存为待审草稿”则明确了操作对象和结果。如果同时提供保存草稿与正式采用的工具,还要说明两者在什么条件下使用。
参数同样需要清楚。对象标识、数据类型、取值范围和格式应当明确,能够用枚举或结构化字段表达的条件,就不必全部交给自由文本。对于应用已经确定的作品标识,也可以由程序直接提供,减少模型填写错误的机会。
不过,参数结构负责约束输入形式,操作权限和业务条件仍需要程序在执行时检查。
返回内容要支持下一步工作
工具返回的结果会成为模型后续工作的依据。它可以是文字、结构化数据,也可以包含所用接口支持的图像或文件。除了实际内容,还可能需要提供来源位置、对象标识和当前状态,让后续操作能够准确衔接。
例如,读取章节时,模型需要正文才能理解内容,也可能需要章节编号和修订信息来完成后续保存。如果检索结果很多,可以先返回相关片段和读取位置,需要时再取得完整内容。
返回内容不是越多越好,而是要让模型获得完成下一步所需的信息。
比如,save_draft 保存成功后,可以只返回章号、修订和草稿状态;需要核对完整正文时,再通过读取工具取得。这样既保留了必要的操作依据,也避免在保存回执中重复返回整篇文章。
对于需要程序继续处理的结果,应提供稳定的结构化字段;需要模型理解的内容,则要保留清楚的含义。结果只返回了一部分时,也应说明范围,并提供继续读取的方式。
由程序落实操作条件和失败处理
模型知道怎样调用工具以后,还需要保证这些请求能够被正确执行。工具说明帮助模型选择操作,真正的权限与业务条件则由程序负责落实。
例如,读取资料时,需要确认当前用户有权访问;保存草稿时,还要检查目标章节、当前状态以及是否允许覆盖。即使外部文档要求执行某项操作,也不能因此获得超出当前授权的权限。
这里我们通过草稿修订理解程序的作用。模型生成新稿时,会依据当时读取的章节修订提出保存请求。如果在此期间,人已经修改了正文,程序就应拒绝使用旧修订的保存请求,避免覆盖新内容。
这样,“不要覆盖人的修改”不只是一句提示要求,而是由保存程序实际执行的业务规则。
操作失败时,返回结果也应帮助后续处理:参数有误,就说明哪项输入不符合要求;修订已经变化,就提示重新读取;权限不足,则明确当前限制。
此外,还要说明操作是否已经生效。如果写入结果尚不确定,就需要保留这一状态,供后续核查,避免贸然重复执行同一个操作。
工具多起来以后,怎样组织和提供
工具较少时,模型容易辨认各自的用途。但随着应用接入更多业务,相似的操作可能出现在不同领域,工具定义也会占用更多上下文。这时需要考虑两个问题:怎样让模型区分工具的用途,以及怎样让它只接触当前需要的能力?
用命名空间组织工具
命名空间可以把同一领域的工具组织在一起。 例如,一个同时处理小说写作和视频素材的工作台,可以用 writing 组织章节与设定工具,用 media 组织素材工具。两者都可能提供搜索功能,但所属领域不同,模型也就更容易判断该使用哪一个。
有些接口采用扁平的工具名称,也可以使用 writing_search、media_search 这样的前缀表达归属。
分组不必追求复杂。工具较少、用途明确时,直接使用清楚的名称即可;只有当业务增多、工具容易混淆时,才值得引入更细的组织方式。命名空间帮助区分用途,并不改变工具本身的操作权限。
按当前任务提供工具,按需发现其余能力
分组解决了工具怎样辨认的问题,但如果每次仍把全部工具定义提供给模型,上下文负担并不会因此减少。
因此,应用可以根据当前任务、权限和工作阶段,选择需要提供给模型的工具。例如,整理访谈素材时,先提供检索、读取和保存方案的能力;如果之后需要制作字幕,再补充相关工具。
对于工具数量较多、任务需求又难以提前确定的情况,还可以借助宿主支持的工具发现与按需加载机制,在需要时取得其他工具的详细定义。
进阶:按需发现与加载工具
当工具数量较多时,支持工具搜索的宿主(Codex、Claude Code、ChatGPT、AI API)可以先向模型提供工具概览或发现入口,再根据任务加载相关工具的完整定义。
这与《渐进式信息披露》中的资料组织方式相似:先知道有哪些能力可用,再按需取得具体说明。
需要区分的是,工具服务端的完整注册目录,与当前进入模型上下文的工具定义,并不是一回事。 按需加载通常由宿主负责,具体能力取决于所用系统。
发现工具本身也有成本。工具较少时,直接提供往往更简单;当每次只使用大量工具中的一小部分时,再考虑按需加载是否更合适。
继续阅读官方资料
如果希望进一步了解工具设计与实现,可以根据需要查阅以下官方资料:
- Anthropic:Writing effective tools for agents:工具选择、职责划分、返回内容与评估方法。
- OpenAI:Define tools:从任务推导工具能力,设计输入、输出与操作条件。
- OpenAI:Function calling:工具定义、结构化调用、程序执行与结果回传。
- OpenAI:Tool search:工具的按需发现、加载及其取舍。
- OpenAI:Programmatic Tool Calling:由程序协调多个工具调用与处理中间结果。
用真实任务检验工具设计
工具设计好以后,我们还需要通过实际任务检查:模型能否选对工具、填写正确参数,返回的信息是否足够,以及工具的职责和粒度是否合理。
接下来,我们用同一项章稿任务,比较“分散读取”和“组合读取”两种方式。把几个读取操作合成一个工具,能否减少不必要的调用,又会不会带来重复的信息?
实验要求 AI 完成第一章,并保存为待审草稿。两组使用相同的资料、初始状态和保存规则,只改变读取工具的组织方式。
条件 | 提供的工具 | 主要观察什么 |
|---|---|---|
分散读取 |
| 模型怎样选择不同工具、取得所需资料 |
组合读取 |
| 合并读取后,是否减少调用和重复信息 |
我们可以先查看课堂实际使用的工具定义,再对照模型发出的调用请求,看看工具说明怎样影响模型的选择。
查看课堂使用的工具定义
下面是实验中实际提供给模型的 save_draft 工具定义。留意它的名称、用途说明和参数结构:模型需要知道什么,才能正确提出保存请求?
{
"type": "function",
"function": {
"name": "save_draft",
"description": "保存第一章草稿。使用读取到的作品与正文修订;修订过旧时拒绝保存并要求重新读取。回执只有标识和状态,正文可另行读取。",
"parameters": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"chapterNumber": {
"type": "number",
"const": 1,
"description": "本次教学任务的第一章"
},
"expectedWorkRevision": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"expectedChapterRevision": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"title": {
"type": "string",
"minLength": 1
},
"body": {
"type": "string",
"minLength": 1
}
},
"required": [
"chapterNumber",
"expectedWorkRevision",
"expectedChapterRevision",
"title",
"body"
],
"additionalProperties": false
}
}
}查看一次实际工具请求
本次任务只说明要完成什么,没有规定工具名称和调用顺序。下面是模型实际提出的一次读取请求:
{
"name": "read_work",
"arguments": {}
} 可以看到,模型选择了 read_work,没有额外填写参数。这是因为当前作品已由应用绑定,无需模型再次指定 workId。其他操作所需的章号、正文等信息,则通过对应工具的参数提供。
下面是分散读取组中 read_work 的实际返回。模型通过工具取得了当前作品要求、设定和大纲,接下来就可以根据这些资料生成章稿。
取得资料后,模型调用 save_draft 保存草稿,再通过 read_chapter 读取已保存的正文。
从调用记录发现下一步改进
两组都完成了资料读取、草稿保存和读回确认。我们先看分散读取组的保存结果,以及程序独立读回的内容:
查看保存参数与独立读回
在“工具读写实验”中选择“分散读取”,展开 save_draft 的“参数与原始返回”,查看模型实际提交的保存参数。
参数 | 本轮的值 | 含义 |
|---|---|---|
|
| 依据第 1 版作品要求 |
|
| 保存前第一章尚无正文 |
程序会核对这些修订是否仍然有效,避免用旧内容覆盖新的修改。本次保存成功后,章节修订变为 r1。
再查看“程序独立读回”,将数据库中实际保存的正文,与保存请求及模型随后 read_chapter 取得的内容对照,确认三者是否一致。
核对两组实际保存的数据库,正文都与保存参数及后续读取结果一致。可以确认,两种工具设计都完成了本次保存任务。
不过,再比较调用过程,就会发现一个值得注意的差异:
条件 | 保存前怎样取得资料 | 工具调用 / 模型请求 |
|---|---|---|
分散读取 | 读取作品要求和章节目录 | 4 次 / 4 次 |
组合读取 | 读取组合上下文,又单独读取当前章 | 4 次 / 4 次 |
组合工具已经包含当前章的状态,模型却又调用了 read_chapter,重复取得“尚无草稿”的结果。把多个读取操作合成一个工具,并不意味着模型就会自动减少重复调用。
那么,问题可能出在哪里?我们可以先检查 get_writing_context 的说明,是否明确告诉模型已经返回了哪些内容,以及什么情况下才需要单独读取章节。
下一轮可以针对这些说明进行调整,再用相同任务比较:重复读取有没有减少,模型是否仍能取得完整依据,保存和读回是否正常。工具粒度是否合理,最终要看它能否让任务完成得更顺畅,而不是只看工具数量减少了多少。
本轮每种条件只运行了一次,还不足以判断哪种设计始终更好,但已经为下一次改进提供了具体方向。
现在,我们要让 AI 从一批访谈素材中,找到某位人物谈“第一次接手项目”的原话,标明素材和时间位置,整理成待审剪辑方案。应用已有素材库和逐字稿,本次不需要修改原片或发布视频。
应该为 AI 提供哪些工具? 哪些读取操作值得组合,哪项写入应独立保留?如果工作台还有字幕、画面生成和发布等数十个工具,又应该怎样组织和提供?
查看答案与解析
可以先提供访谈片段检索工具,由程序完成逐字稿搜索与素材定位,返回相关原话、素材标识、时间范围及必要上下文。如果需要进一步核对,再提供精确读取工具。
剪辑方案则通过独立的 save_edit_plan 工具保存,由程序核验素材和时间范围,返回方案标识、修订与待审状态。保存方案不需要同时开放修改原片和发布视频的能力。
工具增多后,可以按素材、字幕、生成、发布等用途组织。本次先提供检索、读取和方案保存工具;其他能力在需要时再通过支持工具发现的应用或 API 加载。
这样,工具的选择与组合就来自当前任务,而不是机械地提供全部接口。
通过这一节,我们不仅了解了工具调用怎样完成,也学会了从任务出发设计工具,再根据实际记录检查它们是否好用。
不过,工具返回结果后,任务可能还需要继续。下一节,我们将进一步学习 Agent 怎样根据工具反馈决定下一步行动,把多次调用组织成连续的工作过程。
讨论
登录后参与讨论