为什么需要 Agent,而不只是 Chat API
很多人第一次做 AI 应用时,都会从一个很自然的起点开始:把用户输入丢给模型,然后把模型输出展示出来。
这当然没错。事实上,很多场景根本不需要 Agent,一个简单的 Chat API 就能解决问题。问题在于,当任务开始要求模型去找信息、做判断、执行动作、根据结果修正下一步时,单轮对话就会越来越吃力。
这一章的目标,就是把这条边界讲清楚。我们不会急着写复杂代码,而是先建立一套后面整本教程都会反复用到的心智模型:什么时候只需要一个“会回答”的模型,什么时候你其实需要的是一个“会持续决策和行动”的系统。
从 Chat API 开始#
假设我们要做一个最小 AI 问答页面,代码可能像这样:
const response = await model.generate({
system: "你是一个 TypeScript 助手",
prompt: userInput,
});
return response.text;这个模式非常适合下面这类任务:
- 改写一段文案
- 解释一个概念
- 把一段中文翻译成英文
- 根据你已经提供的上下文做总结
这些任务的共同点是:模型只需要基于当前输入生成一个输出。它不需要自己查资料,不需要调用工具,也不需要把问题拆成多个步骤。
我们可以把这类系统称为 Chatbot,它的核心职责只有一件事:接收输入 -> 生成回复。
这类系统简单、便宜、延迟低,而且已经能覆盖非常多的真实需求。
所以在继续往下之前,先记住一个重要判断:
不是所有 AI 应用都需要 Agent。能用简单方案解决的问题,就不要先把系统做复杂。
再看 Workflow#
当单轮问答不够时,很多团队会自然走到第二步:加一条固定流程。
例如,我们希望系统完成这样一个任务:
读取一篇文章,提取重点,再输出一页摘要。
这时我们可能会写出如下流程:
- 先调用模型提取文章大纲
- 再调用模型把大纲整理成摘要
- 最后调用模型润色语言
这已经不是简单的聊天了,而是一个 Workflow。它比 Chat API 更强,因为它允许我们把任务拆成多步。但它仍然有一个很明显的特点:每一步都是预先写死的。
这类系统适合处理:
- 流程稳定
- 输入结构固定
- 每一步都可以提前设计好的任务
例如:
- OCR 后做结构化提取
- 客服工单分类后再分发
- 会议录音先转写再总结
它的优点是稳定、可控、容易调试;缺点也很明显:只要真实情况稍微偏离预期,固定流程就会开始别扭。
问题在决策#
来看一个更接近 Agent 的任务:
帮我阅读这个 TypeScript 项目,告诉我怎么启动它;如果 README 不完整,就继续查 package.json 和配置文件。
这个任务麻烦的地方,不在于“模型要写出一段文字”,而在于它必须自己决定:
- 先看哪个文件
- README 是否已经足够
- 如果不够,下一步该读
package.json还是tsconfig.json - 如果遇到多个脚本,哪个更可能是启动入口
- 是否还要继续查别的线索
这时你很难提前写出一条完全固定的流程,因为系统是否继续、往哪走、何时停止,都依赖中间结果。
这就是 Agent 出场的地方。
Agent 是什么#
这套教程里,我们采用一个非常工程化、也非常克制的定义:
Agent 是一个围绕状态运行的系统。它会根据当前目标和已有观察,决定下一步动作,并把动作结果写回状态,再继续决策,直到任务完成或停止。
这个定义里最重要的不是“智能”,而是下面这几个要素:
目标:当前想完成什么任务状态:系统目前已经知道什么动作:下一步可以做什么观察:动作执行后得到了什么结果停止条件:什么时候应该结束
把它写成最小形态,大概就是下面这个闭环:
while (!done) {
const nextAction = await decide(state);
const observation = await act(nextAction);
state = update(state, observation);
}请注意,这里最关键的不是模型本身,而是这个循环。
模型只负责一部分工作:根据当前状态判断下一步该做什么。
真正让系统像 Agent 的,是它具备了“行动之后再看结果,并基于结果继续前进”的能力。
三种系统的差别#
我们可以把三者放在一起看:
| 类型 | 核心机制 | 适合的问题 | 主要局限 |
|---|---|---|---|
| Chatbot | 单轮输入输出 | 问答、改写、总结、翻译 | 不会主动查资料,不会多步行动 |
| Workflow | 预先设计好的多步流程 | 流程稳定、结构明确的任务 | 遇到分支和例外时不灵活 |
| Agent | 根据中间结果持续决策 | 开放式、多步、路径不确定的任务 | 更复杂,成本更高,更难调试 |
可以把它们理解成三种不同的工程选择,而不是三种“能力等级”。
这点很重要。
Agent 不是 Chatbot 的升级版,也不是 Workflow 的上位替代。很多时候,最好的系统反而是:
- 外层是固定工作流
- 某个节点里嵌一个 Agent
- 简单节点仍然只用普通模型调用
也就是说,Agent 是一种可选能力,而不是所有 AI 系统的默认答案。
用同一任务来比较#
我们用同一个任务来比较三种方案:
用户问:“这个项目怎么启动?如果 README 没写清楚,请自己继续找。”
Chat API#
你只能把已有内容直接喂给模型,然后让它回答。
如果没有额外上下文,模型只能猜。
如果你手动把一堆文件都贴进去,模型上下文又会迅速膨胀。
Workflow#
你可以设计:
- 先读 README
- 再读 package.json
- 最后输出启动步骤
这样已经比单轮问答强很多,但它默认这三步总是正确的。如果 README 已经足够,这个流程还是会继续执行。反过来,如果真正的关键线索在 docker-compose.yml 或 Makefile 里,这条流程又会漏掉它。
Agent#
Agent 的处理方式更像这样:
- 先决定从 README 开始
- 读完后判断信息是否足够
- 如果不够,再决定读取
package.json - 根据脚本内容判断还要不要继续查配置文件
- 信息足够后停止,并输出答案
这里最关键的变化是:路径不是预先固定的,而是根据观察动态生成的。
Workflow 为什么会失效#
很多人第一次接触 Agent 时,会有一种疑问:
我把流程写复杂一点,不就等价于 Agent 了吗?
不完全是。
固定工作流的问题不在于“步数太少”,而在于它对未来路径做了过多假设。现实任务中最难提前写死的,往往正是这些部分:
- 哪一步才是真正重要的信息来源
- 当前结果是否已经足够
- 失败后是否要换条路继续
- 是继续深入,还是应该停止
一旦任务存在这些不确定性,系统就不再只是“执行预设步骤”,而是在做基于环境反馈的决策。这时再用纯 Workflow 去模拟,代码往往会迅速膨胀成一大堆分支判断,最后既不灵活,也不好维护。
Agent 的意义就在这里:把“下一步该做什么”这件事从硬编码分支里解放出来,交给模型在约束内做决策。
什么时候用 Agent#
说到这里,容易出现另一种误解:既然 Agent 更灵活,那我们是不是应该尽量都做成 Agent?
答案同样是否定的。
先看代价#
Agent 的代价非常真实:
- 请求次数更多
- 延迟更高
- token 成本更高
- 状态管理更复杂
- 调试难度更大
- 行为不确定性更强
所以真正重要的问题不是“Agent 强不强”,而是“这件事值不值得用 Agent 来做”。
适合的场景#
当一个任务同时满足下面几项时,可以优先考虑 Agent:
- 任务需要多步完成
- 每一步的路径不能完全提前写死
- 系统需要根据中间结果决定下一步
- 任务需要调用工具或访问外部资源
- “是否继续”和“查什么”本身就是问题的一部分
典型例子:
- 代码库分析助手
- 资料调研助手
- 能搜索、读取、整理信息的研究助手
- 会使用工具完成任务的自动化执行器
不适合的场景#
如果任务更接近下面这些特征,优先考虑简单方案:
- 只是单轮问答或改写
- 流程非常稳定,完全可以提前写死
- 不需要调用外部工具
- 不需要根据中间结果改变路径
- 成本和延迟比灵活性更重要
典型例子:
- 文案润色
- 固定模板摘要
- FAQ 问答
- 表单数据转结构化 JSON
一句话总结就是:
如果系统只是“回答”,那多半不需要 Agent;如果系统必须“边做边判断”,才值得考虑 Agent。
本教程的主线案例#
为了让后面的章节不碎片化,我们会围绕一个统一案例展开:
用 TypeScript 构建一个“研究与工程助手”。
这个助手一开始只会做很简单的事:理解任务、调用一个工具、拿到结果后继续回答。
随着教程推进,我们会一点点给它补上更完整的能力:
- 第 2 章:先让它拥有最小 Agent Loop
- 第 3 章:让它学会稳定地调用工具
- 第 4 章:让它能用 ReAct 方式边想边做
- 第 5 章:让它具备显式规划能力
- 第 6 章:解决上下文组织问题
- 第 7 章:让它通过 RAG 读取外部知识
- 第 8 章:接入 MCP 生态
- 第 9 章:把重复任务沉淀成 Skill
- 第 10 章:把这些能力组装成一个真正可用的 Agent
你可以把整套教程理解成一条连续的升级路径:
我们不是在学很多零散概念,而是在亲手把一个 Agent 从“能跑”慢慢做成“能用”。
小结#
这一章最重要的不是记住术语,而是记住边界:
- Chat API 适合单轮生成任务
- Workflow 适合流程稳定、步骤已知的任务
- Agent 适合路径不确定、需要根据观察持续决策的任务
Agent 的本质,不是“更会聊天”,而是:
- 会维护状态
- 会决定下一步动作
- 会根据动作结果继续前进
后面所有章节,本质上都在回答同一个问题:
如果我们真的要做一个 Agent,它最小应该长什么样?
下一章#
下一章我们会把上面的抽象真正落成代码,用 TypeScript 写出一个最小可运行的 Agent Loop。
到那时你会看到:Agent 最核心的骨架,其实并不复杂,它本质上只是一个围绕“决策 -> 执行 -> 观察 -> 更新状态”持续运行的循环。