ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

前端Leader的72天AI Agent实战:来自伪Agent到工程化的经验

前端Leader的72天AI Agent实战:来自伪Agent到工程化的经验

第72天。老实说,这个数字放到两年后的简历上,可能只是个微不足道的注脚。但它对我来说有明确的分界意义:它刚好踩在"从知道到做到"的那条线上——前一个月我做出来的所谓AI Agent,回头看全是伪Agent;真正能拿上台面的东西,是最近这两周才跑通的。

我是做了多年前端、目前带一个小团队的Leader,白天要处理排期、评审、上线,学Agent的时间基本靠晚上和周末挤。下定决心往这个方向走,不是跟风。真实的原因是:今年我们组接到的需求里,凡是带"智能化"字样的案子,全团队只能干看着,没人能接。与其等外部力量来救,不如自己先趟一遍水。

这篇不是学习日记流水账,更不是炫耀贴。我想站在第72天这个节点,把验证过的、被推翻过的、踩过之后才看懂的东西,整理成一份可复用的判断框架——尤其是面向跟我一样戴着"前端Leader"这顶帽子、正犹豫要不要往AI Agent方向走的人。你可以把它当成一份"两个多月亲测后的体检报告"来看。

1. 第72天回头看:前30天我写的全是"伪Agent"

1.1 一个判断标准:你的系统有没有"闭环"

前一个月,我所谓的"Agent",本质就是一个超长提示词 + 一次模型调用 + 把结果渲染到页面上的转发器。当时自我感觉良好,觉得"能对话、能生成报告"就是Agent了。现在回头看,它只是一层套了对话壳的接口请求。

我现在用一个很简单的问题来区分伪Agent和真Agent:系统在产生输出之后,有没有能力自己去判断"这个输出是否满足了目标",并且根据判断结果采取下一步动作。伪Agent的输出是终点,打印完就结束了;真Agent的输出只是中间状态,它会基于外部反馈继续迭代,甚至推翻自己刚才的方案重做。

这个区别特别像前端里的"一次性渲染"和"响应式更新"。一次性渲染就是数据到视图,画完就完;响应式是数据变化之后视图自己会修正。Agent要的就是后者——它能根据工具返回的结果、异常信息、中间产物,持续修正自己的执行路径。

1.2 真Agent的四要素:环境、工具、决策、记忆

真正让一套系统配得上"Agent"称呼,我拆下来至少需要四样东西,缺一样都只是"高级聊天机器人":

  • 环境感知:能接收任务,也能接收任务执行过程中的反馈,包括异常反馈、超时信号、空结果。
  • 工具调用:能调用外部能力去改变或获取现实世界的信息——查数据、写文件、调内部系统接口,而不是只会"说"。
  • 自主决策:目标不明确、路径有分叉时,能自己规划步骤,并根据实际反馈调整计划。
  • 记忆:跨轮次保留任务上下文、执行结果和用户偏好,而不是每次对话都从零开始。

这四样东西放到我们熟悉的工程语境里,分别对应:回调与事件机制、SDK调用、状态机与策略、缓存与存储。做过前端的人其实都不陌生,只是需要把"UI的状态迁移"换成"任务的状态迁移"。

1.3 第72天我的验收标准

现在我在判断一个Agent能不能上生产环境时,只问四个问题:它有没有明确的终止条件?工具调用的每一步是否可观测、可回放?失败时是走降级路径还是直接崩?模型输出格式变化时,系统是报错还是能自我修复?

这四条,本质上跟我以前验收一个前端组件是否"健壮"的逻辑一样——边界条件、错误处理、可观测性。想明白这一点之后,我最大的焦虑消失了:Agent工程没有脱离软件工程的基本盘,它只是把不确定性从"用户行为"转移到了"模型行为"上。防御的思路是相通的。

2. 前端Leader的底子迁移:哪些能吃老本,哪些必须清零

2.1 五项能打的底子

学了两个月之后,我发现前端经年在日常工作中练出来的很多肌肉记忆,放到Agent开发里不是废掉,而是换个姿势继续用。下面这个对照表是我给团队做分享时用的:

前端老本行Agent开发里的映射为什么能打
异步模型(事件循环、流式处理、长列表分片渲染)模型流式输出、工具调用并发、长任务调度处理过流式数据和并发请求的人,接手Agent的消息流几乎没有障碍
状态管理(单向数据流、reducer、状态机)Agent执行状态机、工具调用上下文、多轮会话管理UI状态换成语境状态,套路完全一致
数据结构意识(强类型、接口定义、schema)模型结构化输出、工具参数签名、校验规则前端对JSON的肌肉记忆,在设计工具签名时就是巨大优势
组件化与复用思维工具(Tool)的定义与复用、提示词模板封装工具就是一个无状态函数组件,输入输出约定清楚,谁都能维护
可观测性与调试习惯链路追踪、运行日志回放、调用成本统计用浏览器开发者工具定位DOM问题的耐心,直接迁移成Agent运行日志排查

说一个最典型的例子:状态管理。以前做复杂页面,我要设计数据树、动作、规约器,防止状态散落得到处都是。做Agent之后我遇到的第一个坎就是语境管理——每轮对话、每次工具结果、每个子任务的状态,如果不做统一的状态约束,模型会在两个工具之间反复横跳,表现得像个没有短期记忆的人。把前端的单向数据流搬到Agent调度层,是我这两个月里做过最顺畅的一次技术迁移。

2.2 三个必须清零的惯性思维

能打的部分说完了,再说必须主动丢掉的。

第一,对确定性的执念。前端在相同输入下必须渲染出相同结果,这是基本功。但模型在相同输入下可能给出不同的输出,哪怕参数一点没动。这是概率性系统的本质,不是bug。你要做的不是"把提示词再写细一点"来追求100%稳定,而是用校验、重试、降级、人工兜底把不确定性收敛到可接受的范围内。

第二,对"用户输入"和"模型输出"的认知差异。前端防御性编程防的是用户的非法输入,所以在入口做校验。但Agent要防的是模型"看似合法、实则编造"的输出——幻觉。这意味着校验层的重心要从"入口拦截"挪到"出口验证"。我见过很多前端同事学Agent第一反应是去拦输入,这是方向性错误,成本白花。

第三,发布思维。前端改一行代码,回归一遍功能列表就敢上线。Agent改一个提示词,可能让同一个任务的表现时好时坏。你没法凭一次手动测试的感觉来判断"这个改动到底是变好还是变差"。必须建一个评估集,用一批固定任务样本量化对比,否则团队协作时谁都不敢动提示词。

3. 72天里最贵的三个翻车现场:花真金白银买来的教训

我学Agent最大的成本不是课程费,是token和调试时间。下面三个问题,全部发生在我自己搭的"会议纪要智能体"内部原型上。这个场景我选得很刻意:会议纪要有真实需求、有外部数据源、需要多步工具调用,而且效果好不好团队一眼就能判断。

3.1 翻车一:工具调用死循环,半天烧掉一周预算

现象:某次内部演示,系统在一个"查询排期"的工具上来回打转,日志显示同一个工具、同一组参数被调用了二十多次,当天账单异常上涨。

排查链路,我一步步还原给大家:

  1. 先看链路追踪里的工具调用序列,发现模型每隔两轮就绕回同一个工具,表现像是"再查一次就能成功"。
  2. 检查终止条件,发现我的循环判断只认"是否生成最终答案",工具调用本身没有任何步数上限。模型在犹豫不决时就会反复试探同一个动作。
  3. 检查工具返回,发现工具在没有匹配结果时返回了一个空数组。这个返回格式合法,但模型从空数组里读不出"这条路走不通"的语义,于是继续换着花样重试。

修复方案:加最大步数上限;对同一个工具加同参数连续调用的计数,超过阈值强制结束,并把"重复尝试无效"作为新信息回喂给模型;同时改造工具,让它无结果时返回明确的状态码,而不是一个语义模糊的空壳。

// 反例:没有兜底的工具循环 while (agent.status !== "done") { const result = await agent.step(); // 如果模型一直想调用同一个工具,这里会无限循环 }
// 修正:最大步数、工具调用去重、异常强制结束 const MAX_STEPS = 10; const repeatedCalls = new Map(); while (step < MAX_STEPS && agent.status !== "done") { const call = agent.nextToolCall(); const key = `${call.name}:${JSON.stringify(call.args)}`; repeatedCalls.set(key, (repeatedCalls.get(key) || 0) + 1); if (repeatedCalls.get(key) > 2) { agent.forceFinish(`工具 ${call.name} 连续重复调用,已中止`); break; } const result = await executeTool(call); agent.feedBack(call, result); step++; }

这条修完,我最大的体会是:Agent代码里最不能省的就是"边界防守",它跟防止用户无限点击提交按钮是同一件事。

3.2 翻车二:结构化输出开了强约束,还是偶发坏格式

现象:提取"负责人、截止时间、行动项"的任务,模型偶尔会漏字段,日期格式说变就变。

排查步骤:先排除模型版本因素,然后用同一批输入连续跑50次,统计失败率。结果发现失败集中在上下文特别长的样本上——转写文本越长,模型在末尾对输出格式约束的遵循率越低。这其实不是模型"变笨"了,而是长上下文里早期的指令被稀释了。

修复:不靠加大提示词里"务必遵守"的力度,而是在模型输出后面加一层独立的校验器。校验失败时,把具体的校验错误(不是笼统说"格式不对",而是"deadline缺失、日期格式应为YYYY-MM-DD")回喂给模型做一次修正;修正一次仍失败,就走人工兜底。

// 结构化输出的兜底校验 const schema = { actionItems: { type: "array", minItems: 1 }, owner: { type: "string" }, deadline: { type: "string", format: "date" }, }; const parsed = safeParse(modelOutput); const report = validate(parsed, schema); if (!report.valid) { // 关键点:把校验错误反馈给模型,而不是用同样的提示词重试 const fixed = await model.call(buildRepairPrompt(parsed, report.errors)); }

这条的教训是:提示词是配置,不是承诺。把希望寄托在模型"每次都听话"上,等于把系统稳定性押在运气上。校验层必须是你自己可控的代码。

提示:任何从模型拿到的结构化数据,都必须先过一道schema校验再进入业务逻辑。这个习惯能帮你挡掉80%的脏数据问题。

3.3 翻车三:把整场会议记录全塞进上下文,效果反而更差

现象:最初为了"不丢信息",我把两小时会议的全部转写文本一次性塞进上下文。结果单次请求的token费用高到离谱,而且提取出来的行动项漏了一大半。

根因:上下文太长时,模型对中间段落的注意力会明显下降。我把所有信息都给它,它反而记不住最重要的几条结论。这就像开会时给你塞了一份十万字的材料,你大概率只记得开头和结尾。

修复:分阶段处理。先把转写文本按时间窗切段,逐段让模型做压缩摘要——只保留结论、分歧点、待办事项;然后用这些摘要作为输入,做全局的结构化整理。改完之后,成本降了大约七成,行动项的完整度反而提高了。

核心原则我记在笔记本上:上下文是你的工作记忆,不是仓库。所有原始材料都放外部存储,Agent的记忆里只保留加工过的信息。这个思路跟前端"不要把所有数据都挂在大组件里"的分层思想一模一样。

4. 给前端同仁的转行路线:我验证过的四个阶段

我把72天重新拆成四段,每段有明确任务和验收标准。这比我当初"今天看看这个、明天试试那个"的低效状态好太多了,你可以直接照抄。

4.1 阶段一(第1~2周):把模型当普通接口,不做任何封装

任务清单:

  • 直接调大模型API,理解输入输出、温度参数、token计费方式;
  • 用SSE流式接收输出,做一个打字机效果的页面,感受"流"的体验;
  • 跑通多轮对话——本质就是维护一个消息数组,这个前端最熟了。

验收标准:10分钟内从零搭出一个能对话的页面,并且能说清楚一次请求的token是怎么算出来的。

这个阶段千万不要引入任何编排框架。框架解决的是复杂问题,你连基础问题都没碰到,直接上框架只会让认知变成空中楼阁。

4.2 阶段二(第3~4周):让模型学会"用工具"

这一阶段是分水岭,做完你会真正理解"模型负责决策、工具负责执行"的分工。

任务:

  • 把前端里"函数调用"的思维迁移到模型工具调用上:定义一个查询函数、一个写入函数,让模型自己判断何时调用;
  • 做一个"工具型"demo,模型不直接回答,而是通过工具拿到外部数据后再组织答案;
  • 重点打磨工具的定义描述:参数名、类型、枚举值、必填项、失败说明。工具描述写得烂,模型就会乱叫一气。

验收标准:模型能通过工具拿到真实数据,并且在工具不可用时能明确说"我没有这个能力",而不是硬编。

我额外提醒一句:这一阶段很多教程会教你把工具描述写出花,但其实更重要的是失败语义。工具返回什么才算"查无结果"、什么算"出错",必须定义得清清楚楚,否则模型会把空结果当成有效结论。

4.3 阶段三(第5~8周):学习"规划-执行-反馈"的循环

这阶段才是真Agent的开始:

  • 实现一个带状态机的Agent主循环:接收任务 → 规划步骤 → 调用工具 → 接收反馈 → 判断是否完成 → 输出结果;
  • 给Agent加记忆:短期记忆负责当前任务上下文,长期记忆负责历史偏好和结论复用;
  • 做一个需要多步工具调用的完整成品,比如自动搜集资料并生成一份分析报告。

验收标准:给Agent一个含分支的任务,它能自己拆解步骤,并且在某一步失败后换一条路继续走,而不是直接放弃或假装成功。

4.4 阶段四(第9~10周起):工程化,这才是拉开差距的地方

大多数人学到这里就停了,觉得"能跑通demo已经很棒"。但真正能作为团队能力沉淀的,恰恰是工程化:

  • 建一个最小的评估集:收集50条真实任务样本,每次修改提示词或工具定义之前,先在评估集上跑一遍,量化"变好还是变差";
  • 加可观测性:每次调用的token数、耗时、工具调用序列、失败节点,全部落日志;
  • 设计降级策略:模型超时怎么办、工具服务挂了怎么办、校验不通过怎么办;
  • 控制成本:结果缓存、合并请求、对长历史做摘要压缩,而不是每次都全量重发。

提示:评估集就是Agent时代的"自动化测试"。没有评估集,你改提示词就像盲改前端样式——看起来没问题,一上线就翻车。

4.5 必须避开的弯路

三个弯路,我全部亲自走过:

  • 别花两周时间背框架用法。先手写一个几十行的无框架最小循环,再引入框架,你才看得懂框架究竟替你解决了什么。
  • 别沉迷提示词技巧。提示词是配置,不是产品。把时间花在结构、校验、可观测性上,收益高得多。
  • 别一上来就做"万能助手"。选公司内部一个真实存在的小场景——会议纪要、告警分析、周报生成——做到能实际使用,比做一百个花哨demo都有价值。

另外顺带提一句:最近业内讨论度很高的"模型上下文协议",思路是统一工具调用的标准接口,值得关注,但它解决的是工具生态互通问题,不是入门第一课。入门阶段先把基础循环跑通,比追任何热点都重要。

5. 一个人会了不算数:第72天我在团队里做的四件事

作为Leader,学习AI Agent还有另一重身份:把个体能力变成团队能力。说句实话,我一个人的学习如果没有在组里长出"手脚",那对团队来说就只是"Leader自己玩得很开心"。

5.1 先做可用原型,再开分享会

我花了两周把会议纪要Agent做到内部可用的最小版本,然后在一个组会上给大家演示。我没有讲概念,而是把架构画成三张卡片:模型负责什么、工具负责什么、校验层负责什么。

前端的同学对"组件边界"天生敏感。用组件化的语言讲Agent架构,效果出奇的好——有人当场就说,"这不就是把一个异步组件换成了会自己调用接口的组件吗"。对,就是这个理解,方向基本对了。

5.2 建立"评估集"共识

我做的第二个关键动作,是给团队的第一个Agent原型配了50条固定测试任务。每次改提示词或工具定义之前,先在组里跑一遍评估集,把通过率贴在白板上。

这个动作把团队对Agent的认知从"玄学"拉回了"工程"。前端同学都习惯自动化测试,接受度非常高。现在组里有人改完提示词,会主动说"我先跑一遍评估集再给你"——这个习惯的建立,比我讲十次PPT都管用。

5.3 定三条不可逾越的红线

  • 模型输出必须过校验器才能进入下游;
  • 任何Agent任务必须有终止条件与最大步数;
  • 所有模型调用必须记录token与耗时。

这三条是给团队新人兜底的,防止有人急着上线,把一个不稳定但"看起来无敌"的Agent捅到生产环境。它跟前端组里的代码审查规则是一个性质——不是限制创造力,是保护大家别被自己绊倒。

5.4 Leader的定位:不是自己转岗,而是带出第一批会用的人

走到第72天,我对自己的定位也越来越清楚:我大概率不会彻底转岗做一个全职的Agent工程师,我的价值应该在于成为团队的"AI Agent技术桥梁"。目标是半年内带出一两个能独立交付Agent工程的同学,再把工具定义模板、校验器模板、评估集模板这些know-how沉淀成组内资产。

学AI Agent这件事,对Leader来说最大的回报不是自己多牛,而是团队从此遇到"智能化需求"时,不再只能回一句"做不了"。

最后说一点个人体会:这两个多月里,真正拦住我的从来不是技术难度,而是心态上对"不确定性"的抗拒。我花了不少时间才接受了"系统偶尔会犯错、但可以通过工程手段把错误控制在可接受范围"这件事。如果你也是前端出身,转到Agent方向时遇到同样的心理障碍,别急着否定自己——那说明你还在用旧世界的尺子量新世界的家具。给自己一个72天,你会重新找到那把尺子。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进