构建一个有明确设计取向且极简的编码代理时,我学到了什么

2025-11-30

注:为避免改动可执行示例的语义,文中的代码块、命令和配置示例保留原文。

不算多,但它属于我。

目录

过去三年里,我一直在用 LLM 辅助编程。如果你会读到这篇文章,那你大概率也经历过同样的演进过程:从把代码复制粘贴到 ChatGPT 里,到 Copilot 自动补全(反正我这边一直不好用),再到 Cursor,最后是 2025 年成为我们日常主力的新一代编码代理框架,比如 Claude Code、Codex、Amp、Droid 和 opencode。

我在大多数工作里更偏爱 Claude Code。四月那会儿,在用了一年半 Cursor 之后,我第一次试了它。那时候它还要朴素得多。这非常契合我的工作流,因为我是个喜欢简单、可预测工具的朴素家伙。可在过去几个月里,Claude Code 已经变成了一艘宇宙飞船,其中 80% 的功能我根本用不上。它的系统提示词和工具定义每次发版都会变,这会打断我的工作流,也会改变模型行为。我很讨厌这一点。而且,它还会闪屏。

这些年我也自己做过不少代理,复杂度各不相同。比如我的小型 browser-use 代理 Sitegeist,本质上就是一个活在浏览器里的编码代理。在这些实践里,我学到的一件事是:上下文工程至关重要。精确控制哪些内容会进入模型上下文,能显著改善输出,尤其是在模型写代码的时候。现有的许多框架会偷偷往上下文里塞东西,而且 UI 里甚至不会展示出来,这让这件事变得极难,甚至不可能做好。

说到“展示出来”,我希望自己能检查我和模型交互的每一个方面。基本没有哪个框架真正允许你这么做。我还想要一种文档清晰、可自动后处理的会话格式,以及一种在代理核心之上构建替代 UI 的简单方式。现有框架里虽然有些能做到一点,但它们的 API 一股“自然生长”出来的味道。这些方案一路积累了很多历史包袱,而这些包袱会直接体现在开发体验上。我不是在怪谁。如果一大堆人都在用你的玩意儿,而你还得维持某种向后兼容,那这就是你要付出的代价。

我这些年也折腾过自托管,既有本地部署,也有跑在 DataCrunch 上的。有些框架,比如 opencode,确实支持自托管模型,但通常体验都不太好。主要原因是它们依赖了类似 Vercel AI SDK 这样的库,而这些库出于某些原因和自托管模型的配合并不理想,尤其是在工具调用这件事上。

所以,一个对着 Claude 大喊大叫的老头子该怎么办?当然是自己写一个编码代理框架,再起一个根本没法被 Google 到的名字,这样就永远不会有用户。也就意味着 GitHub issue tracker 里也永远不会有 issue。能有多难呢?

为了把这件事做成,我需要构建: