NAVI · 产品月报

这两周
Navi 长出了记性

从"单机记忆、一重启就失忆",到崩溃也不丢活儿;还学会了帮顾客重置密码、认清"这活儿是冲谁去的"。
2026.06.10 – 06.23 · 按 T 切主题 · ← → 翻页 · F 全屏

90次提交
2个代码库
4项大升级

一句话总结

这两周主要在给 Navi 装"防丢防重"的底盘,并补上两个它原本不会的本事。

主题一

崩溃也不丢活儿

pod 被杀/部署重启,请求不丢、不重复、不卡死

主题二

帮顾客重置密码

Slack 一句话,自动走完 Shopify 整套重置流程

主题三

认清"这活儿冲谁去"

不再把"提需求的你"和"操作对象"搞混

主题四

控制台 + 内部鉴权

Config Center 升级,调内部服务有了正经认证

主题一 / 占了这两周一多半的工作

崩溃也不丢活儿

把 Navi 从"把活儿记在脑子里就开干",改造成"每一步都先记进账本,再动手"。

以前为什么会出事

它把请求记在自己脑子里,服务器一重启就失忆

在 Kubernetes 里,容器(pod)被回收、被部署、被杀是家常便饭。原来 Navi 的"进度"只活在那台机器的内存里——机器一没,三种坏事就会发生:

🫥

活儿丢了

没人接着干,你在 Slack 里干等回复

👯

干了两遍

Slack 自动重发消息,它又从头跑一次

♾️

永远"运行中"

留下一条卡死的记录,再也不会结束

🍳 打个比方:像厨师把订单全记在脑子里就开炒。店里一停电,订单全忘光——客人干等,或者客人再催一次时又炒了一遍。

现在怎么做 · 每一步都落账

一条"防丢防重"的流水线

01
去重门 DEDUP

同一条 Slack 消息只放行一次;Slack 的自动重发被当场拦下。

02
进工单队列 REDIS WORKQ

请求先进持久队列;被领取时原子地挪进"处理中"格子。pod 被杀,处理中的工单还在,下个 pod 开机自动捡回来重跑。

03
领写锁 + 栅栏 WRITER LEASE · FENCE

同一对话同一时刻只有一个 worker 能写;锁被抢走后,旧 worker 在建 PR / 发消息这类外部动作前会被栅栏拦下,绝不重复产生副作用。

04
带断点干活 CHECKPOINT

只存一个"游标",恢复时按事件日志重新拼出对话历史,从断点继续——而不是存一整坨消息。

05
发件箱:先存档再发 OUTBOX

回复先存档、发送成功才销账。就算在"已生成、还没发出"那一瞬挂掉,开机后补发——回复绝不丢。

前后对比

以前
现在
进度只在内存里,重启即失忆
每步落进 Redis/数据库账本,可恢复
Slack 重发 = 重复跑一遍
去重门把重发挡在门外,只干一次
部署时正在跑的活儿直接没了
优雅退场:先存好、释放锁,开机续传

配套改造 · 已在生产开启
收件 / 干活拆成两个进程: web 只负责"收消息 + 入队"(轻、快、不 clone 代码库);worker 专门干重活——跑 agent、拉仓库、调模型。两边靠 Redis 协同,互不拖累。

主题二 / 一个全新的本事

帮顾客重置 Shopify 密码

顾客忘了 Mercaso 商城的密码,以前要人工去后台折腾。现在 Slack 里 @Navi 一句话就行。

它会做什么

"帮 Jane 重置密码" → 先按名字找到人(不用先报邮箱/ID),同名让你选,然后两条路:

路线 A · 轻

给顾客发官方重置邮件

Shopify 直接把重置链接发到顾客自己的邮箱,线程里回执成功。

路线 B · 代办

代为重置,把新密码私信给你

生成 8 位新密码私信给你;线程里只报"已完成",从不回显密码

路线 B 全程自动: 触发重置 → 轮询收件箱拿重置链接(封顶 3 分钟,超时会说清卡在哪一步)→ 只认本次这封新邮件、用完即清理 → 生成密码、调内部 API 重置 → 还原邮箱。

上线后的一个坑 · 顺手修了

表面是"老超时",真因是 Shopify 把我们当机器人

现象

重置总是"超时",像是流程太慢。

真因

邮件其实到了、也读到了。但 Shopify 的邮件追踪链接,对"看起来像机器人"的访问直接回 403。我们的轮询器自报家门叫 NaviResetBot——被拦了。

修法:访问链接时伪装成正常浏览器(完整的 Chrome User-Agent + 请求头),403 消失,链接正常跳转。

🔑 顺带:认证简化成"一把钥匙"——优先用静态 ADMIN_TOKEN,没有就用 client-credentials 自动换 Admin token,再派生 Storefront token。一个密钥,两个 API 全覆盖。

主题三 / 多智能体的"认人"问题

认清"这活儿是冲谁去的"

当主管 agent 把活儿派给子 agent,系统原来会把"提需求的你"和"操作对象"搞混——给顾客重置,结果差点重置到你自己头上。

解法 · 给委派加一个"对象"字段

每次派活儿都明确写清:操作对象是谁、这身份从哪来

需要"对象"的 agent 会声明 requires_subject;少了就被打回重派。来源只能三选一:

user_request

从你的原话里取目标(把你说的原文照搬给子 agent,别再认错人)

prior_step

取自上一步的结构化结果,必须带 ref 指向那一步

user_selection

你从消歧选项里选的那个,必须带 ref = 确认的实体 id,子 agent 不再重查

🧷 为什么强制 ref: Navi 问"你指 A 还是 B",你回"1",它把选择锚定成实体 id 带下去。就算长对话被摘要、选项列表从上下文里消失了,因为有 ref,也不会沦为"用户选了某个、但不知道是哪个"的死循环。

交接保证 · 答案绝不被悄悄丢掉

每个子 agent 必须以一次 submit_handoff 收尾。两个加固:

① 打捞被写错格式的交接

有的模型(实测 DeepSeek)会把"工具调用"错当成纯文本吐出来(DSML 标记)。现在能把这段文本解析、还原成真正的交接,而不是当垃圾丢掉。

② 拒绝"空交接"

交接里答案是空的?先强制重答一次;再不行就兜底成最佳散文。绝不出现"明明查到了,用户却收到一句没数据"的情况。

这三件事(认对象、扛压缩、保交接)合起来,堵住了过去"派活儿派错人 / 长对话后答非所问 / 答案凭空消失"这一类最让人困惑的故障。

主题四 / 控制台与基础设施

Config Center 升级 + 调内部服务有了正经认证

🔐 内部服务鉴权 M2M + Basic

Navi 调订单/客户等内部微服务时的服务到服务认证。凭据在控制台管理、加密存储、UI 永不显示明文;缺失/禁用会返回明确错误,不再静默失败。

⌨️ 控制台导航升级

Slack 用户选择器、方向键导航、域分组的侧边栏,外加 Cmd+K 菜单搜索——找设置更快。

⏰ 定时任务更可靠

轮询器跑在 worker 里、运行中续租数据库锁;"Run now"跨容器秒级唤醒,跑完还能查状态。

👁️ 配置可见性

requires_subject 等字段在 UI 里可见(dev 可改、prod 只读);菜单显示名做到单一来源、不再前后打架。

如果你只有 10 分钟

按这个顺序看

1

崩溃也不丢活儿 — 占了这两周一多半的工作,决定了 Navi 在生产里稳不稳。

2

帮顾客重置密码 — 唯一对外可见的全新能力,含一个值得讲的 403 排查故事。

3

认清操作对象 — 修掉了多智能体里最让人困惑的一类错。

4

控制台 + 内部鉴权 — 日常运维更顺手,调内部服务更安全。

一句话收尾

这两周,我们给 Navi 装了
一本账、一道闸、一个发件箱,
和一块认人的牌子。

账本让它崩溃也不失忆,闸门挡住重复,发件箱保证回复不丢,认人的牌子让它分得清"为谁办事"。

NAVI · 2026.06.10 – 06.23 · 90 commits

← → 翻页 · T 换主题 · F 全屏
01 / 01