阿里巴巴 AI Agent 研发一面面经
- 轮次
- 一面
- 结果
- 凉经
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
手撕
- 手撕:最长有效括号。
- 手撕:岛屿数量,先写 DFS 再写 BFS。(追问:矩阵很大时 DFS 递归会不会栈溢出?)
面试问答
- 自我介绍。
- 你这个 CR Agent 具体解决什么问题?
- 为什么用 Agent,不用固定 Workflow?
- Workflow 和自治 Agent 的区别是什么?什么场景更适合 Workflow?
- ReAct 和 Plan-and-Execute 怎么选?
- Skill、MCP、Function Calling 三者区别是什么?
- 你项目里的 Skill 怎么设计?输入输出契约是什么?
- Skill 怎么渐进式加载?工具特别多怎么办?
- MCP 获取工具列表的完整流程讲一下。
- 如果有 100 个 MCP 工具,Agent 怎么选?怎么保证稳定性?
- 你怎么理解 Harness?Harness 和 Agent 框架的关系是什么?
- 看过 DeepSeek Harness 吗?和 Claude Code 有什么区别?
- Agent 上下文超限怎么处理?滑动窗口和摘要压缩各自牺牲了什么?
- 工具调用失败怎么兜底?重试策略怎么设计?
- 多 Agent 写同一个文件怎么避免冲突?
- Agent 长任务跑失败,怎么定位是模型、检索还是工具的问题?
- 长任务从 5 分钟变成 20 分钟,怎么分析延迟?
- 线上高并发场景,Agent 服务怎么限流、降级、熔断?
- RAG 召回高但答案不准,怎么排查?
- 文档切分策略怎么选?Markdown 没标题怎么切?
- BM25 和向量检索怎么融合?RRF 的 k 值怎么设?
- Java 线程池核心参数怎么配?IO 密集和 CPU 密集分别怎么设?
- ThreadLocal 原理,为什么会内存泄漏?
- MySQL 深分页为什么越往后越慢?怎么优化?
- Redis 缓存击穿、穿透、雪崩分别怎么解决?
- 先更新数据库再删缓存,删缓存失败了怎么办?
- 如果消息队列重试删除缓存,但旧值又写回来了,怎么保证一致性?
- AI Coding:写一个商品计价系统,优惠策略可以随时更新,你会怎么设计?
- 反问。
《参考解析》
两道手撕的解法与追问。最长有效括号用栈:栈底先压一个 -1 当哨兵,遇到 ( 压入下标,遇到 ) 先弹出,如果栈空说明当前 ) 没有匹配,把它的下标记为新哨兵,否则「当前下标 − 栈顶」就是以当前位置结尾的最长有效长度,取最大值即可,时间 O(n)、空间 O(n);也可以用 DP,dp[i] 表示以 i 结尾的最长有效括号长度,遇到 ) 时分 () 和 )) 两种形态转移。岛屿数量两种遍历都要会写:DFS 用递归把相连的 1 就地改成 0(或加 visited 标记),代码短但递归深度等于岛屿最大连通规模,矩阵一大就有栈溢出风险;BFS 用队列逐层扩散,空间可控,代价是需要一个显式的队列和标记。所以追问「矩阵很大怎么办」的正确答法是:改用 BFS 或迭代式 DFS(自己用栈模拟),并且注意原地修改会破坏输入,需要一份数据时要用 visited 数组。
Workflow、自治 Agent 与两种推理模式。判断标准是任务路径能否预先穷举:路径固定、只是步骤多的(订单处理、数据 ETL、定时报表、CI 流水线)用 Workflow,稳定、可测、便宜;路径依赖中间观察结果、需要动态换策略的(代码审查、复杂问答、行程规划)才用 Agent。把 Agent 用在做定时报表这种场景上,结果是每次都要调模型,成本高还不稳定——成本降 90% 往往就是把不该 Agent 化的部分退回 Workflow。ReAct 是 Think→Act→Observe 边走边看,灵活但效率低、容易路径震荡(反复调同一个工具);Plan-and-Execute 先规划再执行,效率高但初始计划可能不准。工程上合理的形态是混合:Planner 出粗粒度计划,每个步骤内部用 ReAct 执行,执行不下去再回退到 Planner 重新规划。
Skill、MCP、Function Calling 与工具路由。Function Calling 是模型层能力:模型输出结构化调用指令,框架解析执行,它不管工具怎么发现和管理。MCP 是协议层标准:定义工具如何暴露、发现、调用和传参,一个 Server 写一次,所有支持 MCP 的 Agent 都能用。Skill 是场景层封装:一个 Skill 可能包含多个工具调用,外加 prompt 模板与业务逻辑。所以「查天气」是 Tool,「规划行程」是 Skill。Skill 契约要显式定义 name、description、inputSchema(JSON Schema,写清类型、必填、枚举)、输出统一为 status/data/error/metadata,并把超时与重试策略也写进契约;一旦发布参数不能随便改名,真改就要加版本兼容层。工具多的时候必须分层路由:先加载只有名称和一句话描述的索引(控制在几千 token 内),模型判断类别后再加载该类完整 Schema;或者对每个 Skill 的 brief 做 embedding,按 query 相似度取 Top-20 再展开。100 个工具全塞进 prompt 的结果是 prompt 爆炸且模型频繁选错,加上分层路由准确率能从六成提到九成。稳定性则靠调用前参数校验、调用后结果校验、以及连续失败自动熔断。
上下文压缩、工具兜底与多 Agent 冲突。滑动窗口牺牲早期上下文、保住最近对话,简单快但会丢早期关键信息;摘要压缩牺牲细节、保住结论,不会整体丢上下文,但摘要本身会丢信息(关键数字、ID 最容易被压缩没)且有生成开销。实用组合是滑动窗口 + 结构化摘要,实体和结论保留原文,事件待办用短描述,检索时按需召回。工具失败兜底分三层:先区分可重试(超时、网络抖动、限流)与不可重试(参数错误、权限错误),再对可重试的做指数退避重试(1s/2s/4s,最多 3 次),最后降级(切备用工具、返回缓存或默认值);重试必须带 request_id 幂等键,否则下单这类操作会重复执行,同时要有全局限流避免重试风暴。多 Agent 写同一份文件优先用乐观锁加版本号重试,而不是分布式锁——Agent 场景下持锁进程挂掉会让其他 Agent 一直等;更细粒度可以按区域分段锁,核心是把「冲突」变成可重试的失败而不是死等。
长任务定位与延迟分析。定位模型、检索还是工具的锅,靠分段排查:每一步的输入输出都留日志,Thought 不合理是模型问题、检索结果不相关是检索问题、工具返回错误是工具问题;更有效的是「决策链路追踪」,每个决策点记录输入状态、决策内容、备选方案、最终选择,按 trace_id 回放就能看出哪一步错了——最常见的根因是某步工具返回了脏数据、模型基于脏数据做了错误决策。任务从 5 分钟变 20 分钟同理,先分段计时找出最慢的一步,再看常见原因:模型调用变慢(上游限流或模型切换)、工具下游变慢、向量库索引膨胀导致检索变慢、上下文变长导致推理时间线性增长。用 Prometheus 记录每步 P50/P95/P99、Grafana 展示,瓶颈一眼可见。
RAG 与缓存一致性。召回高但答案不准,说明相关文档找到了,问题在生成或上下文构建:先看 Rerank 后的 Top-K 里到底有没有正确答案,再看上下文拼接顺序(关键信息放开头或结尾,别埋在中间)、prompt 指令是否明确、多文档说法冲突时有没有冲突检测。切分粒度按文档类型定:技术文档 512 token 左右,法律合同 256 左右,代码按函数切,重叠窗口 10%~15% 保证跨块句子不被截断;Markdown 没有标题时按段落和空行切,代码块与表格整体保留。BM25 与向量用 RRF 融合:score = Σ 1/(k + rank_i),k 一般取 60——k 越小头部权重越大、长尾好结果容易被淹没,融合后再用 Reranker 精排取 Top-5。Java 侧:线程池核心数 IO 密集设 2×CPU、CPU 密集设 CPU+1,队列必须有界,拒绝策略用 CallerRunsPolicy 形成背压;ThreadLocal 泄漏源于线程池线程复用且 key 是弱引用、value 是强引用,必须在 finally 里 remove;深分页慢是因为 LIMIT 100000,10 要先扫前十万行,优化用游标分页(WHERE id > last_id LIMIT 10)、覆盖索引先取 ID 再回表、或限制最大页数。缓存与一致性是同一套:穿透用布隆过滤器或短 TTL 空值缓存,击穿用互斥重建,雪崩用过期时间打散加多级缓存;写路径「先更新库再删缓存」,删除失败用消息队列重试或订阅 binlog 兜底;「旧值又被写回来」的并发窗口用延迟双删、缓存版本号或同数据串行化解决。计价题的思路一致:策略模式加配置化,优惠链叠加与互斥用规则引擎控制,涉及金额必须加校验与测试。