「JS全栈AI Agent学习」五、目标、监控与容错:让 Agent 像靠谱的开发者一样工作

6 阅读15分钟

📌 系列简介:「JS全栈AI Agent学习」系统学习 21 个 Agent 设计模式,篇数随学习进度持续更新。

⏱️ 预计阅读时间:15 分钟

📖 原书地址adp.xindoo.xyz

前端转 JS 全栈,正在学 AI,理解难免有偏差,欢迎批评指正 ~


🗺️ 系列导航

主题状态
第一篇提示链 · 路由 · 并行化
第二篇反思 · 工具使用 · 规划
第三篇多智能体 · 记忆管理 · 学习适应
第四篇MCP 协议
本篇目标设定与监控 · 异常处理与恢复

前言

我在做 my-resume 的全栈改造——把一个静态展示页面,改成 NestJS 后端 + 数据库 + 前端交互 + AI 能力 + 部署上线的完整项目。

在设计 AI 能力这块,我一直在思考一个问题:

如果我要做一个 Agent,帮用户自动优化他的简历内容,这个 Agent 应该怎么工作?

这个问题看起来简单,但细想下去,有三个坑:

坑一: Agent 怎么知道"优化完了"?没有明确的完成标准,它可能会一直改、改到跑偏。

坑二: Agent 执行到一半,LLM 接口没有响应,怎么办?已经处理好的内容就丢了吗?

坑三: LLM 正常返回了,但内容是错的——用户有2段工作经历,AI 整理出了4个,自相矛盾。代码不会报错,但结果是坏的。

这三个坑,正好是这篇文章的全部内容:

  • 第11章:目标设定与监控——解决坑一,让 Agent 知道自己在做什么、做到什么算完成
  • 第12章:异常处理与恢复——解决坑二和坑三,让 Agent 在出错时不失控

两章放在一起讲,因为它们本质上是同一件事的两面:

第11章是"正向设计"——怎么让 Agent 朝着目标跑 第12章是"防御设计"——跑的过程中出了问题怎么兜底


一、一个问题热热身

假设你雇了一个实习生,让他帮你做 my-resume 的全栈改造。

你只说了一句话:"帮我把这个项目改造成全栈的",然后你去忙别的了。

三天后你回来,面对三个问题:

  1. 你怎么判断他做得好不好?
  2. 他自己怎么知道该在哪里停下来?
  3. 如果他走偏了,你们怎么发现?

我自己的答案是这样的:

问题一:回看需求,看有没有完成最终任务,偏差能不能接受。

问题二:每到一个里程碑,做任务拆解,符合单一职责,每完成一个 task 做 review / 自测 / 验证,没有偏离就 commit,然后继续开发。

问题三:丢了任务就不管,3天后看结果,根据结果比对判断。

这三个答案,就是第11章的全部内容——只不过那个"实习生",换成了 AI

实习生开始工作

PS: 目前初步重构已OK,这个系列学习完会作为下阶段的实战项目再放出来,现在AI模块还没接入和完成 …

1、先确定技术选型

作为学习项目难得用用React,这次就准备用 monorepo + Next.js 来进行了。

可以让 AI 出一版技术选型方案,比如我们作为前端选 MongoDB 还是 SQLite、PostgreSQL,让AI分析并给出理由我们来确认就好了。

现在有了AI辅助,思路要变,不要畏惧,边做边学就好。于是我的技术选型也确认了

# 个人简历 Monorepo 重构总方案(v1 学习版)

## Summary

- **目标**:把现有静态 Vue 简历站,重构为一个**可学习、可开源、可部署、可写教程系列**的全栈 monorepo。
- **v1 产品边界**:只做 **1 份标准通用版双语简历(`zh/en`)**,不做按 JD 派生的多版本简历;JD 定制版、商业版能力全部后置。
- **主题策略**`light / dark` 作为 `v1` 基础能力纳入设计;多模板主题暂不实现,但要预留扩展钩子。
- **推荐技术栈**`pnpm workspace` + `Turborepo` + `Next.js(App Router)``web/admin`)+ `NestJS` + `Drizzle ORM` + `SQLite`- **角色模型**`admin` 可编辑/发布/触发 AI;`viewer` 只读,只能体验**缓存好的预设分析结果**,不能发起真实 AI 调用。
- **导出策略**`pdf/md` 统一由 `NestJS` 生成与下载。
- **部署主线**`web/admin` 部署到 `Vercel``NestJS/Redis/SQLite(libsql)` 部署到云服务器;CI/CD 作为正式里程碑纳入教程。

## Key Changes

### Monorepo 结构

- `apps/web`:公开简历展示,SSR/SEO 优先,提供在线浏览与导出下载入口。
- `apps/admin`:后台管理,登录后可编辑简历、发布、查看 AI 结果、体验缓存报告。
- `apps/server`:唯一业务后端,承载鉴权、简历 CRUD、AI、文件、导出、队列、权限。
- `packages/ui`:共享 React UI 组件与主题。
- `packages/api-client`:共享 API 请求层、DTO 类型、错误码。
- `packages/config`:共享 `tsconfig``eslint`、环境变量约束。

### 前端选型

- `web``admin` 都使用 `Next.js App Router + HeroUI + TypeScript + Tailwind`- 后台数据请求统一使用 `TanStack Query`;表单统一使用 `React Hook Form + Zod`- 不引入 Redux;局部状态保持简单。

### 后端选型

- `NestJS` 继续作为唯一业务后端。
- `Redis/BullMQ` 用于 AI 任务、文件解析、重试和状态流转。
- AI Provider 使用**适配器模式**,允许用户通过 `.env.local` 配置自己的模型、协议和 base URL。

### 数据库与内容模型

- 只维护**一份标准简历**,同一条记录直接包含 `zh/en` 多语言内容。
- 数据按模块拆分:`profile``education``experiences``projects``skills``highlights``attachments`- 增加“**草稿 / 已发布**”状态,后台编辑草稿,公开站只读取已发布内容。

接下来就是让你的 OpenCode / Claude Code / CodeX 跑起来:

为了更好的效果,记得提前把相关 skills 安装一下,推荐一下 frontend-design

我准备重构我的 my-resume 项目,技术方案如下(上面那大段粘贴进来)

1. 评估重构方案进行 milestone 规划,并拆分相应的 issue;
2. 进行 TDD 开发,开发完成自测,完成后再继续;
3. 自测通过后,记录开发文档到docs目录下,按标准git流程提交并推送到远端;
4. 并继续下一个里程碑内issue,按上述步骤进行;
5. 该里程碑 issue 进行后继续下一阶段规划直到重构全部完成。

并不是一次完成的,主要思路是这样,中间有些忘了。这只是个小插曲,继续回到我们的学习中来.


二、第11章:目标设定与监控

2.1 目标要具体到"可以被判断"

"优化简历"不是一个好目标,因为它没法被判断——什么叫优化好了?

my-resume 的场景里,我想到了两种目标模式:

模式A:以用户自身为原点
  → 补全和完善
  → 基本信息、工作履历、项目经验都解释清楚了
  → 成功标准:完整性 ✅

模式B:以企业JD为导向
  → 根据 JD 来补全当前欠缺的部分
  → 成功标准:和 JD 的关键词匹配度 ✅

两种模式都可以,但对 Agent 来说,模式B 更友好——因为有外部锚点,完成度可以被量化比对,Agent 知道什么时候该停。

💡 一句话原则:目标要具体到"可以被程序判断 True/False"

这也是第11章一个很妙的设计——

用 LLM 来判断"是否达标",返回 True/False

把"简历质量好不好"这种模糊的主观判断,变成可以被程序处理的布尔值。这是第4章 Reflection(反思)模式在目标监控里的具体应用。


2.2 执行循环:你的开发节奏就是 Agent 的工作节奏

我平时开发的节奏是这样的:

里程碑拆解
  → 符合单一职责的 task
  → 完成一个 task
  → review / 自测 / 验证
  → 没偏离就 commit & push
  → 继续下一个

翻译成 Agent 语言:

我的开发节奏Agent 里的概念
里程碑拆解Sub-goal Decomposition(子目标分解)
单一职责的 taskAtomic Action(原子动作)
review / 自测 / 验证Self-evaluation(自我评估)
commit & pushCheckpoint(检查点)
继续下一个Next iteration(进入下一轮)

这套节奏,就是 Agent 的 Plan → Execute → Evaluate 循环。

第11章的核心模式图:

定义目标
+ 成功标准
+ 容忍阈值
     ↓
拆解子目标(里程碑)
     ↓
执行 → 自我评估 ──── 偏离 ──→ 重新规划 ──┐
     ↓         ↑                          │
   通过        └── 检查点 ─────────────────┘
     ↓
终态评估:达成目标?
├─ 是 → 结束 ✅
└─ 否 → 重新规划 or 上报

2.3 和前几章的关系

第11章不是新技能,而是一个元模式——把之前学的能力组织起来,给 Agent 装上方向盘和仪表盘:

章节负责什么在第11章里的位置
第6章 规划生成计划、拆解子目标"拆解子目标"这一步
第4章 反思评估输出质量"自我评估"这一步
第10章 MCP工具怎么调用"执行"这一步的底层
第11章把上面串起来,加上目标和监控整个循环的框架

🎯 第11章是一个"元模式"——它不引入新技能,而是给之前所有模式装上"方向感"和"自我管理能力"


三、第12章:异常处理与恢复

第11章解决了"Agent 要做什么",第12章解决"做的过程中出了问题怎么办"。

3.1 两种完全不同的错误

先做一个区分,这非常重要——

Agent 调用 LLM 优化第三段工作经历,LLM 正常返回了,没有超时,没有报错,但返回的内容是:

"该用户在2015年同时担任 Google 工程师和 Facebook CTO"

代码层面会报错吗?不会。

但这个结果显然是错的——一个人同一时间只能在一家公司任职。

这说明 Agent 的错误有两种完全不同的类型:

错误类型检测方式简历 Agent 举例
硬规则错误格式、字段、语法、依赖代码 try/catch字段为空、日期格式错误、LLM 接口超时
语义层错误逻辑矛盾、因果不对LLM 来判断时间线冲突、职位与工作内容不符

硬规则错误,代码能发现。语义层错误,只有 AI 能发现。

💡 用 AI 检测 AI 的输出——这是第4章 Reflection 模式的另一个具体应用


3.2 出错了,Agent 应该怎么决策?

发现错误之后,Agent 有三条路:

路径A:自己修复
路径B:问用户
路径C:任务失败,干净退出

怎么决定走哪条?我自己推导出来的判断链是这样的:

发现错误
  ↓
临时抖动?→ retry(重试)
  ↓ 还是不行
有备用节点?→ 切换备用,继续
  ↓ 备用也挂了
影响最终结果?→ 告知用户,询问是否降级继续
  ↓ 用户不同意 / 无法降级
任务失败,干净退出

这个链条在第12章里叫做 异常升级(Escalation)——问题解决不了,就往上"升级"一层处理,直到有人能接手。


3.3 Checkpoint:出错不从头来

回到最开始的问题:LLM 接口没有响应,已经处理好的内容就丢了吗?

答案是:不应该丢,因为有 Checkpoint。

这个概念和 git commit 是同一个道理:

每完成一个稳定的功能点,就 commit 一次。 即使后面出问题,也能回到上一个稳定状态,而不是从头来。

在简历 Agent 里,Checkpoint 的打法是这样的:

① 识别简历内容,读取文件 → Checkpoint 1
② 梳理大纲结构,分层归类 → Checkpoint 2
③ 整理第一段工作经历     → Checkpoint 3
④ 整理第二段工作经历     → Checkpoint 4
⑤ 整理第三段工作经历     → ❌ LLM 无响应
   → 从 Checkpoint 4 恢复,重试第三段

不用从头来,成本最小。


3.4 Human-in-the-loop:什么时候让人拍板

不是所有错误都该 Agent 自己处理。

有一类错误,影响范围大、涉及用户核心信息、难以撤回——这种必须让人来决定。

比如简历 Agent 检测到:

用户说有5段工作经历,但整理完只有3段时间线,有2段找不到对应的时间区间。

这种情况,Agent 不能自己"脑补"填上去,必须告知用户,让用户来核实。

但另一方面,如果 Agent 什么都要问用户,就会变成这样:

"你确定要输入这个字吗?" → 确认 "你确定要移动光标吗?" → 确认 "你确定要删除这个空格吗?" → 确认

这不是助手,这是折磨。

所以需要一个原则——最小干预(Minimal Footprint)

条件Agent 自己处理需要问用户
影响范围小、局部大、影响全局
可逆程度容易撤销难以撤回
用户授权已明确授权未授权

对应到简历 Agent:

Agent 默默处理(最小干预):
  ✅ 错别字:「负则」→「负责」
  ✅ 日期格式:「2020.3」→「2020-03」
  ✅ 语言流畅度优化(用户已授权"帮我润色")

必须问用户(Human-in-the-loop):
  ⚠️ 工作经历数量对不上
  ⚠️ 同一时间段出现两家公司
  ⚠️ 职位描述和工作内容严重不符
  ⚠️ 用户没有授权的内容扩写

💡 一句话原则:只要是对用户最终结果有影响、难以撤回的,都该人工介入


3.5 执行前验证:在出错之前就预判风险

有没有办法在出错之前,就预判到"这一步可能有风险"?

比如用户突然说:

"帮我把所有工作经历都删掉,只保留教育背景"

Agent 在执行之前,应该先质疑一下合理性:

"您的目标是优化简历,工作经历是简历的核心部分。确认要删除全部工作经历吗?"

这叫做 Pre-execution Validation(执行前验证)——在执行高风险操作之前,先做一次意图确认。

它和 Human-in-the-loop 的区别是:

Human-in-the-loop:出错之后,让人来决定怎么处理  → 事后补救
Pre-execution Validation:执行之前,先确认用户真的要这么做 → 事前预防

两个都需要,缺一不可。


四、把两章串起来:完整的简历 Agent 设计

现在把第11章和第12章的所有概念,放进简历 Agent 的完整流程里:

用户输入:"帮我优化整份简历,一共5段工作经历"
     ↓
【目标定义】(第11章)
  目标:5段工作经历全部优化完成
  成功标准:完整性 + 清晰度 + 一致性全部通过
  容忍阈值:小的格式问题可以自动修复
     ↓
【执行前验证】(第12章)
  检查输入:简历文件是否可读?字段是否齐全?
     ↓
【循环执行】(第11章 + 第12章)
  ┌──────────────────────────────────────┐
  │  处理第N段工作经历                    │
  │       ↓                              │
  │  硬规则检测:字段完整?格式正确?     │
  │       ↓                              │
  │  语义层检测:逻辑一致?时间线正确?   │
  │       ↓                              │
  │  发现问题?                           │
  │  ├─ 小问题(错别字/格式)→ 自动修复  │
  │  └─ 大问题(矛盾/缺失)→ 问用户     │
  │       ↓                              │
  │  Checkpoint:保存当前进度            │
  │       ↓                              │
  │  LLM 出错?→ retry → 备用 → 上报    │
  └──────────────────────────────────────┘
     ↓ 5段全部完成
【终态评估】(第11章)
  LLM 裁判:整份简历达到目标了吗?
  ├─ True  → 输出结果 ✅
  └─ False → 重新规划,继续改进

五、核心洞察总结

概念核心思想一句话记住
目标定义目标要具体到可以被判断能返回 True/False 的才是好目标
子目标分解大任务拆成原子动作你的里程碑拆解,就是 Agent 的 Sub-goals
Checkpoint每个稳定点存档就是 git commit,出错不从头来
硬规则检测代码发现格式错误try/catch 能抓到的
语义层检测AI 发现逻辑矛盾代码看不出来,要用 LLM 当裁判
异常升级问题层层往上处理retry → 备用 → 问用户 → 退出
Human-in-the-loop影响结果的让人拍板影响最终结果 + 难以撤回,就介入
最小干预小事默默处理默默兜底的好伙伴
执行前验证高风险操作先确认事前预防 > 事后补救

结语

这两章放在一起,讲的其实是同一件事:

怎么让 Agent 像一个靠谱的开发者一样工作。

靠谱的开发者是什么样的?

  • 接到任务,先搞清楚"做到什么算完成"
  • 拆成里程碑,每完成一个就 commit
  • 遇到小问题自己解决,不麻烦别人
  • 遇到大问题及时上报,不自作主张
  • 出了 bug,从上一个稳定版本恢复,不从头来

这套工作方式,我们作为开发者已经内化了。第11章和第12章,就是把这套工作方式,显式地教给 Agent

学到这里,越来越觉得:AI 工程和软件工程,底层真的是同一套思维。 目标管理、检查点、容错分层——这些事工程师早就在做了,只不过现在执行者从代码变成了模型,从人变成了 Agent。

对于 my-resume 的全栈改造来说,这两章给了我一个很清晰的设计原则:

AI 能力不是"扔给 LLM 就完事",而是需要设计目标、检查点、容错机制——就像设计一个可靠的后端服务一样。


下一篇预告: 第13章——人机协同(Human-in-the-Loop)。这章会把"什么时候让人介入"这个问题讲得更系统,期待一下 🚀


💬 系列地址:持续更新中 📖 原书地址adp.xindoo.xyz 🛠️ 实战项目:my-resume(静态页面 → NestJS + 数据库 + AI + 部署上线,进行中)

如果这篇对你有帮助,欢迎点赞收藏,我们下篇见 👋