我是先看到宠物的。一只水豚,带一顶高礼帽,在终端提示符旁边眨眼。那会儿我以为是谁做的皮肤,往下翻才发现这段逻辑来自被还原的客户端源码。
先把边界说清楚:泄出来的是本地命令行工具的 npm 包,不是模型权重,不是后端服务,也没有用户数据。所以这些彩蛋只能反映工程文化,说明不了能力。真正让我停下来的是另一段代码——用环境变量区分内外用户的那一段。
十八只宠物和一个哈希
宠物系统的实现比想象中正经。物种、稀有度、性格不是每次启动随机,而是用账号 ID 做哈希算出来的。也就是说,同一只宠物跟定一个人,换机器、重装、升级版本都不变。稀有度有明确分布,从常见到百里挑一,最稀有的那一档大概在百分之一上下;装饰物另算,礼帽、竹蜻蜓、巫师帽之类的可以叠。
物种命名带着很重的社区口味:水豚代表情绪稳定,钝口螈是极客圈的常客,还有一个直接叫“圆滚滚的胖子”。空闲时会眨眼、做小动作,偶尔弹一句十秒的对话。系统里还有个专门的互动命令,触发时终端会画出一个符号作为回应。
这东西在发布版里是关掉的,靠特性开关加死代码消除在构建阶段整段移除。想看到它得自己把源码跑起来,改掉编译条件。
死代码消除这个细节,比宠物本身更值得注意。它意味着这段逻辑在最终产物里连字节都不存在,用户拿到的包是干净的。但源码映射文件把这个“干净”推翻了:被消除的代码仍然以字符串形式留在 map 的 sourcesContent 里。构建时做了减法,发布时又原样带了回去。
我注意到的是那种“确定性的随机”:同样一个输入,永远得到同样的结果,不存在“这次是一只猫下次变成幽灵”。做产品做久了会对这个细节敏感——任何需要长期陪伴感的东西,随机性都得是有边界、可复现的,否则用户会觉得世界不稳定。
从实现角度看这个选择也很省:不用在服务端存一张“谁养了什么”的表,不用处理跨设备同步,不用怕用户换账号之后数据对不上。一个哈希函数就替代了一套用户资产系统。稀有度的分布写在代码里,改起来也只是一次发版。这类设计谈不上多高级,但很干净,是我会愿意抄的那种。
从投入产出看,这功能对核心任务的帮助是零。但它透露了一件事:团队在自己的工具上花的时间足够长,长到有余力往里面塞和 KPI 无关的东西。我不认为这是浪费,也不认为这是值得效仿的标配。它更像一个温度计。
我见过一些团队学这类彩蛋,结果做得很难看:启动时随机弹一句“今天也要加油哦”,或者给命令行加一堆没有信息量的 ASCII 画。问题不在于趣味本身,而在于趣味是不是从真实使用里长出来的。宠物系统之所以成立,是因为开发者每天要在终端里待七八个小时,那个位置本来就该有点别的东西。
内部员工的那套提示词
if (process.env.USER_TYPE === 'ant') 后面跟着的东西,比宠物有意思得多。
对外部用户,助手的基调是配合的:解释可以长一点,拿不准的地方会铺垫,遇到模糊需求倾向于先做一版再问。对内部员工,这套礼貌被剥掉了,留下的是行为约束:尽量不新建文件,优先改已有的;没用的代码直接删,不要为了兼容加垫片;子任务运行中不许中途读它的输出,更不许编一个结果;破坏性操作先确认。语气也不同,对外的规则会解释原因,对内的多数只给结论——读者是同事,不需要铺垫,也不吃“这样做更好”这种话。
这些规则单独看都很朴素,放在一起就成了一份代码规范。它约束的不是模型“说什么”,而是模型“做什么”以及“什么时候停”。我印象最深的是一条禁令:删掉没用的代码,而不是加一层兼容垫片。它反的是工程里最常见的那种“先垫住再说”的惯性。
维护两套提示词的成本不在写,在同步。一条通用规则改了,两边都要过一遍,否则内部版本会慢慢变成只对某个团队生效的分支,谁也说不清哪边才是准的。我倾向于把共用部分抽成模板,差异项单独列,宁可多一层拼装,也不要两份手抄文本。
我自己的体感是,给 Agent 写系统提示词时最容易犯的错,是把它写成人物小传:你是一位资深工程师,你严谨、有耐心、注重质量。这类句子几乎不产生行为差异。真正生效的是可判定的句子:不许创建新文件,不许改测试,失败两次就停下来问。前者是形容词,后者是断言。
后来我给自己那个小 Agent 加了三行,效果比之前调的两百字人设都明显:改动超过三个文件就先列计划等我确认;连续两次工具报错就停下,不要换参数再试;不确定路径时先列目录,不要猜。这三条都不是“性格”,是“停止条件”。Agent 出问题往往不是因为不够聪明,是因为不知道什么时候该停。
反面也有代价。内部那套规则里有一条很长的“谨慎执行”指令,几百个 token,逐条列出什么情况下要先问。这类指令确实能减少误操作,但它占上下文,也会稀释别的规则。我试过把类似的清单堆到十几条,结果模型开始只遵守最后两条。规则的有效数量和上下文预算是绑在一起的,写得多不等于管得严。
好的系统提示词读起来像代码规范,不像自我介绍。
两套提示词并存这件事本身也值得记一笔。同一个模型,在不同的权限上下文中被要求表现出不同的行为边界。对外用户,风险主要来自误解和误操作,所以要慢、要解释;对内部员工,代码库是自己的,出错成本由内部承担,于是可以激进、可以删代码。这不是双标,是把风险敞口算清楚了。
顺带说,“内部先用”这件事本身就是一种测试策略。让员工每天用自己的工具写自己的代码,暴露出来的问题比任何内测都真实。代价是内部习惯会悄悄塑造产品:一套为自家 monorepo 优化的规则,放到一个只有三个文件的小项目里,可能会显得过度谨慎。这个偏差不容易被发现,因为做决策的人正处在被优化的那个环境里。
特性开关不等于路线图
源码里还有一批开关,名字指向多智能体路由、上下文压缩、MCP 的试验性传输、终端渲染的双缓冲。卧底模式则更进一步:绕过 schema 校验、打开调试日志、运行时切换内外两套提示词。
绕过校验这一条值得单独说。它意味着内部人员可以把不符合工具定义的参数直接塞进去,用来测边缘情况;同时还能拿到完整的运行日志,包括错误恢复的每一层堆栈、token 预算的实时消耗、上下文压缩的触发时机。这套东西在外部用户那里是看不到的,因为它是为“排查”设计的,不是为“使用”设计的。
这些名字很容易被读成产品预告。我看到过不少“下一代功能已确认”的说法,依据只是代码里出现了某个变量。
我的看法保守:特性开关在大规模商业软件里有三种常见归宿——即将发布、正在 A/B、以及被无限期搁置的废案。仓库里还留着上一个季度的黑客松产物,这是常态。能确认的只有“团队在做或做过这件事”,不能确认它会不会出现在公开版本里,更不能确认时间。
几个开关本身倒是透露了方向:一个多智能体路由的名字,说明他们在试把复杂任务拆给多个子 Agent;一个上下文压缩的开关,对应长会话里的记忆瘦身;还有终端渲染的双缓冲,明显是为了解决高频刷新时的闪烁。这三个放在一起看,指向的是“更长、更并发”的会话形态,而不是更强的单次回答。
不过这类开关确实解释了泄露面为什么这么大。为了支持灰度和主干开发,实验性逻辑被打进生产包,靠白名单下发配置。功能没上线,代码已经在用户机器上。这是一个明确的取舍:换来了发布灵活性,付出了“任何人都能看到未发布内容”的代价。做 To B 产品时我也遇到过同样的选择,最后选了服务端下发而不是客户端内置,代价是离线场景变差。
客户端内置还有一个副作用:功能能被绕过。开关的判定条件如果写在本地,只要有人愿意改二进制或环境变量,就能提前打开。对内部调试工具来说这无所谓,对涉及计费或权限的功能就成了实质风险。判断标准很简单:这段逻辑泄露出去会不会造成损失,会,就放到服务端。
我自己维护开关的习惯是在定义旁边写一行“关掉之后会发生什么”。写不出来,说明这个开关没有明确的回收条件,大概率会一直挂着,变成半年后没人敢删的代码。能写出来的,通常三个月内就能清掉。
我的读法比较笨:先看目录树,判断代码主要花在哪;再看几个核心类的字段,因为字段暴露的是“系统认为什么重要”;最后才看提示词。营销号的概括通常是反过来的——先摘几句提示词,配上“震惊”,把工程判断全跳过。
这也解释了同一个事件为什么会有完全不同的解读。有人看到宠物,觉得这公司不务正业;有人看到特性开关,开始预测下一代产品;我看到的是一套把权限、缓存、错误处理都写在代码里的工具,以及一个忘了关的构建选项。
我对这份源码的兴趣,到这儿基本用完了。宠物是谈资,开关是谈资,中间那套内外有别的提示词才是能直接拿走的东西——它不说明模型有多强,只说明别人怎么给一个不确定的系统划边界。
评论