快手大模型 Agent 研发一面:Reconcile、Lease 与多 Agent 架构
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- Reconcile 的恢复是怎么做的?
- Lease 是什么?Lease 过期后怎么办?
- 进程退出或崩溃后,Lease 应该如何处理?
- 数据库存储会不会发生先后写入、相互覆盖的问题?
- Fencing Token 是怎么实现的?
- 为什么不把 Fencing Token 直接放进 Lease?
- 能否保证同时只有一个 Worker 在构建?
- Fencing Token 会不会浪费?
- 为什么要使用多 Agent?
- 当前项目是否真正使用了多 Agent?
- 单 Agent 和多 Agent 做过对照评测吗?
- 单 Agent 是怎么评测的?
- Runtime 适配时,事件是怎么适配的?
- 除了事件,Runtime 还需要适配什么?
- CLAUDE.md 和 AGENTS.md 是怎么处理的?
- Skill 是怎么加载的?
- 把配置和会话数据保存在目录中,会不会有严重的信息泄露问题?
- 会话恢复采用什么方式?
- 如果新开一个会话,直接复用旧会话恢复,会有什么问题?
- Trace 放在哪里?
《参考解析》
Reconcile 与 Lease:控制循环 + 租约:Reconcile 是声明式控制循环——期望状态存在中心存储里,控制器周期性或事件驱动地读取实际状态,算出 diff,然后执行动作把实际状态推向期望状态。它「恢复」靠的不是记住上次做到哪,而是每次从当前实际状态重新推导该做什么,所以进程崩溃后重启就能自然续上,前提是每个动作都幂等(同一个动作执行两次和一次的结果一致)。Lease(租约)是一份带过期时间的持有权:worker 周期续租来证明自己活着,租约到期就视为持有者已死、其他 worker 可以接管。所以进程崩溃时不需要(也做不到)让它主动释放,靠 TTL 自然过期即可;工程上续租周期要显著小于 TTL(例如 TTL 15s、5s 续一次),且单个工作单元的执行时间不能超过 TTL,否则会出现「旧 worker 其实还活着、但租约已被别人抢走」的双主。
Fencing Token:为什么不能只靠租约、也不放进 Lease 里:租约只能降低双主的概率,消不掉——被判定死亡的 worker 可能只是长 GC 或网络分区,醒来后仍然会往存储里写,与新 worker 的写互相覆盖。Fencing Token 就是给这个场景兜底的单调递增版本号:每次获取租约时把 token 自增,worker 每次写存储都带上自己的 token,存储端记住已见过的最大 token 并拒绝任何更小的写入,于是迟到的旧 worker 的写会被静默丢弃。为什么不是「把 token 放进 Lease」:Lease 本身只是一份记录,它没有强制力,worker 完全可以不看它继续写;仲裁必须发生在真正落盘的存储端点,token 必须跟随每一次写请求由存储校验,才能形成「租约互斥 + token 单调 + 存储校验」的闭环。追问两个点:token 由谁分配(共享的单调计数器,例如 etcd revision 或数据库序列),以及会不会浪费——存储端每个 key 只需要记一个最大 token,代价是常数级,而它换来的是崩溃恢复期的写入安全,不是浪费。
为什么用多 Agent、什么时候不该用:多 Agent 的真实收益来自三件事:上下文隔离(每个子 Agent 只装自己需要的工具和知识,避免工具定义把主上下文挤爆、选择准确率下降)、职责与权限分离(只读分析型 Agent 与可写执行型 Agent 分开,降低误操作面)、并行(彼此不依赖的子任务同时推进)。代价同样明确:token 与延迟放大、状态与错误跨 Agent 传播、链路变长后难调试、评测口径难统一。所以判断标准不是「多就先进」,而是单 Agent 加多工具是否已经出现上下文溢出、工具选错率偏高,或者任务本身可以并行切分。面试官问「当前项目是否真的用了多 Agent、有没有做过对照评测」时,要拿得出一组可复现的 A/B:同一批任务、同一个模型、同样的工具,比成功率、平均轮数、token 消耗、P95 延迟和失败分类。没有这组数据就照实说没有,硬吹一定会在下一问「那你单 Agent 是怎么评的」上塌掉。
单 Agent 怎么评测:先把「任务集」固定下来——从真实使用场景采样,刻意覆盖简单单步、需要多跳、以及必须失败(信息不足或越权)的负例,每题写清判分标准:最终答案对不对、有没有调用到关键工具、参数是否正确、有没有产生不该有的副作用。然后每题跑多次取均值和方差(LLM 有随机性,单次跑分没有意义)。指标别只看成功率,还要看平均轮数、token 成本、P95 延迟,以及失败归因分布(选错工具 / 参数错 / 幻觉 / 死循环不终止 / 上下文溢出)。只拿几道 demo 题试出来的「效果不错」不算评测,评测集要能进 CI、能对比两次改动的差异,否则改了提示词也说不清是变好还是变坏。
目录化配置与会话恢复的安全边界:把 CLAUDE.md、AGENTS.md、Skill 和会话历史都放在项目目录里,等于把这些文件放进了模型的指令层:只要目录可写(多租户、多人共享工作区、或处理的是别人给的代码仓),任何人都能塞一份指令进去做提示注入,让 Agent 去读密钥或执行命令——所以配置应只读挂载、Skill 要限定加载目录并校验路径(防目录穿越与符号链接),会话目录按用户/租户隔离。会话数据本身往往含代码片段、内部路径、token,落盘前要脱敏、设置文件权限与保留期限,并避免把「原始对话」当日志长期堆积。会话恢复也别直接复用旧会话对象:旧的上下文里工具定义、配置、代码都已经变了,历史假设可能不再成立,token 会一轮轮滚大且越来越贵,正确做法是把旧会话压缩成结构化摘要(目标、已确认的事实、未决问题、已改动的文件)注入新会话,而不是把旧消息整段重放——Trace 也同理,按「可关联、可采样、可过期」来设计存储与字段,而不是无脑全量落盘。