📘 原文信息
- 项目名: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_execMCP——所有 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/),做一次重述与解读,重点回答:
- 为什么”一题一仓库”是核心设计选择,而不是营销话术?(第 2 节)
- JavaScript 启动 + Python 运行时这套双层架构,是怎么解决”用户友好 + 状态权威”这对矛盾的?(第 3 节)
- 三个内置 MCP(memory / artifact / bash_exec)各自承担什么,为什么”只暴露三个”是优势?(第 4 节)
- Prompt + 19 个 Skill 怎么替代”巨型状态机”?(第 5 节)
- Canvas(那张漂亮的拓扑图)到底是怎么从 Git + 文件”长出来”的?(第 6 节)
- 10 套 Connector 怎么共用一份 quest state?(第 7 节)
- BenchStore 和
optimizeskill 如何让”算法优先”和”论文优先”两条路都跑得通?(第 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 团队没这么做,原因有三:
- 用户安装习惯。目标用户群(研究生 / 工程师)90% 已经装了 Node.js,但不一定有干净的 Python 3.11+ 环境(尤其 macOS 系统 Python 不可写、Windows 没自带)。
- 跨平台工具链。
uv管理的 Python 环境隔离 + 自动 install,比让用户自己venv/conda友好得多;而uv又可以通过 npm 包来调度。 - 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:20999textdocs/en/90_ARCHITECTURE.md 里专门有一句话:
“
bin/ds.jsshould stay thin. Product behavior belongs in Python services, prompts, and skills.”
这条约束意味着:任何”产品行为”都不应藏在 JavaScript 里。launcher 只做”启动 + 暴露端口”,所有业务逻辑都在 Python。
3.3 Python 端的两层骨架#
Python 端(src/deepscientist/,134 个文件)按职责拆成几块:
| 子系统 | 关键文件 | 职责 |
|---|---|---|
cli | cli.py | 薄壳,只转发到 quest / config / doctor / runtime 服务 |
daemon | daemon/app.py(8890 行) | HTTP server + turn scheduler + API 路由 + connector 协调 |
quest | quest/service.py(8327 行)、quest/layout.py | quest 创建、快照、状态、布局契约 |
artifact | artifact/service.py(16105 行) | Git-backed 结构化记录、批准、报告、interactions |
memory | memory/service.py、memory/frontmatter.py | 全局 + quest 级 Markdown 记忆 |
bash_exec | bash_exec/service.py(1659 行) | 可暂停、可重连、可追溯的 shell session |
mcp | mcp/server.py | 三个内置 MCP 命名空间(memory/artifact/bash_exec) |
runners | runners/codex.py、runners/claude.py、runners/opencode.py、runners/kimi.py | 4 套 runner 适配 |
bridges/connectors | 10+ 桥接器 | 把外部 IM 转成 quest 事件 |
channels | channels/feishu_long_connection.py 等 | 10+ 个 channel 的轮询 / 长连接实现 |
runtime_tools | runtime_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_executionis forbidden for this workflow. Every terminal-like action must be executed throughbash_exec(...).
它把 MCP 表面严格限制在三个:
| Namespace | 用途 | 典型操作 |
|---|---|---|
memory | 沉淀可复用知识 | write / read / search / list_recent / promote_to_global |
artifact | 推进 quest 状态 | interact / experiment_record / branch_transition / arxiv / complete_quest |
bash_exec | 执行 shell | start / read / list / kill |
4.1 三个 MCP 各自的工程含义#
memory 命名空间——所有记忆卡都是带 YAML frontmatter 的 Markdown 文件,支持 6 种 kind:
papers | ideas | decisions | episodes | knowledge | templatestext为什么是 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 hashbranch_transition(...):记录一次分支决策(为什么开新分支、为什么放弃)decision_record(...):把”路线判断”沉淀为可被以后 recall 的卡片interact(...):与用户的对话流,带kind=milestone | progress | blocker区分complete_quest(...):唯一允许”宣告完成”的地方——必须有用户显式 approve
bash_exec 命名空间——它解决的是 LLM 跑 shell 的几个老问题:
| 问题 | 传统 shell | bash_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, orruntime_toolMCP 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 disciplinemarkdown5.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 到 decisiontext也就是说: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 messagetext第 8 段尤其重要——memory 注入是 stage-aware 的。例如:
scout阶段优先拉papers/knowledge/decisionsbaseline阶段优先拉papers/decisions/episodes/knowledgeidea阶段优先拉papers/ideas/decisions/knowledgeexperiment阶段优先拉ideas/decisions/episodes/knowledgeanalysis-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 节点的生命周期#
典型流程:
- agent 完成 baseline → 写
artifacts/baselines/xxx.json+git commit; - agent 决定开 idea 分支 → 调
artifact.branch_transition(...)→ 自动git checkout -b; - node_traces 从新的 Git history 重建 DAG → Canvas 自动多一个节点;
- 前端通过
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) ...text10 套 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 → finalizetext但如果 quest 是”算法优先”(比如 hyperparameter search / prompt 优化 / 模型融合),论文主循环就显得太重。idea/SKILL.md 里有这样一段:
When
startup_contract.need_research_paper = falseand the quest already has a concrete optimization handle,ideamay stop after selecting or seeding a direction and then hand off intooptimizeinstead of insisting on the full paper-oriented ideation loop.
也就是说,optimize 是一个分支 skill,专门服务”不发 paper、只要 frontier”的场景。它的子模式有 5 个:
explore | exploit | fusion | debug | stoptext每轮 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 里,典型流是这样的:
start_research时选”Algorithm-first” →need_research_paper = false;scout锁定 baseline 之后 →idea简短给一个2-3 个候选 brief的 slate;optimize接管 → 走explore跑一批候选 →exploit优化 frontier → 必要时fusion融合 → 直到stop;- 因为不发 paper,
write阶段被跳过(或只写个内部 SUMMARY); 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 providerpython当前内建的是 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:20999bash如果是源码 install:
git clone https://github.com/ResearAI/DeepScientist.git
cd DeepScientist
bash install.sh
dsbash如果想要本地 LaTeX 编译:
bash install.sh --with-tinytexbash10.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 |
|---|---|---|
| 状态载体 | 内存对话 + 临时 sandbox | Git 仓库 + 文件 + 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 系统的工程师的几点启示#
- “持久化”是研究方法论问题,不是工程问题。当你的”研究”以 Git 为单位时,你能
revert一条假设、cherry-pick一次消融、diff两个 baseline——这些操作在 AI Scientist 类系统里基本是空集。 - MCP 表面越小,prompt 越干净。DeepScientist 把表面收缩到 3 个 namespace,这意味着 agent 的工具选择空间变小但每个都”够厚”。“加一个 MCP 比加一个 prompt 复杂”——这一句话值千金。
- “Shell 必须过 MCP”是一条值得抄的红线。
system.md第 0 节”Hard execution redlines”把”shell_command是 forbidden”写死,所有 shell 调用必须经bash_exec。这一条约束让训练崩溃、kill 重连、命令审计都成为可能。 - “Stage 切换”放在 prompt 里,不在 daemon 里。daemon 只读
active_anchor、不写它,切换由 agent 在 artifact 落盘之后自己改。这让加新 stage 的成本是 O(SKILL.md 文件),不是 O(daemon commit)。 - Canvas 不应该是图数据库,应该是 Git 的视图。
node_traces.py从 Git + artifact 重建 DAG,任何端拿到的 Canvas 都是一致的。“视图”而不是”主存”是它能跟 10 套 connector 协作的关键。 - “算法优先”和”论文优先”应该分轨。
optimize+BenchStore让不发 paper 的 frontier 推进有干净路径。这比”所有研究都按论文流程跑”更工程化。 - 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 GitHub ↗
- DeepScientist Paper (OpenReview, ICLR 2026) ↗
- DeepScientist 官网 ↗
- npm 包 @researai/deepscientist ↗
- docs/en/90_ARCHITECTURE.md(维护者架构参考) ↗
- docs/en/13_CORE_ARCHITECTURE_GUIDE.md(用户面架构指南) ↗
- docs/en/06_RUNTIME_AND_CANVAS.md(运行时与 Canvas) ↗
- docs/en/07_MEMORY_AND_MCP.md(三个内置 MCP 协议) ↗
- docs/en/02_START_RESEARCH_GUIDE.md(Start Research 契约) ↗
- docs/en/11_LICENSE_AND_RISK.md(运行前必读风险声明) ↗
- src/prompts/system.md(1280 行核心 system prompt) ↗