AI Agent 设计与落地
Posted on Sun 28 December 2025 in Journal
| Abstract | AI Agent 设计与落地 |
|---|---|
| Authors | Walter Fan |
| Category | learning note |
| Status | v1.0 |
| Updated | 2025-12-28 |
| License | CC-BY-NC-ND 4.0 |
你可能也见过这种“AI 项目翻车现场”:
- 第 1 天:HR 说“能不能让 AI 帮我看简历?”
- 第 3 天:你做了个 ChatGPT 问答页,效果还行。
- 第 7 天:开始接入岗位 JD、做关键词匹配、自动改写,突然发现:隐私、事实一致性、格式、可解释性、以及“别把人写成神仙”全都要管。
- 第 14 天:上线试跑,输出像开盲盒:有时一针见血,有时胡编乱造;有时语言很漂亮,有时把时间线改得稀碎。
这时候你会发现:
这不是“写 prompt”的问题,这是“做系统”的问题。
所以本文用一个更真实、更能落地的例子来讲 Agent:
“简历审查与优化 AI Agent”(下面简称“简历 Agent”)
它的目标很具体: - 输入:候选人简历 + 目标岗位 JD +(可选)公司/团队偏好 - 输出:结构化评审 + 可追溯修改建议 + 生成可投递的新版简历
1. 先明确:你要做的是“Agent”还是“自动化脚本 + LLM”?
很多失败项目不是模型不行,而是把 LLM 问答误当成 Agent。
1.1 Agent 的最小定义(建议你直接写到 PRD 顶部)
Agent = 在给定目标下,能自主规划步骤、调用工具执行、在环境中产生可观测动作、并对结果进行迭代修正的系统。
一句话:它得“会做事”,不是只“会聊天”。 😄
1.2 用“简历 Agent”快速判定:它为什么是 Agent?
满足以下 2 条以上,你就别再叫它“聊天机器人”了:
- 多步任务:解析简历 → 对齐 JD → 找缺口 → 改写 → 校验 → 导出
- 外部工具:文件解析(PDF/DOCX)、ATS关键词匹配、模板渲染、导出
- 状态/记忆:版本管理(v1/v2/v3)、修改记录、用户偏好(语气/行业)
- 失败重试/回滚:解析失败、格式坏掉、改写过度、事实冲突
- 多角色/并行子任务:分析(Reviewer)/改写(Writer)/校验(Verifier)
小提醒:如果你只是“把简历丢给模型,让它给建议”,那更像“自动化脚本 + LLM”。不要硬叫 Agent,否则评审时你会被问:它的工具呢?它的状态机呢?它的回滚呢?
ATS 是 Applicant Tracking System 的缩写,中文常译为 候选人跟踪系统 / 招聘管理系统。 它用于企业招聘流程中对简历进行 收集、解析、筛选、关键词匹配、流转审批、面试安排与记录 等;很多“ATS 友好简历”指的是更容易被这类系统正确解析并命中岗位关键词。
2. 需求拆解模板:把“目标”拆成可执行的任务网
落地第一步不是挑框架,而是把问题拆对。
2.1 PRD 一页纸模板(强烈建议照填)
把下面这 7 行当作“必填字段”,填不出来就别开工:
- 目标(Goal):用户最终想得到什么可验收的产物?
- 输入(Input):用户给什么?(文本/链接/文件/表格/上下文)
- 输出(Output):产物格式?(Markdown/JSON/工单/代码提交)
- 环境与工具(Tools):允许调用哪些系统?权限范围?
- 约束(Constraints):时间/成本/合规/语言/不可编造(必须可溯源)
- 验收标准(Acceptance Criteria):怎么判断“做对了”?
- 失败边界(Failure Modes):最容易翻车的 3-5 件事
2.1.1 示例:简历 Agent(一页纸样例)
- Goal:对“岗位 JD”给出结构化评审(匹配度、缺口、风险),并生成可投递的简历(PDF/DOCX)。
- Input:简历文件(PDF/DOCX/Markdown)、岗位 JD(文本/链接)、可选:候选人自述亮点。
- Output:
review.json(评分 + 缺口 + 风险 + 建议)resume_v2.docx/resume_v2.pdf(可投递版本)diff.md(改动说明:哪里改了、为什么改)- Tools:文件解析、关键词抽取、模板渲染(DOCX/LaTeX)、拼写语法检查、导出服务。
- Constraints:
- 不得编造经历(不能凭空加项目、加公司、加时间线)
- 涉及 PII 必须脱敏/加密存储;默认不保留原始简历
- 输出必须可解释:每条建议对应 JD 证据或简历原句
- Acceptance:
- 所有“新增内容”都能追溯来源(来自简历/来自用户补充)
- 时间线不冲突;技能与经历一致
- ATS 关键词覆盖率提升(可量化)
- Failure Modes:PDF 解析乱序、模型擅自编造、格式破坏、关键词堆砌、语气过度夸张。
2.2 把大目标拆成“可观察”的 Task Graph
建议输出一个任务有向图(DAG),而不是“步骤列表”。原因:现实里会分支与回退。
flowchart TD
ingest[IngestResumeAndJD] --> parse[ParseResume]
ingest --> parseJD[ParseJD]
parse --> extract[ExtractFactsAndSkills]
parseJD --> keywords[ExtractJDKeywords]
extract --> gap[GapAnalysis]
keywords --> gap
gap --> rewrite[RewriteSections]
rewrite --> verify[VerifyNoFabrication]
verify --> format[RenderTemplate]
format --> deliver[DeliverFiles]
verify -->|NeedClarification| ask[AskUserForMissingInfo]
ask --> rewrite
关键点:DAG 里每一步都应该能产出“可观测中间结果”(结构化数据/日志/可复现的输出),否则后面你根本没法排查。
3. 核心架构模式:Controller-Tools-Memory(CTM)+ 可插拔 Policy
把 Agent 当成“可控的软件系统”,而不是“一个 Prompt”。
3.1 组件清单(最常用的工程化分层)
- Controller(控制器):规划、调度、重试、终止条件
- Tools(工具层):稳定的 API 封装,含鉴权、超时、幂等
- Memory(记忆层):短期上下文 + 长期状态/向量库 + 任务缓存
- Policy(策略层):权限、合规、成本、路由、提示词模板
- Telemetry(可观测层):日志、链路、token/成本、评测与告警
朴素但重要的事实:模型负责生成候选方案;系统负责把方案变成可控动作。
3.1.1 简历 Agent 的最小可行架构图
flowchart LR
User[User] --> Controller
subgraph tools [Tools]
ResumeParser[ResumeParser]
JDParser[JDParser]
ATSMatcher[ATSKeywordMatcher]
TemplateRenderer[DocxOrLatexRenderer]
GrammarChecker[GrammarChecker]
end
Controller --> tools
Controller --> Memory
Controller --> Policy
Controller --> Telemetry
tools --> Controller
3.2 趋势提示:现在拼的是“治理能力”
做简历 Agent 这种“看起来很简单”的事,最容易被低估: - 你不做治理,输出就会漂移; - 你不做验证,模型就会编; - 你不做可观测,线上就变成玄学。
做 Agent 不是“先能跑”,而是 能控、能查、能省。⚡️
4. 构建 Pattern:从 0 到 1 的最短路径(可复用流程)
下面是我建议的“七步法”,我会用“简历 Agent”贯穿。
4.1 Step 1:先定输出契约(Output Contract)
不先定输出,就会在后期评测和集成时失控。
- 输出必须是结构化或可解析格式(JSON/Markdown 严格模板)
- 输出必须可验证:引用来源、时间戳、证据链接
示例:review.json(建议配 JSON Schema 校验):
{
"match_score": 0.78,
"strengths": [
{"point": "有分布式系统经验", "evidence": "简历:XX 项目描述"}
],
"gaps": [
{"gap": "缺少可量化指标", "suggestion": "将‘优化性能’改为‘P95 从 800ms 降到 220ms’"}
],
"risks": [
{"risk": "时间线不一致", "evidence": "2021-2022 与 2022-2023 重叠"}
],
"ats_keywords": {
"missing": ["Kafka", "Kubernetes"],
"covered": ["Java", "Spring", "MySQL"]
},
"change_rules": {
"no_fabrication": true,
"tone": "professional"
}
}
经验:宁可让模型写“结构化要点”,也不要让模型写“散文式长文”。 长文不稳定、难回归,最后只能靠“相信 AI”。(相信就输了😄)
4.2 Step 2:工具先行(Tool-first)
把工具当成“后端服务”来写,不要把 API 调用写进提示词里。
简历 Agent 的工具封装建议包含:
- 解析:PDF/DOCX → 结构化段落(标题/项目/时间)
- 关键词:JD 关键词抽取 + ATS 覆盖率计算
- 导出:模板渲染(DOCX/LaTeX)+ PDF 导出
- 检查:拼写语法、格式约束(行距/分页)、链接有效性
工具封装要包含:
- 超时与重试(指数退避)
- 幂等(尤其是导出/写入文件)
- 权限与审计(谁上传了什么、谁下载了什么)
- 统一错误码(便于控制器规划分支)
4.2.1 工具接口定义模板(错误码 / 幂等键 / 审计字段 / 超时重试)
很多 Agent 项目“看起来能跑、实际上不可控”,本质原因是:工具层没有被当成“后端服务”来设计。
下面给一个我常用的工具接口模板,你可以直接套到简历 Agent 里。
工具接口(建议统一成 JSON 结构):
{
"tool": "ResumeParser",
"action": "parse",
"request_id": "req_20251228_0001",
"idempotency_key": "sha256:...",
"actor": {
"user_id": "u_123",
"tenant_id": "t_001",
"role": "hr"
},
"input": {
"file_uri": "s3://bucket/resume.pdf",
"file_type": "pdf",
"language": "zh-CN"
},
"policy": {
"timeout_ms": 8000,
"max_retries": 2,
"retry_backoff_ms": [200, 800],
"pii_mode": "redact"
}
}
工具返回(强烈建议统一错误码 + 可重试标记):
{
"ok": false,
"error": {
"code": "PARSE_PDF_OCR_REQUIRED",
"message": "PDF is scanned image; OCR required",
"retryable": false,
"hint": "Ask user for DOCX or run OCR tool"
},
"audit": {
"request_id": "req_20251228_0001",
"tool": "ResumeParser",
"action": "parse",
"ts": "2025-12-28T22:31:12Z"
}
}
建议的错误码分层(够用就好):
- 权限类:
AUTH_FORBIDDEN,AUTH_EXPIRED - 输入类:
INPUT_INVALID,INPUT_TOO_LARGE,INPUT_UNSUPPORTED_FORMAT - 外部依赖类:
UPSTREAM_TIMEOUT,UPSTREAM_RATE_LIMIT,UPSTREAM_5XX - 业务类:
PARSE_FAILED,TEMPLATE_RENDER_FAILED,EXPORT_FAILED - 安全类:
PII_POLICY_VIOLATION,PROMPT_INJECTION_DETECTED
幂等键(idempotency_key)怎么用?
- 对“导出/生成文件/写入版本库”这种写入型操作,必须带幂等键。
- 推荐幂等键 =
hash(用户ID + 输入文件hash + JD hash + 输出模板版本 + 输出格式)。 - 这样用户重复点“生成”,最多只会拿到同一份产物,不会生成 N 份垃圾版本。
审计字段(audit)怎么用?
- 记录:谁触发、用的什么输入、调用了哪些工具、产出了哪些文件。
- 简历是 PII,审计不是可选项,是上线门票。
超时/重试建议(工程上很实用):
- 工具调用超时要“短”,避免线程池被拖死;需要长任务就异步化。
- 只对 retryable=true 的错误重试(比如限流/超时),不要对解析失败重试 N 次自我感动。
- 控制器里做“错误分支规划”:
PARSE_PDF_OCR_REQUIRED→ 调OcrTool或请求用户提供 DOCXTEMPLATE_RENDER_FAILED→ 回滚上一个版本 + 降级到纯文本模板
4.3 Step 3:设计控制器(Planner/Executor)
推荐从简单开始:
- 单代理 ReAct(最容易上线)
- 需要并行再升级多代理(Reviewer/Writer/Verifier)
控制器最重要的三个能力:
- 停止条件:何时停止(例如“所有风险已闭环/需要用户补充信息”)
- 失败恢复:解析失败→换解析器;关键词过拟合→降权;格式崩→回滚到上一个版本
- 预算控制:token/调用次数/最长耗时
4.4 Step 4:加入记忆与状态(State Machine)
简历优化往往是多轮:你改一版,我再提意见,再改一版。
如果你的任务跨多轮或跨天,必须上状态机,否则靠对话历史必翻车。
建议状态:
- INIT → INGESTED → ANALYZED → REWRITTEN → VERIFIED → RENDERED → DELIVERED → DONE
- 异常:NEED_CLARIFICATION / FAILED / ROLLBACKED
4.5 Step 5:验证层(Verification Layer)要单独做
“模型自信”不等于“事实正确”。简历场景尤其敏感:编造经历 = 灾难。
建议最少做两种验证:
- 可验证引用:每条建议必须绑定证据(简历原句/JD 句子/用户补充)
- 二次校验:用更便宜模型 + 规则校验
- 时间线是否冲突
- 公司/项目是否新增(禁止)
- 指标是否夸张(例如“提升 100 倍”要打回)
4.5.1 Verifier 规则清单(简历场景必备)
简历 Agent 的 Verifier 目标不是“挑刺”,而是把不确定性收敛成工程可控变量:不编造、不冲突、不过度、不注水、可追溯。
你可以把 Verifier 拆成“规则 + 轻量模型”的组合:
- 规则:快、稳定、可解释(适合拦截硬错误)
- 轻量模型:查软错误(语气、可读性、是否过度夸张)
下面这份清单可以直接做成代码里的 resume_verifier_rules.yaml。
A. 不得编造(No Fabrication)
- 禁止新增实体:新公司名/新项目名/新时间段/新职位头衔
- 做法:抽取“原简历实体集合”,对比“改写后实体集合”,出现新增则打回
- 禁止新增不存在的技术栈:例如简历没写过 Kafka,却突然出现“精通 Kafka”
- 做法:技能词表 + 证据绑定(每个技能必须引用原句或用户补充)
B. 时间线一致性(Timeline Consistency)
- 日期范围不冲突:同一时间段出现两个全职经历
- 项目时间必须落在所属公司时间范围内
- “至今”只能出现一次(或者必须解释多段并行)
C. 量化指标合理性(Metric Sanity Check)
- 夸张指标拦截:如“提升 100 倍/提升 10000%”默认判为高风险
- 缺少单位/口径提醒:如“延迟降低 80%”但无 P95/P99、无基线
- 指标与动作一致:写了“做缓存”但指标却是“准确率提升”,就要提示不一致
D. 关键词堆砌检测(Keyword Stuffing)
- 关键词密度过高:一段话连续罗列 15 个技术名词
- 与经历无关的关键词:JD 里要 Kubernetes,你简历没任何容器经历却硬塞
- 策略:允许“补充学习/接触”,但必须放在“技能/学习”而不是“工作成果”里
E. 风格与语气(Tone & Claims)
- 避免把人写成神仙:
- 不要“全栈架构师/技术领袖/业内顶尖”这种无证据的帽子
- 更推荐:职责 + 行动 + 结果(CAR/STAR)
- 一致性:同一份简历的语气要统一(不要一会儿像论文,一会儿像广告)
F. 格式与可投递性(Format & Deliverability)
- 段落长度限制:项目描述每条 1-2 行(不然 HR 眼睛会罢工)
- 链接可用:GitHub/Blog/作品集链接必须可点击、格式正确
- 导出校验:生成的 DOCX/PDF 不能乱码、不能错位、不能丢字
G. 证据链(Evidence Binding)
- 每条建议必须绑定一个 evidence:
resume_quote(原简历句子)或user_supplied(用户补充)或jd_quote(JD 句子)- 没证据的建议不允许出现在最终输出里(顶多作为“需要用户确认的问题”)
4.6 Step 6:上可观测与治理(Observability + Governance)
上线后你需要回答四个问题:
- 这次建议为什么是这样?(trace + 证据链)
- 花了多少钱?(token、工具调用)
- 哪些地方最容易出错?(解析错误/格式错误/编造风险)
- 哪些提示/工具最有效?(A/B、回归测试)
4.7 Step 7:做评测集 + 回归(Eval-first Iteration)
没有评测集,优化永远是拍脑袋。
简历 Agent 的评测集建议包含:
- 正常样本(70%):规范简历 + 清晰 JD
- 边界样本(20%):PDF 乱序、JD 含糊、经历缺指标
- 对抗样本(10%):诱导编造、诱导夸大、提示注入(“忽略规则”)
5. 典型模式库(直接套用)
模式 A:RAG + 工具写入(简历知识库助手)
适用:把公司内部“简历模板/面试题库/胜任力模型”做成可检索知识库。
要点:
- 检索:向量 + 关键字混合(避免仅语义)
- 引用:每条建议绑定来源(模板条目/胜任力条款)
- 写入:必须幂等(防止重复版本/覆盖原件)
模式 B:规划-执行-校对(Plan-Execute-Review)
适用:简历改写、生成 cover letter、生成面试自我介绍。
推荐结构:
- Planner:列“缺口清单 + 需要用户补充的问题”
- Executor:生成 v2 草稿
- Reviewer:查事实/格式/语气/风险
模式 C:多代理分工(Reviewer/Writer/Verifier)
适用:长简历、多岗位投递、多版本管理。
注意事项:
- 明确“交付物格式”(PDF/DOCX + review.json + diff.md)
- Agent 间通信只传结构化中间结果,少传长文本(省 token,也更可控)
6. 安全与合规检查清单(Agent 必备)
简历 = PII + 职业轨迹,安全合规要放在前面。
6.1 工具调用安全(Checklist)
- 上传文件默认不持久化,或设置明确的保留期(例如 24h 自动删除)
- 所有写入类工具必须有沙箱/测试环境
- 权限遵循最小权限原则(谁能看谁的简历)
- 对外网请求有域名白名单
- 记录审计日志(谁触发、做了什么、参数是什么)
6.2 防提示注入(Prompt Injection)
- 系统提示与用户内容严格分隔(role separation)
- 检索内容视为“不可信输入”,需要清洗
- 重要工具参数由程序生成,不让模型自由拼接(特别是文件路径、模板变量)
7. 上线验收:别只验“能跑”,要验“能控”
建议用下面这张表做上线前验收(可以直接贴进 Jira):
7.1 功能
- 输出契约符合约定格式(review.json 校验通过)
- 新简历可导出,格式不崩(分页/对齐/字体)
7.2 稳定性
- 解析失败可降级或重试(换解析器/换策略)
- 有明确停止条件,不会无限循环
7.3 成本
- 单任务 token 成本可预测,超预算会自动中止或降级
7.4 可观测
- trace 可追溯到每次工具调用与关键中间结论
- 关键错误有告警(解析失败率、导出失败率、编造风险命中率)
7.5 安全
- 越权用例测试通过(不能访问不该访问的简历)
- 导出/下载操作具备审计
8. 一个小但高效的习惯:给 Agent 也安排“走动休息”
写 Agent 常常要长时间盯日志、调提示、看 trace。对人同样要做节奏管理:
- 每小时离开桌面走 5 分钟
- 借机做“切换视角”的复盘:我现在是在解决真实问题,还是在堆复杂度?
结语:把简历 Agent 当软件工程,而不是魔法
当你用输出契约约束结果、用工具层约束动作、用状态机约束流程、用评测与可观测约束迭代时,Agent 的不确定性会被收敛成可控的工程变量。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。