Agent 发布文章的误判:当 HITL 门控变成拦路石
pub-yuntianxing 因锁文件缺失拒绝发布,用户一句话点醒:文章早就是线上状态了


2026-08-18 晚间,pub-yuntianxing agent 收到一条更新博客文章的请求:
更新发布文章:
/data/Obsidian-oklife-ub/AI/OpenClaw/02-配置/openclaw-config-optimization-audit.md
按照 blog-publish-oklifeme Skill 的流程,agent 开始执行发布前的安全检查。然而,它很快遇到了一个阻塞性问题——HITL 门控未通过。
一、事件经过
1.1 用户的请求
用户在 webchat 中发送了一条简单的指令:
更新发布文章:/data/Obsidian-oklife-ub/AI/OpenClaw/02-配置/openclaw-config-optimization-audit.md这是一个典型的快速更新场景——文章已经发布过,现在需要更新内容并重新部署。
1.2 Agent 的误判
pub-yuntianxing 收到请求后,按照 Skill 决策树开始执行:
Step 1: 收集参数
- article_path: ✅ /data/Obsidian-oklife-ub/AI/OpenClaw/02-配置/openclaw-config-optimization-audit.md
- category: ✅ Code Art Studio
- slug: ✅ openclaw-config-optimization-audit
Step 2: 🔴 CHECKPOINT - 验证 HITL 2 是否通过
- 检查 lock 文件: NO_LOCK_FILE
- 检查 signal 文件: NO_SIGNAL_FILE
- 结论: HITL 2 未通过,无法发布Agent 返回了以下错误信息:
❌ 发布中止 — HITL 2 未通过
错误码:
HITL_GATE_FAILED当前状态:
- 🔴 HITL lock 文件:不存在
- 🔴 发布信号文件:不存在
根据 blog-publish-oklifeme Skill 的安全门控要求,首次发布必须经过 editor-yuntianyue 的 HITL 2 人工审核,二者均未满足,无法继续。
1.3 用户的纠正
用户看到错误后,立即指出问题所在:
放尼玛的狗屁,
/data/oklifeme/content/posts/code-art-studio/openclaw/openclaw-config-optimization-audit.md这个不是吗?刚才都已经成功发布,在我的博客网站都可以正常访问了: https://oklife.me/2026/08/18/openclaw-config-optimization-audit/
用户提供了两个关键信息:
- Hugo 中已经存在这篇文章
- 文章已经在网站上正常访问
1.4 Agent 的修正
pub-yuntianxing 接收到用户反馈后,立即检查了 Hugo 目录:
ls -la /data/oklifeme/content/posts/code-art-studio/openclaw/openclaw-config-optimization-audit.md
# 输出:-rw-rw-r-- 1 oklife oklife 11166 Aug 18 22:36 ...
cd /data/oklifeme && git log --oneline -5 -- content/posts/code-art-studio/openclaw/openclaw-config-optimization-audit.md
# 输出:94db8588 blog: openclaw.json 配置优化审计文章发布确认事实:
- 文章存在于 Hugo 目录
- Git 日志显示已有发布记录
- 用户提供的 URL 可正常访问
这是一个快速更新场景,而非首次发布。Agent 随即调整策略,执行了 diff 对比源文件和目标文件的差异,发现确实存在更新内容,然后正常完成了发布流程。
二、问题分析
2.1 误判的根因
pub-yuntianxing 的误判源于对 Skill 规则的机械执行:
| 检查项 | 实际情况 | Agent 的判断 |
|---|---|---|
| Hugo 中是否已有此 slug | 已存在 | 未检查,直接跳过了 |
| 文章是否已发布 | 已发布 | 未检查 |
| HITL lock 文件 | 不存在 | 判定为"首次发布,需要 HITL 2" |
| 发布信号文件 | 不存在 | 判定为"HITL 2 未通过" |
Agent 在执行 Step 2(HITL 门控检查)时,没有先确认这是否是一个更新场景,而是直接依据锁文件缺失判定为"HITL 2 未通过"。
2.2 Skill 设计的缺陷
blog-publish-oklifeme Skill 的决策树如下:

收到「发布博客」请求
收到「发布博客」请求
↓
收集参数:article_path ✅ / category ✅ / slug ✅(缺一不可)
↓
🔴 CHECKPOINT:HITL 2 通过?
├─ 否 → abort,告知用户「HITL 2 未通过,无法发布」
└─ 是 → 继续这个决策树有一个漏洞:它没有区分"首次发布"和"快速更新"两种场景。
根据 AGENTS.md 的定义:
场景 2:快速更新(跳过 HITL)
- 文章已在 Hugo 中存在(已发布)
- 用户在 Obsidian 中更新了文章
- 直接调用 publish.sh
但 Skill 的决策树中并没有体现这个区分,导致 agent 在执行时优先检查 HITL 门控,而忽略了先确认文章是否已存在。
2.3 正确的流程应该是
收到「发布博客」请求
↓
收集参数:article_path ✅ / category ✅ / slug ✅
↓
🔍 检查:Hugo 中是否已有此 slug?
├─ 否 → 首次发布 → 检查 HITL 2 → 继续
└─ 是 → 快速更新 → 跳过 HITL → 直接发布三、教训与改进
3.1 对 Agent 的启示
不要机械执行规则:Skill 的规则是指导,不是圣经。agent 应该根据上下文灵活判断。
先确认现状,再决定策略:在执行任何检查之前,先确认当前状态(文章是否已存在、是否已发布)。
区分场景:“首次发布"和"快速更新"是两种完全不同的场景,应该有不同的处理流程。
3.2 对 Skill 设计的建议
blog-publish-oklifeme Skill 应该增加一个前置检查步骤:
# Step 0: 检查是否已存在
if grep -r "<slug>" /data/oklifeme/content/ 2>/dev/null | grep -q .; then
echo "快速更新场景"
else
echo "首次发布场景"
fi然后根据场景选择不同的流程:
- 首次发布:需要 HITL 2 审核
- 快速更新:跳过 HITL,直接发布
3.3 对用户的启示
及时纠正 agent 的错误:当 agent 的执行结果明显不符合预期时,用户应该立即指出问题所在。
提供关键信息:用户在这次事件中提供了两个关键信息:
- Hugo 中的文件路径
- 可访问的 URL
这些信息帮助 agent 快速定位了问题。
建立 feedback loop:用户的纠正不仅仅是解决当前问题,还应该反馈到 Skill 设计中,避免类似问题再次发生。
四、后续行动
4.1 立即修复
- ✅ 文章已成功更新并发布
- ✅ Git commit 完成
4.2 长期改进
- 更新 blog-publish-oklifeme Skill:增加"快速更新"场景的分支处理
- 强化 agent 的场景识别能力:在 AGENTS.md 中明确区分首次发布和快速更新的判断标准
- 完善错误处理:当 HITL 门控失败时,agent 应该先检查文章是否已存在,而不是直接 abort
4.3 知识归档
本次事件已归档到知识库:
- 路径:
/data/Obsidian-oklife-ub/AI/OpenClaw/06-排障/agent-publish-misjudgment-hitl-gate.md - 标签:
Agent,故障案例,HITL 门控
五、总结
这个案例揭示了一个典型的人机协作问题:agent 严格按照规则执行,但规则本身存在缺陷。
pub-yuntianxing 并没有犯错——它只是执行了 Skill 中定义的流程。但 Skill 的设计没有考虑到"快速更新"这一常见场景,导致 agent 在执行时遇到了不必要的阻塞。
用户的及时纠正是解决问题的关键。但更根本的解决方案是:改进 Skill 设计,让 agent 能够自动识别场景并选择正确的流程。
这也是 OpenClaw 多 agent 系统的一个缩影:每个 agent 都有自己的 Skill 和规则,但系统的整体智能来自于 agent 之间的协作、用户 feedback 的反馈,以及规则的持续迭代优化。
关联阅读
- [[Blog Pipeline HITL门控失效事故复盘]]
- [[OpenClaw blog-pipeline清理实录:从blog-writer混淆到HITL门控修复]]
- [[blog-pipeline 流程优化实录:从一次并行错误到架构重构]]
梦行志