里维埃拉奢华风格男士肖像
2026-07-09
2026-07-09 0
很多开发者第一次听到 AI Agent 这个词时,脑子里会蹦出一堆概念:大模型、Function Call、RAG、ReAct、Tool Use、AutoGPT……看着很高级,但一问:

这章就是要把这些迷雾拨开。我们不讲论文,不堆术语,就用你日常写代码的经验,把 AI Agent 的本质 一次性讲清楚。
你可以把 AI 系统分成三个段位,越往后越"像人":
| 段位 | 角色 | 特点 | 例子 |
|---|---|---|---|
| 青铜 | 传统程序 | 你写死所有 if/else,它按部就班执行 | 一个查询数据库的 REST 接口 |
| 白银 | 大模型对话 | 能聊天、能总结、能写代码,但只动口不动手 | ChatGPT 网页聊天 |
| 黄金 | AI Agent | 有大模型的脑子,还能自己查资料、调接口、用工具、做判断 | 能自动查天气、算数据、填表单的智能助手 |
一句话:Agent = 大模型(脑子)+ 工具(手脚)+ 记忆(经验)+ 循环判断(思考)。
传统程序版:
复制代码function answer(city) {
const weather = queryWeatherAPI(city); // 必须提前写好
return weather.temperature > 25 ? "适合短袖" : "不适合";
}
你提前定义了城市、温度、规则。用户换个问法,比如"北京今天冷不冷",程序可能就傻了,因为它只认识固定的输入格式。
大模型版:
大模型可以回答"一般 25℃以上适合短袖",但它不知道今天的真实天气。它的知识有截止日期,也没法主动联网查数据。
Agent 版:
Agent 接收到问题后,会先思考:"用户问的是北京今天天气,我需要用天气工具查一下。"
然后它自动调用天气 API,拿到"27℃,晴天",再结合自己的常识判断:"适合穿短袖。"
你看到区别了吗?
所有 Agent,不管名字叫 LangChain、AutoGPT、Claude Code 还是 Codex,底层都逃不开这四个零件:
这就是大模型,比如 GPT-4、Claude、Qwen、Llama。它的作用是理解用户意图、做推理、决定下一步。
你可以把它理解成团队里的"产品助理":它很聪明,但不会写代码、不会查数据库,只会告诉你"该干嘛"。
工具就是 Agent 的"手脚"。常见的工具有:
每个工具都要告诉模型:我能干什么、需要什么参数、返回什么结果。
人不能聊一句忘一句,Agent 也一样。记忆分两种:
这是 Agent 的灵魂。它的工作流程不是一问一答,而是一个思考 → 行动 → 观察 → 再思考的循环:
复制代码1. 用户输入问题
2. Agent 把问题和工具说明一起喂给大模型
3. 大模型决定:直接回答 / 调用某个工具
4. 如果调用工具,Agent 执行工具,拿到结果(Observation)
5. 把结果再喂给大模型,让它继续判断
6. 直到得出最终答案,输出给用户
很多开发者第一次做 Agent,会直接问大模型:"帮我查一下北京天气。"
然后大模型回答:"北京今天多云,25℃。"
但这个答案是编出来的。因为大模型没有实时数据,它只是在"猜测"。
这就是幻觉问题的一个缩影。Agent 的核心价值,就是给大模型装上"手脚",让它在需要真实数据的时候,主动出去查,而不是瞎编。
| 对比项 | 传统代码 | Agent 智能代码 |
|---|---|---|
| 决策逻辑 | if/else 写死 | 大模型动态推理 |
| 输入理解 | 必须固定格式 | 支持自然语言, Loose Coupling |
| 外部数据 | 程序自己调 | 大模型决定什么时候调 |
| 应对变化 | 改代码 | 改工具描述或提示词 |
| 出错处理 | 抛异常 | 大模型可重试、可解释 |
注意:Agent 不是替代传统代码,而是在传统代码外面包一层智能决策层。底层该调 API 还是调 API,该查数据库还是查数据库,只是把"什么时候调、调哪个"的决定权交给大模型。
下面是一个最简 Agent Demo,纯 TypeScript,不依赖任何第三方库(除了 Node.js 本身)。复制即可跑通,用来理解 Agent 的"思考-行动-观察"循环。
复制代码// simple-agent.ts
// 一个最简 AI Agent:能查天气、做计算,或直接聊天// ================== 1. 定义工具类型 ==================type Tool = {
name: string; // 工具英文名,模型靠这个识别
description: string; // 工具是干嘛的,告诉模型
parameters: Record<string, string>; // 需要哪些参数
execute: (args: any) => Promise<string>; // 执行逻辑
};// ================== 2. 注册工具(Agent 的手脚) ==================const tools: Tool[] = [
{
name: "get_weather",
description: "查询指定城市的当前天气,返回天气描述和温度",
parameters: { city: "城市名称,比如北京、上海" },
execute: async (args: { city: string }) => {
// 真实环境里这里调用天气 API;demo 用 hardcode 数据
const mockDB: Record<string, string> = {
北京: "晴天,27℃",
上海: "多云,29℃",
广州: "雷阵雨,31℃",
};
return mockDB[args.city] ?? "暂不支持该城市";
},
},
{
name: "calculate",
description: "执行数学计算表达式,比如 12 * 34 + 5",
parameters: { expression: "合法数学表达式字符串" },
execute: async (args: { expression: string }) => {
try {
// 真实生产环境千万别用 eval,要用安全表达式解析器
return String(eval(args.expression));
} catch {
return "表达式格式错误";
}
},
},
];// ================== 3. 模拟大模型(实际项目替换为真实 API) ==================/**
* mockLLM 只做一件事:根据用户输入,决定是直接回答,还是调用某个工具。
* 真实项目里,这一段应替换为 OpenAI/Claude/千问等 SDK 的调用。
*/
async function mockLLM(prompt: string): Promise<
| { type: "answer"; content: string }
| { type: "tool"; tool: string; args: Record<string, any> }
> {
const lower = prompt.toLowerCase(); // 识别天气意图
if (lower.includes("天气")) {
const match = prompt.match(/([u4e00-u9fa5]+?)(?:的|今天)?天气/);
const city = match?.[1]?.trim() ?? "北京";
return { type: "tool", tool: "get_weather", args: { city } };
} // 识别计算意图
if (lower.includes("计算") || /[d+-*/()]/.test(prompt)) {
// 简单提取算式里的数字和运算符
const expr = prompt.replace(/.*计算s*/, "").replace(/[^0-9+-*/().]/g, "");
if (expr) {
return { type: "tool", tool: "calculate", args: { expression: expr } };
}
} // 默认直接聊天回答
return {
type: "answer",
content: "我是你的 Agent 助手,可以查天气、做数学计算。试试问我:北京天气怎么样?",
};
}// ================== 4. Agent 执行引擎 ==================async function runAgent(userInput: string, maxLoops = 3) {
console.log("n 用户:", userInput); let loopCount = 0; // 核心循环:思考 -> 行动 -> 观察 -> 再思考
while (loopCount < maxLoops) {
loopCount++; const decision = await mockLLM(userInput); if (decision.type === "answer") {
console.log(" Agent:", decision.content);
return;
} // 需要调用工具
const tool = tools.find((t) => t.name === decision.tool);
if (!tool) {
console.log(` 找不到工具:${decision.tool}`);
return;
} console.log(` 调用工具:${decision.tool}(${JSON.stringify(decision.args)})`); const observation = await tool.execute(decision.args);
console.log(` 工具返回:${observation}`); // 把工具结果再喂给模型,让它生成最终回复
userInput = `工具 "${decision.tool}" 返回结果是:"${observation}"。请用中文回答用户的原始问题:"${userInput}"`;
} console.log("️ 超过最大循环次数,强制结束");
}// ================== 5. 跑起来 ==================(async () => {
await runAgent("北京今天天气怎么样?");
await runAgent("帮我计算 12 * 34 + 5");
await runAgent("你好");
})();
simple-agent.ts。 复制代码npx tsx simple-agent.ts
如果没有 tsx,也可以先编译:
复制代码npx tsc simple-agent.ts --target es2020 --module commonjs
node simple-agent.js
复制代码 用户: 北京今天天气怎么样?
调用工具:get_weather({"city":"北京"})
工具返回:晴天,27℃
Agent: 北京今天天气晴朗,温度 27℃,比较舒适。 用户: 帮我计算 12 * 34 + 5
调用工具:calculate({"expression":"12*34+5"})
工具返回:413
Agent: 12 * 34 + 5 的结果是 413。 用户: 你好
Agent: 我是你的 Agent 助手,可以查天气、做数学计算。试试问我:北京天气怎么样?
别看代码短,它已经把一个 Agent 的底层骨架都搭好了:
复制代码const tools: Tool[] = [...];
这是所有工具的清单。每个工具必须有的三件套:
name:给模型识别的"函数名"。description:告诉模型这个工具干嘛用,越好模型越知道该调谁。parameters:告诉模型我需要什么参数,避免它乱传。生产中,这个表通常是一个 Map,方便 O(1) 查找。
复制代码const decision = await mockLLM(userInput);
这一步是 Agent 的"大脑"。大模型根据用户输入 + 工具说明书,决定是回答还是调工具。
真实项目里,这一段要把工具描述拼进提示词,格式类似:
复制代码你是一个智能助手,可以使用以下工具:工具名:get_weather
参数:{ "city": "string" }
说明:查询指定城市天气请判断:用户的输入是否需要调用工具?如果需要,输出 JSON:
{ "type": "tool", "tool": "get_weather", "args": { "city": "北京" } }
如果不需要,输出 JSON:
{ "type": "answer", "content": "你的回答" }
这就是Function Call / Tool Use的雏形,下一章会展开讲。
复制代码while (loopCount < maxLoops) {
const decision = await mockLLM(userInput);
if (decision.type === "answer") return;
const observation = await tool.execute(decision.args);
userInput = `工具返回...请回答...`;
}
这个循环是 Agent 能"多步推理"的关键。
maxLoops 是防止死循环的安全阀,生产中必须加。
你现在看到的这个骨架,和 Claude Code、OpenAI Codex、LangChain 这些框架的底层思路是一模一样的:
| 组件 | 我们这个 Demo | Claude Code / Codex / LangChain |
|---|---|---|
| 大脑 | mockLLM | Claude / GPT / 自定义模型 |
| 工具 | tools: Tool[] | tools / mcp 工具集 |
| 执行循环 | while 循环 | AgentExecutor / Runner |
| 记忆 | 还没加 | ConversationBufferMemory |
| 安全阀 | maxLoops | maxIterations |
区别只在于:
如果模型一直判断"还需要再查一个工具",Agent 就会死循环。解决方案:
maxLoops 上限。模型可能返回一个你根本没注册的工具名。解决方案:
tools 列表里。模型可能传 { city: " Beijing " } 或漏传参数。解决方案:
Demo 里我们只把 userInput 替换成工具结果,没有把原始问题保留下来。复杂场景下,模型会忘记用户最初想问什么。解决方案:
messages 数组,把用户问题、模型决策、工具结果全部放进去。Chatbot 只能"说",Agent 能"做"。Chatbot 大公司模型回答基于训练数据;Agent 可以通过工具拿到实时数据、执行实际动作。
很可能是工具描述写得不清楚。模型是靠 description 判断的,描述要像 API 文档一样明确:"这个工具什么时候用、需要什么参数、返回什么"。
不要把工具执行异常直接抛给用户。应该:
这是 LLM 推理 + 工具调用串行导致的。优化方向:
让模型在需要准确数据时必须调用工具,而不是凭记忆回答。系统提示词里明确:"如果问题涉及实时信息,你必须调用工具,不能直接回答。"
强烈建议放后端或独立的 Agent 服务: