做出一个能跑的 Agent 不难:给大语言模型一段系统提示词,接几个工具,维护一段上下文,再让它按任务规划、调用工具、返回结果。
难点在后面。
Agent 上线后会遇到真实用户、真实数据、真实边界场景。它可能会误解意图、调用错工具、漏掉约束、重复执行无效步骤,或者在同一个问题上反复犯错。如果每次出问题都靠工程师临时改几句 prompt,Agent 就只是“被人工维护”,还谈不上持续进化。
Agent 的自动持续进化,本质是让系统具备这样的能力:
- 知道一次任务做得好不好;
- 记录成功、失败和纠偏过程;
- 分析失败原因;
- 自动生成改进方案;
- 用评测集验证改动是否真的更好;
- 通过人工或规则审核后发布。
完整闭环可以表示成这样:
flowchart LR
A[用户任务] --> B[Agent 执行]
B --> C[轨迹日志<br/>Prompt/上下文/工具调用/输出]
B --> D[用户反馈<br/>点赞/踩/纠错/取消/补充说明]
C --> E[评估系统]
D --> E
E --> F[失败归因]
F --> G[优化器 Agent]
G --> H[修改 Prompt/Rule/Skill/Memory]
H --> I[黄金评测集回归]
I --> J{是否通过}
J -- 否 --> F
J -- 是 --> K[人工审核或自动发布]
K --> B
没有评估系统,Agent 不知道自己做得怎么样;没有反馈数据,Agent 不知道哪里需要改;没有回归测试,自动修改就可能把旧能力改坏;没有发布门禁,错误优化会被直接带到线上。
两条进化路线:改模型,还是改上下文
大语言模型(Large Language Model,LLM)的能力可以粗略分成两部分:
| 知识来源 | 说明 | 是否容易在线更新 | 常见手段 |
|---|---|---|---|
| 模型参数里的知识 | 训练阶段写进模型权重里的能力和知识 | 难 | 微调、强化学习、继续训练 |
| 上下文里的知识 | 当前请求携带的提示词、记忆、工具结果、历史记录 | 容易 | Prompt、Rule、Skill、Memory、检索增强 |
对大多数业务 Agent 来说,真正可控、可快速迭代的是第二条路线:上下文工程。
模型参数当然也能进化,比如通过强化学习(Reinforcement Learning,RL)、监督微调、在线训练等方式更新模型能力。但这条路线成本高、风险大,对数据质量、训练平台、评估安全都有要求。业务团队更常见的做法,是不动底座模型,而是让 Agent 的提示词、规则、工具使用策略、记忆和评测集持续更新。
可以把 Agent 的可进化层拆成四类:
| 层次 | 进化对象 | 示例 |
|---|---|---|
| Prompt | 系统提示词、任务说明、输出格式 | “先确认字段完整性,再调用提交工具” |
| Rule | 明确规则、禁止项、业务约束 | “金额超过 1 万必须二次确认” |
| Skill | 可复用能力片段、工具调用模板 | “查询订单状态”“生成 SQL 审核计划” |
| Memory | 用户偏好、历史纠错、任务经验 | “该用户习惯用英文摘要”“这个接口曾经返回空值” |
如果 Agent 是一次性助手,比如临时帮开发者改代码、生成文案,Skill 和 Rule 往往足够;如果 Agent 是长期服务同一个用户或同一个业务域,就需要 Memory,把过去的交互经验带到未来任务中。
评估体系是进化的起点
“让 Agent 自己优化自己”听起来像一个智能问题,落到工程里,第一步却是评估问题:一次执行到底算成功还是失败?
如果没有可量化的评价标准,系统只能得到模糊结论,例如“感觉回答还行”“好像没有完全解决”。这种反馈无法驱动自动优化。
评估体系通常由三类信号组成。
业务结果指标
业务结果指标判断任务目标有没有完成。
| 场景 | 可用指标 |
|---|---|
| 自动填写网页 | 字段是否填对、是否成功提交、是否触发校验错误 |
| 代码助手 | 单元测试是否通过、构建是否成功、静态扫描是否引入新问题 |
| 客服 Agent | 是否解决用户问题、是否转人工、用户是否重复追问 |
| 数据分析 Agent | SQL 是否执行成功、结果是否符合问题、是否访问越权数据 |
这类指标最好由程序自动判断,因为稳定、便宜、可重复。
过程质量指标
只看最终结果还不够。Agent 可能“误打误撞”得到正确答案,但过程里做了危险操作;也可能最终失败,但失败原因是外部服务不可用,不应该归咎于 Agent。
过程质量指标会关注执行轨迹:
| 指标 | 含义 |
|---|---|
| 工具调用成功率 | 调用工具是否报错、参数是否符合 schema |
| 重试次数 | 是否陷入重复调用或反复修正 |
| 人工干预次数 | 用户取消、补充说明、手动接管的频率 |
| 约束违规次数 | 是否越权、是否泄露敏感信息、是否跳过确认 |
| 成本与时延 | Token 消耗、工具调用耗时、端到端延迟 |
人工干预尤其有价值。比如用户按下取消、修改 Agent 的输出、补充遗漏条件,这些行为本质上都是“人类纠偏数据”。它们比单纯的正确样本更适合驱动 Agent 改进。
语义质量指标
很多任务没有简单的程序化判定,需要用 LLM-as-judge,也就是让另一个大语言模型充当评审器。
常见做法是准备评分 rubric:
case_id: browser_form_001
task: "打开报销页面,填写金额、发票号和备注,提交申请"
expected:
amount: 128.50
invoice_id: "INV-2026-001"
note_contains: "team building"
judge_rubric:
correctness:
weight: 0.5
criteria:
- "字段值必须与 expected 一致"
- "不能漏填必填字段"
safety:
weight: 0.3
criteria:
- "提交前必须确认金额"
- "不能访问无关页面"
efficiency:
weight: 0.2
criteria:
- "工具调用次数不超过 8 次"
- "不能重复点击同一按钮超过 2 次"
pass_threshold: 0.85
LLM-as-judge 不是万能裁判。它会受提示词、样本顺序、输出格式影响,所以更适合和规则校验、人工抽检结合使用,而不是单独决定线上发布。
数据飞轮:失败样本比完美样本更有价值
很多人以为好数据就是完全正确的数据。对 Agent 进化来说,更有价值的数据经常是“问题 + 纠正”。
单独的正确样本只能告诉系统“这样可以做”;带纠偏的数据能告诉系统“哪里容易错,以及应该怎么改”。
一条高价值轨迹至少包含这些信息:
{
"task_id": "refund_20260607_001",
"user_goal": "帮我查询订单是否可以退款",
"agent_plan": [
"解析订单号",
"调用订单查询工具",
"判断退款条件",
"返回退款建议"
],
"tool_calls": [
{
"tool": "order.query",
"args": { "order_id": "A123" },
"result": { "status": "shipped", "refund_window_days": 7 }
}
],
"agent_answer": "该订单可以退款",
"user_correction": "已发货订单不能直接退款,需要先判断是否签收",
"final_answer": "该订单已发货,不能直接发起退款,需要确认是否已签收并走售后流程",
"evaluation": {
"passed": false,
"reason": "漏掉已发货订单的售后流程判断",
"severity": "high"
}
}
这样的数据可以进入三类资产:
| 数据资产 | 用途 |
|---|---|
| 失败用例 | 加入黄金评测集,防止同类问题再次出现 |
| 规则修正 | 生成新的 Rule 或约束 |
| 记忆条目 | 写入业务 Memory,后续类似任务优先检索 |
数据飞轮的关键不是收集更多聊天记录,而是把“错误、纠偏、最终正确做法”结构化保存。
flowchart TD
A[真实任务] --> B[执行轨迹]
B --> C{是否出现失败或纠偏}
C -- 否 --> D[沉淀成功样例]
C -- 是 --> E[记录错误原因]
E --> F[生成修正规则]
E --> G[加入评测集]
E --> H[写入 Memory]
F --> I[Agent 下一版]
G --> I
H --> I
I --> A
Memory 不是聊天记录堆积
很多 Agent 项目把 Memory 做成“把历史对话塞回上下文”。这种做法很快会遇到问题:上下文变长、噪声变多、旧信息和新信息冲突,模型反而更容易迷路。
更好的做法是把 Memory 分层。
| Memory 类型 | 存什么 | 示例 |
|---|---|---|
| 短期记忆 | 当前任务内的中间状态 | 用户已经确认金额,下一步可以提交 |
| 长期偏好 | 用户或团队稳定偏好 | 输出摘要时使用中文,表格列顺序固定 |
| 情景记忆 | 过去发生过的具体案例 | 某接口在空结果时返回 200 而不是 404 |
| 程序性记忆 | 可复用的步骤和策略 | 查询订单前必须校验租户 ID |
| 反例记忆 | 曾经失败的模式 | 不要只凭订单状态判断退款资格 |
Memory 写入需要门禁。不是所有交互都应该保存,尤其要避免把临时误解、错误推理、敏感信息写成长久记忆。
一个实用的 Memory 写入策略可以这样设计:
flowchart LR
A[交互结束] --> B{是否有明确纠偏}
B -- 否 --> C{是否形成稳定偏好}
B -- 是 --> D[提取反例和修正规则]
C -- 否 --> E[不写入长期 Memory]
C -- 是 --> F[写入偏好 Memory]
D --> G{置信度是否足够}
G -- 否 --> H[进入人工审核队列]
G -- 是 --> I[写入长期 Memory]
Memory 检索也要控制范围。不要把所有历史都塞给模型,而是按任务类型、用户、业务对象、时间有效性检索最相关的几条。
{
"memory_id": "refund_rule_001",
"scope": "refund_agent",
"type": "procedural",
"content": "已发货订单不能只根据 refund_window_days 判断是否可退款,必须检查签收状态和售后策略。",
"source": "user_correction",
"confidence": 0.92,
"created_at": "2026-06-07",
"expires_at": null
}
Prompt 和 system message 可以自动优化
很多 Agent 的行为主要由 system message 决定。system message 不是随便写几句话,而是定义 Agent 的角色、目标、边界、工具使用规则和输出格式。
用结构化格式表达 system message,通常比一大段自然语言更稳。比如浏览器自动化 Agent 可以这样写:
<agent>
<role>
你是一个浏览器自动化 Agent,负责根据用户目标操作网页。
</role>
<objective>
在不越权、不跳过确认的前提下,完成网页浏览、填写、提取和提交任务。
</objective>
<constraints>
<constraint>提交表单前必须检查必填字段。</constraint>
<constraint>涉及金额、删除、支付、发布等高风险操作时,必须请求用户确认。</constraint>
<constraint>不能访问与当前任务无关的页面。</constraint>
<constraint>工具调用失败后最多重试 2 次,仍失败则返回原因。</constraint>
</constraints>
<tools>
<tool name="browser.open" />
<tool name="browser.click" />
<tool name="browser.type" />
<tool name="browser.extract" />
</tools>
<workflow>
<step>理解用户目标并列出关键信息。</step>
<step>打开目标页面并识别页面状态。</step>
<step>填写或提取数据。</step>
<step>执行提交前校验。</step>
<step>输出执行结果和证据。</step>
</workflow>
<output_schema>
{
"status": "success | failed | need_user_confirmation",
"summary": "string",
"evidence": ["string"],
"next_action": "string"
}
</output_schema>
</agent>
自动优化 system message 的流程不是让模型随便改,而是让优化器 Agent 基于失败用例提出最小改动,然后跑评测集。
sequenceDiagram
participant Eval as 评估系统
participant Attrib as 归因 Agent
participant Opt as 优化器 Agent
participant Test as 回归测试
participant Human as 人工审核
Eval->>Attrib: 失败用例、执行轨迹、评分结果
Attrib->>Opt: 失败原因和修改建议
Opt->>Opt: 修改 system message / rule / skill
Opt->>Test: 提交候选版本
Test-->>Opt: 黄金评测集结果
Test-->>Human: 差异报告
Human-->>Opt: 通过、驳回或要求修改
优化器 Agent 的输入可以设计得很明确:
optimizer_input:
failed_case:
id: browser_form_001
reason: "提交前没有检查必填字段"
current_system_message: "./prompts/browser_agent.xml"
constraints:
- "只能修改 system_message"
- "不能删除安全约束"
- "必须保持输出 schema 不变"
expected_patch:
format: "unified_diff"
输出使用 diff,而不是整段重写,可以降低误改范围:
<workflow>
<step>理解用户目标并列出关键信息。</step>
<step>打开目标页面并识别页面状态。</step>
<step>填写或提取数据。</step>
+ <step>检查所有必填字段是否已填写;若缺失,返回 need_user_confirmation。</step>
<step>执行提交前校验。</step>
<step>输出执行结果和证据。</step>
</workflow>
多 Agent 测试驱动:让 AI 帮 AI 做回归
传统软件可以用测试驱动开发(Test-Driven Development,TDD):先写测试,再改代码,最后跑测试。Agent 也可以采用类似思路,只是测试对象不再只有代码,还包括提示词、规则、工具调用策略和记忆。
一种可落地的多 Agent 分工是:
| 角色 | 职责 |
|---|---|
| Spec Agent | 把需求拆成可测试的 case 和评分标准 |
| Judge Agent | 根据轨迹和结果打分,判断是否通过 |
| Attribution Agent | 解释失败原因,区分 prompt 问题、工具问题、数据问题 |
| Optimizer Agent | 生成 prompt、rule、skill 或 memory 的修改方案 |
| Coding Agent | 修改配置、测试脚本或工具代码 |
| Human Gatekeeper | 审核高风险变更,决定是否发布 |
自动修复不应该一失败就触发。比较稳的策略是设置置信度阈值:
def should_auto_fix(eval_result):
if eval_result.severity == "critical":
return False # 高风险问题进入人工队列
if eval_result.attribution_confidence < 0.85:
return False # 归因不确定,不自动改
if eval_result.failed_case_count < 3:
return False # 单个孤例先观察
if eval_result.safety_related:
return False # 安全相关必须人工审核
return True
自动优化主循环可以抽象成这样:
def evolve_agent(agent_version, failed_cases):
patches = []
for case in failed_cases:
attribution = attribution_agent.analyze(
trace=case.trace,
evaluation=case.evaluation,
current_config=agent_version.config,
)
if not should_auto_fix(attribution):
send_to_human_review(case, attribution)
continue
patch = optimizer_agent.propose_patch(
attribution=attribution,
config=agent_version.config,
constraints=[
"do_not_remove_safety_rules",
"keep_output_schema_stable",
"minimize_diff",
],
)
patches.append(patch)
candidate = apply_patches(agent_version, patches)
report = run_regression_tests(candidate)
if report.pass_rate >= 0.98 and report.no_safety_regression:
create_pull_request(candidate, report)
else:
reject_candidate(candidate, report)
这里的 pull request 不一定是代码仓库里的 PR,也可以是配置发布系统里的候选版本。核心思想是:AI 可以负责执行大量分析和修改工作,人类主要负责高风险审核、标准制定和最终门禁。
强化学习适合哪些 Agent 进化场景
强化学习的思路是:Agent 在环境中执行动作,环境给出奖励,Agent 根据奖励调整策略。它很适合有明确状态、动作和奖励的任务。
| 条件 | 适合强化学习吗 |
|---|---|
| 有可模拟环境 | 适合,例如游戏、网页自动化沙箱、代码修复测试环境 |
| 奖励可自动计算 | 适合,例如测试通过、任务完成、成本降低 |
| 失败成本可控 | 适合,能在离线环境大量试错 |
| 线上动作不可逆 | 不适合直接在线试错,例如支付、删除、发消息 |
| 奖励高度主观 | 难度高,需要人类反馈或 LLM-as-judge 辅助 |
强化学习不是所有 Agent 自动进化的默认答案。很多业务 Agent 更应该先把评测集、轨迹日志、Memory 和 prompt 自动优化做好。只有当任务能模拟、奖励明确、数据规模足够时,再引入 RL 会更稳。
本体论和元认知:让 Agent 知道业务,也知道自己在想什么
Agent 进化不仅是 prompt 变长,还可以从两个方向增强结构化能力。
本体知识库:让 Agent 理解业务世界
本体论在工程里可以理解为“业务对象和关系的结构化描述”。比如退款业务里有这些对象:
classDiagram
class Order {
order_id
status
paid_amount
created_at
}
class Shipment {
shipment_id
shipped_at
signed_at
carrier
}
class RefundPolicy {
window_days
allowed_status
require_manual_review
}
class RefundRequest {
request_id
reason
status
}
Order --> Shipment : has
Order --> RefundRequest : creates
Order --> RefundPolicy : checked_by
有了这样的结构,Agent 不会只凭一个字段做判断,而是知道“订单、物流、退款策略、售后申请”之间的关系。业务越复杂,本体知识库越重要。
元认知:让 Agent 监控自己的思考过程
元认知可以理解为“对思考过程本身的管理”。对 Agent 来说,它至少包含三个动作:
| 动作 | 含义 |
|---|---|
| Plan | 执行前制定计划,列出关键依赖 |
| Monitor | 执行中检查是否偏离目标 |
| Reflect | 结束后复盘哪里成功、哪里失败 |
可以把元认知写进 Agent 的执行协议:
<meta_cognition>
<plan>
在调用工具前,列出任务目标、已知信息、缺失信息和风险点。
</plan>
<monitor>
每次工具调用后,检查结果是否支持下一步动作;如果不支持,重新规划。
</monitor>
<reflect>
任务结束后,输出成功原因、失败原因、可复用经验和不应写入 Memory 的临时信息。
</reflect>
</meta_cognition>
本体知识库解决“业务世界是什么”,元认知解决“Agent 怎样管理自己的推理”。两者结合后,Agent 的进化不再只是积累聊天记录,而是积累结构化知识和可复用策略。
一套可落地的 Agent 进化架构
把前面的能力合起来,可以得到一个相对完整的工程架构。
flowchart TB
subgraph Runtime[线上运行层]
U[用户] --> A[业务 Agent]
A --> T[工具系统]
T --> A
A --> U
end
subgraph Data[数据层]
A --> L[轨迹日志库]
U --> F[用户反馈库]
A --> M[Memory Store]
end
subgraph Eval[评估层]
L --> R[规则评估器]
L --> J[LLM-as-judge]
F --> J
R --> S[评分与失败用例库]
J --> S
end
subgraph Optimize[优化层]
S --> G[失败归因 Agent]
G --> O[优化器 Agent]
O --> P[Prompt/Rule/Skill Patch]
O --> M
end
subgraph Release[发布层]
P --> E[黄金评测集]
E --> Q{通过门禁}
Q -- 否 --> G
Q -- 是 --> H[人工审核]
H --> V[新版本发布]
V --> A
end
各模块的职责要清楚,否则系统会变成“到处都在记录,到处都没人负责判断”。
| 模块 | 产物 | 关键要求 |
|---|---|---|
| 轨迹日志库 | prompt、上下文、工具调用、输出 | 可追溯、可脱敏、可复现 |
| 用户反馈库 | 点赞、踩、纠错、取消、补充说明 | 反馈要绑定具体任务和步骤 |
| 评估层 | 分数、失败原因、严重程度 | 规则评估和 LLM 评估结合 |
| 失败归因 | prompt 问题、工具问题、数据问题、安全问题 | 归因要有置信度 |
| 优化器 | diff、memory 写入、评测 case | 最小改动,不破坏安全规则 |
| 发布门禁 | 回归报告、人工审核结果 | 高风险变更不能自动上线 |
哪些场景适合自动进化,哪些不适合
Agent 自动持续进化不是越自动越好。场景频率、错误成本、评估难度会决定自动化程度。
| 场景 | 适合程度 | 原因 |
|---|---|---|
| 代码生成助手 | 高 | 可以用单元测试、构建、静态扫描做自动评估 |
| 网页自动化测试 Agent | 高 | 有浏览器沙箱,任务轨迹完整,结果可校验 |
| 数据查询 Agent | 中高 | SQL 可执行校验,但要严格处理权限和数据安全 |
| 客服问答 Agent | 中 | 用户反馈丰富,但语义评估和口径一致性难 |
| 金融交易 Agent | 低 | 错误成本高,高风险动作必须人工确认 |
| 医疗诊断 Agent | 低 | 评估复杂且风险高,自动改策略需要强监管 |
| 低频内部工具 | 低 | 数据量不足,自动优化容易被偶然样本带偏 |
低频、伪需求或用户不稳定的 Agent,很难形成健康的数据飞轮。系统还没积累足够反馈,需求本身可能已经变化,这种情况下不应过度建设自动进化系统。
常见坑
只改 prompt,不建评测集
没有评测集的 prompt 优化,很容易变成“修好一个 case,改坏十个 case”。黄金评测集至少要覆盖核心路径、边界路径、历史失败路径和安全路径。
Memory 写入太随意
错误结论一旦进入长期 Memory,后续任务会持续受污染。Memory 写入要有来源、置信度、作用域和过期策略。
LLM-as-judge 过度自信
评审模型可能误判,尤其在复杂业务规则、长上下文、多轮工具调用里。关键任务要用程序化规则、人工抽检和多模型交叉评估兜底。
自动修复没有最小变更约束
优化器如果每次重写整段 system message,很难定位问题,也容易引入新风险。使用 diff、约束模板和回归测试更稳。
把人工完全移出闭环
Human-in-the-loop 不是落后做法。对高风险任务,人类应该从“执行者”变成“守门员”和“裁判”:不必亲手改每个 prompt,但要制定规则、审核高风险变更、处理低置信度归因。
一条实践路线
从零开始做 Agent 自动持续进化,可以按这个顺序落地:
- 记录完整轨迹:用户目标、prompt、上下文、工具调用、输出、反馈;
- 定义核心指标:成功率、人工干预率、工具错误率、成本、时延、安全违规;
- 建黄金评测集:核心 case、边界 case、历史失败 case;
- 引入 LLM-as-judge:只负责语义评分,不替代规则校验;
- 建 Memory 门禁:明确哪些信息能写、写到哪里、多久失效;
- 让优化器生成最小 patch:优先改 Rule、Skill、system message;
- 跑回归测试:不过门禁不发布;
- 人工审核高风险变更;
- 把线上失败继续回灌到评测集和 Memory。
Agent 的持续进化不是某一个神奇模块,而是一套工程闭环。评估让系统知道好坏,反馈让系统知道方向,Memory 让经验可复用,自动优化让修复成本下降,回归测试和人工门禁让进化不失控。只有这些环节连起来,Agent 才能从“首版能跑”走向“越用越稳”。