作者描述Claude Code通过两次MCP调用找到应用的共享契约,随后遭遇可用记录不足的问题。文章从新会话缺少既有系统上下文的体验切入。
很高兴你来到这里。每周一到周五,TNS 的优质内容都会送到你面前,帮助你及时掌握新闻动态,在工作中保持领先。
请查看收件箱中的确认邮件,你可以在邮件中调整订阅偏好,还可以加入其他群组。
在你喜欢的社交媒体平台上关注 TNS。
在 LinkedIn 上关注 TNS。
等待第一封 TNS newsletter 的同时,不妨看看最新的精选文章和热门报道。
每个 Claude Code 用户都见过新会话从零开始的情形。你打开上周刚搭好的系统,让它加一个小功能,Agent 却先开始重新摸清你自己的架构:哪个服务负责数据,哪个前端调用这个服务,两者共享哪个类型。解释过这些事情的对话已经消失,或者被压缩成了一份摘要;源码文件只能展示现有的东西,却没有说明谁依赖谁。
到目前为止,主要的解决办法是 memory。Claude Code 会在每次会话开始时加载 CLAUDE.md 指令和自己的 auto-memory 笔记。自 9 月 17 日起,重新设计的 Projects 在 Claude Code 云端会话中进入 beta,能够在线程之间保留共享 memory,让 Claude 记住“发布改到周五了”,或者“修改计费服务前该找谁确认”。我想测试另一种上下文来源:构建平台在创建组件的每个版本时写入的依赖记录。
利益披露:我是 Bit Cloud 的工程师。这个平台从第一个组件开始,就能构建、托管和部署应用,哪怕只有一个应用,coding Agent 也能通过 MCP 在平台上开展工作。我让 Claude 在这个平台上构建项目,想看看当平台在各部分及其依赖被赋予版本时记录下这些信息,Agent 能做到什么。项目和构建记录都是公开的。
这个系统是一个小型客服控制台,我之前用 Claude Code 构建了它,并另写了一篇文章介绍构建和部署过程。启动那次构建的 prompt 只用两个词提到了工具:“using Bit”,其余内容都是产品描述。系统包含四个组件:一个 React 应用、一个以 MongoDB 为后端数据库的 Express 服务、一个共享的 ticket entity,以及一个将应用和服务置于同一个 gateway 后面的平台组件。四个组件都在公开的 scope bit-oss.support 中进行版本管理,控制台通过 HTTPS 在生产环境运行。
为了测试仅凭这些记录能提供多少上下文,我在一个空 workspace 中开启了全新的 Claude Code 会话,没有对话历史,也没有本地代码,然后提出了这个要求:
Add filtering by ticket status and assignee to the support console in bit-oss.support.
Claude 检查了 workspace,发现没有本地组件。它接着说:“workspace 是空的,所以客服控制台位于远端。让我通过 MCP 读取 bit-oss.support scope。”它先对 bit-oss.support 调用了 read_scope,拿到了四个组件及其依赖。随后,它针对应用、服务和 ticket entity 调用了 read_components,在导入源码或编辑代码之前,先获取了 API 参考文档和文件清单。
应用和服务都依赖同一个版本的 ticket entity。这个类的文档写着:“由客服服务和面向客服人员的应用共享”,API 参考文档也包含了这句话。即使没有原来的对话,项目本身也能提供这份上下文。
Claude 使用 bit import 导入了全部四个组件,检查源码,并在应用中实现了客户端筛选。验证结果显示,41 项测试通过,其中包括九项新增的筛选测试。MCP 帮它发现了系统结构;源码检查和测试则确定了该如何修改。改动只发生在应用内部,共享的 ticket entity 和服务都没有变。知道哪些东西是共享的,也能告诉 Agent 哪些地方不该动。
到了行为层面,记录就不够用了。应用的 API 参考文档确实列出了它调用的路由:GET /tickets、POST /tickets、PATCH /tickets/:id 和 POST /tickets/:id/comments。但这些内容写在测试所用的 fake service 文档里,没有任何机制将这份列表与真实服务进行核对。记录告诉了 Claude 哪些组件共享 ticket contract;至于两端的路由是否仍然匹配,就必须靠人工阅读和测试来确认。
构建通过所能证明的事情,也比看起来要少。如果临时数据库无法在 CI runner 上启动,MongoDB 集成测试就会跳过,所以构建通过并不能说明这些测试实际运行过。我手动检查了持久化:创建一张工单,添加一条评论,让平台连接同一个数据库重新启动,再确认工单和评论都还在。
而且,这只是一个 demo,带有预设的 demo 账号和公开的签名密钥。并发控制、数据库迁移、恢复流程,以及强制执行数据库测试,都还没有完成。这些都是常规的工程工作,也是我希望工程师把时间花在上面的地方。
memory 保存的是有人选择记下来的信息。在 Claude Code 中,这包括人编写的 CLAUDE.md(或 AGENTS.md)指令,以及 Claude 根据纠正意见和偏好写下的 auto-memory 笔记。重新设计的 Projects 还会补充决策信息,例如为什么取消了某项导出功能,这些内容是任何构建系统都不会记录的。每条笔记反映的都是写下它那一刻的信息。Claude Code 会记录每个 memory 文件的写入时间,文档也解释了原因:“时间戳表明这条事实有多新。”
构建系统在创建组件版本时写入依赖记录,这份记录就是该版本的一部分。客服应用被赋予版本时,构建系统记录了它依赖 ticket entity 的某个特定版本,不需要任何人判断这件事是否值得记下来,而且记录不会与它描述的版本发生偏离。由于 read_scope 返回的是每个组件的最新版本,Claude 读取的记录也是当前的。memory 笔记带有写入时间,却没有任何机制将它与代码版本绑定。在这次测试中,会话没有对话历史,也没有本地代码。workspace 中唯一的 memory 是 bit new 写入的通用 AGENTS.md,它告诉 Agent 去平台上查找信息。剩下的工作都由记录完成:这些记录足以找到共享 contract。
两者覆盖的范围不同,结合使用效果最好:memory 用来保存意图,比如发布日期、该找谁询问,或者为什么砍掉某个功能;记录则用来保存结构和含义,说明什么组件的哪个版本依赖什么组件的哪个版本。Nx 通过 MCP 向 Agent 提供 project graph,Sourcegraph 则提供跨仓库的代码搜索和导航;两者都很好地完成了各自的工作。这次测试中,我想要的东西更具体:每个组件都有一份在创建其版本时写入的记录,即使依赖关系的另一端位于 Agent 尚未建立索引的地方,这份记录也依然有效。
从第一个组件开始。这次测试中的记录没有产生任何额外成本,因为从第一天起,每个版本创建时都会写入记录。我使用 bit new 创建 workspace,它在 .mcp.json 中提供了 Bit Cloud MCP 连接,还生成了一份包含 Agent 指令的 AGENTS.md。在最初的构建开始时,Claude 利用这个连接,浏览了一个已有的 design system scope,寻找可以复用的部分。现在,这四个组件依赖 16 个已有组件,其中十个来自那个 design system。等到一个团队重命名了共享字段,另一个团队从错误日志中才发现这件事,再回头重建这张依赖关系图,做的还是同一件事,只是代价更高。
这些都不要求使用我们的产品;只需要在实际开展工作的地方记录依赖关系。
Agent 已经能够把应用带到生产环境。而在第一次请求之后的每一次请求中,它们仍然缺少的,是对即将修改的系统的整体认识。在第二个组件出现之前建立这份认识,成本最低。