多数人对 Agent 的第一印象是"能自己干活的聊天机器人"。这个描述不算错,但太模糊,落到工程上没法下手。
我的定义更朴素:Agent = 大模型 + 工具 + 记忆 + 一个循环。前三个是零件,最后一个才是让它"动起来"的发动机。
什么是 Agent
先和两种常见形态做个区分:
| 形态 | 输入 → 输出 | 谁能调用外部世界 |
|---|---|---|
| 纯对话 | 问题 → 回答 | 没有人 |
| Workflow | 问题 → 固定流程 → 结果 | 开发者(写死在代码里) |
| Agent | 目标 → 自主规划 → 结果 | 模型自己决定 |
关键差别在最后一行:调用什么工具、调用几次、什么时候停,由模型决定,而不是由你预先编排。这既是它的威力来源,也是它不稳定、难调试、成本不可控的根源。
四个核心部件
1. 模型(大脑)
负责判断"下一步该做什么"。要求不高但有两件事必须满足:
- 支持 function calling / tool use,否则拿不到结构化的调用意图
- 上下文足够长,装得下工具描述 + 历史步骤
2. 工具(手脚)
工具就是普通函数,关键在于描述写得好不好。模型只看描述来决定用不用、怎么用。
ts
const tools = [
{
name: 'search_order',
description: '按订单号查询订单状态。当用户提供订单号并询问物流、状态时使用。',
parameters: {
type: 'object',
properties: { orderNo: { type: 'string', description: '订单号,形如 SO20260922001' } },
required: ['orderNo']
}
}
]描述的三要素
做什么 + 什么时候用 + 参数长什么样。缺第二项,模型会在不需要的时候乱调用。
3. 记忆(上下文)
分三层,别一股脑全塞进 prompt:
- 短期:当前会话的消息列表,直接进上下文
- 中期:本次任务的中间结论,压缩后保留
- 长期:用户画像 / 业务知识,按需检索(这就是 RAG 的入口)
4. 循环(发动机)
一次调用不叫 Agent,能反复"思考 → 行动 → 观察"才叫:
text
while (未结束 && 步数 < 上限) {
模型输出 = LLM(目标 + 历史 + 工具描述)
if (模型输出 是工具调用) {
结果 = 执行工具(模型输出)
历史 += 结果
} else {
结束,返回模型输出
}
}最小可用实现
下面是一个约 40 行的骨架,把上面的循环跑通(伪代码,替换掉 llm 和 runTool 即可运行):
ts
type Msg = { role: 'user' | 'assistant' | 'tool'; content: string }
async function runAgent(goal: string, maxSteps = 8): Promise<string> {
const history: Msg[] = [{ role: 'user', content: goal }]
for (let step = 0; step < maxSteps; step++) {
const res = await llm.chat({ messages: history, tools })
// 没有工具调用 = 模型认为任务完成
if (!res.toolCalls?.length) return res.content
for (const call of res.toolCalls) {
const result = await runTool(call.name, call.args)
history.push({ role: 'tool', content: JSON.stringify(result) })
}
history.push({ role: 'assistant', content: res.content ?? '' })
}
throw new Error('超出最大步数,任务未完成')
}跑通之后你会立刻遇到三个现实问题,按踩坑概率排序:
- 死循环:模型反复调用同一工具。解法是步数上限 + 相同参数重复调用的熔断。
- 参数瞎编:模型会造出不存在的订单号。解法是在工具内部做参数校验,并把错误原样回传,让它自己改。
- 成本失控:历史越滚越长。解法是只保留最近 N 步的原文,更早的压缩成摘要。
别忘了幂等
Agent 会重试,工具如果写库就可能重复执行。所有写操作都要带幂等键。
什么时候不该用 Agent
以下场景用固定 Workflow 更划算,别为了"智能"付不必要的成本和不确定性:
- 流程固定且已知:例如"下单 → 扣库存 → 发券",写死即可
- 要求 100% 可预期:对账、风控、结算这类,模型的不确定性不可接受
- 延迟敏感:多轮循环意味着多倍 RT,接口超时扛不住
- 任务极简单:一次 LLM 调用能解决的,就别套循环
判断标准其实只有一条:需要"视情况而定"的决策,才值得交给 Agent。
小结
- Agent 的本质是模型自主决定工具调用的循环
- 四个零件里,工具描述的质量和循环的容错最容易被低估
- 上线前必备:步数上限、参数校验、幂等键、成本上限