Agent开发进阶指南(第 1 章):AI Agent 到底是什么?

本系列定位:零基础可上手、工程向、可落地实操的 AI Agent 进阶教程。拒绝空洞理论,只讲看得懂、画得出图、写得出代码、跑得出效果、能直接用到项目里的内容。


1. 开篇导读

这章解决什么问题?

很多开发者第一次听到 AI Agent 这个词时,脑子里会蹦出一堆概念:大模型、Function Call、RAG、ReAct、Tool Use、AutoGPT......看着很高级,但一问:

  • Agent 到底和 ChatGPT 对话框有什么区别?
  • 为什么我的大模型回答不了实时问题?
  • 企业项目里到底什么时候该用 Agent,什么时候不该用?

这章就是要把这些迷雾拨开。我们不讲论文,不堆术语,就用你日常写代码的经验,把 AI Agent 的本质 一次性讲清楚。

学完这章你能掌握什么?

  • 用一个生活化类比,彻底理解 Agent 和传统程序、大模型对话的区别。
  • 画出 Agent 的核心执行链路图。
  • 写出一个可运行的最小 Agent Demo(TypeScript,几十行代码)。
  • 知道企业生产环境中,Agent 最容易踩的几个坑。

适合什么场景?

  • 企业内部的智能客服、智能表单填写助手。
  • 能调用内部 API 的私有部署 Agent。
  • 本地运行的代码助手、数据分析 Agent。
  • 网页端集成大模型 + 工具调用的前端 Agent。

2. 核心原理通俗讲解

2.1 一句话定义:Agent 是个能自己动手的"智能员工"

你可以把 AI 系统分成三个段位,越往后越"像人":

段位 角色 特点 例子
青铜 传统程序 你写死所有 if/else,它按部就班执行 一个查询数据库的 REST 接口
白银 大模型对话 能聊天、能总结、能写代码,但只动口不动手 ChatGPT 网页聊天
黄金 AI Agent 有大模型的脑子,还能自己查资料、调接口、用工具、做判断 能自动查天气、算数据、填表单的智能助手

一句话:Agent = 大模型(脑子)+ 工具(手脚)+ 记忆(经验)+ 循环判断(思考)。

2.2 类比:传统程序、大模型、Agent 的区别

场景:用户问"今天北京天气怎么样,适合穿短袖吗?"

传统程序版:

js 复制代码
function answer(city) {
  const weather = queryWeatherAPI(city); // 必须提前写好
  return weather.temperature > 25 ? "适合短袖" : "不适合";
}

你提前定义了城市、温度、规则。用户换个问法,比如"北京今天冷不冷",程序可能就傻了,因为它只认识固定的输入格式。

大模型版:

大模型可以回答"一般 25℃以上适合短袖",但它不知道今天的真实天气。它的知识有截止日期,也没法主动联网查数据。

Agent 版:

Agent 接收到问题后,会先思考:"用户问的是北京今天天气,我需要用天气工具查一下。"

然后它自动调用天气 API,拿到"27℃,晴天",再结合自己的常识判断:"适合穿短袖。"

你看到区别了吗?

  • 传统程序:人把所有分支都写死
  • 大模型:脑子聪明,但没有手脚
  • Agent:有脑子,有手脚,能自己决定什么时候动手

2.3 Agent 的四大核心零件

所有 Agent,不管名字叫 LangChain、AutoGPT、Claude Code 还是 Codex,底层都逃不开这四个零件:

零件 1:大脑(LLM)

这就是大模型,比如 GPT-4、Claude、Qwen、Llama。它的作用是理解用户意图、做推理、决定下一步

你可以把它理解成团队里的"产品助理":它很聪明,但不会写代码、不会查数据库,只会告诉你"该干嘛"。

零件 2:工具(Tools)

工具就是 Agent 的"手脚"。常见的工具有:

  • 查询天气 API
  • 查数据库
  • 调用搜索引擎
  • 执行代码
  • 调用企业内部接口
  • 读写文件

每个工具都要告诉模型:我能干什么、需要什么参数、返回什么结果

零件 3:记忆(Memory)

人不能聊一句忘一句,Agent 也一样。记忆分两种:

  • 短期记忆:当前这轮对话的上下文,比如用户前面说"查北京天气",后面问"那上海呢",Agent 要知道"那"指的是天气。
  • 长期记忆:跨会话保存的用户偏好、历史记录,比如"这个用户习惯用摄氏度"。

零件 4:执行循环(Loop)

这是 Agent 的灵魂。它的工作流程不是一问一答,而是一个思考 → 行动 → 观察 → 再思考的循环:

text 复制代码
1. 用户输入问题
2. Agent 把问题和工具说明一起喂给大模型
3. 大模型决定:直接回答 / 调用某个工具
4. 如果调用工具,Agent 执行工具,拿到结果(Observation)
5. 把结果再喂给大模型,让它继续判断
6. 直到得出最终答案,输出给用户

2.4 不这么做会有什么坑?

很多开发者第一次做 Agent,会直接问大模型:"帮我查一下北京天气。"

然后大模型回答:"北京今天多云,25℃。"

但这个答案是编出来的。因为大模型没有实时数据,它只是在"猜测"。

这就是幻觉问题的一个缩影。Agent 的核心价值,就是给大模型装上"手脚",让它在需要真实数据的时候,主动出去查,而不是瞎编。

2.5 传统代码 VS Agent 智能代码

对比项 传统代码 Agent 智能代码
决策逻辑 if/else 写死 大模型动态推理
输入理解 必须固定格式 支持自然语言, Loose Coupling
外部数据 程序自己调 大模型决定什么时候调
应对变化 改代码 改工具描述或提示词
出错处理 抛异常 大模型可重试、可解释

注意:Agent 不是替代传统代码,而是在传统代码外面包一层智能决策层。底层该调 API 还是调 API,该查数据库还是查数据库,只是把"什么时候调、调哪个"的决定权交给大模型。


3. 架构流程图 / 原理图

3.1 Agent 整体执行链路图

flowchart TD A[用户输入<br/>自然语言问题] --> B[Agent 接收请求] B --> C[组装提示词<br/>系统提示 + 工具说明 + 用户输入 + 历史记忆] C --> D[调用大模型 LLM] D --> E{LLM 判断} E -->|直接回答| F[生成最终回复] E -->|需要工具| G[解析工具名和参数] G --> H[执行工具<br/>API / 数据库 / 计算] H --> I[获得 Observation<br/>工具执行结果] I --> C F --> J[返回给用户] I --> K{是否需要继续?} K -->|是| C K -->|否| F

3.2 核心模块依赖关系

flowchart LR subgraph Agent[Agent 核心] direction TB LLM[大模型引擎] Planner[推理/规划器] ToolExec[工具执行器] Memory[记忆模块] end User[用户/前端] --> Agent Agent --> Tools[外部工具/API] Tools --> Agent Agent --> Output[输出结果] Memory --> Planner Planner --> LLM LLM --> Planner Planner --> ToolExec ToolExec --> Tools

3.3 用户输入 → 模型 → 工具 → 结果全流程

sequenceDiagram participant U as 用户 participant A as Agent participant LLM as 大模型 participant T as 工具/API U->>A: &#34;北京今天天气怎么样?&#34; A->>A: 读取历史记忆 + 工具清单 A->>LLM: 发送:系统规则 + 工具说明 + 用户问题 LLM-->>A: 决定调用 get_weather(city=&#34;北京&#34;) A->>A: 解析出工具名和参数 A->>T: 执行 get_weather 工具 T-->>A: 返回:&#34;晴天,27℃&#34; A->>LLM: 发送工具结果,让模型组织语言 LLM-->>A: &#34;北京今天晴天,27℃,适合穿短袖。&#34; A-->>U: 返回最终答案

4. 手把手实操代码(可直接运行)

下面是一个最简 Agent Demo,纯 TypeScript,不依赖任何第三方库(除了 Node.js 本身)。复制即可跑通,用来理解 Agent 的"思考-行动-观察"循环。

真实项目中,你只需要把 mockLLM 替换成 OpenAI / Claude / 通义千问的 API 调用即可。

4.1 代码:simple-agent.ts

typescript 复制代码
// 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("你好");
})();

4.2 怎么运行?

  1. 确保你装了 Node.js(建议 v18+)。
  2. 把上面代码保存为 simple-agent.ts
  3. 在命令行执行:
bash 复制代码
npx tsx simple-agent.ts

如果没有 tsx,也可以先编译:

bash 复制代码
npx tsc simple-agent.ts --target es2020 --module commonjs
node simple-agent.js

4.3 运行结果长什么样?

text 复制代码
👤 用户: 北京今天天气怎么样?
🔧 调用工具:get_weather({"city":"北京"})
📥 工具返回:晴天,27℃
🤖 Agent: 北京今天天气晴朗,温度 27℃,比较舒适。

👤 用户: 帮我计算 12 * 34 + 5
🔧 调用工具:calculate({"expression":"12*34+5"})
📥 工具返回:413
🤖 Agent: 12 * 34 + 5 的结果是 413。

👤 用户: 你好
🤖 Agent: 我是你的 Agent 助手,可以查天气、做数学计算。试试问我:北京天气怎么样?

5. 源码核心底层剖析

5.1 这段代码为什么这样设计?

别看代码短,它已经把一个 Agent 的底层骨架都搭好了:

工具注册表(Tool Registry)

typescript 复制代码
const tools: Tool[] = [...];

这是所有工具的清单。每个工具必须有的三件套:

  • name:给模型识别的"函数名"。
  • description:告诉模型这个工具干嘛用,越好模型越知道该调谁。
  • parameters:告诉模型我需要什么参数,避免它乱传。

生产中,这个表通常是一个 Map<string, Tool>,方便 O(1) 查找。

决策层(Planning)

typescript 复制代码
const decision = await mockLLM(userInput);

这一步是 Agent 的"大脑"。大模型根据用户输入 + 工具说明书,决定是回答还是调工具。

真实项目里,这一段要把工具描述拼进提示词,格式类似:

text 复制代码
你是一个智能助手,可以使用以下工具:

工具名:get_weather
参数:{ "city": "string" }
说明:查询指定城市天气

请判断:用户的输入是否需要调用工具?如果需要,输出 JSON:
{ "type": "tool", "tool": "get_weather", "args": { "city": "北京" } }
如果不需要,输出 JSON:
{ "type": "answer", "content": "你的回答" }

这就是Function Call / Tool Use的雏形,下一章会展开讲。

执行循环(Execution Loop)

typescript 复制代码
while (loopCount < maxLoops) {
  const decision = await mockLLM(userInput);
  if (decision.type === "answer") return;
  const observation = await tool.execute(decision.args);
  userInput = `工具返回...请回答...`;
}

这个循环是 Agent 能"多步推理"的关键。

  • 第一次进循环:问题是用户的原始问题。
  • 第二次进循环:问题是"工具已经返回了结果,请你组织语言回答"。
  • 如果结果还不够,还可以继续调下一个工具。

maxLoops防止死循环的安全阀,生产中必须加。

5.2 企业级框架的同源设计思想

你现在看到的这个骨架,和 Claude Code、OpenAI Codex、LangChain 这些框架的底层思路是一模一样的:

组件 我们这个 Demo Claude Code / Codex / LangChain
大脑 mockLLM Claude / GPT / 自定义模型
工具 tools: Tool[] tools / mcp 工具集
执行循环 while 循环 AgentExecutor / Runner
记忆 还没加 ConversationBufferMemory
安全阀 maxLoops maxIterations

区别只在于:

  • 大厂框架把工具调用、错误处理、流式输出、上下文管理都封装好了。
  • 我们这个 Demo 把这些暴露了,方便你理解"原来框架底层就这样"。

5.3 真实坑点解析

坑点 1:无限循环

如果模型一直判断"还需要再查一个工具",Agent 就会死循环。解决方案:

  • 设置 maxLoops 上限。
  • 记录已经调用过的工具,避免重复调用同一个工具。
  • 给模型明确的终止条件,比如"当你觉得可以直接回答时,必须返回 type=answer"。

坑点 2:工具找不到

模型可能返回一个你根本没注册的工具名。解决方案:

  • strict 校验:工具名必须在 tools 列表里。
  • 捕获异常后,把"没有这个工具"的信息反馈给模型,让它重试。

坑点 3:参数格式错误

模型可能传 { city: " Beijing " } 或漏传参数。解决方案:

  • 每个工具做参数校验(Zod / JSON Schema)。
  • 校验失败后,把错误信息送回模型,让它修正。

坑点 4:上下文丢失

Demo 里我们只把 userInput 替换成工具结果,没有把原始问题保留下来。复杂场景下,模型会忘记用户最初想问什么。解决方案:

  • 维护一个 messages 数组,把用户问题、模型决策、工具结果全部放进去。
  • 每次调用模型都带上完整历史。

6. 常见问题 & 生产踩坑总结

Q1:Agent 和 Chatbot 到底有什么区别?

Chatbot 只能"说",Agent 能"做"。Chatbot 大公司模型回答基于训练数据;Agent 可以通过工具拿到实时数据、执行实际动作。

Q2:我的 Agent 总是乱调用工具怎么办?

很可能是工具描述写得不清楚。模型是靠 description 判断的,描述要像 API 文档一样明确:"这个工具什么时候用、需要什么参数、返回什么"。

Q3:工具调用失败了,Agent 直接崩溃?

不要把工具执行异常直接抛给用户。应该:

  1. try/catch 捕获异常。
  2. 把错误信息格式化后喂给模型。
  3. 让模型决定重试、换工具、还是向用户道歉。

Q4:Agent 回答慢,每次都要等很久?

这是 LLM 推理 + 工具调用串行导致的。优化方向:

  • 使用流式输出(SSE),先把"我在查天气"的提示给用户。
  • 多个独立工具 parallel 执行。
  • 给工具加超时控制。

Q5:模型编造数据怎么办?

让模型在需要准确数据时必须调用工具,而不是凭记忆回答。系统提示词里明确:"如果问题涉及实时信息,你必须调用工具,不能直接回答。"

Q6:Agent 应该放在前端还是后端?

强烈建议放后端独立的 Agent 服务

  • 安全性:API Key 不能暴露给前端。
  • 可控性:工具调用、超时、限流、日志都在服务端好管理。
  • 可扩展性:多个前端可以共用同一个 Agent 服务。

相关推荐
咖啡星人k1 小时前
从Vibe Coding到Prompt Engineering:AI编程的新技能树
面试·职场和发展·ai编程
小小小小宇1 小时前
模型相关知识
前端
小小小小宇2 小时前
模型相关知识二
前端
IT_陈寒2 小时前
Python装饰器竟然偷偷改了函数名?这个坑我爬了三天
前端·人工智能·后端
阿里云大数据AI技术2 小时前
DataWorks Data Agent “又双叒叕”升级:更低成本、更强智能、更多连接
人工智能·agent
牧艺2 小时前
Cursor 多 Agent 与 Worktree:大重构不再赌一把
人工智能·agent·cursor
jy2 小时前
支付后端研发的 AI 工作流实践:巡检、排查、开发全流程落地
后端·ai编程
DreamWear3 小时前
Figwright:让 AI 直接驱动 Figma 画布的双向工具
agent
Momo__3 小时前
Vite 8.1 打包开发模式——10000 组件冷启动 15 倍,"No Bundle Dev" 七年后被自己终结
前端·vue.js·vite