wth2jhl.online

Back

📘 原文信息

  • 项目名:DeepScientist
  • 副标题:Now, Stronger AI Pushes Frontiers, Stronger Our Shared Future.
  • 作者:Yixuan Weng、Minjun Zhu、Qiujie Xie、QiYao Sun、Zhen Lin、Sifan Liu、Yue Zhang(ResearAI)
  • 论文:DeepScientist: Advancing Frontier-Pushing Scientific Findings Progressively(ICLR 2026 Top 10)
  • 发布日期:v1.6.0(2026-05-12,包含 Claude Code / OpenCode / Kimi Code / BenchStore / 科研证据工作流)
  • 仓库:https://github.com/ResearAI/DeepScientist ↗
  • 论文链接:https://openreview.net/forum?id=cZFgsLq8Gs ↗
  • 官网:https://deepscientist.cc/ ↗
  • License:Apache-2.0
  • 代码规模:75.9 MB(主仓),134 个 Python 模块 + 19 个 Stage Skill + 完整 Web/TUI/Connector 套件

一、为什么这篇值得读?#

2026 年的”AI Scientist”赛道已经卷了一年,但绝大多数”自主科研”系统仍然在两个极端之间反复横跳:

  • 极端一:巨型 Chatbot。接一篇论文进去,聊二十回合,出一段花哨的研究计划,第二轮 prompt 一起,前面的上下文就丢了。
  • 极端二:云端黑盒 Agent。点一下按钮,过 6 小时出结果,中间到底跑了什么、哪个分支死掉、哪份 baseline 没复现,完全看不到。

ResearAI 团队在 ICLR 2026 Top 10 的论文 DeepScientist: Advancing Frontier-Pushing Scientific Findings Progressively,以及它配套的开源仓库,试图给出第三种答案——把”做研究”本身当成一个本地操作系统来设计。在这个操作系统里:

  • 每个研究课题(quest)都是一个独立的 Git 仓库——分支、worktree、文件、commit 就是研究结构本身;
  • 状态全部沉淀在文件 + Git + Memory 卡片 + Artifact 记录——刷新页面不丢,关掉电脑不丢;
  • AI 跑的命令必须走 bash_exec MCP——所有 shell 操作是”可暂停、可重连、可追溯”的;
  • 行为规则全部写在 system.md + 19 个 stage skill——没有藏在 Python if-else 里的硬编码阶段机;
  • Web / TUI / 微信 / QQ / 飞书 / Slack / Telegram / Discord / WhatsApp / Lingzhu 10 套入口共用同一份 quest state——你在哪问,quest 就在那跟。

DeepScientist 不是另一个”AI Scientist clone”,它的野心是:让”长程科研”这件事,在工程师的主机上,能像数据库一样持久、像 IDE 一样可调试、像 CI 一样可回放。

本文按仓库的文档结构(docs/en/90_ARCHITECTURE.md / 13_CORE_ARCHITECTURE_GUIDE.md / 06_RUNTIME_AND_CANVAS.md / 02_START_RESEARCH_GUIDE.md)和源码结构(src/deepscientist/ + src/prompts/ + src/skills/),做一次重述与解读,重点回答:

  1. 为什么”一题一仓库”是核心设计选择,而不是营销话术?(第 2 节)
  2. JavaScript 启动 + Python 运行时这套双层架构,是怎么解决”用户友好 + 状态权威”这对矛盾的?(第 3 节)
  3. 三个内置 MCP(memory / artifact / bash_exec)各自承担什么,为什么”只暴露三个”是优势?(第 4 节)
  4. Prompt + 19 个 Skill 怎么替代”巨型状态机”?(第 5 节)
  5. Canvas(那张漂亮的拓扑图)到底是怎么从 Git + 文件”长出来”的?(第 6 节)
  6. 10 套 Connector 怎么共用一份 quest state?(第 7 节)
  7. BenchStore 和 optimize skill 如何让”算法优先”和”论文优先”两条路都跑得通?(第 8 节)

二、核心设计哲学:为什么是”一题一仓库”?#

DeepScientist 仓库里反复强调的一句话是:One quest, one Git repository.这个选择听起来像营销,实际上它是整个系统所有”可观测性 / 可恢复性 / 可回放性”的根基。

2.1 传统 AI Scientist 的状态模型#

AI Scientist / autoresearch 类系统的状态模型大致是这样的:

{ in-memory chat history, ephemeral sandbox, transient workspace, post-hoc PDF }
text

特征:

  • 研究结构 = 对话结构。分支、对比、消融只能靠 prompt 描述,运行结束就散。
  • 失败路径 = 垃圾桶。跑错的实验被覆盖,半年后想复盘,什么都找不回。
  • 可观测性 = 日志尾巴。只能在终端翻最后几百行 JSON,看不到完整的拓扑。

2.2 DeepScientist 的状态模型#

{ Git repository(quest), quest.yaml + brief.md + plan.md + status.md + SUMMARY.md,
  .ds/events.jsonl, .ds/interaction_journal.jsonl,
  memory/ cards, artifacts/ records, branches + worktrees, run logs }
text

特征:

  • 研究结构 = 文件系统 + Git 历史。你做了一次分支对比,分支就在那里;git log --graph 就是研究史。
  • 失败路径 = 资产。所有 dead-end 都保留在某个分支上,等下次 memory search 时被复用。
  • 可观测性 = git status + cat .ds/events.jsonl + Canvas 视图。网页、终端、外部聊天都看同一份数据。

2.3 这一选择换来了什么#

维度”对话式”系统”一题一仓库”系统(DeepScientist)
状态恢复重新上传上下文 / 重新解释cd ~/DeepScientist/quests/<id>/ 直接续上
分支管理用 prompt 假装有分支真正的 Git branch + worktree
失败资产跑完即丢保留在分支,可在 decisions memory 里被检索
多端协作每个聊天工具各自一套状态Web / TUI / 微信 / 飞书都查询同一份 quest state
审计看模型自己说”我做了什么”看 git log + .ds/events.jsonl + artifact 记录

💡 小吴笔记:这一节的真正价值是把”持久化”从”工程问题”提升成了”研究方法论问题”。当你的”研究”以 Git 为单位时,你能 revert 一条假设、cherry-pick 一次消融、diff 两个 baseline——这些操作在 AI Scientist 类系统里基本是空集。DeepScientist 等于在 LLM 时代把”实验”和”代码”放回同一个版本管理空间。

三、启动链:JavaScript 装用户,Python 管状态#

DeepScientist 的”用户面”是 npm install -g @researai/deepscientist,但”权威运行时”是 Python。这种”JavaScript 当 launcher、Python 当 runtime”的混合架构看起来诡异,但每一步都有具体理由。

3.1 为什么不让 Python 直接当 launcher?#

直觉上 pip install deepscientist && ds 似乎更省事。但 DeepScientist 团队没这么做,原因有三:

  1. 用户安装习惯。目标用户群(研究生 / 工程师)90% 已经装了 Node.js,但不一定有干净的 Python 3.11+ 环境(尤其 macOS 系统 Python 不可写、Windows 没自带)。
  2. 跨平台工具链。uv 管理的 Python 环境隔离 + 自动 install,比让用户自己 venv / conda 友好得多;而 uv 又可以通过 npm 包来调度。
  3. Web UI / TUI 是 JavaScript 资产。React + Vite 的前端、Ink 的终端,本来就是 Node 生态,装在 npm 包里一次到位。

3.2 bin/ds.js 的真实职责#

bin/ds.js 是个故意保持 thin 的 launcher,它的工作只有 5 步:

1. 检测 Node.js >= 18.18,npm >= 9
2. 确保 ~/DeepScientist/runtime/python-env 存在(没有就跑 uv sync)
3. 启动 Python daemon(后台)
4. 暴露共享 web/TUI API 端口(默认 20999)
5. 提示用户打开 http://127.0.0.1:20999
text

docs/en/90_ARCHITECTURE.md 里专门有一句话:

“bin/ds.js should stay thin. Product behavior belongs in Python services, prompts, and skills.”

这条约束意味着:任何”产品行为”都不应藏在 JavaScript 里。launcher 只做”启动 + 暴露端口”,所有业务逻辑都在 Python。

3.3 Python 端的两层骨架#

Python 端(src/deepscientist/,134 个文件)按职责拆成几块:

子系统关键文件职责
clicli.py薄壳,只转发到 quest / config / doctor / runtime 服务
daemondaemon/app.py(8890 行)HTTP server + turn scheduler + API 路由 + connector 协调
questquest/service.py(8327 行)、quest/layout.pyquest 创建、快照、状态、布局契约
artifactartifact/service.py(16105 行)Git-backed 结构化记录、批准、报告、interactions
memorymemory/service.py、memory/frontmatter.py全局 + quest 级 Markdown 记忆
bash_execbash_exec/service.py(1659 行)可暂停、可重连、可追溯的 shell session
mcpmcp/server.py三个内置 MCP 命名空间(memory/artifact/bash_exec)
runnersrunners/codex.py、runners/claude.py、runners/opencode.py、runners/kimi.py4 套 runner 适配
bridges/connectors10+ 桥接器把外部 IM 转成 quest 事件
channelschannels/feishu_long_connection.py 等10+ 个 channel 的轮询 / 长连接实现
runtime_toolsruntime_tools/tinytex.py 等本地工具管理(TinyTeX / 未来 pandoc / graphviz)

💡 小吴笔记:daemon/app.py 单文件 8890 行不是”屎山”,而是一个有意识的折衷——daemon 既是 HTTP server 又是 turn scheduler 又是 connector 协调器,拆太碎反而会拖慢 IPC。仓库里有清晰的”运行时边界”章节(CLI / Daemon / Quest / Artifact / Memory / Bash / Runner / Bridge),跨边界调用必须经过 service 层,这是有纪律的”胖 daemon”而不是无组织的”长文件”。

四、三个内置 MCP:为什么”只暴露三个”是优势#

DeepScientist 的 system.md 第一节(也是最重的一节)叫”Hard execution redlines”,第一条就写:

Native shell_command / command_execution is forbidden for this workflow. Every terminal-like action must be executed through bash_exec(...).

它把 MCP 表面严格限制在三个:

Namespace用途典型操作
memory沉淀可复用知识write / read / search / list_recent / promote_to_global
artifact推进 quest 状态interact / experiment_record / branch_transition / arxiv / complete_quest
bash_exec执行 shellstart / read / list / kill

4.1 三个 MCP 各自的工程含义#

memory 命名空间——所有记忆卡都是带 YAML frontmatter 的 Markdown 文件,支持 6 种 kind:

papers | ideas | decisions | episodes | knowledge | templates
text

为什么是 Markdown 而不是向量数据库?因为:

  • 用户可读(cat ~/DeepScientist/quests/<id>/memory/decisions/x.md 就能看);
  • 可被 git 追踪、可被 PR review;
  • 跨 quest promote_to_global 时就是 cp + 重写 frontmatter。

PromptBuilder 按 stage 智能注入 memory(第 5 节会展开),这意味着记忆不是统一灌入,而是按当前阶段的需求”拉”进 prompt。

artifact 命名空间——它是 quest 状态的”权威写入器”。所有”客观发生过的事”都通过它落盘:

  • experiment_record(...):记录一轮主实验的 metric + 配置文件 + commit hash
  • branch_transition(...):记录一次分支决策(为什么开新分支、为什么放弃)
  • decision_record(...):把”路线判断”沉淀为可被以后 recall 的卡片
  • interact(...):与用户的对话流,带 kind=milestone | progress | blocker 区分
  • complete_quest(...):唯一允许”宣告完成”的地方——必须有用户显式 approve

bash_exec 命名空间——它解决的是 LLM 跑 shell 的几个老问题:

问题传统 shellbash_exec
训练跑到一半崩了进程组孤悬,日志散乱session 可 list / read / kill,崩溃后能续
命令需要回看history 只有命令,没有 stdout每次 start 都在 .ds/bash_exec/<id>.log 留全量记录
危险命令误执行没有”必须过 MCP”的边界system.md redline 强制”绕开就违规”
长时间没回应用户干等可在 prompt 里回头 read 进度

4.2 为什么”只暴露三个”反而是优势#

docs/en/90_ARCHITECTURE.md 有一条”红线”写得很清楚:

Do not introduce public git, connector, or runtime_tool MCP namespaces.

这意味着:

  • Git 操作 = artifact 内部职责,不外泄成 MCP(避免 agent 乱 git push);
  • Connector = bridge 层职责,不外泄(避免 agent 调外部 IM 写用户数据);
  • runtime_tool = daemon/CLI 职责,不外泄(避免 agent 擅自装 TinyTeX)。

这种”严格只暴露三个 MCP”的取舍,在 LangChain / OpenAI Assistants / Claude Tools 类生态里反而是稀缺品——MCP 表面越大,prompt 越乱,误调概率越高。把 surface 收缩到 3 个,意味着 agent 的工具选择空间变小但每个都”够厚”。

💡 小吴笔记:DeepScientist 团队对 MCP 的态度很值得其他 Agent 框架借鉴——“加一个 MCP 比加一个 prompt 复杂”。一旦加了,就要负责:文档、prompt 示例、错误处理、安全边界、测试,以及在 system.md 里加规则。三个 namespace 是精心称量过的最小集。

五、Prompt + 19 个 Skill:怎么替代”巨型状态机”#

如果你打开 src/prompts/system.md(1280 行),它会花大量篇幅告诉 agent:

  • 不要用 native shell,要用 bash_exec;
  • 写代码前先想清楚 assumption;
  • 不要做超出需求的事;
  • 修改代码要 surgical,不要顺手 refactor 周边;
  • 任务完成必须 verify,不能”模型说做了就做了”。

但这 1280 行没有任何一行规定”在 X 阶段之后必须跳到 Y 阶段”。整个工作流阶段切换,都被外移到 src/skills/<stage>/SKILL.md 里了。

5.1 19 个 Skill 的组织#

仓库里的 stage skill 一共 19 个,按 skill_role 字段分三类:

stage       | 主流程:scout, baseline, idea, experiment, analysis-campaign, write,
            |         finalize, decision, optimize, intake-audit
companion   | 辅助:paper-plot, figure-polish, review, rebuttal, paper-outline,
            |         nature-*, science
custom      | 预留
text

每个 skill 是一个目录,核心是 SKILL.md 顶部的 YAML frontmatter + 后续的”SOP body”:

---
name: scout
description: Use when a quest needs problem framing, literature scouting...
skill_role: stage
---

# Scout
## Match signals
## One-sentence summary
## Control workflow
## AVOID / pitfalls
## Constraints
## Validation
## Interaction discipline
markdown

5.2 Skill 选择的算法(非常简单)#

docs/en/06_RUNTIME_AND_CANVAS.md 第 5.2 节”Which skill is used for the turn”明确写着:

1. 如果 latest user message 是对某个 active blocking interaction 的回复 → decision
2. 否则读 quest.yaml.active_anchor
3. 如果 active_anchor 是标准 skill → 用它
4. 否则 fallback 到 decision
text

也就是说:daemon 自己不”驱动”阶段切换,而是”读” quest.yaml 里的 active_anchor。切换是 agent 自己在写完当前阶段的 artifact 之后,通过 artifact.interact(...) 报告”我做完 baseline 了,接下来 idea”,同时修改 quest.yaml.active_anchor。

这是极端的”轻 daemon”哲学:

“the daemon should persist and route state, but avoid becoming a rigid workflow scheduler.”

5.3 PromptBuilder 的 11 段组装#

每一轮 turn,PromptBuilder.build(...) 会按顺序拼出 11 段 prompt:

1.  system.md(全局 kernel)
2.  runtime context(ds_home / quest_id / active_anchor / runner / model / ...)
3.  active communication surface(本地还是哪个 connector)
4.  canonical skill root + 当前 skill 路径
5.  quest context files(brief / plan / status / SUMMARY)
6.  recent durable state(最近 N 个 artifact 摘要)
7.  interaction style instructions
8.  priority memory for this turn(按 stage 拉 memory)
9.  recent conversation window
10. current turn attachments
11. current user message
text

第 8 段尤其重要——memory 注入是 stage-aware 的。例如:

  • scout 阶段优先拉 papers / knowledge / decisions
  • baseline 阶段优先拉 papers / decisions / episodes / knowledge
  • idea 阶段优先拉 papers / ideas / decisions / knowledge
  • experiment 阶段优先拉 ideas / decisions / episodes / knowledge
  • analysis-campaign 还会额外拉相关 papers

这样”哪种阶段读哪种 memory”被硬编码到 builder 里,agent 不需要自己决定”现在该 recall 啥”。

💡 小吴笔记:这是 Agent 框架里非常优雅的解耦——“流程纪律”是 prompt 的事,“状态权威”是 daemon 的事。如果未来要加 optimize 之外的新 stage(比如 rebuttal-v2),只改 SKILL.md + PromptBuilder 的 stage-aware memory 列表,daemon 不用动一行。这跟 LangGraph / AutoGen 那种”状态机里到处是 if”的设计哲学正好相反。

六、Canvas:从 Git + 文件”长出来”的拓扑图#

打开 DeepScientist 的 web workspace,你会看到一张类似 DAG 的”研究地图”,节点是 quest 状态,边是分支切换。这张图不是某个 Neo4j 实例,它是从 Git + 文件状态实时重建出来的。

6.1 Canvas 的三份原料#

docs/en/13_CORE_ARCHITECTURE_GUIDE.md 第 12 节明确说:

“Canvas is not a separate graph database. It is reconstructed from:

  • Git branch structure
  • artifact records
  • quest events”

具体实现端:

  • src/deepscientist/quest/node_traces.py——从 artifact 记录和 Git 历史抽出节点;
  • src/deepscientist/gitops/diff.py——计算节点之间的 diff / 共同祖先;
  • src/ui/src/lib/plugins/lab/components/LabQuestGraphCanvas.tsx——前端 React 组件负责可视化。

6.2 为什么这个设计是”对”的#

传统 BI / 研究管理工具把拓扑图当成”主存储”——结果:

  • 节点状态不一致(agent 改了文件,图没更新);
  • 删除/恢复难(只能改图,改不了文件);
  • 没法跑 git diff 复盘。

DeepScientist 反过来——Git + 文件是真,Canvas 是视图:

行为在”图主存”系统里在 DeepScientist 里
节点状态写图库 + 写文件(可能不一致)只写文件 + artifact
看进度读图库重新跑 node_traces.py 从 Git + artifact 推
回滚改图库 + 改文件git revert 一行
多端一致同步图库任何端都从同一份 Git 推

6.3 一个 Canvas 节点的生命周期#

典型流程:

  1. agent 完成 baseline → 写 artifacts/baselines/xxx.json + git commit;
  2. agent 决定开 idea 分支 → 调 artifact.branch_transition(...) → 自动 git checkout -b;
  3. node_traces 从新的 Git history 重建 DAG → Canvas 自动多一个节点;
  4. 前端通过 GET /api/quests/<id>/node-traces 拉新数据 → 刷新视图。

整套流程没有任何”图数据库写入”步骤。Canvas 本质是 Git log 的可视化。

💡 小吴笔记:这是”用工程换智能”的又一个例子——不引入图数据库,不引入事件溯源框架,直接用 Git 当 source of truth。代价是节点层级不能太深(否则 Git log 过长),收益是任何会 git 的工程师都能直接调试 quest 状态。

七、10 套 Connector:同一个 quest,10 个入口#

打开 src/deepscientist/channels/builtins.py 和 bridges/connectors/,你会看到:

discord_gateway.py        feishu_long_connection.py    qq_gateway.py
slack_socket.py           telegram_polling.py          weixin_ilink.py
whatsapp_local_session.py lingzhu(在 connector_runtime) ...
text

10 套 IM 入口(Discord / 飞书 / QQ / Slack / Telegram / 微信 / WhatsApp / Lingzhu / Rokid / Lingzhu-灵珠,加上一个本地 TUI)全部指向同一份 daemon,共享同一份 quest state。

7.1 Connector 的三层切分#

DeepScientist 把”接入外部 IM”切成 3 层:

Channel(传输层)  ←→  Bridge(语义层)  ←→  Quest(状态层)
text
  • Channel:discord_gateway.py / feishu_long_connection.py / weixin_ilink.py 等,只负责”怎么连”——长连接 / 短轮询 / WebSocket / Socket Mode。
  • Bridge:bridges/connectors/,负责”连进来的消息算什么”——是不是指令 / 是不是要回 / 附件怎么存。
  • Quest:核心 artifact + quest 服务,只关心”这消息对 quest 意味着什么”。

这种切分的好处是:任何一个 channel 死掉或换协议,都不影响 quest 状态。比如微信 iLink 协议被收口,只要重写 weixin_ilink.py 就行,artifact 层一行不用改。

7.2 飞书 Connector 实战#

channels/feishu_long_connection.py 用的是飞书长连接(WebSocket),可以:

  • 接收文本消息 → 解析为 quest turn 的 user input;
  • 接收图片 / 视频 / 文件 → 落到 quest.userfiles/feishu/<batch>/,让 agent 通过 bash_exec 读取;
  • 主动发送文本 / 图片 / 视频回到同一个 chat;
  • 关键 milestone 自动生成 metric 曲线图发回。

绑定的入口在 Web UI 的 Settings > Connectors > Feishu,扫码 / 配置 token 即可,不需要任何 npx 或外部服务。

7.3 Connector 的安全边界#

docs/en/11_LICENSE_AND_RISK.md 反复强调:

“DeepScientist can execute commands, modify files, install dependencies, send external messages, and read or write project data.”

所以绑定任何一个 connector 之前,文档强制要求:

  • Docker / VM / WSL2 隔离;
  • 非 root 用户;
  • 不在生产机上跑;
  • 不暴露 0.0.0.0;
  • 不随便分享本地 URL。

这是因为 connector 一旦绑定,agent 就有了”主动发消息”的能力,任何 prompt 注入都可能变成对外攻击。这个攻击面必须在文档里写清楚,而不是藏着。

💡 小吴笔记:很多 Agent 框架的 connector 实现是”塞个 webhook 就完事”,不区分传输层和语义层。DeepScientist 的三层切分让”换协议”(比如哪天 Slack Socket Mode 收费了,换回 Webhook)只需要改 channel,bridge/quest 都不用动。这种”明确分层”是它能同时支持 10 套 connector 的工程基础。

八、BenchStore 与 optimize:论文优先 vs 算法优先的双轨#

在 19 个 skill 里,有两个特别值得展开:optimize 和 BenchStore 配套机制。

8.1 论文优先 vs 算法优先#

DeepScientist 默认的研究主循环是”论文优先”:

scout → baseline → idea → experiment → analysis-campaign → write → finalize
text

但如果 quest 是”算法优先”(比如 hyperparameter search / prompt 优化 / 模型融合),论文主循环就显得太重。idea/SKILL.md 里有这样一段:

When startup_contract.need_research_paper = false and the quest already has a concrete optimization handle, idea may stop after selecting or seeding a direction and then hand off into optimize instead of insisting on the full paper-oriented ideation loop.

也就是说,optimize 是一个分支 skill,专门服务”不发 paper、只要 frontier”的场景。它的子模式有 5 个:

explore | exploit | fusion | debug | stop
text

每轮 optimize 必须选一个主模式,推进一个”有 justified 证据的 frontier 步骤”,然后停。

8.2 BenchStore:YAML 写一遍,所有 quest 都能复用#

docs/en/22_BENCHSTORE_YAML_REFERENCE.md 描述了一个”benchmark 集市”机制:

  • 任何 YAML 文件放在 AISB/catalog/**/*.yaml,BenchStore 自动发现;
  • id 唯一(可由文件 stem 派生);
  • <stem>.zh.yaml 是中文 variant,locale 切到 zh 时自动替换;
  • schema_version = 1,字段全在 docs 22 章里。

这一机制解决的是”benchmark 复用”问题——你不应该在每个 quest 里都重新描述 GLUE / SuperGLUE / HumanEval 是什么,而是写一遍 YAML,所有 quest 引用即可。

8.3 BenchStore 怎么配合 optimize#

在算法优先 quest 里,典型流是这样的:

  1. start_research 时选”Algorithm-first” → need_research_paper = false;
  2. scout 锁定 baseline 之后 → idea 简短给一个 2-3 个候选 brief 的 slate;
  3. optimize 接管 → 走 explore 跑一批候选 → exploit 优化 frontier → 必要时 fusion 融合 → 直到 stop;
  4. 因为不发 paper,write 阶段被跳过(或只写个内部 SUMMARY);
  5. finalize 留下可复用的 brief frontier。

这种”论文优先”和”算法优先”双轨并存,是 DeepScientist 比传统 AI Scientist 系统更工程化的一个证据——不是所有研究都要发 paper,frontier 推进本身就有价值。

九、Runtime Tools:本地工具也用 Registry 管理#

最后看一个细节:runtime_tools/ 模块。

docs/en/90_ARCHITECTURE.md 第 19 节”Managed Local Runtime Tools”说,DeepScientist 把”可选 helper 运行时”也用 registry 模式管:

runtime_tools/registry.py   # register_runtime_tool() / get_runtime_tool_factory() / list_runtime_tool_names()
runtime_tools/service.py    # 高层 status / install / binary resolution
runtime_tools/builtins.py   # 内建注册
runtime_tools/tinytex.py    # TinyTeX provider
python

当前内建的是 TinyTeX(用于本地 pdflatex 编译论文),未来候选有 pandoc / graphviz / ffmpeg。

这种”registry-first 扩展点”是 DeepScientist 哲学的另一面——用一个小而显式的注册表,替代大型的 if-else 分支。runners / channels / connector_bridges / skill_discovery / runtime_tools 全部走 register_*() / get_*() / list_*() 三件套。

💡 小吴笔记:这是软件工程里很经典的小原则——“如果将来要加一种,就先把它做成 registry”。DeepScientist 没有在 daemon/app.py 里 if-elif-else 一长串判断”用户要装哪个 runner / 哪个 channel / 哪个工具”,而是在每个子系统的 __init__.py 里 register,daemon 启动时统一 list_*()。这让”加第 5 个 runner / 第 11 个 channel”的成本始终是 O(1)。

十、复刻流程与局限#

10.1 5 分钟本地启动#

npm install -g @researai/deepscientist
codex login                    # 或 claude / opencode / kimi
ds --here                      # 默认 http://127.0.0.1:20999
bash

如果是源码 install:

git clone https://github.com/ResearAI/DeepScientist.git
cd DeepScientist
bash install.sh
ds
bash

如果想要本地 LaTeX 编译:

bash install.sh --with-tinytex
bash

10.2 安全前置(必读)#

docs/en/11_LICENSE_AND_RISK.md 列了完整 checklist,核心是:

  • 用 Docker / VM / WSL2 隔离;
  • 非 root 用户运行;
  • 不在生产机 / 敏感数据机上跑;
  • 不暴露 0.0.0.0;
  • 绑定任何 connector 前再读一遍风险文档。

因为 DeepScientist 会执行 shell、读写文件、装依赖、主动发消息,给它过高的权限等同于给一个能上网的 shell 脚本。

10.3 当前局限#

  • Windows 原生支持仍 experimental。文档明确推荐 WSL2。
  • Stage 切换不自动。docs/en/06_RUNTIME_AND_CANVAS.md 第 6 节承认:active_anchor 不会由 daemon 自动推进,需要 agent 自己写 artifact + 改 quest.yaml。这让”完全无人值守”仍有一段距离。
  • ICLR 2026 Top 10 的论文还没有公开 arXiv 全文。仓库里的”论文”是 OpenReview 链接 + CITATION.cff 元数据,没有 PDF 副本。要评估”论文的实验部分”,得等 openreview 上的 supplementary。
  • runner 路径仍以 Codex 为主路径,Claude / OpenCode / Kimi 是”experimental”。生产建议 Codex。

十一、总结与启示#

回头看 DeepScientist,它给”长程 AI 科研”赛道留下了一份诚实的工程答卷——不画饼、不卖 agent-as-a-service,而是开源一个能让单个工程师在自己的笔记本上跑半年的本地操作系统。

维度旧”AI Scientist”范式DeepScientist
状态载体内存对话 + 临时 sandboxGit 仓库 + 文件 + artifact
阶段管理if-else 状态机prompt + skill 双驱动
MCP 表面越多越好严格 3 个(memory / artifact / bash_exec)
Shell 边界任意执行必须走 bash_exec,绕开即违规
研究结构看模型说看 git log + Canvas
多端入口一套聊天对应一套状态10 套入口共享同一 quest
失败资产跑完即丢永久保留在分支 + memory
Benchmark 复用每个 quest 重新描述BenchStore YAML 一次写,处处引

给做 Agent 系统的工程师的几点启示#

  1. “持久化”是研究方法论问题,不是工程问题。当你的”研究”以 Git 为单位时,你能 revert 一条假设、cherry-pick 一次消融、diff 两个 baseline——这些操作在 AI Scientist 类系统里基本是空集。
  2. MCP 表面越小,prompt 越干净。DeepScientist 把表面收缩到 3 个 namespace,这意味着 agent 的工具选择空间变小但每个都”够厚”。“加一个 MCP 比加一个 prompt 复杂”——这一句话值千金。
  3. “Shell 必须过 MCP”是一条值得抄的红线。system.md 第 0 节”Hard execution redlines”把”shell_command 是 forbidden”写死,所有 shell 调用必须经 bash_exec。这一条约束让训练崩溃、kill 重连、命令审计都成为可能。
  4. “Stage 切换”放在 prompt 里,不在 daemon 里。daemon 只读 active_anchor、不写它,切换由 agent 在 artifact 落盘之后自己改。这让加新 stage 的成本是 O(SKILL.md 文件),不是 O(daemon commit)。
  5. Canvas 不应该是图数据库,应该是 Git 的视图。node_traces.py 从 Git + artifact 重建 DAG,任何端拿到的 Canvas 都是一致的。“视图”而不是”主存”是它能跟 10 套 connector 协作的关键。
  6. “算法优先”和”论文优先”应该分轨。optimize + BenchStore 让不发 paper 的 frontier 推进有干净路径。这比”所有研究都按论文流程跑”更工程化。
  7. Registry-first 扩展点优于 if-else 大开关。runners / channels / bridges / skills / runtime_tools 全走 register_*() / get_*() / list_*() 三件套,加第 11 个 connector 的成本始终是 O(1)。

未解决的问题与未来#

  • 完全自动的 stage 推进仍没实现——active_anchor 还需要 agent 自己改 quest.yaml 来触发。要做到”无人值守”,daemon 需要引入”我观察到 X artifact 落盘了 → 自动改 active_anchor”这种事件驱动逻辑。
  • 跨 quest 的强一致性目前靠 git + 文件级操作,没有 transaction。两个 quest 同时改一个全局 memory 卡,目前是先到先得(虽然有 file_lock.py 提供基础锁)。要更严格的并发安全,需要进一步在 artifact 层加 CAS。
  • 评测协议本身缺位。DeepScientist 关注”跑通一个研究”的过程,不关注”怎么系统化比较 5 个 DeepScientist 实例谁更优”。它需要一个类似 OmniDocBench 那样的 “QuestBench”,目前仍空白。
  • Skill 市场未开放。19 个内建 skill 之外的生态,目前没有公开的注册表,需要用户自己 cp -r 复制别人的 skill 目录。这跟 dbt / Hugging Face Spaces 的”包市场”相比还有距离。

参考资料:

深入解析 DeepScientist:把长程科研从"对话"拉回"本地操作系统"
https://wth2jhl.online/blog/deepscientist-local-research-os/
Author 小吴同学
Published at August 6, 2026