1. 为什么“会写Agent”和“能交付Agent”是两回事
这两年Agent这个词被炒得火热,但真正在团队里落地过Agent项目的人都有一个共同感受:写一个能跑的Demo可能只需要一个下午,但把它变成一个能稳定交付、能扛住线上流量、能持续迭代的工程系统,那是完全不同的量级。我面过不少候选人,简历上写着“熟悉Agent开发”,聊下来发现大部分人的经验停留在“调通了一个对话流程”或者“跑通了一个工具调用示例”。一旦问到部署、监控、成本控制、失败重试这些工程化问题,回答就开始模糊了。
这篇文章想聊的,就是Agent工程化面试里最常被追问的5个关键问题。它们覆盖了从开发到部署的完整链路,也是区分“玩过Agent”和“做过Agent工程”的分水岭。如果你正在准备相关面试,或者正在团队里推进Agent项目落地,这5个问题的思考框架应该能帮你少走一些弯路。
先明确一下讨论范围。这里说的Agent,指的是基于大语言模型、具备任务规划、工具调用、记忆管理能力的智能体系统。它可能是一个客服助手、一个代码生成工具、一个数据分析管道,也可能是一个多Agent协作的复杂工作流。不管具体形态如何,工程化要解决的问题是共通的:怎么让它在真实环境里稳定、可控、可维护地运行。
2. 关键问题一:Agent的架构设计如何兼顾灵活性与可控性
2.1 为什么架构选型是面试第一道坎
面试官问架构,不是想听你背ReAct、Plan-and-Execute这些名词。他想知道的是:你在面对一个具体业务需求时,怎么在“让Agent自由发挥”和“保证输出可控”之间做取舍。这个问题之所以关键,是因为Agent系统的架构决策会直接影响后续的部署复杂度、调试难度和运行成本。
我见过两种极端。一种是过度设计,上来就搞多Agent协作、动态规划、自适应工具选择,结果系统复杂度爆炸,一个简单任务要调用七八次模型,延迟高得没法用,出了问题根本不知道是哪一环导致的。另一种是过度简化,把所有逻辑塞进一个超长Prompt里,看起来架构简单,但一旦业务逻辑变化,Prompt就变成了一团乱麻,改一处崩三处。
2.2 分层架构:把确定性逻辑和不确定性逻辑分开
我的经验是,Agent架构设计的核心原则是分层。把系统中确定性的部分和不确定性的部分明确分开。确定性部分包括:输入解析、权限校验、工具注册、结果格式化、日志记录。这些逻辑用传统代码写,稳定可靠。不确定性部分才是交给模型处理的:意图理解、任务规划、工具选择、结果总结。
具体来说,一个可落地的Agent架构通常包含这几层:
- 接入层:处理请求路由、鉴权、限流、会话管理。这一层完全不涉及模型调用,纯工程逻辑。
- 编排层:决定任务怎么拆解、按什么顺序执行、什么时候需要人工介入。这一层可以用代码定义状态机,也可以用模型做动态规划,取决于业务对灵活性的要求。
- 执行层:实际调用工具、查询数据库、调用外部API。每个工具都是独立的函数,有明确的输入输出契约。
- 模型层:负责自然语言理解和生成。这一层要处理Prompt管理、模型选择、输出解析、重试策略。
- 观测层:贯穿所有层,负责日志、指标、追踪、告警。
这样分层的好处是,每一层可以独立测试、独立替换、独立扩容。比如模型层从某个模型切换到另一个模型,只要输出格式契约不变,上层逻辑完全不用动。
2.3 状态机 vs 自由规划:怎么选
面试里经常被问到的一个具体问题是:任务编排用状态机还是让模型自由规划?我的回答通常是:看任务的确定性程度。
如果业务流程是固定的,比如“先查订单,再判断是否符合退款条件,符合就发起退款,不符合就转人工”,那用状态机。每个状态之间的转移条件用代码写死,模型只负责在特定节点做判断或生成话术。这样系统的行为完全可预测,测试用例也好写。
如果任务路径高度依赖上下文,比如“帮用户分析这份销售数据并给出建议”,那可以给模型更大的规划空间。但即便如此,也要设置边界:限制最大步数、限制可调用的工具集合、对每一步的输出做格式校验。
实操心得:我通常会在编排层做一个“混合模式”——主干流程用状态机固定,在需要灵活处理的节点嵌入模型决策。这样既保证了核心流程的稳定性,又保留了应对复杂情况的弹性。
2.4 工具设计的契约思维
工具调用是Agent能力的核心,但很多人在设计工具时缺乏契约思维。什么叫契约思维?就是每个工具必须有明确的输入Schema、输出Schema、错误码定义和超时设置。模型看到的工具描述要足够清晰,让它在正确的时候选择正确的工具。
我见过一个典型问题:工具描述写得太模糊,模型经常在不需要的时候调用某个工具,或者传错参数。解决办法是把工具描述当成API文档来写,包含:功能说明、适用场景、参数含义、返回值格式、可能的错误情况。如果工具之间有依赖关系,还要在描述里说明前置条件。
另外,工具的数量要控制。给模型太多工具选择,它会困惑。我的经验是单次可选的工具不超过10个,如果业务需要更多工具,就做分组或者用路由层先做一轮筛选。
3. 关键问题二:Prompt工程如何从“调参”升级为“工程”
3.1 Prompt不是写出来的,是管出来的
面试里聊Prompt,如果候选人只说“我调了很久Prompt终于让模型输出正确了”,这基本就暴露了他没有工程化经验。在生产系统里,Prompt不是一次性写好的静态文本,而是需要版本管理、A/B测试、灰度发布、回滚机制的动态资产。
为什么这么说?因为模型会更新,业务需求会变化,用户输入分布会漂移。今天好用的Prompt,下个月可能就效果下降了。如果没有一套管理机制,每次调整都是手工改字符串、重新部署,效率极低且容易出错。
3.2 Prompt模板化的几个关键决策
把Prompt工程化,第一步是模板化。但模板化不是简单地把变量用占位符替换,而是要决定哪些部分动态、哪些部分固定、哪些部分可配置。
我的做法是把Prompt拆成几个模块:
- 系统指令模块:定义Agent的角色、能力边界、行为准则。这部分相对稳定,但需要版本管理。
- 上下文模块:注入对话历史、用户信息、业务数据。这部分动态变化,需要控制长度和相关性。
- 工具描述模块:根据当前可用的工具动态生成。工具集变化时自动更新。
- 输出格式模块:定义模型输出的结构。这部分要和下游解析逻辑严格对齐。
- 少样本示例模块:提供输入输出示例。这部分需要根据线上失败案例持续迭代。
每个模块独立管理,组合成最终Prompt。这样当需要调整时,可以精准定位到某个模块,而不是重写整个Prompt。
3.3 输出解析的鲁棒性设计
Prompt工程化的另一个重点是输出解析。模型输出是自然语言,但下游系统需要结构化数据。这个转换过程必须足够鲁棒。
常见的做法是要求模型输出JSON,然后用JSON Schema校验。但实际运行中,模型可能输出带Markdown代码块的JSON、可能多输出一段解释文字、可能字段名拼写错误。所以解析层要能处理这些情况:先用正则提取JSON部分,再尝试解析,解析失败则触发重试或降级。
注意:不要假设模型每次都能输出完美格式。我通常会设置三层防护——Prompt里明确要求格式、解析时做容错处理、失败后自动重试并记录日志。重试时可以在Prompt里追加错误信息,让模型自我纠正。
3.4 Prompt版本管理与效果追踪
生产环境里,每次Prompt变更都应该有记录:改了什么、为什么改、预期效果是什么、实际效果如何。这听起来像废话,但很多团队就是缺这个环节,导致出了问题无法回溯。
我的做法是给每个Prompt版本打标签,关联到具体的代码提交。线上请求的日志里记录使用的Prompt版本号。这样当发现效果下降时,可以快速定位是不是某次Prompt变更导致的。同时,定期用离线评测集跑回归测试,确保新版本不会在已有场景上退化。
4. 关键问题三:Agent的部署与扩缩容怎么做
4.1 Agent服务的部署形态选择
Agent服务的部署和传统Web服务有相似之处,也有特殊挑战。相似的是都需要考虑无状态化、水平扩展、健康检查。特殊的是Agent服务通常有更长的处理时间、更高的外部依赖、更复杂的失败模式。
部署形态上,常见的选择有:
- 同步API服务:适合响应时间要求高、任务步骤少的场景。用户请求后等待结果返回。缺点是长任务容易超时。
- 异步任务队列:适合任务步骤多、处理时间长的场景。请求提交后立即返回任务ID,后台Worker处理,客户端轮询或通过回调获取结果。
- 流式响应服务:适合需要实时展示中间过程的场景。通过SSE或WebSocket推送模型生成的token。
选择哪种形态,取决于业务对延迟的容忍度和交互方式的要求。我的经验是,大部分Agent场景适合异步任务队列,因为Agent任务往往涉及多次模型调用和工具调用,同步等待体验很差。
4.2 扩缩容的关键指标
Agent服务的扩缩容不能只看CPU和内存。更关键的指标是:
- 并发请求数:当前正在处理的请求数量。
- 队列等待时间:任务从提交到开始处理的延迟。
- 模型调用延迟:单次模型调用的P50、P95、P99延迟。
- 工具调用失败率:外部依赖的稳定性。
- Token消耗速率:直接影响成本,也是容量规划的依据。
基于这些指标做扩缩容决策,比单纯看CPU利用率准确得多。比如模型调用延迟升高但CPU不高,说明瓶颈在外部API,扩容本地实例没用,应该考虑限流或降级。
4.3 冷启动与预热策略
Agent服务通常依赖模型API,冷启动时可能面临连接建立、认证、模型加载等开销。如果扩缩容策略过于激进,新实例还没预热好就接收流量,会导致大量超时。
我的做法是给新实例设置一个预热期:启动后先执行几次轻量级的模型调用,确认连接正常后再加入负载均衡。同时,缩容时不要立即杀掉实例,而是先停止接收新请求,等待正在处理的任务完成后再下线。
4.4 多环境隔离与配置管理
Agent系统通常需要区分开发、测试、生产环境。不同环境的模型版本、工具配置、Prompt版本可能不同。配置管理要能做到环境隔离,同时保证配置变更可追溯。
我推荐用配置中心来管理这些参数,而不是写在代码里或环境变量里。配置中心的好处是支持动态更新、版本管理、权限控制。但要注意,配置变更后要有生效机制,不能要求重启服务。
5. 关键问题四:怎么监控和调试一个运行中的Agent
5.1 Agent可观测性的三个层次
Agent系统的监控比传统服务复杂,因为它的行为具有不确定性。我通常把可观测性分为三个层次:
- 基础设施层:CPU、内存、网络、容器状态。这部分用常规监控工具即可。
- 服务层:请求量、延迟、错误率、队列深度。这部分需要埋点。
- Agent行为层:任务完成率、平均步数、工具调用分布、模型输出质量。这部分是Agent特有的,也是最难做的。
行为层的监控需要记录每次任务的完整轨迹:输入是什么、模型每一步的决策是什么、调用了哪些工具、返回了什么、最终输出是什么。这些数据不仅用于监控,也是后续优化和调试的基础。
5.2 全链路追踪的实现
实现全链路追踪的关键是给每个请求分配一个唯一Trace ID,并在所有相关组件中传递。对于Agent来说,一次任务可能涉及多次模型调用和工具调用,每次调用都要关联到同一个Trace ID。
具体实现上,可以在接入层生成Trace ID,通过上下文对象在编排层、执行层、模型层之间传递。每次模型调用和工具调用都记录Span,包含开始时间、结束时间、输入输出摘要、状态。这样当出现问题时,可以通过Trace ID还原整个任务的执行路径。
实操心得:记录输入输出时要注意脱敏和截断。用户输入可能包含敏感信息,模型输出可能很长。我通常会记录摘要和哈希值,完整内容存在单独的日志存储里,设置较短的保留期。
5.3 常见故障模式与排查思路
Agent系统的故障模式有一些典型特征。我整理了一个速查表:
| 故障现象 | 可能原因 | 排查方向 |
|---|---|---|
| 任务完成率下降 | Prompt变更、模型更新、工具接口变化 | 对比变更前后的Trace,检查失败任务的共同特征 |
| 延迟突然升高 | 外部API限流、模型服务降级、队列积压 | 检查各层延迟指标,定位瓶颈环节 |
| 输出格式错误增多 | 模型输出漂移、解析逻辑bug | 抽样检查原始输出,验证解析逻辑 |
| 工具调用异常 | 工具接口变更、认证过期、参数错误 | 检查工具调用日志和错误码 |
| 成本异常增长 | 任务步数增加、Token消耗上升 | 分析Token消耗分布,检查是否有异常长任务 |
排查时的一个关键技巧是对比分析:拿正常任务和异常任务的Trace做对比,差异点往往就是问题所在。
5.4 人工介入与反馈闭环
生产环境中的Agent不可能100%正确,所以需要设计人工介入机制。当Agent置信度低、或者任务涉及高风险操作时,应该转人工处理。人工处理的结果要反馈回系统,作为后续优化的依据。
这个反馈闭环很重要。没有它,Agent系统就是一个黑盒,无法持续改进。我的做法是建立一个反馈队列,人工处理的结果标注后进入训练集或评测集,定期用于Prompt优化和模型微调。
6. 关键问题五:成本控制与性能优化的平衡
6.1 Agent成本构成分析
Agent系统的成本主要来自几个方面:模型调用费用、工具调用费用、基础设施费用、人力运维成本。其中模型调用费用通常是最大头,也是最容易优化的部分。
模型调用费用 = 调用次数 × 每次Token数 × 单价。所以要降成本,要么减少调用次数,要么减少Token数,要么换更便宜的模型。这三个方向都有具体的工程手段。
6.2 减少模型调用次数的策略
减少调用次数的核心思路是能不用模型就不用模型。具体手段包括:
- 规则前置:能用规则判断的,不要交给模型。比如意图分类,如果关键词匹配能覆盖80%的情况,就先用规则过滤。
- 缓存复用:相似的问题可以复用之前的回答。用向量相似度做语义缓存,命中后直接返回。
- 批量处理:多个独立任务合并成一次模型调用。比如多个分类任务可以放在一个Prompt里让模型一次性输出。
- 小模型分流:简单任务用小模型,复杂任务才用大模型。可以用一个路由层根据任务复杂度做分发。
6.3 Token优化的实操技巧
Token优化要从Prompt设计和输出控制两方面入手。Prompt方面:
- 精简系统指令,去掉冗余描述。
- 上下文只保留相关部分,不要把所有历史都塞进去。
- 工具描述用简洁的Schema,不要写长篇说明。
- 少样本示例控制在必要数量,通常3-5个足够。
输出方面:
- 明确要求模型输出简洁,不要客套话。
- 用结构化输出代替自然语言,减少Token数。
- 设置max_tokens上限,防止模型生成过长内容。
注意:优化Token时不要牺牲效果。我通常会做A/B测试,确认优化后的Prompt在关键指标上不退化。
6.4 性能与成本的权衡框架
成本和性能往往是一对矛盾。更快的响应通常意味着更多的计算资源或更贵的模型。怎么权衡?我的框架是:
- 定义SLA:明确不同场景的延迟和准确率要求。
- 分级处理:核心场景用高配,边缘场景用低配。
- 动态调整:根据实时负载和成本预算动态调整策略。
- 持续监控:跟踪单位任务成本和质量指标,及时发现异常。
这个框架的关键是分级。不是所有请求都值得用最好的模型、最快的响应。把资源集中在真正影响用户体验的环节上。
7. 面试中如何展示Agent工程化能力
7.1 用项目故事代替名词罗列
面试时最忌讳的是堆砌名词。说“我用了ReAct、CoT、RAG、Function Calling”不会加分,反而显得没有深度。更好的方式是讲一个具体的项目故事:遇到了什么问题、考虑了哪些方案、为什么选了这个、实施中踩了什么坑、最后效果如何。
比如聊到架构设计,可以说:“我们当时面临的问题是任务步骤不固定,用纯状态机太死板,用纯自由规划又不可控。最后我们做了一个混合方案,主干流程用状态机,在意图识别和结果总结两个节点用模型决策。这样既保证了核心流程的稳定性,又保留了处理复杂情况的弹性。实施后发现模型在意图识别上的准确率有波动,我们又加了一层规则兜底……”
这样的回答既有技术深度,又有工程判断,还能体现解决问题的能力。
7.2 准备几个“踩坑与解决”的案例
面试官很喜欢问“你遇到过什么难题,怎么解决的”。提前准备几个真实的踩坑案例,比临场编造要自然得多。案例的结构可以是:问题现象、排查过程、根因分析、解决方案、后续预防。
比如:“有一次线上任务完成率突然从95%掉到70%,排查发现是某个工具的接口返回格式变了,模型解析失败后一直重试。我们当时的监控只看了整体成功率,没有细分到工具级别,所以发现得比较晚。后来我们加了工具级别的成功率监控和告警,同时给工具调用加了熔断机制,连续失败就快速失败而不是无限重试。”
7.3 展示对权衡的理解
工程化的本质是权衡。面试中要展示你理解不同方案之间的取舍,而不是认为存在“完美方案”。比如聊到模型选择,可以说:“我们试过用大模型做所有任务,效果确实好,但成本和延迟都受不了。后来做了分级,简单任务用小模型,复杂任务用大模型,整体成本降了60%,关键指标只掉了2个百分点。这个取舍我们认为是值得的。”
这种回答体现的是工程思维,比单纯说“我们用大模型”要有说服力得多。
8. 从面试题到落地:一份可执行的检查清单
聊完这5个关键问题,最后给一份实操检查清单。不管你是准备面试还是推进项目,都可以对照着过一遍:
架构设计
- 确定性逻辑和不确定性逻辑是否分离
- 工具是否有明确的输入输出契约
- 是否设置了最大步数和工具调用上限
- 是否有降级和兜底方案
Prompt工程
- Prompt是否模块化管理
- 是否有版本管理和变更记录
- 输出解析是否有容错和重试
- 是否有离线评测集做回归测试
部署与扩缩容
- 部署形态是否匹配业务延迟要求
- 扩缩容指标是否包含Agent特有指标
- 是否有冷启动预热策略
- 配置是否环境隔离且可动态更新
监控与调试
- 是否有全链路Trace
- 是否记录Agent行为层指标
- 是否有常见故障的排查手册
- 是否有人工介入和反馈闭环
成本与性能
- 是否分析过成本构成
- 是否有减少模型调用的策略
- 是否做过Token优化
- 是否有分级处理和动态调整机制
这份清单不是标准答案,而是一个思考框架。实际项目中,每个团队的情况不同,需要根据具体约束做调整。但核心思路是一致的:把Agent当成一个工程系统来对待,而不是一个模型调用的包装。
我在实际项目中最深的体会是,Agent工程化的难点不在于技术本身,而在于思维方式的转变。从“让模型输出正确结果”转变到“让系统在不确定的环境中稳定运行”。这个转变一旦完成,很多设计决策就变得清晰了。