Agent 为什么不能只保存最终答案:从游戏验证项目讲 Trace、Evidence 与可回放性
从游戏变更验证 Agent 的文件化工作流出发,解释为什么 Agent 系统需要记录模型调用、状态变化、候选历史、工具证据与失败样本,以及 Trace、Evidence、Checkpoint 和 Replay 之间的区别。
普通的 LLM 应用很容易只关心两个东西:
Input
↓
Model
↓
Output
用户问了什么,模型最后回答了什么。
如果只是聊天,这通常已经足够。
但 Game Change Verification Agent 的一次运行可能经历:
Requirement Agent
↓
Candidate
↓
确定性校验
↓
人工授权
↓
Baseline Engine Run
↓
Candidate Engine Run
↓
Telemetry
↓
Quality Review Agent
↓
Policy Gate
↓
Repair
↓
重新运行
最终如果只留下:
status = accepted
其实会丢掉大部分真正重要的信息。
例如面试官或者开发者继续问:
为什么最后接受了这个 Candidate?
Quality Review Agent 当时看到了哪些证据?
模型真正返回的是什么,Policy Gate 又把它解释成了什么?
第二轮 Candidate 和第一轮相比改了哪里?
峰值子弹从多少变成多少?
是模型自己改了数值,还是确定性 Repair Tool 改的?
如果流程失败,到底失败在模型调用、JSON 解析、静态校验、Unity,还是 Policy Gate?
如果系统回答不了这些问题,那么 Agent 即使最后“跑成功了”,也很难真正调试。
所以这个项目没有把一次 Agent Workflow 当成一段执行完就消失的函数调用。
而是为每个 Workflow 创建一个独立目录,把:
输入
状态
模型调用
候选版本
验证结果
引擎证据
修复历史
失败信息
最终决策
分别保存下来。
这篇文章就从这套设计出发,解释我对 Agent Trace、Evidence 和“可回放”这几个概念的理解。
项目地址:theHerta27/game-change-verification-agent
为什么最终结果远远不够
假设 Agent 最终给出的结论是:
{
"decision": "accept"
}
从业务结果看:
完成了
但这几乎无法帮助我们判断这个 Agent 到底靠不靠谱。
因为下面两种流程最终都可能得到 accept。
第一种:
真实 Telemetry 全部达标
↓
Quality Review Agent 正确读取证据
↓
Policy Gate 一致
↓
accept
第二种:
Telemetry 某项其实没通过
↓
模型看漏了
↓
直接说 accept
最终字符串都是:
accept
但意义完全不同。
所以 Agent 系统不能只记录:
最后决定了什么。
还要记录:
这个决定是怎样形成的。
一次 Workflow 本身就是一个可检查对象
创建 Workflow 时,项目会生成独立:
workflow_id
例如:
bullet_20260909_123456_a1b2c3d4
随后创建对应目录。
里面不是只存一个:
result.json
而是逐步产生很多 Artifact。
例如:
requirement.json
structured_goal.json
baseline_config.json
candidate_config.json
candidate_history.json
config_diff.json
validation_results.json
feasibility_gate.json
model_evidence.json
agent_runs.json
quality_reviews.json
repair_history.json
baseline_telemetry.json
candidate_telemetry.json
comparison_report.json
workflow_manifest.json
badcases.json
这些文件其实在回答不同问题。
可以粗略分成几组。
第一组:输入到底是什么
首先保存:
requirement.json
记录原始自然语言需求。
例如:
第二阶段改成更密集的双向螺旋弹幕,
但峰值存活子弹不能超过 350,
低分位 FPS 不能低于 55。
然后:
baseline_config.json
保存这次 Workflow 开始时使用的 Baseline。
为什么 Baseline 也必须保留?
因为如果几天以后正式:
baseline.json
已经发生修改,仅仅保存:
Candidate
就无法再准确知道:
它当时究竟是在什么基础上生成的?
所以:
Requirement
+
Baseline Snapshot
共同定义了这次任务的初始上下文。
第二组:模型到底理解成了什么
Requirement Agent 并不是直接从:
自然语言
跳到:
Unity
中间还会产生:
structured_goal.json
以及:
candidate_config.json
前者表示:
模型怎样理解用户目标。
后者表示:
模型根据这个理解提出了什么具体 Candidate。
这样以后如果 Candidate 有问题,可以继续区分:
需求理解错了?
还是
需求理解对了,但生成配置错了?
如果只保存最终 Candidate,这两个问题就混在一起了。
第三组:Candidate 为什么允许进入执行阶段
模型输出以后还有:
validation_results.json
里面保存:
Schema
Reference
Rule Engine
Safety Gate
对应的验证结果。
另外:
feasibility_gate.json
记录当前 Candidate:
accepted
还是:
blocked
以及具体原因。
因此一次执行不是:
Agent Output
→ Engine
而是可以还原成:
Agent Output
↓
Validation Evidence
↓
Gate Decision
↓
是否允许继续
这就是 Trace 和安全边界结合的地方。
不是只知道:
它被挡住了
而是知道:
被哪一层挡住,以及为什么。
workflow_manifest.json 更像整条流程的目录
项目还有一个核心文件:
workflow_manifest.json
它不会保存所有具体业务数据。
而是记录 Workflow 的整体状态。
例如:
{
"workflow_id": "...",
"provider": "openai_compatible",
"engine": "unity",
"status": "running_candidate",
"authorization": {...},
"budget": {
"max_unity_runs": 3,
"max_model_calls": 4,
"unity_runs_used": 1,
"model_calls_used": 2
},
"current_iteration": 1,
"final_decision": null,
"error": null,
"timeline": [...]
}
所以 Manifest 主要回答:
现在跑到哪里了?
用了多少预算?
有没有授权?
当前第几轮?
有没有失败?
最终有没有人工决策?
而详细 Candidate、Telemetry、Review 等内容再去对应 Artifact 中查看。
可以理解成:
workflow_manifest.json
↓
整次运行的索引和状态
其他 *.json
↓
每一个阶段的详细证据
Timeline 为什么和日志不完全一样
Manifest 里维护:
timeline
每一次重要状态变化都会添加:
{
"step": step,
"status": status,
"timestamp": _utc_now(),
"detail": detail,
}
例如:
Requirement structured
→ completed
Bullet Hell Feasibility Gate
→ accepted
Candidate engine run
→ running
Candidate engine run
→ completed
Quality Review Agent
→ repair
Bounded repair policy
→ REDUCE_BULLETS_PER_WAVE
这和普通:
print("running")
不同。
Timeline 保存的是:
业务状态转换。
普通日志更容易回答:
某行代码发生了什么
Timeline 更接近:
这次 Agent Workflow 在业务意义上经过了哪些阶段。
所以对于状态机类型 Agent,我觉得:
Application Log
和:
Workflow Trace
最好不要完全混成一件事。
agent_runs.json 专门记录模型调用
模型调用本身又单独保存到:
agent_runs.json
每次记录包括:
agent_name
prompt_name
provider
model
latency_ms
usage
token_estimate
status
model_call
input_artifacts
output_artifacts
iteration
例如 Requirement Agent:
{
"agent_name": "requirement_agent",
"prompt_name": "bullet_hell_requirement_agent",
"provider": "openai_compatible",
"model": "...",
"latency_ms": 1300,
"status": "succeeded",
"model_call": true,
"input_artifacts": [
"requirement.json",
"baseline_config.json"
],
"output_artifacts": [
"structured_goal.json",
"candidate_config.json"
]
}
Quality Review Agent 还会额外记录:
iteration
这样可以知道:
这次模型调用属于第几轮修复。
为什么记录 Input Artifacts,而不是只记录 Prompt 字符串
例如 Quality Review Agent 的输入来自:
requirement.json
structured_goal.json
config_diff.json
comparison_report.json
repair_history.json
这些名字会写进 Agent Run:
input_artifacts=[
"requirement.json",
"structured_goal.json",
"config_diff.json",
"comparison_report.json",
"repair_history.json",
]
这相当于保存了一条:
数据依赖关系。
可以读成:
Quality Review Agent 第 2 轮决策
依赖:
Requirement
Structured Goal
当前 Config Diff
当前 Comparison Report
之前 Repair History
而输出:
quality_reviews.json
这样以后检查一次错误 Decision 时,不只是知道:
模型说错了
还可以继续问:
它当时到底依据了哪些 Artifact?
Token 和 Latency 为什么也属于 Agent Trace
项目还记录:
latency_ms
usage
token_estimate
这些看起来更像:
性能监控
但对于 Agent Workflow 来说,它们也和行为有关。
假设:
一次 Requirement Agent
+
三次 Quality Review Agent
理论最大:
4 次模型调用
如果突然某次 Workflow 产生:
12 次模型调用
就意味着:
循环预算可能失效
或者调用路径发生异常。
同样,如果某个模型调用:
平时 2 秒
突然变成:
30 秒
即使最终成功,也会直接影响整条 Agent Workflow 的体验。
所以 Agent Observability 不只是:
模型回答对不对
还应该看到:
调用了几次
用了多久
消耗多少
在哪一轮发生
quality_reviews.json 为什么同时保存 Agent Output 和 Policy Gate
Quality Review 最终记录的不是单纯:
{
"decision": "repair"
}
而是:
agent_output
+
policy_gate
+
deterministic_evaluation_passed
例如:
{
"iteration": 1,
"agent_output": {
"decision": "repair",
"repair_action": "REDUCE_BULLETS_PER_WAVE",
"reason": "...",
"evidence_refs": [...]
},
"policy_gate": {
"passed": true,
"effective_decision": "repair",
"effective_action": "REDUCE_BULLETS_PER_WAVE",
"expected_action": "REDUCE_BULLETS_PER_WAVE"
},
"deterministic_evaluation_passed": false
}
为什么不直接保存:
effective_decision
因为:
模型建议和系统最终采用的动作是两个不同事实。
如果模型说:
REDUCE_BULLET_SPEED
但 Policy Gate 认为:
Expected =
REDUCE_BULLETS_PER_WAVE
最终可能:
effective_decision =
human_review
如果只保存最终 Decision:
human_review
以后就看不到:
为什么触发人工复核?
保留两份信息以后才能看到:
模型怎么想
↓
程序策略怎么判断
↓
最终真正做什么
这对调试 Agent 特别重要。
Trace 最重要的价值之一,就是不要让系统“偷偷纠错”
假设模型建议错了。
一种系统设计可以:
Agent:
REDUCE_BULLET_SPEED
程序发现不对
↓
偷偷替换成
REDUCE_BULLETS_PER_WAVE
↓
运行成功
从最后结果看:
成功
甚至 Benchmark 看起来也不错。
但这会隐藏一个真正的问题:
Agent 本身做出了错误 Decision。
Game Change Agent 当前不会这么做。
Policy Gate 冲突时:
human_review
而且两边信息都保存在:
quality_reviews.json
中。
所以 Trace 不只是为了:
以后查 Bug
它还防止系统通过隐藏中间错误制造虚假的“最终成功率”。
evidence_refs 又解决了什么
Quality Review Agent 的输出要求:
evidence_refs: list[str]
例如:
comparison_report.json.evaluation.checks
这让模型的:
reason
不只是:
我觉得应该修复。
而是尽量指向:
我依据哪份 Evidence 做出这个判断。
当然,这还不是一种形式化证明。
一个字符串引用本身不能保证模型真的正确阅读了那份证据。
但至少系统开始要求:
Decision
+
Reason
+
Evidence Reference
而不是只保留:
Decision
这让后续人工检查和 Eval 更容易进行。
Engine Evidence 为什么也要单独保存
Agent 的决策不只依赖模型。
真正关键的 Observation 来自 Unity / UE5。
所以 Workflow 保存:
baseline_telemetry.json
candidate_telemetry.json
以及引擎层验证后的:
baseline_engine_evidence.json
candidate_engine_evidence.json
最终再生成:
comparison_report.json
它们分别承担不同层次。
Raw / Normalized Telemetry
→ 引擎实际产生了什么
Engine Evidence
→ 这份运行结果是不是完整可信
Comparison Report
→ Baseline 和 Candidate 相比结果如何
所以 Agent 下一轮真正使用的不是一句:
Unity 跑完了
而是一条证据链。
Evidence 必须能回答“属于哪次 Action”
在外部执行系统里,一个很危险的问题是:
现在看到的 Telemetry 真的是刚才这个 Candidate 产生的吗?
如果运行目录里残留一份旧:
telemetry.json
而新进程没有正确输出结果。
系统如果只是:
文件存在
→ 成功
就可能把旧结果当成新证据。
项目的 EngineRunner 因此还会结合:
config hash
run id
variant
固定路径
验证 Evidence。
这实际上是在建立:
Action
↓
Execution
↓
Evidence
之间的绑定。
否则 Trace 虽然保存得很多:
却可能串错了不同运行的证据
那反而更加危险。
candidate_history.json 为什么不能只保存最后一个 Candidate
假设第一轮:
peak_alive_bullets = 420
于是执行:
REDUCE_BULLETS_PER_WAVE
第二轮变成:
peak_alive_bullets = 330
如果 Workflow 每次都直接覆盖:
candidate_config.json
最后只剩:
Candidate V2
就很难知道:
V1 到底是什么?
为什么改?
改完有没有改善?
因此还有:
candidate_history.json
初始保存:
{
"iteration": 0,
"source": "initial_proposal",
"config": {...}
}
每次 Engine Run 以后继续加入:
{
"iteration": 1,
"source": "unity_evidence",
"config": {...},
"evaluation": {...}
}
于是 Candidate 不再只是:
当前值
而拥有版本历史。
repair_history.json 和 Candidate History 有什么区别
两者看起来都在记录修改。
但关注点不同。
candidate_history.json 记录:
每轮 Candidate 当时是什么,以及评估结果怎样。
而:
repair_history.json
记录:
从这一轮到下一轮为什么修改,以及执行了什么 Repair。
例如:
{
"iteration": 1,
"action": "REDUCE_BULLETS_PER_WAVE",
"applied": true,
"before": 30,
"after": 22,
"reason": "..."
}
所以:
Candidate History
→ 状态历史
Repair History
→ 状态转换历史
这和数据库中:
Snapshot
与:
Event
有一点类似的直觉。
为什么修复历史必须进入下一轮 Agent 输入
Quality Review Agent 每轮都会收到:
repair_history
而不是只看当前 Candidate。
为什么?
因为两个状态看起来完全相同的 Workflow,历史可能不同。
例如:
当前 FPS = 50
场景 A:
还没有修过
场景 B:
已经连续两次降低弹幕数量
仍然 FPS = 50
显然第二种情况下继续:
再降低一点
未必合理。
历史本身就是决策上下文。
所以 Agent State 不是只有:
Current State
还可能需要:
Relevant History
Trace 一旦保存下来,就可以有选择地重新注入下一轮决策。
“可回放”到底是什么意思
这里我不想把 Replay 说得太神奇。
Game Change Agent 当前所谓的可回放,更准确地说是:
一次 Workflow 的关键输入、中间状态、模型调用信息、Candidate、Telemetry、Evaluation、Repair 和最终 Decision 都有持久化 Artifact,因此事后可以重新检查这条决策链。
例如看到:
Iteration 2
Quality Review Agent
→ repair
可以回头读取:
requirement.json
structured_goal.json
candidate_history.json
comparison_report.json
repair_history.json
quality_reviews.json
重新还原当时的大部分决策上下文。
这是一种:
审计和复盘意义上的 Replay。
Replay 不等于“重新调用模型一定得到同样输出”
如果今天重新用同一个 Prompt 调一次真实 LLM:
Input 一样
也不能保证:
Output 字节级完全一样
原因可能包括:
模型本身具有随机性
模型版本变化
Provider 后端变化
采样参数
所以真正可靠的 Replay 不能依赖:
重新请求一次模型,
希望它说同样的话
更可靠的是直接保存:
当时真正得到的 Agent Output
以及:
它依据的 Evidence
因此:
可回放更重要的是保存过去实际发生过什么,而不是假设未来可以重新生成过去。
Engine Replay 为什么反而更容易做得稳定
相比 LLM,项目里的 Runtime 更强调:
固定随机种子
固定时间步
固定玩家轨迹
固定运行时长
Baseline 和 Candidate 使用相同:
seed = 20260727
这让:
Engine Observation
尽量具有可重复性。
所以项目同时存在两类不同的 Replay 思路。
LLM 部分
重点:
保存真实 Output 和 Evidence
Engine 部分
重点:
固定执行条件,
尽量让重新运行结果可比较
两者不能混为一谈。
badcases.json 为什么是 Agent 开发特别重要的文件
如果 Agent 失败,项目不会只:
raise Exception
还会生成 Badcase。
例如 Requirement Agent 出错时保存:
workflow_id
stage
error_type
error_message
raw_model_output
provider
model
Quality Review Agent 出错还会记录:
iteration
例如模型返回了:
JSON 语法错误
可以保存原始:
raw_model_output
以后分析。
这对 Agent 调试非常重要。
普通程序 Bug 可能通过:
stack trace
定位。
但 Agent Failure 还可能来自:
模型误解 Prompt
输出格式错误
模型字段遗漏
Provider 返回异常
模型决策与 Policy 冲突
这些问题单靠 Python Stack Trace 不够。
所以 Badcase 本身就是 Agent Evaluation 的原始材料。
为什么“失败样本”可能比成功样本更有价值
假设:
100 次运行
97 次成功
3 次失败
只看:
97% 成功率
当然有意义。
但真正改善 Agent 时,更需要看那三个:
为什么失败?
例如三次分别是:
1. JSON Parse Error
2. Agent Repair Action 与 Policy 冲突
3. Evidence 缺失
对应的改进方向完全不同:
Schema / Structured Output
Prompt / Decision Quality
Tool / Runtime Reliability
所以项目中不仅保存:
metrics
也保留:
badcases
这是我现在觉得做 Agent Eval 时特别重要的一点:
Aggregate Metric 告诉你系统好不好,Badcase 告诉你为什么不好。
Trace 还能帮助区分“模型问题”和“系统问题”
假设最后 Workflow:
blocked
如果没有 Trace,很容易一句:
模型又失败了。
但实际可能完全不是模型问题。
例如:
Requirement Agent
→ succeeded
Candidate Validation
→ passed
Unity
→ failed to launch
这显然是:
Runtime / Tool Problem
而不是:
Agent Reasoning Problem
也可能:
Unity → success
Evaluation → failed
Quality Review Agent → correct repair
Policy Gate → passed
Repair Tool → failed to apply
这又属于:
Tool Implementation Problem
所以 Agent 系统的 Observability 应该能把失败定位到:
Model
Validation
Tool
Environment
Policy
Workflow
不同层次。
否则所有错误最后都会被模糊成:
“AI 不稳定。”
Trace 和传统后端日志有什么区别
传统服务里,我们经常有:
Request ID
HTTP Status
Latency
SQL Error
Agent 系统仍然需要这些东西。
但还多了一类:
决策过程数据。
例如:
Prompt Name
Model
Agent Output
Evidence Refs
Iteration
Policy Gate
Repair Action
State Transition
普通 HTTP 服务一般不会问:
这个 Handler 为什么决定调用这个数据库函数?
业务规则写死在代码里。
但 Agent 的一部分 Decision 来自模型。
因此:
模型决策本身也变成了一种需要观测的数据。
这就是我理解 Agent Observability 和普通 Application Logging 最大的区别之一。
Trace 不是越多越好
既然 Trace 有用,是不是把:
所有 Prompt
所有 Context
所有原始文件
所有日志
所有用户输入
全部永久保存最好?
也不是。
首先会遇到:
存储成本
然后是:
隐私
敏感信息
Prompt 中可能出现的业务数据
还有:
大量无关 Trace
反而更难定位问题
所以更合理的是先明确:
为了调试、审计和复现,我真正需要留下哪些事实?
这个项目目前主要保存的是:
Artifact
状态
模型元数据
Agent Output
Evidence
Error
而不是试图录制整个机器的一切行为。
为什么 Artifact 读取还要白名单
Workflow 暴露 Artifact 时并不会接受:
任意文件路径
而是明确允许:
requirement.json
structured_goal.json
candidate_config.json
candidate_history.json
comparison_report.json
repair_history.json
workflow_manifest.json
agent_runs.json
quality_reviews.json
...
如果名称不在:
allowed
集合里,就拒绝。
这说明:
可观测性接口本身也不能变成任意文件读取接口。
Trace 是为了让系统更透明。
不能因为:
为了方便 Debug
就顺手破坏原来的数据访问边界。
文件化状态和 LangGraph Checkpoint 是不是一回事
不是完全一回事。
这个项目当前自己实现的是:
File-backed Workflow
也就是把:
Manifest
Candidate History
Repair History
Agent Runs
Evidence
写入 JSON 文件。
这样即使 HTTP 请求本身早就结束,后面仍然可以通过:
workflow_id
重新查询这些状态和 Artifact。
但我不会把它直接描述成:
实现了 LangGraph Checkpoint。
因为 LangGraph Checkpoint 是框架里的具体持久化和执行恢复机制。
当前项目没有使用 LangGraph 来运行这条主流程。
所以更准确的说法是:
项目实现了显式的文件化 Workflow State 和 Trace 持久化,它和 Checkpoint 解决的问题有重叠,但不是在使用 LangGraph Checkpointer。
当前文件化状态能不能做到“进程崩溃后从任意节点自动续跑”
也不能直接这样声称。
项目确实会持续:
_write_manifest()
_save(...)
保存运行状态。
但当前代码的主要目标是:
检查状态
获取 Artifact
保留 Evidence
复盘 Workflow
而不是实现一个通用的:
进程在第 2 轮任意一行崩溃
重启以后自动从准确 Node 恢复
的 Workflow Engine。
所以:
State Persistence
和:
Automatic Execution Recovery
要区分开。
这是写简历和面试时很重要的边界。
那真正的 Checkpoint 还需要解决什么
如果未来要实现真正更完整的 Checkpoint / Resume,至少需要继续考虑:
当前 Node 是否已经执行?
Tool 有没有产生副作用?
结果有没有成功持久化?
崩溃发生在 Tool 前还是 Tool 后?
重新执行会不会重复副作用?
下一条 Edge 应该从哪里继续?
例如:
Unity 已经运行成功
↓
Telemetry 已写出
↓
进程在更新 Manifest 前崩溃
重启以后只看:
status = running_candidate
到底应该:
重新运行 Unity
还是:
复用已经存在的 Telemetry
这已经涉及:
Tool Idempotency
Atomic State Transition
Checkpoint Consistency
所以 Checkpoint 并不只是:
定期保存一个 JSON。
它和整个执行语义有关。
“可回放”为什么和确定性 Tool 很搭
Game Change Agent 一个很重要的设计是:
LLM 负责选择有限意图
确定性代码负责计算精确修改
比如:
REDUCE_BULLETS_PER_WAVE
真正的:
before → after
由 apply_repair() 根据 Evaluation 算。
这意味着如果保存:
Candidate Before
Action
Evaluation
就能重新检查:
Deterministic Repair 是否应该得到相同的新 Candidate。
相比:
让 LLM 自己重新算一次数值
这种行为更容易测试和复盘。
所以:
想让 Agent 更可回放,一个有效办法就是尽量把可确定的执行逻辑留给确定性 Tool。
测试也应该验证 Trace,而不只是验证最终状态
项目测试中不会只写:
assert completed["status"] == "evidence_ready"
还会进一步检查:
assert [
run["agent_name"]
for run in completed["agent_runs"]
] == [
"requirement_agent",
"quality_review_agent",
]
如果发生自动修复:
assert (
completed["repair_history"][0]["action"]
== "REDUCE_BULLETS_PER_WAVE"
)
还会检查最后 Candidate History:
evaluation passed
也就是说测试不仅关心:
最后成功
还关心:
它是不是沿着预期路径成功
这也是 Agent 测试和普通函数测试的一个有趣区别。
为什么“路径正确”也值得成为测试条件
假设两个系统最后都:
evidence_ready
系统 A:
第一轮失败
→ 正确 Repair
→ 第二轮通过
系统 B:
第一轮失败
→ Agent 错误 accept
→ 某个 Bug 让状态仍然 evidence_ready
只检查 Final Status:
二者一样
检查:
Quality Review
Policy Gate
Repair History
Candidate History
才能发现差别。
所以对于 Agent Workflow:
正确性不只是最终状态正确,还包括关键决策路径没有绕过边界。
面试时我会怎样回答
如果面试官问:
你简历里说 Agent 调用和运行证据可回放,具体是什么意思?
我会回答:
我的主流程是 file-backed workflow。每个 workflow_id 都有独立目录,不只保存最终结果,还会持久化原始 requirement、structured goal、baseline/candidate snapshot、config diff、validation result、candidate history、repair history、agent runs、quality reviews、engine telemetry、comparison report 和 workflow manifest。
agent_runs.json会记录每次 Requirement Agent / Quality Review Agent 使用的 provider、model、prompt、latency、token usage、输入输出 Artifact 和 iteration;quality_reviews.json同时保存模型原始 Decision 和确定性 Policy Gate 的最终 Decision,所以可以区分“模型怎么判断”和“系统最后执行了什么”。所以这里的可回放主要指事后能够沿 Artifact 重新检查一次决策链,而不是说重新请求同一个 LLM 一定得到完全相同输出。
如果继续问:
这是不是 LangGraph Checkpoint?
我会回答:
不是。我这条主流程没有用 LangGraph,而是自己把 Workflow State 和 Evidence 持久化到文件。它和 Checkpoint 在“保存执行状态”这个问题上有相似性,但我不会把它包装成 LangGraph Checkpointer,也没有声称已经实现任意崩溃点的自动续跑。
如果继续问:
Trace 为什么要记录模型 Output 和 Policy Gate 两份结果?
我会回答:
因为模型建议和真正允许执行的动作是两个不同事实。如果模型建议和确定性失败路由冲突,系统会转 human_review。如果只保存最终 human_review,就不知道冲突从哪里来的;保留 Agent Output 和 Policy Gate 才能分析到底是 Prompt、模型还是确定性策略存在问题。
如果继续问:
为什么还要保存 Badcase?
我会回答:
Aggregate Metric 只能告诉我系统整体表现怎么样,Badcase 才能告诉我为什么失败。Agent 的失败可能发生在 JSON Parse、Schema、模型决策、Provider、Engine 或 Policy Gate,不保留 stage、raw model output、error type 等信息,就很容易把所有问题都归成一句“模型不稳定”。
我从这个问题中理解到的事情
以前我会把:
Agent Memory
Trace
Checkpoint
Log
这些词混在一起。
真正实现以后,我觉得它们关注的问题其实不完全相同。
State
→ 系统现在是什么状态
History
→ 系统以前经过了哪些状态
Trace
→ 一次执行到底经过了哪些决策和动作
Evidence
→ 每个结论依据的事实是什么
Log
→ 程序运行过程中发生了什么事件
Checkpoint
→ 保存到什么程度,才能在执行中断后继续
Replay
→ 以后能不能重新检查或重现一次执行过程
在 Game Change Agent 当前实现里,最明确做到的是:
File-backed State
+
Structured Trace
+
Evidence Persistence
+
Candidate / Repair History
+
Badcase Recording
它让我可以从最后:
accepted
一路向前问:
为什么 accepted?
↓
Quality Review 说了什么?
↓
Policy Gate 怎么判断?
↓
当时哪些指标通过?
↓
Telemetry 是什么?
↓
当前 Candidate 是怎么来的?
↓
上一轮修了什么?
↓
最初 Requirement 又是什么?
而不是只能看到:
Agent 最后说:“完成了。”
我现在觉得,这也是 Agent 从 Demo 走向工程系统以后很重要的一步。
普通聊天允许:
答案看起来合理
很多时候就够用了。
但一个真正会调用工具、修改状态、消耗资源甚至触发外部动作的 Agent,需要能够回答:
这件事到底是怎么发生的?
如果它自己都不能留下这条证据链,就很难:
调试
测试
评估
审计
改 Prompt
比较模型
定位 Badcase
所以 Trace 的价值并不是让 Agent 看起来更“高级”。
它解决的是一个很朴素的工程问题:
当 Agent 做对或者做错一件事以后,我能不能知道为什么。
而我觉得真正值得追求的可回放,也不是:
再运行一次,希望模型碰巧重复昨天的答案。
而是:
把当时真正发生的输入、决策、动作和证据留下来,让以后的人能够重新沿着这条路径检查。
这才是我在这个项目里对 Agent Trace 和 Evidence 最直接的理解。
延伸阅读
- LangGraph:Persistence / Checkpoints
- OpenTelemetry:Tracing
- OpenAI:Tracing and Agent Observability
- Anthropic:Building Effective Agents