跳到正文

目录

Deli_AutoResearch 工程解构:长时自主任务的脚手架设计

让一个 coding agent 跑三天,回来发现它第二天就卡住了——会话还活着,轮询还在跑,但工作已经停了。它卡在一个局部最优里反复尝试,或者干脆停下来等用户反馈。这不是模型不够聪明,是工程脚手架缺失

Deli_AutoResearch 是一个针对长时自主任务(数天到数周)的协议框架。它真正解决的不是模型能力问题,而是把"工程脚手架缺失"带来的三类失败模式降到可控。本文拆解它的五条主线,分析每条设计的取舍和边界。

信息来源约定:本文内容混合了两个来源——框架原文(框架页 及其 SKILL.md 全文)和基于工程经验的推断。文中不再逐一标注"框架原文"或"作者推断",而是直接陈述,仅在关键判断处说明来源。涉及具体数字(72 小时、自评分数等)时,会标注测试条件。


总览图

整套框架可以被拆成五条相互独立但相互配合的主线:

主线解决的问题关键产物
行为约束防止 agent 在无人监管时主动停下来问问题5 条硬性规则
状态文件系统让多次会话之间不靠对话记忆累积state/ + logs/ 目录约定
停滞检测与转向当 agent 卡在局部最优时强制换方向stale_count + 结构约束切换
三层看门狗当业务循环自己死掉时由独立层兜底L0 守护 shell / L1 durable cron / L2 业务 loop
子代理调度模式决定一次迭代里要不要并行、要不要验证4 种 Pattern A/B/C/D

三类失败模式:一个共同的工程根因

长时运行(数天到数周)的代码型 agent 普遍会遇到三类失败(以下分类与命名来自框架原文):

  1. 认知循环:连续几次迭代都在差不多的方向上尝试,回报越来越低,自己走不出局部最优。
  2. 停止运转(stalling):agent 把一段活干完,给出一份总结,然后停下来等用户反馈。从外部看,会话还活着,轮询还在跑,但工作其实已经停了。运行日志显示,这种情况比崩溃还常见。
  3. 运行时脆弱:上下文压缩会让循环悄悄断掉。关闭一个会话会把它附带的定时器一起带走。失败在默认情况下不会被人发现。

三类失败的共同根因是工程脚手架缺失,不是模型能力不足。框架里的每一条机制都是为了对付这三类问题而存在的。

行为约束:5 条从真实失败里归纳出来的硬规则

以下 5 条规则每条都对应一次真实发生过的失败。不是"良好实践建议",而是"违反了就复现失败"。

i. 零交互。运行期间不向用户提问。不进入 Plan Mode、不调用 question 工具、不以问题结尾。继续干到被用户停止。遇到歧义自己解决,把推理写到日志里(level=decision)。

ii. 就绪即执行。最常见的隐藏违规是"准备都做完了,然后问一句要不要提交"。准备的目的就是执行。提交、重新提交、修问题、启动监控,都是常规操作,不需要确认。

iii. 回调即报活。上下文压缩之后循环会悄悄死掉。每次回调的第一件事就是更新自己的 last_seen,再检查存活。如果发现挂了,立即重启并写日志。

iv. 状态文件持久化。所有进度写到 state/ 文件里,不放在对话记忆里。每次迭代开一个新会话,只注入筛选过的状态,不要用 resume。

v. 守护者 / 工人分离。心跳巡逻对自己不负责的任务只能做三件事:存活检查、重启、轻微推动。它不能读别人的数据、不能改别人的状态文件、不能替别人回报用户。这条规则的来源是:有一次巡逻越界去管了别人的活,结果导致上下文污染、回报漂移和并发写风险。

状态文件系统

每个任务有独立的 state 和 log 目录。三种进程类型分别写各自的日志流,调试时不需要跨文件关联。

{task}/state/
├── task_spec.md          # 目标 / 里程碑 / 成功标准
├── progress.json         # {iteration, status, stale_count, ...}
├── findings.jsonl        # 累积的发现(append-only)
├── directions_tried.json # 已经试过的方向
└── iteration_log.jsonl   # 每轮迭代的摘要

{task}/logs/
├── work.jsonl            # 工作 agent 写,决策打 level=decision 标签
├── orchestrator.jsonl    # 编排者写
└── heartbeat.jsonl       # 心跳看门狗写

日志行的统一格式(前 5 个键必须保持):

{"ts": "...", "source": "...", "level": "info|warn|error|decision", "event": "...", "detail": "..."}

这里有一个经常被忽略的设计取舍:state 目录和 log 目录分离。state 是结构化的事实,log 是带时间戳的事件流。前者用于决策,后者用于事后排查。混在一起会让"我现在处于什么状态"和"我是怎么走到这一步的"两个问题都变得难回答。

停滞检测与转向

机制规则
停滞检测一次迭代没有新发现,或指标下降,stale_count 加 1
强制转向stale_count >= 2 → 改结构性约束,不调战术参数;>= 4 → 标人工关注
方向多样性新方向必须和所有试过的方向都不同;停滞后注入扰动策略
轮次上限单个工作会话最多 15 轮或 30 分钟

“转向结构,不转向战术"这条原则来自框架原文的实践归纳。当一个任务在某个框架里反复停滞时,决定性的进展往往来自纠正环境本身或结构性约束,而不是在现有框架里把策略参数调得更紧。两次停滞应该让人怀疑环境,而不是让人在同一方向上挖更深。

三层看门狗

业务循环本身是不可靠的,需要一个独立的守护层。三层互相检查:任何一层挂了,能被另一层发现并恢复。

形式依赖角色
L0常驻 shell 守护不依赖任何会话心跳时间戳超过 2 小时没更新 → 用无头 agent 启动紧急巡逻
L1durable cron,每小时一次依赖一个活着的交互会话检查每个循环的 last_seen,重启超时循环,发现停滞就推动
L2业务循环每个循环自己一个会话每次回调的第一行更新自己的 last_seen

停滞检测阈值:如果进度超过 2 小时没有更新,且最近一次输出是个问题,判定为停滞。启动推动子代理:注入任务的 task_specprogress,让它继续干并更新状态。连续 3 次推动都没进展,判定为结构性卡住,停止推动,重新用新方向打开。

2 小时阈值故意比 4 小时的任务卡住阈值短:停滞是主动停下来,成本低,值得早一点发现。

L0 那行特别值得展开:它"不依赖任何会话”。这意味着即使所有 OpenClaw / Claude Code / Cursor 会话都被关掉,或者上下文压缩把定时器全部带走,L0 仍然在工作。这就是把"会话存活"和"任务存活"解耦的设计——会话是易失的,任务必须由一个不依赖会话的层来兜底。

子代理调度模式:4 种 Pattern

Pattern适用场景关键想法
A 目标驱动研究迭代注入已试过的方向,要求可验证的发现,写回 findings.jsonl
B 并行探索复杂子问题在一条消息里启动多个 agent:调研、反驳、跨领域类比
C 实验运行长时计算任务提交后立即按分钟级轮询:自动诊断错误、修复、重新提交
D 验证迭代后质量检查一个独立的子代理审计 findings 的证据链

子代理 prompt 应该包含:背景、可验证的交付物、工作目录、文件/行数上限、完成标准。

四种模式可以组合。一次"写一篇综述"的任务:先用 Pattern B 把问题拆给三个 agent 并行做调研,再用 Pattern A 把每个方向的发现沉淀,最后用 Pattern D 让一个独立 agent 审计整篇综述的引用是否都能追到原文。

工程约束:6 条会让任务停下来的红线

这 6 条来自框架原文的元学习循环归纳,违反它们会引发停滞或回退。

  1. 每次迭代最多 5 个大文件;单个文件不超过 300 行。
  2. 状态通过文件注入,不通过对话历史。
  3. 验证(test / compile / check)必须在迭代之间跑。
  4. 类引用内容每 20 条就要核实一次,不能攒到最后。
  5. 多个候选方向并存时,优先加多样性,不是在一个方向上挖更深。
  6. 外部依赖失败无法解决时升级:完整报告 + 通知负责人 + 轮询等回复;不能静默放弃。

第 5 条和"停滞检测"那一节呼应:多样性优先于深度。第 6 条对应真实场景里最让人恼火的那种失败——agent 在外部 API 不可用时静默卡住,负责人完全不知道发生了什么。

任务流案例:三天写一篇 ICLR 格式综述

下面用一个具体任务把这套系统串起来(说明性案例,用于展示机制如何协作,非框架原文记录的真实运行日志):

Day 0(准备):
  - 写 task_spec.md:目标 = ICLR 综述一篇,约 60 页、≥200 篇引用
  - 初始化 progress.json:{iteration: 0, status: init, stale_count: 0}
  - 初始化 directions_tried.json:空
  - 注册 L1 cron 每小时一次
  - 启动 L0 shell 守护

Day 1(探索阶段):
  - 编排者从 progress.json 读出当前状态
  - 启动 Pattern B:3 个并行 agent
    - agent-1:调研"agent 评估方法"的近 3 年文献
    - agent-2:调研"长上下文模型"的近 3 年文献
    - agent-3:调研"tool use 安全性"的近 3 年文献
  - 每个 agent 写自己的 findings.jsonl 行
  - 编排者汇总,更新 progress.json,iteration + 1

Day 2(迭代阶段):
  - 编排者读 directions_tried.json,注入新方向"从反例视角看 agent 失败"
  - 启动 Pattern A:单 agent 在新方向上迭代
  - 这次 0 新发现 → stale_count = 1
  - 又一次 0 新发现 → stale_count = 2 → 触发结构约束切换
  - 编排者把"单 agent 串行"改成"Pattern D 验证 + Pattern A 写入"的两阶段模式
  - 新方向找到关键反例文献 12 篇

Day 2 中段(停滞处理):
  - L1 cron 检查 progress.json 发现 4 小时没更新
  - L1 启动推动子代理
  - 推动子代理读 task_spec + progress,发现是 L1 误判(agent 还在运行)
  - 推动子代理等待,不打扰业务循环

Day 3(验证阶段):
  - 启动 Pattern D:独立 agent 审计所有 findings.jsonl 的引用
  - 找出 3 条不可验证的引用(DOI 无效、PDF 已下架)
  - 触发"类引用内容每 20 条核实一次"红线,自动替换为可验证来源
  - 渲染最终 PDF,iteration + 1,status: done

这个例子展示了几件事:

  • L0 不依赖会话,所以即使 Day 1 晚上所有 agent 会话被关掉,shell 守护仍能感知。
  • 编排者在 Day 2 转向时不是调策略参数(更细的检索词),而是改结构约束(从单 agent 变成两阶段)。
  • Pattern D 验证抓出了引用造假问题——这是框架诚实披露的"虚构引用"在流程上的机械约束。

验证与限制

框架已经支撑过几个异构的长时任务。论文写作轨道的产出:

论文页数引用数自评
Autonomous Research Agents592288.0
Continual Learning653268.0
Long-Horizon Decision-Making553848.0
Self-Play(285B RL 实验 + 理论硬化)752178.6

测试条件与读法限制

  1. 自评分数:由框架内多角色模拟评审给出,评审者本身是 LLM 角色,不是人类同行评审。分数只在同一协议的不同版本之间纵向可比,不是外部质量声明,不能拿来和真实期刊/会议评审结果对照。
  2. 72 小时连续运行记录:这是框架披露的最长连续运行记录,期间有 6 次方向性人工输入。运营层面零干预,方向性干预保留。测试任务类型、模型版本、硬件配置等细节未完整披露,72 小时不可外推为任意任务的可靠性上限。
  3. 虚构引用和数据伪造的源头是 LLM 本身。框架把外部核实做成流程里的机械步骤,但没消除错误源头。
  4. 职责分离靠的是协议约束,不是模型自律。去掉约束,越界行为会回来。

第 3 条是这套框架最诚实的一条自白:它解决的是"工程脚手架缺失",不是"模型会造假"的问题。把这两件事混在一起看,会高估它的能力。

采用顺序与适用边界

任务类型是否建议采用从哪里开始
数天到数周的研究型任务(综述、benchmark 调研)强烈建议直接照搬 5 条行为约束 + state/ 目录约定
长时的代码迁移(一次性大规模重构)建议加上三层 watchdog,但可以只用 L1 + L2
短时的日常任务(一个 PR、一次调试)不建议引入 state 目录的开销大于收益
不可中断的真实生产任务不建议72 小时连续运行的可靠性不足以承担生产责任
完全无外部依赖的纯本地任务部分建议6 条工程约束里的"外部依赖升级"可以省掉

最小可行起步:只做两件事就比裸跑好得多。把进度写到 state/progress.json,把行为约束 i 和 ii 写进 system prompt。剩下三条行为约束和三层 watchdog,可以在第一次停滞发生之后再加。

常见问题

Q:为什么不直接用长上下文窗口 + 单一长会话? A:长上下文本身会引入"认知循环"。模型在同一个会话里反复做类似的尝试,回报递减且无法换方向。框架的回应是"每次迭代开新会话 + state 文件注入",把"会话存活"和"任务存活"分开管理。

Q:三层 watchdog 会不会太重? A:L0 + L1 + L2 是为 72 小时级别的任务设计的。单日任务只用 L1 就够了。判断标准:任务跨过了几次会话重启边界,就需要至少 L1。

Q:和 MetaGPT / AutoGen / CrewAI 是什么关系? A:那些框架关注的是"多个 agent 如何协作"。Deli_AutoResearch 关注的是"任务如何不静默死掉"。两者互补,不是替代——可以在它的状态文件系统之上跑 MetaGPT 式的多 agent 协作。

Q:state 文件会不会成为瓶颈? A:当 findings.jsonl 累积到几千条时确实会变慢。两个缓解办法:定期把已读部分归档成 findings.archive.jsonl,或者改成 SQLite + 向量检索。框架本身不强加存储格式。

Q:怎么防止 agent 写假引用? A:不防止,只能检测。第 4 条工程约束要求每 20 条引用就核实一次,Pattern D 的独立验证是另一道闸门。注意:这两道闸门降低造假率,不消除造假源。LLM 本身仍可能在第 21 条时造假。

错误处理与排查指引

长时任务的问题往往不是"崩溃"而是"静默退化"。下面按症状集中给出排查路径。

症状 1:任务跑着跑着就停了,会话还活着但没新输出。 这是"停止运转"失败模式。先看 {task}/logs/orchestrator.jsonl 最近 1 小时有没有 event=iteration_start;如果没有,说明编排者没在推进。再看 {task}/state/progress.jsonstatus 字段,如果是 waiting_user 之类的值,说明 agent 违反了行为约束 i(零交互)停下来等用户了。修复:检查 system prompt 里行为约束 i 是否生效,确认 agent 没有进入 Plan Mode 或调用 question 工具。

症状 2:last_seen 时间戳超过 2 小时没更新,但 L0 没启动紧急巡逻。 排查 L0 是否还活着。L0 是常驻 shell 守护,用 ps aux | grep <l0_process_name> 看进程是否还在。如果 L0 进程不在了,说明 L0 自己挂了——这是三层看门狗的盲区,需要用 systemd / launchd 把 L0 做成自动重启的服务。如果 L0 进程在但没启动紧急巡逻,检查 L0 的心跳超时阈值配置是否被改过。

症状 3:stale_count 反复在 1 和 2 之间跳,任务有进展但很慢。 排查 {task}/state/directions_tried.json,看最近几个方向是否过于相似。如果相似,说明"方向多样性"约束没生效。修复:在编排者的 prompt 里强化方向多样性检查,或手动注入一个差异更大的方向。

症状 4:findings.jsonl 里有引用,但 Pattern D 验证时大量失败。 排查失败引用的模式:如果是 DOI 无效,可能是 agent 编造了 DOI 格式正确的字符串;如果是 PDF 已下架,可能是引用真实但来源不可访问。前者需要回到第 4 条工程约束检查核实步骤是否真的在跑;后者需要换可验证来源。两种情况都不能靠"让 agent 自己再查一遍"解决。

症状 5:外部 API 不可用时 agent 静默卡住,负责人完全不知道。 排查 {task}/logs/work.jsonl 里有没有 level=errorevent=external_dependency_failed 的记录。如果没有,说明 agent 没按约束升级报告。修复:在 system prompt 里强化第 6 条约束。

通用排查原则:先看 logs/ 再看 state/logs/ 告诉你"发生了什么",state/ 告诉你"现在处于什么状态"。两者对不上时,优先信 logs/——state/ 可能因为 agent 异常退出而没来得及更新。

术语对照

英文中文备注
orchestrator编排者监控 state、检测停滞、注入新方向的进程
work agent工作 agent真正干活的子代理
heartbeat watchdog心跳看门狗独立于业务循环的存活检测层
guardian / worker separation守护者 / 工人分离心跳不能越界去管别人的活
stale_count停滞计数连续 0 新发现时累加
pivot structure, not tactics转向结构,不转向战术改环境而非改策略参数
callback means report-alive回调即报活上下文压缩后第一件事是更新 last_seen
last_seen最后活跃时间戳存活信号
nudge subagent推动子代理判定停滞后启动的轻量级继续执行者
durable crondurable cron跨会话存活的定时任务

参考与延伸阅读

  • 框架页:victorchen96.github.io/auto_research/framework.html
  • 框架 SKILL.md 全文同页底部可一键复制
  • 相关对比方向:MetaGPT、AutoGen、CrewAI、OpenHands、ChatDev——它们关注"如何协作",这套关注"如何不静默死掉",是互补而非替代

这套框架真正解决的是把"长时任务"和"短时任务"在工程层面区分开。短时任务可以靠模型的瞬时注意力。长时任务必须靠"会话死了活能继续"。它没有让模型变聪明,它让模型在变得不聪明的时候不会把任务拖下水。

这也是为什么它的设计取舍都偏向"反直觉的克制"——零交互、不问问题、回调先报活再干活、守护者不能越界。每一条都在对抗"看起来更礼貌、更主动、更有判断力的 agent"。礼貌和主动是会话层面的价值。在任务层面,它们是浪费。

做长时 agent 任务时,先把第 5 条工程约束(多样性优先于深度)和第 iv 条行为约束(状态文件持久化)写进 prompt。跑两周。再决定要不要把整套框架搬过来。

参与讨论

使用 GitHub 登录。欢迎补充事实、异议与实践。