我用开源栈复刻了一个“科研 Agent“:29 个技能、24 个 MCP 服务、一个有状态的内核——全都可复用
我用开源栈复刻了一个科研 Agent:29 个技能、24 个 MCP 服务、一个有状态的内核——全都可复用给大模型配一张真正的实验台,难的从来不是模型,而是脚手架。一句话概括Open Science Toolkit是一套在全开源栈上搭建 Claude-Science 风格科研 Agent 的可复用组件。它包含:29 个科研技能——AlphaFold2、Boltz、Chai-1、ESMFold2、OpenFold3、DiffDock、ProteinMPNN、ESM-2、Evo 2、Borzoi、scGPT、scVI……每个都是自包含的SKILL.md,按需加载;24 个领域 MCP 服务,封装了 62 个公开科学 API(PubMed、ChEMBL、临床试验、基因组、变异、表达、本体……);4 个 Agent 画像,身份与工作风格解耦,按角色裁剪工具;一个有状态的 Python 内核,变量跨 cell 存活,就像 Agent 自己操作的一个 notebook;一个自包含的浏览器聊天 UI,内置3D 结构查看(3Dmol.js,不依赖外部 CDN)。跑在 OpenHands V1 SDK 上,开箱无需 Docker;大脑可接任意 OpenAI 兼容端点。Apache-2.0 许可。pipinstall-e.--no-depscp.env.example .env# 填 LLM_BASE_URL / LLM_MODEL / LLM_API_KEYpython-mopen_science.server--serve--port8000仓库地址:https://github.com/WangHuiNEU/open-science-toolkit为什么做这个现在有一类 AI 产品,不只是聊科学,而是真的在做科学:折叠蛋白、设计序列、检索文献、跑数据、出图。它们很惊艳,但也都是闭源的。有意思的是,这类系统最难的部分并不是模型本身,而是脚手架——你怎么给一个语言模型配一张能干活的实验台?它怎么知道 AlphaFold2 存在、什么时候该调用它?怎么在不被二十几个生信 API 的工具定义淹没的前提下把它们都接进来?第 3 步算出的变量怎么活到第 8 步?一个.pdb文件怎么渲染成人能看的结构?Open Science Toolkit 就是我在开源栈上把这些零件逐一造出来的尝试——而且关键在于,每个零件都可以单独拆出来用。你不必整套照搬:clone 下来,只取技能加载器,或只取 MCP 聚合层,或只取有状态内核,接到你自己的 Agent 上即可。四个硬骨头,以及它们怎么被解决1. 技能:Agent 怎么知道自己会什么?把 29 个工具定义一股脑塞进系统提示,是烧穿上下文窗口、把模型搞晕的经典做法。这里换个思路:每个能力是一个技能(skill)——一个目录,含一个SKILL.md(YAML 头 指令)和它需要的辅助脚本。加载器采用渐进式披露:Agent 先看到一份精简的技能菜单(名字 一行描述),只有当某个技能与当前任务匹配时,才注入它的完整正文。相当于给 Agent 能力做懒加载。29 个技能分六大主题:结构预测与对接(6)、蛋白设计与嵌入(4)、基因组与单细胞(4)、图表与可视化(2)、文献与写作(4)、计算与工作流(9)。最后一组是元层:Modal / SSH-SLURM 上的远程 GPU 执行、用来写新技能的skill-creator、用来自省会话的self-awareness。因为格式遵循标准的 Agent Skills 约定,这些技能能直接放进任何兼容的框架。2. 数据源:接 62 个 API 而不付工具定义税科学都藏在 API 后面——PubMed、bioRxiv、ChEMBL、ZINC、临床试验、基因组装配、变异库、表达图谱、本体。全都朴素地接进来,工具列表就废了。工具箱把它们封装成24 个领域 MCP 服务——标准的 Model Context Protocol 服务,按领域分组(文献、基因组、变异、化学、试验……),把62 个 HTTP 客户端收在一个公共层之后,统一处理限流、重试、门控。服务按查询领域按需注入,所以 Agent 永远只看到与当前任务相关的工具。而且因为它们就是普通的 MCP 服务,可以独立用在任何MCP 客户端里——Claude Desktop、Cursor,随你。3. 状态:要的是内核,不是计算器大多数 Agent 的代码执行是无状态的:每段代码在真空里跑。真实分析不是这样——你加载一次数据集,然后一直在它上面干活。KernelSession封装了jupyter_clientipykernel,给 Agent 一个持久的 IPython 内核。变量跨 cell 存活:第一步加载 DataFrame,三步之后变换它,最后画出来——和人在 notebook 前一模一样。就这一个组件,直接改变了多步分析能做到什么程度。4. 身份 vs. 能力:用共享零件拼出四个 Agent一个 Agent 画像就是一份metadata.yaml,含身份提示(它是谁)、工作风格规则(它怎么做事)、能力开关。工具箱自带四个:operon——主科研计算 Agent,全套工具;onboarding——首次运行的引导设置,只问不做;reviewer——审查对话记录中的幻觉/编造;bookmarker——从对话里抽取要点。一个漂亮的工程细节是工具裁剪:OpenHands 用正向匹配的正则(filter_tools_regex)过滤工具,但画像是用excluded_tools黑名单来写的——这样读起来自然得多。中间的桥把黑名单编译成负向先行断言(negative-lookahead)正则,于是你写排除这几个,框架执行其余全放行。小细节,但写 Agent 时体验提升很大。架构一览层实现运行时OpenHands V1 SDK(MIT),LocalWorkspace——开箱无需 Docker大脑任意 OpenAI 兼容端点,凭据仅走环境变量内核KernelSession(jupyter_clientipykernel),变量持久技能基于检索的懒注入加载器(先菜单,匹配后注入正文)AgentOpenHandsAgentfilter_tools_regex工具裁剪3D 查看器3Dmol.js 内嵌在自包含 Web UI 里大脑刻意做成模型无关:三个环境变量指向任意 OpenAI 兼容端点即可。凭据只存在于环境中,绝不进任何提交的文件。盒子里到底有什么装配代码——src/open_science/(约 340 个 Python 文件):FastAPI 服务、Agent 加载器、内核、大脑、技能加载器、数据源注册表、溯源层、产物渲染、远程计算胶水、Web UI;29 个技能——skills_assets/(29 个SKILL.md 79 个辅助脚本);4 个 Agent 画像——agents_assets/;24 个 MCP 数据源——src/open_science/datasources/vendor/(62 个 API 客户端);设计拆解——docs/design-teardown/(9 章,讲清背后的模式:配置即调优记录、身份/工作风格分离、追溯而非重算、渐进式披露、MCP 聚合、自省与自知);验证脚本——tests/(分阶段冒烟测试:大脑往返、有状态内核、MCP 源、技能加载、Agent 裁剪)。一切都为可复用而设计。那 9 章设计拆解就是专门写来让你偷思路的,而不只是偷代码。五条值得偷走的设计原则(哪怕你永远不碰这个仓库)用渐进式披露替代大提示词。先给菜单,匹配后注入正文。上下文是预算。追溯,别重算。一个只读的溯源层,让 Agent 查历史产物,而不是重跑昂贵计算。身份与工作风格分离。它是谁和它怎么做事是两个轴,放在不同字段里,自定义画像才能只改一个而不丢另一个。把 API 聚合到一个带门控的公共层后面。限流、重试、门控属于共享层,而不是复制粘贴进 62 个客户端。状态本身就是特性。持久内核能解锁无状态执行器根本做不到的分析。上手gitclone https://github.com/WangHuiNEU/open-science-toolkitcdopen-science-toolkit pipinstall-e.--no-depscp.env.example .env# 填 LLM_BASE_URL / LLM_MODEL / LLM_API_KEYpython-mopen_science.server--serve--port8000# http://localhost:8000/ 聊天 UI# http://localhost:8000/docs API 面板Apache-2.0许可,基于 OpenHands(MIT)与 3Dmol.js(BSD)。模型权重各自遵循自身许可。如果这里面任何一个组件对你有用——技能加载器、MCP 聚合、有状态内核、黑名单→正则的工具裁剪桥——拿去用就好。它就是为此而生的。⭐ 仓库:https://github.com/WangHuiNEU/open-science-toolkit欢迎提 Issue、PR 和问题。