Agent越来越智能,但我发现软件工程仍然很重要
我发现,我现在越来越离不开 Agent。
它能更聪明了。
以前每次需要我指明改哪里,有时候为了害怕改错了,我都会把代码位置指出来。有时候,还会担心它写不出来(或者说是理解不了)。而现在,它似乎比你更懂你的工程,也会很清楚你接下来想干的事,我几乎不担心它是否能完成我交代的任务了。
前天,我在考虑给 Browser Bridge 添加服务端认证模式。这个模式下,允许浏览器插件,连接到非本地的 Agent。
因为多了层网络,所以需要添加一些鉴权的功能。
整个认证的流程并不复杂,主要是登录和服务端鉴权两个部分。
登录(获取token)
这里是在浏览器插件中完成。在浏览器插件中,发起 Http 请求,得到鉴权之后的 token 和 user_id。接着,拿着这个 token 和 user_id 去进行 websocket 连接。
Websocket服务端鉴权
WebSocket 服务端在建立连接的时候需要获取 token 和 user_id,然后同样的需要请求鉴权接口,来验证 token 和 user_id 的合法性。
在做认证接口的时候,我只贴了鉴权的API及其响应结果的样例。但是,代码还是很快就写好了。
只不过调试的时候登录不上。
我看了下错误堆栈。发现是因为API返回的响应格式和代码里预期的不一样。
本来没什么,改改就好了。
然后,接着又有报错。一看,发现返回的 user_id 类型是 number,但代码里定义成了 string。
这种小问题,Agent 分分钟就给你改好了。
但是,继续测试时发现虽然现在能登录上。但连接在不断的重连,日志里面没有具体的内容,只有重连的日志。
我让 Agent 帮我查了查,它说是因为 user_id 在服务端仍然是当做 string 在用,导致报错了。之所以不打日志,是因为那个地方把异常吃掉了。服务端抛异常,客户端只能不断地重连。
也许是缘分到了,想起当天中午在卡兹克之公众号里面提到的两个技巧“第一性原理”、“对抗式审查”。
于是,我抱着试一试的心态,让 Agent 使用第一性原理来找根儿上的问题。
没过一会儿,它找到了,原来是同一个接口的定义,在两边定义。之前都是按照之间的字符串来定义的,刚刚报错 Agent 只改了当时报错的地方,换句话说只改对了一半儿!
Agent 问我要不要保持两边接口定义的一致?可我想问它,为什么你不知道改其他类似的地方呢?
这现象有点反直觉。按往常来看,Agent 改 bug 时,在修复完后会找跟这个地方有关联的代码跟着一起修改,怎么这次它突然不灵了?
鉴于当时的上下文已经被清理,而且是使用 SubAgent 实现的这个功能,中间的日志也太多,也不好找。所以,我开始猜想。会不会是 copy 代码的问题?
因为,是 copy,所以两个定义响应内容的地方根本没有引用关系。因此,Agent 做代码扫描的时候很可能通过 grep 只找到了当时需要修改的那个地方所在的方法,然后顺着调用链路来查,就结束了。
如果真实这样,那即使是在 MonoRepo 这样的项目里面,也确实不一定能关联到所有需要变动的地方。
我突然间想起刘震云的一句话,“这事儿从根上就错了”。
我想了下,这事儿就不是要不要保持一致,而是一定要保持强一致。
代码是两个地方有一模一样的类型定义,要改的话,得两个地方都改。如果只在一个地方定义,所有地方共用一份代码,那这才是从根儿上解决了这个问题吧?
如果代码还是两个地方都有,仅仅是保持两个地方的代码一致。装一点来说,“这并不本质”。
为了让所有用到API的地方都保持强一致,必须在共享包目录下来定义。然后,各个 repo 去依赖这个共享包,这个模式让我突然想到“服务契约”。
本身这是在微服务中用的很多的,按说我这个 monorepo 项目,本质上就是一个单体应用,理论上是用不到的。
为什么这里又能扯到服务契约呢?
多端的代码在一个 Codebase 下,Agent 肯定是能识别到的,而如果能识别到,那在代码实现的时候 Agent 应该会自觉遵守。毕竟,换成人来写代码,如果发现两个地方的 API 用的是一样的我肯定是知道这两个地方的响应结构是一样的。
但实际上,我这个场景隐含了一个假设。那就是第一次定义 API 响应内容的时候,一定是正确的。
我第一次使用这个 API 时使用的是错误的响应,以致于后面写的代码会照抄这个响应逻辑。
等到报错之后,我才发现我要 API 的响应结构。可是修改的时候 Agent 只会改你提到的地方,不会进一步思考是不是会有其他地方也需要改。
等等,这个易错模式,我有点熟悉。好像在 《重构》 里面提到过“霰弹式修改(Shotgun Surgery)”——需要修改的代码散落在各处,难以找到他们,容易修改遗漏。
这样一解释,完全就说通了。
想要从根上解决,还得靠软件工程这些年下来沉淀的经验。
虽然现在的代码不由人来维护,但人的精力还是有限。软件工程沉淀下来的约束,可以让 Agent 更好地管理代码,跑得更有效率。
GitHub - dkisser/browser-bridge: Let AI agents and scripts control your local browser through a simple CLI — keeping your sessions, cookies, and credentials local. · GitHub