“让你负责一个生产级 Agent,你会怎么设计?”
如果要你来回答,你会怎么说?是不是一上来就开始背诵 ReAct、Function Calling、Skills 这些概念?如果真这么做了,面试官听了估计会直摇头。他要是没摇,我都要替他摇了(手动狗头)。
这道题其实只是冰山一角。下面是读者反馈来的真实面试题,有需要的小伙伴可以收藏起来慢慢琢磨。别光死记硬背,试着把它们背后的逻辑吃透。

(全程干货,系好安全带,我们出发了~)
文中项目用的是 PaiCLI,一个类 Claude Code 的终端 Agent,已在 GitHub 开源,感兴趣的小伙伴可以去看看。

源码和面试题都在这儿了,主打就是一个真诚。
01. 设计思路:三条路径,一套基础设施
面试官老王开门见山:“上一个项目里,最大的技术挑战是什么?”
“是让三种 Agent 运行模式共享同一套基础设施。” 我解释道。拿 PaiCLI 来说,它支持 ReAct 主循环、Plan-and-Execute(先规划后执行)以及 Multi-Agent 多角色协作。这三条执行路径,从逻辑上看完全不同,但它们必须共用一套工具注册表、记忆系统、安全审批和审计日志。

举个例子,文件写入操作在 ReAct 模式要触发审批弹窗,在 Multi-Agent 模式下同样也要。记忆机制也是如此,ReAct 里存下的用户偏好,如果切到 Plan-and-Execute 模式就读不出来了,那就说明底层的 Harness(协调层)没做好。
这一通分析下来,其实是在向面试官阐述你对 AI Agent 工程化架构的理解深度,而不是在背诵定义。
02. 上下文压缩:原始记录到底还要不要?
老王点点头,继续追问:“那咱们聊聊上下文压缩。假设前面10轮对话都被总结成了一个摘要,那原始的聊天记录还需要保留吗?”
“不需要了。” 我回答得很干脆。一旦压缩完成,旧的原始消息就会被清空,系统中只保留生成的摘要和最近几轮的完整对话记录。

压缩策略采用 Map-Reduce(分片摘要),分三步走:
- 切片:把旧消息按每 5 条一组,切成多个小片段。
- Map(摘要):让模型分别对每个片段做摘要,要求它必须保留用户的需求与意图、已执行的操作与结果,以及做出的决策与结论。
- Reduce(合并):等所有片段的摘要都生成完,再把它们合并成一份最终的整体摘要。
压缩完成后,清空旧消息,将最终摘要作为一条新记录写回对话历史,然后把最近 3 轮完整对话原样拼回去。这样,模型在下一轮看到的上下文就是 “摘要 + 最近几轮完整对话”,既有全局记忆,又不超 Token 限制,还能保留最新的操作细节。
03. 长期记忆:爱吃辣还是不能吃辣?
“那这就有个很现实的问题了。”老王笑了笑,“用户一个月前跟你说他喜欢吃辣,一周前又说不能吃辣。现在你该怎么判断他到底能不能吃?”
“核心是‘时间戳加权’。”我先给出结论。两条看似矛盾的记忆都会被保留,不强行合并,也不直接删除旧的。关键在于检索时的排序 —— 按照时间衰减来打分,越新的记忆权重越高。

PaiCLI 的衰减逻辑是 24 小时内,记忆权重从满分衰减到一半。所以,一周前那条 “不能吃辣” 的记录在检索排序中,天然就会排在一个月前 “爱吃辣” 的记录前面。模型第一时间拿到的,永远是最新的状态。
不直接删旧记录,是因为删除操作不可逆。万一用户“不能吃辣”只是因为临时过敏,过两周又恢复了呢?保留变化轨迹,反而能让模型做出更准确的长线判断。
04. 记忆更新:一定要用向量数据库吗?
“既然记忆存在库里,你是怎么更新它们的?” 老王的节奏很快。
如果用向量数据库存记忆,更新流程通常是先语义检索找到旧记录,删掉旧向量,对新内容重新做向量化(Embedding),再把新向量写回去。这里有个工程坑:两个会话同时修改同一条记忆时,会发生版本冲突,需要加乐观锁或时间戳校验。
但 PaiCLI 的记忆系统并没有引入向量数据库。

记忆库里存的都是用户偏好、项目信息这类事实数据,总量通常在几百到上千条。这个体量下,用关键词匹配其实就够了 —— 毫秒级出结果,可解释、可调试,哪条记录被召回、为什么被召回,一目了然。
向量数据库更适合作 RAG 知识库,面对动辄几十个G的非结构化文档,只有语义检索才能应付。
05. 压缩的代价:如果“500元”丢了怎么办?
老王皱了皱眉,直击要害:“上下文压缩会不会丢掉关键信息?”
“会。”我坦白承认,“这是压缩的代价,世上没有真正的无损压缩。但我们可以通过三层防护机制,把信息丢失的风险控制在可接受的范围内。”

- 第一层:事实提取。在触发压缩前,先从旧对话中把那些跨会话依然有价值的稳定事实提取出来,存进长期记忆。这部分数据不参与压缩,所以它不会丢。
- 第二层:摘要指令。压缩的提示词会严格约束模型,要求它必须保留用户的意图、已完成的操作、做出的决策结论以及关键的技术细节。单片摘要控制在 200 字以内,合并摘要控制在 300 字以内,别让它自由发挥。
- 第三层:近期缓冲。不管怎么压,最近几轮的完整对话原样保留,绝不压缩。确保最新的操作步骤和上下文始终在线。
他紧接着追问:“那给你一个具体场景,用户买商品花了 500 元,压缩后偏偏把‘500元’这个金额丢了,怎么办?”
“这就得回到第一层的‘事实提取’了。”

在压缩之前,系统会尝试从对话中提取稳定事实。像“花了500元购买了某商品”这种包含具体金额的交易行为,会被识别为持久事实,直接写进长期记忆。长期记忆不受上下文压缩的影响,模型随时都能调取。
退一步讲,就算事实提取阶段漏掉了这条信息,摘要提示词里“必须保留做出的决策和结论”这条兜底规则,也会引导模型在摘要中保留交易金额。长期记忆 + 摘要指令,这套双保险虽然不敢打包票万无一失,但比直接无脑压缩要可靠得多。
06. 重要信息筛选:三层过滤规则
“你怎么定义哪些内容算‘重要信息’?” 老王继续深挖。
“一句话就能概括:跨会话仍然成立、未来复用仍有价值的稳定事实。” 落地到系统中,PaiCLI 通过三层过滤规则来判断。

- 排除临时任务:句子开头如果是“帮我”、“创建”、“删除”、“本次任务”这类前缀,说明它是一次性指令,果断过滤掉。
- 排除推测性内容:包含“可能”、“应该”、“猜测”、“也许”等词的信息,不是确定事实,也过滤掉,避免噪声积累。
- 保留持久信号:包含“偏好”、“习惯”、“项目”、“配置”、“版本”、“技术栈”、“约定”等关键词的,十有八九是跨会话都有价值的核心事实,必须保留。
07. API 异常处理:重试也得讲策略
“线上环境,API 要是超时或者报错了,你怎么解决?” 老王的提问开始转向运维。
“核心机制是指数退避加重试,并引入随机抖动(Jitter)。”我把策略掰开来讲。默认重试 3 次,等待间隔呈指数级增长,比如 500ms、1s、2s,上限 30s。每次等待都加上约 20% 的随机抖动,防止多个客户端在发生故障的同一时刻集中重试,将服务端瞬间打垮。
重试不是万能的,必须严格区分可重试和不可重试的错误。

可重试的情况:
- HTTP 状态码 408(请求超时)、429(被限流)、500/502/503/504(服务端故障)。
- 网络层异常,如连接超时、连接被重置、DNS 解析失败、流式传输中断。
不可重试的情况:
- SSL 证书错误,这是安全问题,重试纯属浪费。
- JSON 解析错误,说明返回的格式就是错的,重试毫无意义。
- 线程中断,代表用户主动取消了任务。
另外还有一个工程细节值得留意:如果服务端返回了 Retry-After 头,重试间隔必须取“计算出的退避值”和“服务端指定值”中的较大者。服务端说等 5 秒,咱就老老实实等 5 秒。
08. Token 消耗排查:从监控到修复的完整链路
“如果发现 Token 消耗得特别快,你怎么排查?” 老王步步紧逼。
“先看数据,再定位原因。”PaiCLI 每轮模型调用结束,都会自动输出一份详细的 Token 统计报告,包含总输入、总输出、缓存命中以及可用预算等指标。

排查的思路就是从统计报告里找峰值异常。常见原因主要有三个:
- 工具输出过长。某次 Shell 命令输出了几万字符全被塞进了上下文,Token 消耗瞬间拉满。排查时要去寻找这种“爆表”的直接调用。
- 压缩触发太晚。系统默认在可用预算的 90% 才触发压缩,如果一轮里工具调用过多,可能在压缩前就超了。把触发阈值调低到 80% 就能缓解。
- 上下文膨胀:同一份信息被反复检索、反复注入。这种情况需要去检查记忆检索的结果去重机制是否生效。
09. 渐进式披露:按需加载才是王道
“看过你们的 Skill 机制,讲讲它的‘渐进式披露’是怎么回事?” 老王抛出一个架构题。
“渐进式披露本质上就是按需加载。不用的 Skill 不占地方,用到时再展开,最大程度节省 Token。” 具体执行分三个阶段。

- 启动期,索引注入。Agent 启动时,只把所有启用 Skill 的名称和一句话描述注入 System Prompt。用最少的字数让模型知道“我有哪些能力”。
- 使用时,按需加载。模型在对话中判断当前任务需要用哪个 Skill,再主动调用
load_skill 工具,加载这个 Skill 的完整工作指引。
- 运行中,注入缓冲。加载过的完整指引会放入一个缓冲区,下一轮对话自动拼接到用户消息前面。缓冲区最多同时保留 3 个 Skill,超出的按 LRU(最近最少使用)算法淘汰。
那为什么不直接把所有 Skill 的完整指引都塞进上下文呢?我给他算了一笔账:假设 20 个 Skill,每个平均 2000 Token,全部常驻 System Prompt 就是 4 万 Token。

这 4 万 Token 是每轮对话都要花的,可实际上一轮对话可能就用到 1 到 2 个 Skill。渐进式披露只加载需要的,成本能降下一大截。
10. 智能客服架构:四层设计与四个维度
老王呼了口气,抛出了最终的场景题:“现在,你来设计一个智能客服 Agent,要求能根据用户提问,给出尽可能准确的回答。说说你的设计思路。”
“我会把它分为四层架构。”

- 意图识别:用户的第一句话进来,先做个路由,分清他是来产品咨询、售后投诉、退换货还是查物流的。分类结果决定了后面该调哪些工具、查哪些知识库。
- RAG 知识检索:接上产品文档、FAQ、退换货政策等知识库。如果检索不到确凿的证据,模型绝对不能瞎编,必须回复“这个问题我不太确定,帮您转接人工客服”。
- 工具执行:查订单、查物流、发起退款这些操作,Agent 需要调用对应的后端接口。拿到的接口返回结果,再由模型组织成用户能看懂的大白话。
- 人工兜底:当模型连续两轮给不出有效回答,或用户明确表示要找人,立即无缝转接人工。自动处理是有边界的,人工兜底的安全绳不能少。
在四个层面的设计之外,还得兼顾四个维度的考量。

- 准确性:知识库的分块策略要合理,太大了语义模糊,太小了丢失上下文,通常 512 到 1024 Token 一个块,带 20% 重叠。并建议引入 Reranker(重排模型)做二次排序,因为语义相似不等于问题相关。
- 延迟:流式输出是基本体验,不能让用户干等。高频问题的答案可以提前缓存起来,命中缓存直接返回,不走模型。
- 安全性:严防提示词注入,所有工具返回的内容都要按不可信数据处理。对用户的手机号、地址等敏感信息,进行脱敏处理。
- 兜底策略:意图分不清的、知识库查不到的、模型不确定的,全部走人工。宁可多转几次人工,也绝不让模型凭空编造答案。
11. 大促高并发:五道防线应对流量洪峰
“既然是电商场景,那大促的时候,流量尖刺你怎么解决?” 老王问出了最后一个,也是最考验架构功力的问题。
“核心思路就六个字:削峰、分流、兜底。”我拿起笔,在白板上画出五道防线。

- 消息队列,削峰填谷:用户请求先进消息队列,Worker 按容量慢慢消费。LLM 调用本身就慢,同步硬扛只会崩溃。队列解耦后,前端可以秒级响应“正在处理中”,后端按自己的节奏来。
- 模型分层:简单问题走小模型或规则引擎,复杂问题才上大模型。像“我的快递到哪了”这种查个接口就能回复的,根本无需动用“牛刀”。
- 热点缓存:大促期间,像“什么时候发货”、“满减规则是什么”这类高频问题,提前生成标准答案缓存起来。命中缓存直接返回,完全不消耗模型算力。但要记住,缓存的有效期不能设太长,活动规则随时会变,缓存必须支持手动失效。
- 限流保护:对每个用户每分钟的请求数设上限。超出上限就返回“当前咨询量较大,请稍后再试”。这提示虽然有点不近人情,但总比把系统搞崩了强。
- 熔断降级:当 LLM 服务端的响应延迟超过阈值或错误率飙高,自动触发熔断,切换到模板答案或直接转人工,保障核心服务不中断。
以前面试考的是 CRUD 和中间件参数,现在考的是上下文怎么压缩、记忆怎么管理、Token 怎么省、流量洪峰来了怎么扛。
概念谁都会背,但如何把这些概念落地成生产环境里跑得起来的工程细节,这才是面试官真正想听到的东西。Agent 的工程化之路才刚刚起步,许多问题还没有标准答案。谁先把系统里的坑都踩过一遍,谁就有了别人抢不走的底气。
加油吧。
如果你对 Agent 的工程实践、面试求职 心得或者 开源项目 的具体落地感兴趣,欢迎常来 云栈社区 看看,这里有跟你一样在技术上“死磕”的伙伴们。