Agent 是什么:从回答问题到完成任务
把一段代码贴给模型,请它解释函数用途,模型只需要生成回答。换成“检查这个项目中的函数,并告诉我实际发现了什么”,系统就必须找到项目、读取文件,把真实结果交给模型。
这中间增加的环节,正是理解 Agent 的起点。在本专栏里,Agent 指以大语言模型参与决策、通过程序提供的能力处理任务的系统。它可以多轮获取信息、调用工具、根据结果继续行动,但能够做什么,仍由运行它的程序和环境决定。
这一篇要先解决三个新手最容易混淆的问题:模型、宿主和界面各自负责什么;为什么界面像聊天不代表它能真的执行;以及什么时候你其实不需要 Agent。
同一个请求,可以走两条路径
假设项目里有一个 src/greet.ts:
export function greet(name: string) {
return `Hello ${name}`
}这是贯穿本组文章的教学文件,不表示已经对你的项目执行了检查。
如果系统只有模型,它只能根据你提供的文字作答。你没有贴文件,它就没有可靠依据声称文件包含 greet。如果系统提供文件检查工具,模型可以提出检查请求,程序读取允许范围内的文件,再把结果送回来。
两种系统都可能显示一个聊天框。界面长什么样,不决定它是否能够执行真实操作;要看背后接入了哪些能力和控制。 同样,回复里写了一段 shell 命令,也不表示命令已经运行——模型可以生成任意看起来像命令的文本,程序是不是真的执行了它,要看运行记录。
这条区分很实用。判断一个工具靠不靠谱,最快的办法是看它有没有留下执行痕迹,而不是看它的输出描述。
模型、宿主和界面分别做什么
宿主围绕模型组织起来的这些运行与控制能力,常被称为 Harness。这个词没有要求所有产品采用完全相同的模块划分;先抓住“谁执行、谁持有状态和权限”就够了。
“宿主”这个词后面会反复出现,它指的是真正跑代码的那一层:不是界面,不是模型,而是夹在两者之间、负责把模型的请求变成真实系统操作的那个程序。Pi 本身就是一个宿主。
CLI、编辑器助手、网页和桌面工作台都可能充当入口。同一个模型接入不同工具、上下文和运行规则,能完成的任务可能明显不同。因此,比较两个智能体时,不能只问它们用了哪个模型。
自主行动依然有边界
Agent 的“自主”通常表示它能在允许范围内选择动作,并不表示它拥有任意权限,也不表示每一步都无需人参与。例如只读检查可以自动执行,修改文件可能需要额外授权,发消息或发布内容还可能有明确审批规则。
这个边界不是宿主“不够开放”,而是它必须存在。后面权限与提示注入那一篇会展开:即使模型完全被诱导提出了危险调用,宿主仍然要能拒绝执行。这是“自主”的前提,不是“自主”的限制。
一个简单 Agent 甚至只需要一个工具。反过来,把很多工具、记忆和多个模型放在一起,也不自动得到更可靠的系统。关键是这些能力是否围绕任务形成了可检查的闭环。
什么任务不一定需要 Agent
固定字段转换、已知步骤的数据校验,普通代码就可能做得更稳定;一段材料的摘要,有时一次模型调用已经够用。只有当系统需要依据中间结果决定下一步时,多轮决策的价值才更明显。
Anthropic 在讨论工作流与智能体时给出的建议值得直接引用:“我们建议找到最简单的可行方案,只在需要时才增加复杂度。这甚至可能意味着完全不构建智能体系统。” 智能体系统常用时延和成本换取更好的任务表现,只有这个交换划算时才值得。
检查源码的例子里,“文件缺失怎么办”“是否需要查看关联文件”可能需要进一步判断;但实际读取和参数校验仍适合由确定性程序完成。模型负责生成与选择,程序负责可信执行,两者不必互相取代。
这也是判断“要不要上 Agent”最实用的标准:先问下一步是否真的取决于上一步的结果。如果不取决于,写成普通代码或固定流程。
一个可以自己验证的对照
想亲眼看看这个循环跑起来是什么样子,可以用 Pi 的 JSON 模式。它把每一轮内部事件按行打印出来:
pi --mode json "Review this repository"输出里会看到这样的几行:
{"type":"agent_start"}
{"type":"turn_start"}
{"type":"message_start","message":{"role":"user","content":"Review this repository"}}
{"type":"message_end","message":{"role":"user","content":"Review this repository"}}
{"type":"agent_end","messages":[],"willRetry":false}
{"type":"agent_settled","aborted":false}加上工具调用时,中间会多出三段:
{"type":"tool_execution_start","toolCallId":"call_abc123","toolName":"bash","args":{"command":"ls -la"}}
{"type":"tool_execution_update","toolCallId":"call_abc123","toolName":"bash","args":{"command":"ls -la"},"partialResult":{"content":[{"type":"text","text":"partial output"}],"details":{}}}
{"type":"tool_execution_end","toolCallId":"call_abc123","toolName":"bash","result":{"content":[{"type":"text","text":"complete output"}],"details":{}},"isError":false}“模型请求 → 工具执行 → 结果回填”这三段,对应本文说的模型、宿主、结果三个角色。 你可以用同一个 toolCallId 把三段串起来——这也是后面几篇判断“结果到底有没有真的回填”的方法。
小结
理解一个 Agent,可以先回答三件事:它拿到了什么信息,可以调用什么动作,结果如何被核查。下一篇就沿着这条检查任务,把一次执行循环完整走一遍。