面灵AI→

快手大模型 Agent 研发一面:Reconcile、Lease 与多 Agent 架构

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

  1. Reconcile 的恢复是怎么做的?
  2. Lease 是什么?Lease 过期后怎么办?
  3. 进程退出或崩溃后,Lease 应该如何处理?
  4. 数据库存储会不会发生先后写入、相互覆盖的问题?
  5. Fencing Token 是怎么实现的?
  6. 为什么不把 Fencing Token 直接放进 Lease?
  7. 能否保证同时只有一个 Worker 在构建?
  8. Fencing Token 会不会浪费?
  9. 为什么要使用多 Agent?
  10. 当前项目是否真正使用了多 Agent?
  11. 单 Agent 和多 Agent 做过对照评测吗?
  12. 单 Agent 是怎么评测的?
  13. Runtime 适配时,事件是怎么适配的?
  14. 除了事件,Runtime 还需要适配什么?
  15. CLAUDE.md 和 AGENTS.md 是怎么处理的?
  16. Skill 是怎么加载的?
  17. 把配置和会话数据保存在目录中,会不会有严重的信息泄露问题?
  18. 会话恢复采用什么方式?
  19. 如果新开一个会话,直接复用旧会话恢复,会有什么问题?
  20. 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 也同理,按「可关联、可采样、可过期」来设计存储与字段,而不是无脑全量落盘。