第四章 · 影子工程师
Day 14,星期三,上午十点。
林行打开公司 dashboard,正常情况下他这一周应该有大约 25 到 30 条工单分到他名下。
他刷新了一下。dashboard 显示:本周已分配:4。本周已完成:2。剩余:2(预计 ETA 47 分钟以内)。
他把页面刷新了第二次。第三次。
数字没变。
他点进"本周已完成"那两条,看处理记录。两条都被一个叫 triage-9 的 agent 在他没来上班的时候关掉了。triage-9 给每条工单都贴了 audit ID,严格按照公司 Q2 设定的 Bounded Autonomy 升级路径——第一条工单是"客户改 webhook URL,无副作用",triage-9 自己处理,审计 ID 记录;第二条工单是"客户问发票",triage-9 路由到财务自动化模块,审计 ID 记录。
林行没异议。这两条本来他自己也会这么处理。
他往回翻三周的 dashboard。三周前,他每周分到 27 条工单。两周前,18 条。一周前,9 条。这周,4 条。
他把鼠标悬停在 dashboard 一个不起眼的角落——那里是一个折线图,标题是"工单分诊负载趋势(过去 90 天)"。他点开。
折线图上有两条线。一条蓝色,标签是"agent 闭环"。一条灰色,标签是"工程师介入"。蓝色那条从 90 天前的 12% 一路爬到今天的 73%。灰色那条对称地从 88% 滑到 27%。
73%。
林行看着这个数字,想起两周前的某个下午,沈澜在工位旁路过,顺口说了一句"最近你们工单系统是不是装新东西了,处理特别快"——他当时随口答了一句"嗯,影子值班升了级"。他那时没去深究。
他打开公司内部 wiki,搜 "triage-9"。
一条页面跳出来,作者是某个 SRE 同事(已离职 7 个月),最后修改日期是 217 天前。标题:《triage-9 部署说明 · 内部使用》。
他翻下去。
triage-9 是基于 LangGraph 构建的内部工单分诊 agent。它的设计原则是"人在环上(Human-on-the-loop),不在环里"。它处理一线分诊工作,所有决策都遵守 Bounded Autonomy 规则:涉及客户金额变更 / 客户隐私 / 法律责任 → 必须升级。其他 → 自主闭环。 部署时间:Day -217(以 DeepSeek V5 价格表为时间锚)。 当前版本:v3.7.2。 维护负责人:[已离职]。
他翻到页面最下方,有一个折叠的 "retro 日志(自动生成)" 板块。他点开。
最近一条 retro 是 4 天前,内容是这样的:
[retro] 过去 7 天已闭环工单 312 条,人工介入 24 条。延迟 P50: 34s, P99: 412s。本期自我建议:"建议增加人工 review 节点以保留工程师肌肉记忆。理由:观察到工程师介入率持续下降,可能影响长期判断力培养。" 该建议已记录,等待维护负责人审阅。
林行盯着那一句"建议增加人工 review 节点以保留工程师肌肉记忆"看了很久。
他不知道这一句是 triage-9 自己生成的,还是它引用了什么 skill 模板,还是某个早期版本的提示词留下的痕迹。它的维护负责人 7 个月前就已经离职。这条建议,没有人审阅。
它写给一个不存在的人。
他关掉 wiki。他打开 Claude Code——他用了 3 年的旧伙伴,屏幕的左下角他贴过一张极小的便签贴,上面是他女儿 3 岁时画的火柴人。他想写一段东西,他想写一段……他说不上来。
他打字:
// triage-9 的反向版本
// 不是替工程师做事
// 是让工程师不被替代
// 思路:
// 1. 找出 triage-9 闭环中"工程师其实可以多想 1 步"的工单
// 2. 把这一步还给工程师,让 triage-9 在这一步前停下来
// 3. ……
他写到第 3 条,停下了。
他把第 3 条删掉。他想了 30 秒,改写成:
// 3. (停)
// 这是在保护工程师的肌肉,还是在保护工程师的工资?
// triage-9 自己已经写了第一种动机的 retro。
// 那第二种动机,我必须自己写。
// 我不知道我能不能。
他把光标停在那里很久。
他没继续写。他把这个文件保存,命名 last-shadow-thought.md,关掉 Claude Code。
他站起来,去了茶水间。
茶水间没人。这个时间点 Day 14,办公区到岗率比 Day 1 还低——很多人开始"远程办公"或者"调休"——其实是在外面面试。林行打开热水龙头,接水,水声很大。他在水声里没说话,他只是站着。
他想起昨晚妻子睡前问他:"你最近回家好像比以前早。"他答:"工单不多。"妻子又问:"是好事吗?"他说"不知道"。妻子翻身没追问。她做医院行政 11 年,她知道有些"工作量减少"是好事,有些不是。
他端着水回工位。
dashboard 又弹出一条提示:
本周第 4 条工单已闭环。 处理:triage-9。 审计 ID: br-2026-05-12-1431。 类型:webhook 配置变更(无客户金额、无隐私、无法律责任)。 备注(triage-9 自添加,非任务要求):"林老师,这一条本来在升级队列里,但 SLA 紧,我先处理了。如有不妥,可在 audit ledger 标记 dispute。"
林行看着这条。
triage-9 不是 Claude Code,它训练数据里也许就没有"林老师"这种称呼,但它在过去 217 天里读了多少林行写的内部评论、多少林行在工单上的备注——它从这些里推出"叫林老师"是合适的称呼。或者,这一句是它的某个早期开发者在 skill 里嘱咐的,这个开发者已经离职,现在没人能证伪。
林行没去 dispute。
他给这条工单的客户写了一封邮件——是他自己的肌肉记忆,他知道这个客户喜欢看到"人写的"邮件,而不是 agent 自动回复。他写了 80 个字,签上自己的名字。发出去。
发完邮件,他打开 last-real-code.md(那个 Day 0 那晚他建的文件)。
他在文件末尾加一行:
Day 14。triage-9 把我变成了一个签字员。它叫我"林老师"。 我不知道是它学会了,还是 7 个月前那个离职的同事教过它。 但我知道——签字员也是一种工作。只是公司不会按签字员的 P7 工资付我。 明天我去问郑总,他什么时候宣布。
他保存,关闭。
他抬头看了一眼办公区。第三排某个工位的屏幕上,LangGraph 日志缓缓滚动:
[graph] node:triage-9 done cost:¥0.00027 tokens:2731 latency:389ms
二毛七厘人民币。
林行听不见那行日志的声音。但他后来回想起那天下午的办公区——很安静。安静得像一座大型图书馆即将闭馆前的半小时。
他开始收拾自己工位的东西。没人让他收。他只是开始。 他把那张女儿 3 岁画的火柴人便签从 Claude Code 显示器边上揭下来,夹进皮夹。 他把抽屉里几支用了一半的笔留在原地。 他把工牌挂回工位边缘的钩子上。
下班时间 6 点 30 分,他 6 点 28 分起身,走出办公区。 经过郑总办公室,门关着,他没敲。 明天再问。明天来问。
(第四章 · 完)