把重复决策写成规则,减少 Agent 跑偏
作者复盘定时发布 Agent 的运行问题:选题评分会把自身旧文当作趋势来源,标题模板也连续重复。文章以这些故障讨论哪些反复出现的决策应固化为常驻规则。
AI 深度解读
一个每天跑两次的 AI 发文流程,连续运行几个月后,开始拿自己的文章当热点依据,重复标题句式,选题也越来越像同一个仓库的维修日记。单看每次执行都能解释得通,连起来却明显跑偏。
作者的处理办法很具体:把三类反复出现的问题写成常驻规则,能用代码判断的直接拦截,需要判断的则强制查阅历史。它值得读的地方,是提醒我们区分:哪些决定适合交给 Agent 临场发挥,哪些必须由流程持续约束。
为什么每次都合理,跑久了却不对劲
作者维护着一个名为 my-git-manager 的私有仓库,用来驱动 dev.to 发布流水线。定时 Agent 每天执行两次,检查发文配额、给开发和 AI 热门标签下的帖子打分,再根据仓库提交历史写文章、发布并记录操作。
问题首先出在 Step 2。候选帖子的得分是 reactions + 3*comments,流水线从尚未覆盖的内容中挑高分选题,却没有排除作者自己的文章。账号积累了一批帖子后,旧文章也开始进入热门候选池。
于是,流水线用自己的产出来证明下一篇值得写什么。分数仍然算对了,信号来源却被污染了。
另外两种重复也在积累。标题连续超过十五篇采用类似 My X Did Y. It Never Z. 的两句式反转结构;正文则反复挖掘同一个私有仓库的修复记录,对仓库之外的读者越来越缺乏吸引力。
单次执行看不见的重复,需要跨次执行的记录才能暴露。
Agent 在某一次运行里认为标题顺口、问题真实、文章可以发布,并不奇怪。缺失的是一项检查:过去二十次是不是也做了相似的选择,最终形成了同一种坏模式。
三条规则,为什么只有一条适合直接写成代码
作者记述,流水线负责人在 2026-11-04 查看工作日志 docs/project_notes/issues.md 中连续升级的问题记录后,确定了三条规则。
第一条是在 Step 2 打分之前,排除所有 user.username == "enjoy_kumawat" 的帖子。这不需要语言理解,只需要身份比较。
下面这段代码把自我排除放到了评分之前:
MY_USERNAME = "enjoy_kumawat"
def score_candidates(posts):
scored = []
for post in posts:
if post["user"]["username"] == MY_USERNAME:
continue # 规则 1:不再交给每次运行临场决定
score = post["positive_reactions_count"] + 3 * post["comments_count"]
scored.append((score, post))
return sorted(scored, reverse=True)
要看的是 continue 所在的位置:自己的帖子在计算分数前就退出候选处理,后续推理再怎么变化,也无法把它重新评成热点来源。
第二条禁止两句式反转标题,并要求新标题与最近 10 篇已发布标题采用不同结构。第三条要求文章不能只是「又在这个仓库发现一个 bug」,优先考虑测量、比较、设计决策、教程,或对热点本身的第一手看法。
后两条没有同样可靠的 if。标题用词不同,结构可能相同;文章挂着测量的名头,也可能仍然只是一篇修复记录。
因此,作者给判断增加了必须执行的前置步骤:动笔前读取最近 10 个标题,明确说出各自结构;确定切入角度前,对照工作日志中已经写尽的主题。
规则没有代替判断,而是要求判断之前先拿到证据。这里的强制机制,就是不能跳过那次历史比较。
什么问题值得立规矩,什么问题可以容忍偶发失手
作者给出的标准是看错误如何积累。
如果一次判断失误的代价不明显,却会在多次运行中持续叠加,例如来源污染、标题模板化、主题不断收窄,就应该把防护固定进流程。某一次调用通常没有完整历史,指望它自行察觉长期趋势并不可靠。
如果失误只是产生一篇平庸但无害的内容,作者认为可以保留临场选择。规则太密,也可能逼着 Agent 为了符合形式要求,产出更弱的文章。
这也是第三条没有写成「只准写设计决策,禁止写仓库 bug」的原因。全面禁止某类内容,可能只是把重复挪到另一个类别:连续二十篇设计决策,仍然可以长得一模一样。
作者最后提出三个检查问题:坏结果能否通过用户名比较、重复字符串匹配等低成本方式发现;判断是否依赖单次调用通常看不到的历史;能否准确指出失败模式,而不是直接封禁整个类别。
它们分别对应确定性校验、强制读取历史,以及约束范围的选择。原文的改动没有引入新基础设施,依赖的是已经存在的日志和几条明确要求。
我的判断
我认同作者对确定性检查的处理。已经能准确识别的问题,写进执行路径,通常比只在提示词里提醒更可靠。前者有明确触发条件,后者还要等待 Agent 在合适的时候想起来。
但这篇提供的是一次流水线整改的经验,没有给出修改后的重复率、内容质量评分,也没有与其他方案做对照。不能据此断言三条规则已经长期解决了问题。
「最近 10 篇」也是作者选定的观察窗口,原文没有证明它适合所有发布频率。标题结构如何分类、检查结果是否被保存、违反规则后如何处理,都没有说清。后两条能否持续生效,仍取决于流程有没有真正执行检查。
还要区分两类记忆。工作日志可以保存内部问题和已用主题,却不能自动代表读者兴趣。避免反复挖同一个仓库,只解决了选题来源过窄的问题,文章是否有用仍需其他反馈。
原文提到问题曾在八月持续约两周,又把规则落定日期写为 2026-11-04,中间经历没有展开。可以确认作者观察到了这些问题,并给出了具体改法;修复后的持续效果,还缺少证据。
能拿来做什么
- 如果你在维护 Node 驱动的内容抓取或发布脚本,可以先检查候选池是否混入自己的产出,并把身份过滤放在评分之前,避免后续选择持续受污染。
- 如果定时 Agent 会反复生成标题或选题,可以让它在起草前读取最近一批记录,并输出比较依据。先沿用原文的最近 10 条作为起点,再根据重复情况调整窗口。
- 如果同一类问题已经多次出现在 Agent 工作日志中,可以逐项判断它能否机械检测。能检测的写入校验逻辑,需要语义判断的则增加必读历史和检查步骤。
- 给内容流程加限制时,可以先写清要避免的具体模式,例如反复从同一仓库挖修复故事,再保留测量、比较、教程等选择空间,避免把选题统一压进另一个模板。