
现在是晚上十一点四十屏幕右下角的 Docker 还亮着绿灯日志里最后一行停在tool_call completed。Day 45一个普通的工作日晚上我终于把“前端面试出题 Agent”这个 Side Project 完整跑通了。白天我是带 6 个人的前端 Leader负责后台管理系统、组件库还有一堆“图片不能被引用怎么办”的工单晚上我切换成另一个身份在服务器上搭 Agent、调提示词、和工具调用循环死磕的学习者。这个系列写到第 45 天后台收到不少私信问得最多的就两句“前端还有必要学 AI Agent 吗”和“你是怎么坚持下来的”。这篇我把这段时间的完整复盘写出来包括踩过的坑、今天跑通的实战项目、以及我认为前端背景做 Agent 开发真正的优势在哪里。内容会比较长但保证不掺水。1. 为什么是 AI Agent一个前端 Leader 的转型思考1.1 前端岗位的瓶颈和 Agent 赛道的空窗期我干了快十年前端从 jQuery 时代一路写到现在。前三年我在涨薪后三年我在焦虑焦虑的点很具体业务组件越写越熟练但可替代性也越来越高。后台管理系统、中台页面、可视化大屏这些需求正在被低代码平台和 AI 一点点吃掉。我甚至试过用 AI 辅助生成一套标准的 CRUD 页面从路由到表单校验到接口请求几分钟就能产出 80 分的效果。这个体验让我意识到一个问题如果我的核心竞争力只是“把设计稿变成页面”那这个能力正在快速贬值。这不是说前端没前途了而是“纯页面仔”的前途变窄了。但 AI Agent 这个方向是另一个局面。我观察到的实际情况是真正能写好 Agent 的人既要懂大模型的能力边界又要懂业务系统怎么交互还要能落地成产品。这样的人在市场上极度稀缺。前端工程师恰恰同时具备“理解用户界面”和“对接业务系统”的直觉缺的只是对大模型运行机制的系统理解。所以我的判断是前端不是夕阳而是需要换挡换到 AI 应用层去。1.2 前端技能树迁移到 Agent 开发的三个放大器有人觉得前端转 AI Agent 是跨度很大的转型我不这么认为。我复盘了一下前端基本功里有三块能力直接平移到了 Agent 开发中而且每一块都算放大器。第一块是异步编程思维。Agent 的核心运行逻辑就是“模型推理 工具调用”的异步循环每一步都是异步的需要处理并发、错误重试、超时中断。这些东西我在前端天天写Promise、async/await、事件循环、Web Worker换到 Agent 开发里一样适用只是主角从“用户点击按钮”换成了“模型发起的工具请求”。第二块是接口设计能力。写前端每天都在对接后端接口、设计请求参数、处理异常返回值。做 Agent 的时候工具Tool就是你的接口函数定义、入参 Schema、返回结构、错误信息设计逻辑和写 API 一模一样。第三块是对用户体验的敏感度。同样一个 AI 功能前端出身的人会想“流式输出时用户看到什么”“工具调用要不要可视化”“加载中状态怎么展示”这种感知力在很多纯算法背景的人身上是缺失的。1.3 Day 45 是个什么节点从“能看懂”到“能跑通”我给自己定的学习节奏是前 30 天看懂理论第 30 天之后必须动手做真实项目。今天正好是第 45 天我把 Day 30 做的一个失败项目推翻重写换成了现在这个能稳定运行的前端面试出题 Agent。如果给 Day 45 定义一个里程碑那就是“能独立把一个 Agent 从设计到部署完整跑通”。这个节点很微妙。第 20 天的时候我还在“觉得什么都懂了”第 30 天开始动手就觉得“什么都不会”第 40 天勉强能跑通但一换场景就崩总在同一个地方翻车。直到这几天我慢慢摸清了 Agent 的脾气。它不是代码你没法用逻辑推导它每一步会输出什么但它也不是玄学它的不确定性是可以通过约束和评估来控制住的。2. 前 30 天踩过的坑理论派转型最容易死的 3 个地方2.1 以为“提示词工程”就是全部刚开始学的时候我花了很多时间研究提示词什么 CoT思维链、Few-shot、角色设定、输出格式控制感觉自己已经拿到了打开 AI 大门的钥匙。等到自己搭 Agent 的时候才发现提示词只是最表层的东西。提示词写得再花哨模型也会在长流程里跑偏。真正让 Agent 稳定工作的是结构——你要设计清楚模型什么情况下调用工具、工具返回后怎么处理、多轮对话里哪些信息要被保留、哪些要丢弃。我举个例子。Day 20 我尝试做一个翻译 Agent加了“你是一个资深译者”的提示词刚开始翻译效果很高大上但测试到第 5 轮让它翻译同一句话每次结果都不一样。后来我才理解模型推理是概率性的你今天能稳定复现某个好结果很可能只是运气好。提示词只是让模型“更大概率”做对事情如果你想让它“稳定地”做对事情就得靠代码逻辑兜底。2.2 被 LangChain 的抽象绕晕忘了 Agent 本质是个循环第 15 天的时候我照着 LangChain 文档跑了一个 ReAct Agent 示例跑通了但完全没看懂。文档里充满了 Chain、Runnable、Executor、Memory 这些概念每一种都有好几种变体我陷在“工具怎么选”的泥潭里出不来。后来我把 LangChain 源码翻了一部分才发现它本质上就是个循环模型接收消息后判断是否需要调用工具如果需要就输出一个结构化的调用请求代码执行工具后把结果拼回消息列表再把整个上下文塞回模型直到模型认为任务完成。这个循环听起来简单但它解释清楚了 Agent 的所有复杂性的来源。做 Agent 开发核心不是会调某一个大模型的 API而是理解这个循环里每一步的不确定性如果模型不按格式输出怎么办如果工具调用超时怎么办如果模型陷入死循环一直调同一个工具怎么办这些才算真正的 Agent 工程问题。2.3 没有业务场景学了一堆屠龙之技第 25 天到第 30 天我有一周的时间几乎是在“无效学习”今天看 AutoGPT 的原理明天看多 Agent 协作后天尝试用 LangGraph 重构一个复杂工作流。学的时候很爽学完发现什么都落不了地。原因很扎心我压根没有一个真实的业务问题需要解决。没有场景就没有约束就没有反馈学的东西再多都是飘的。后来我是一个很偶然的场景给了我启发。组里小朋友又在群里问“图片未经允许不可引用怎么解决”我翻了翻历史记录这个问题半年内被问过至少 5 次每次的回答都差不多。我突然意识到团队内部知识沉淀是可以被 Agent 化的把常见问题整理成知识库让 Agent 自动检索并生成回答。于是我把第一个真实场景定为“前端面试出题”和“团队常见问题自动应答”又小又具体做起来成就感很强。3. 核心认知Agent 运行逻辑就像前端的事件循环3.1 LLM 只是推理引擎它不是数据库也不是逻辑执行器这个认知扭转非常重要。很多前端同学第一次接触 Agent 的时候容易产生一种误解把大模型当成一个什么都知道的字典问什么它都能给出正确答案。实际上大模型更多的像一个“推理引擎”它擅长的是根据你给的上下文做概率性的内容生成。它的能力边界非常明显没有实时数据、没有精确计算能力、没有可靠的记忆。举个我踩过的例子。让 Agent 计算三个 JSON 数组的交集它花了 20 秒“思考”信心满满地给了个结果交给前端一渲染数据完全错位。后来我给 Agent 加了一个执行 JavaScript 的工具让它把计算结果交给工具去执行准确性直接拉满。这个体验让我彻底想明白了Agent 里的 LLM 更像是一个“调度中心”负责理解任务、拆解计划、指挥工具真正干活的应该是那些确定性的代码工具。千万不要指望模型自己算算术把计算交给eval把数据查询交给接口把文件读取交给文件系统。3.2 工具调用就是前端的事件回调前端开发最常写的是事件回调按钮被点击了回调函数处理点击事件接口返回了处理返回数据。Agent 的工具调用本质也是一种回调只是“触发器”从用户操作变成了模型的输出。你可以把 Agent 的运行过程想象成一个事件循环模型收到用户消息如果需要调用工具会输出一个带有tool_call_id的请求运行时代码收到请求执行对应的函数比如查数据库、查天气、执行代码把函数的返回值作为一条消息追加到上下文里整个上下文再次交给模型模型决定下一步是继续调工具还是给最终答案。这个循环和前端的请求-响应模型太像了。你写前端时怎么处理接口 loading 状态、怎么处理重试、怎么处理竞态在 Agent 开发里全都能用上。比如模型连续两次调用同一个工具如果你不做幂等处理就会产生重复副作用——这跟前端防重复提交是同一个问题。3.3 上下文窗口、记忆与 RAGsessionStorage、localStorage 和 IndexedDB前端开发对浏览器存储一定不陌生sessionStorage 存会话数据、localStorage 存长期数据、IndexedDB 存大型结构化数据。Agent 的记忆机制和这个高度相似只是名字换了。大模型的上下文窗口可以类比为一次请求里的全部输入它是有容量上限的现在主流模型大多是 128K 到 200K token。一次对话里塞太多历史记录既慢又贵还可能让模型抓不住重点。所以做 Agent 的时候你要像管理浏览器存储一样有策略地管理上下文。短期记忆可以用“最近几轮对话摘要”来替代跟你每次即时存储 sessionStorage 是一个道理。长期记忆是怎么做的答案是 RAG检索增强生成把知识库切成小块用向量化索引存起来要回答问题时先检索最相关的几段再把这几段塞进上下文。这就像前端把数据库存在 IndexedDB查询时只取需要的记录而不是把所有数据一次性加载进内存。我实测过一个简单的 RAG 模块用pgvector或者Chroma存储向量检索返回 top 5 相似片段效果比把整份文档全塞进上下文稳定太多成本也能降下来。这块后续我计划专门写一篇落地笔记。3.4 提示词像代码一样需要回归测试前端代码写完了要跑单测、要回归Agent 的提示词和工具调用流程也一样。没有评估体系之前我改了一版提示词觉得效果变好了结果过了两天发现某个历史场景反而变差了。这就是“模型输出的不稳定性”带来的问题你不能靠直觉判断改动是否真的有效。我现在会给每个 Agent 准备一个很小的测试集大概 10 到 20 条典型请求每次改动之后批量跑一遍人工标注结果是好是坏。虽然这个过程比较原始但至少能拦住大部分回退问题。如果你有条件可以引入 LLM-as-a-Judge用一个强模型给结果打分把评估自动化。前端里那句老话在这里同样成立你无法管理无法衡量的东西。4. 今日实战写一个“前端面试出题 Agent”并跑通4.1 为什么选“前端面试出题”作为落地项目前几周我在准备团队招人发现出面试题特别耗时要覆盖 HTML/CSS/JS/框架/工程化/性能优化不同级别对应不同难度还要避免题目太偏或者太旧。市面上现成的题库要么陈旧要么难度标定不准确。我干脆做了一个出题 Agent你告诉它岗位级别和考察方向它生成一整套可用的面试题包括题干、答案要点、追问思路和评级标准。选这个场景还有一个原因整个流程包含“意图理解、工具检索、结构化输出”三个典型 Agent 环节非常适合练手。比如当用户说“需要 3 年经验的前端重点是手写题和性能”Agent 要识别出这是中高级岗位需要从内置题库检索还要实时生成新题最后输出带难度标签的 JSON。4.2 Skills 设计把技能封装成可复用的模块最近很多 Agent 框架都在推“Skills”这个概念它的思路是把某个领域的专家知识封装成一个独立模块包含描述、配置和具体的执行逻辑。我在这个项目里也试了。写了一个interview-question-skill结构类似这样interview-question-skill/ ├── SKILL.md ├── assets/ │ └── question_bank.json └── scripts/ └── generate_questions.pySKILL.md里写了这个技能的核心描述和调用规则这是我试了很多次之后总结的比较稳定的格式--- name: interview_question_generator description: 根据岗位级别和考察方向生成前端面试题及参考答案 version: 1.0.0 rules: - 必须输出 JSON 格式的题目数组 - 每题包含 title、level、category、answer_points、followups 字段 - 题目难度必须覆盖目标级别的上下一档 - 避免直接输出搜索引擎能找到的“八股原题”应适当改写场景 ---skills 相比写在系统提示词里的东西好处在于它是可复用的模块可以被多个 Agent 调用而且每个模块有自己的版本号改一个模块不会影响其他部分。这个思路和前端组件化完全一致我上手很快。你把这个 skill 想象成一个 Web Component有props定义、有内部实现、有对外暴露的方法只是渲染结果换成了对话内容。4.3 核心代码一个最小可运行的 Agent 循环因为我对前端生态最熟这个 Agent 我用 TypeScript 实现。核心只有几件事组装消息、调用模型、执行工具、把结果拼回上下文。这里贴一个精简版本方便理解整个循环import OpenAI from openai; const client new OpenAI({ apiKey: process.env.LLM_API_KEY, baseURL: process.env.LLM_BASE_URL, }); const tools [ { type: function, function: { name: retrieve_questions, description: 从内置题库中检索符合条件的面试题, parameters: { type: object, properties: { level: { type: string, enum: [junior, mid, senior] }, category: { type: string }, count: { type: number }, }, required: [level, category], }, }, }, ]; async function runAgent(userInput: string) { const messages: any[] [ { role: system, content: 你是资深前端面试官。先分析用户的级别要求再调用工具检索题目最后生成JSON题目数组。, }, { role: user, content: userInput }, ]; let rounds 0; const maxRounds 5; while (rounds maxRounds) { rounds; const response await client.chat.completions.create({ model: process.env.LLM_MODEL || qwen-plus, messages, tools, tool_choice: auto, }); const result response.choices[0].message; messages.push(result); if (result.tool_calls) { for (const call of result.tool_calls) { const args JSON.parse(call.function.arguments); const toolResult retrieveQuestions(args); messages.push({ role: tool, tool_call_id: call.id, content: JSON.stringify(toolResult), }); } continue; } if (result.content) { return JSON.parse(result.content); } } throw new Error(Agent 超过最大循环次数未能完成任务); }注意这里有个细节工具调用的结果必须以role: tool的身份追加进消息列表并且要带上对应调用的tool_call_id模型才能把工具结果和之前的请求对应起来。我在 Day 38 踩过一个坑工具结果没带tool_call_id模型直接被告知“消息必须成对出现”一直报错。这个问题网上资料讲得不多我一度以为是模型 API 不稳定后来查官方文档才发现是消息结构问题。4.4 与前端页面的实时通信SSE 比 WebSocket 更省心Agent 跑通之后我给它配了一个前端页面。一开始我用的 WebSocket对接过程遇到一个很现实的问题Agent 一跑就是十几秒甚至几十秒中间有各种状态变化思考中、调用工具、工具返回、生成中WebSocket 需要自己管理连接状态、重连机制、心跳包还要考虑丢消息的补发策略调试成本不低。后来换成 SSEServer-Sent Events体验一下好了很多。SSE 是单向的服务器往客户端推消息前端只需要const eventSource new EventSource(/api/agent/stream?taskIdxxx); eventSource.onmessage (event) { const data JSON.parse(event.data); // data.type 可能是 thinking / tool_call / tool_result / content renderAgentStep(data); }; eventSource.onerror () { console.error(连接中断, eventSource.readyState); // 建议做自动重连EventSource 本身有默认重连逻辑 };SSE 天然支持断线重连不需要像 WebSocket 那样自己实现心跳适合这种“服务端单向推送状态”的场景。如果你之前用 SignalR 比较多理解起来也容易SignalR 是双向的SSE 是单向的但对于 Agent 的实时输出SSE 完全够用。我之前的后端同事看到这个设计第一反应是“怎么不用 SignalR”我说前端接收逻辑越简单越不容易出错这一百毫秒的差异用户根本感知不到。4.5 Docker 部署上线的几个细节开发环境跑通了我把它部署到服务器上。用 Docker Compose 把 Agent 服务和前端静态页面一起编排。这里有几个细节都是踩出来的经验。第一API Key 不要写死在代码里通过环境变量注入services: agent-api: build: ./agent-api ports: - 3000:3000 environment: - LLM_API_KEY${LLM_API_KEY} - LLM_BASE_URL${LLM_BASE_URL} - LLM_MODELqwen-plus第二Agent 的响应时间普遍较长反向代理超时时间要调大。我用 Nginx 做反向代理默认的 60 秒超时根本不够用改成proxy_read_timeout 300s;之后长任务才稳定。第三如果是流式输出务必确认 Nginx 关闭了缓冲location /api/agent/ { proxy_pass http://agent-api:3000; proxy_set_header Connection ; proxy_http_version 1.1; proxy_buffering off; proxy_cache off; proxy_read_timeout 300s; }proxy_buffering off这个参数我折腾了一个多小时。一开始前端页面一直显示空白后端日志明明在正常输出后来用 curl 模拟请求才发现所有内容都积压在 Nginx 缓冲里一次性返回了根本没有流式效果。把这行加上就正常了。前端同学自己上手部署服务的时候这类问题很典型不是代码的问题而是链路中间环节的配置问题。5. 把 Agent 引入团队一个前端 Leader 的带队视角5.1 我不会让组员先报班而是先做三件事最近组里好几个同学问我“Leader我也想做 AI Agent应该先学什么”我的建议不是去报班也不是一上来就啃大模型论文而是先做三件事。第一把大模型当工具用熟。日常在浏览器里装一个 AI 辅助编程插件强迫自己所有重复的前端代码都用 AI 生成在这个过程中积累“提示词手感”尤其是“怎么让 AI 输出可维护的组件代码”这种感觉。第二把一个日常重复劳动流程化。比如每次发版后的回归测试、接口文档的更新、组件库的变更日志挑一个做自动化感受一下 AI 能力在真实工作流中的边界。第三自己搭一个最简单的 Agent。不需要用复杂框架用任何一家大模型厂商的 API写一个“命令行答疑机器人”把一个业务文档丢进去让它基于文档回答问题。这三件事做完基本能判断自己是不是真的对这个方向感兴趣也积累了一个可以放在简历上的项目雏形。5.2 以前高频重复的问题正在慢慢变少做了 Agent 之后我回头看团队日常感受最深的是以前很多“重复性答疑”正在被 AI 替代。比如那个“图片不允许被引用怎么解决”的问题以前每个新人都要问一遍现在我把对应的解决方法写进了团队知识库Agent 会自动检索并给出答案。再比如“前端怎么做上传大文件的分片”“WebSocket 怎么封装”“SignalR 前端怎么接收数据”这些高频问题都能被覆盖。这不代表前端岗要失业了。相反团队里省下来的时间应该花到更重要的事情上——深入理解业务、设计复杂的交互方案、做性能优化。AI 让我从重复劳动里腾出手来去做真正需要判断力和创造力的工作。这也是我跟组员们说的最多的一句话与其焦虑被 AI 替代不如赶紧变成那个“使用 AI”的人。5.3 用 Agent 把团队经验沉淀成可检索的知识库我以前遇到过一个问题团队里的经验都分散在各个人的脑子里人和文档之间有一道巨大的鸿沟。一个组件为什么这么设计、某个接口有什么坑、这个项目为什么用这个框架——这些知识很难被传承。现在我找到了一种比较自然的沉淀方式把团队规范、踩坑记录、设计文档统一整理到知识库然后通过 RAG 的方式让 Agent 可以基于这些内容回答问题。“Obsidian AI Agent 知识库”这个方向我最近也在尝试。Obsidian 的本地 Markdown 文件很适合做知识管理配合向量化检索就问成了一个私人的业务问答系统。我现在的目标是当新人入职的时候与其给他发一份几十页的文档让他自己看不如给他一个入口“有问题直接问 Agent”这个体验比翻文档友好多了。当然知识库的维护也要靠日常积累不是一天能建成的。5.4 “现在转行会不会太晚”怎么回答这个问题几乎每个人都问过包括我自己。我的回答是种一棵树最好的时间是十年前其次是现在。这话听起来像鸡汤但在 AI 领域是句实话。这波 Agent 应用层的机会窗口刚刚打开现在市面上大家都在探索怎么用 Agent 解决真实问题没有哪个流派已经形成绝对垄断也没有哪套知识体系是“非学不可”的定论。前端背景的人只要愿意花时间补齐大模型基础知识在应用层反而有独特的落地优势。而且我发现一个规律真正最后转型成功的往往不是理论功底最强的人而是动手次数最多的人。第 30 天我还在自我怀疑第 45 天我已经能对接真实场景了这个进步速度在技术领域其实很快。6. 45 天学习路线复盘和资源清单6.1 我实际用到的学习材料与顺序我整理了一下这 45 天实际用到的材料不是那种收藏夹吃灰的清单是我真的翻过、跑过、踩过坑的。时间段主要材料/方式产出第 1-5 天看大模型基础科普了解 Token、上下文窗口、Embedding 概念能解释 Transformer 的大致流程但不深入数学第 6-10 天读李博杰分享的《深入理解 AI Agent》笔记网上流传的 PDF 整理版建立了智能体、思维链、工具调用、多智能体的整体框架第 11-15 天跑大厂 API实现一个带 Function Calling 的最小 Demo理解了 tool_call 的消息结构第 16-20 天啃 LangChain/LangGraph 文档翻源码理解了 Agent 循环的本质第 21-25 天尝试多 Agent 协作、AutoGPT 源码分析得出结论现阶段单 Agent 更实用第 26-35 天做失败项目边做边补知识懂得没有场景的学习只是自我感动第 36-45 天做面试出题 Agent引入 RAGDocker 部署上线跑通了第一个生产级 Side Project李博杰那份笔记对我早期帮助非常大它把 Agent 分成了几种流派有类似“搜索引擎”的单步工具调用、有类似“操作系统”的复杂任务拆解、有类似“人类团队”的多智能体协作。这个框架帮我建立了分类能力后来看任何一篇 Agent 技术文章我都会先想它属于哪个流派解决的是哪类问题。它不像很多教程那样只会堆叠概念而是真的能帮你把碎片的认知串起来。6.2 我接下来的计划从出题 Agent 到通用团队助手Day 45 的节点不是终点我后面还有几条线在推进。第一条线是 RAG 的升级。现在我用的是简单的向量检索文档一多检索质量就开始下降下一步引入 rerank 环节把相关性排序做得更好一些。第二条线是前端页面交互优化。我希望用户在 Agent 运行过程中看到更清晰的“工具调用轨迹”比如“正在检索题库→正在生成题目→正在校准难度”这个可视化交互是我作为前端最感兴趣的部分。第三条线是多 Agent 协作实验。让一个 Agent 负责需求理解一个 Agent 负责题目生成一个 Agent 负责审查质量看看效果比单 Agent 好多少。6.3 给正在纠结是否转型的人三条判断标准结合我这段时间的经验我给正在纠结的人三条判断标准不一定对但可以参考。第一条你是否有持续折腾的劲头。AI Agent 领域变化太快今天学的明天可能就被新框架覆盖了如果没有内驱力很容易放弃。第二条你是否愿意接受“不确定性”。写前端代码不对就是不对逻辑可以调试做 Agent同样的输入可能给出不同的输出你得学会在不确定里面找确定性用工程手段把概率性错误控制住。第三条你是否能找到一个真实场景。如果只是想“学 AI 为了不被淘汰”大概率坚持不下来但如果你有一个具体的业务痛点想用 Agent 解决学习的效率会翻倍。我见过太多人收藏了一堆资料却始终没有动手写第一行代码。如果你今天看完这篇也想试试别先问“我该学哪个框架”先打开任何一家大模型的官网申请一个 API Key写一个能跑的“一句话问答机器人”然后一步步加上工具调用。跑通了你的 Day 1 就正式开始了。写到这儿我看了眼时间已经过零点了。今天把出题 Agent 从开发环境搬到 Docker 容器解决掉 Nginx 的流式缓冲问题又顺手把 Group 里一个高频率问题接进了知识库。Day 46 的计划也已经在脑子里了把 RAG 的向量库从内存换成pgvector再给前端页面补上工具调用的可视化时间线。明天继续。