做一个能对话、能调工具的Agent门槛比很多人想的低。跑通一个demo甚至可以在一晚上完成模型接上几个API提示词写得完整一点再配一个简单的工具注册表看起来就已经很像样了。但问题是从“演示惊艳”到“生产级Agent”中间隔着一条很宽的河。上线之后你很快会发现模型开始答非所问、工具调用权限失控、日志里找不到一次完整决策的轨迹、某一个第三方服务一超时整个流程就挂掉。这一点长期构建生产级Agent的Linear团队应该很有发言权。他们分享的五条规则被不少人当成Agent工程化的参考框架。我第一次看到时感觉内容并不花哨没有炫技式的编排也没有鼓动人推翻重来反而更像一套把Agent当作严肃软件来建设的工程纪律。今天把这五条规则展开来聊结合我在实际项目里的观察说说它们到底应该怎么落地以及真正执行时容易卡在什么地方。1. 为什么很多Agent项目在演示时惊艳上线就翻车1.1 演示环境里的“成功路径”太干净了大多数Agent demo能顺利跑完并不是因为代码写得多好而是因为演示环境天然是“成功路径”环境。演示时输入是挑选过的用户问题清晰上下文不复杂工具返回结果正常模型也没有遇到奇怪的json格式。你只需要让Agent走完“理解问题——调用工具——生成回答”这条主线就能获得一次流畅的展示效果。但生产环境根本不是这样。用户输入可能是口语化、有歧义、甚至带着恶意的上下文可能长到超过模型窗口工具可能返回空数据、报错、或者超时模型生成的内容可能不是合法JSON第三方API可能限流不同用户的权限还不一样。这些都不是偶发情况而是日常状态。1.2 生产环境换了一套考核指标demo里唯一重要的指标是“看起来聪明”但生产环境关心的是另一组指标。维度Demo 阶段生产阶段输入范围精选样例真实长尾含噪声和歧义输出要求单次回答听起来对可重复、可稳定交付业务结果执行权限通常不接入真实系统最小权限严格校验异常处理人工盯着失败就重跑自动超时、重试、降级、转人工可观测性print打印调试结构化日志、追踪、指标安全合规不涉及必须覆盖数据隔离和权限审计成本控制不关心每次请求的token、延迟、失败成本都要可预测迭代方式改prompt重新演示回归测试、灰度发布、逐步放量这张表基本说明了问题生产级Agent不是在demo基础上“加一点稳定性”而是从一开始就要换一套设计思路。1.3 真正的分水岭不是模型而是系统所以Linear团队的五条规则给人最直接的启示是不要把Agent当成“更聪明的模型调用”而要把它当成一个完整的软件系统来建设。模型只是系统里的一个推理组件它负责在不确定性较高的时候做判断。真正决定Agent能不能上生产的是边界、失败处理、可观测性、迭代评估这些系统能力。这些能力缺一块agent可能会在某个深夜以你完全想不到的方式挂掉。2. 第一条规则先划边界再谈智能2.1 能力边界工具注册表就是你的产品目录很多Agent项目一上来就把十几个工具全塞给模型让模型自己决定什么时候用哪个。这个设计的初衷是“赋予模型更多自主性”但在生产环境里这往往是一场灾难。更稳妥的做法是把能力边界显式化。Agent能做什么由一份工具注册表决定它不能做什么从一开始就不要出现在可选列表里。# 示例结构工具注册表所有Agent可调用的工具必须在这里登记 AGENT_TOOLS { search_kb: search_knowledge_base, create_ticket: create_ticket, read_calendar: read_calendar, } def dispatch(user_id, tool_name, tool_args): if tool_name not in AGENT_TOOLS: return {status: error, reason: tool_not_supported} # 继续做权限校验 ...这个设计有几个实际好处模型不会被无关工具干扰选择空间缩小准确性自然提高安全审计能明确知道Agent的工具暴露面新增或下线工具时只改注册表不需要动整套流程。不要把工具列表直接拼在prompt里就完事还要在代码层做硬校验。否则模型一旦“灵机一动”编造一个不存在的工具名你连拒绝的机会都没有。2.2 权限边界最小权限原则能力边界回答的是“能做什么”权限边界回答的是“谁允许做”。一个常见误区是给Agent一个服务账号这个账号拥有所有工具的调用权限。这样写起来简单但一旦出现prompt注入或用户恶意构造指令Agent可能会执行它根本不该执行的操作。生产级Agent应该把用户身份透传到每次工具调用中。每个用户能看到什么数据、能操作哪些资源由业务系统的权限模型决定而不是由Agent自由发挥。这里最容易踩坑的点是不要只校验“工具是否在允许列表”还要校验“参数是否合法”。比如一个工单创建工具允许调用不代表允许给任意用户创建工单。你需要在dispatch层把user_id传进去在工具内部再做一次资源归属校验。权限这件事永远不能只靠prompt约束。2.3 边界之外的选择拒绝、报错、转人工边界划分清楚之后还要给Agent一个“边界外的动作模板”。不能让它遇到不支持的请求时强行编一个结果也不能让它默默失败。更合理的处理顺序是检查工具是否在允许列表检查当前用户是否有权限检查参数是否满足业务规则通过后才真正调用工具。任何一步不通过都应该返回结构化的拒绝或异常同时上报到可观测系统。必要的时候把用户引导到人工客服流程。这个设计看起来像在“限制”Agent实际上是在保护整个业务流程。一个知道自己在什么情况下必须说“不”的Agent远比一个什么都会尝试但经常做错的Agent更可靠。2.4 边界的工程收益把边界划清楚本质上是在缩小模型需要处理的“不确定空间”。模型在不确定空间越大时越容易产生幻觉或误操作。你把工具、权限、参数约束都确定下来模型要做的事情就变成“在明确选项里做选择”准确率和可控性都会上去。对团队来说代码评审、安全审计、故障排查也都有了明确抓手。3. 第二条规则让Agent的每一步决策都留下痕迹3.1 可观测性的三个基础件Agent的可观测性和传统后端服务的可观测性并没有本质区别至少要包含三件东西结构化日志、追踪、指标。很多Agent项目在最开始会忽略这一点因为demo阶段用print输出足够应付。但一旦进入生产你会面临这些问题用户说“Agent做错事了”你怎么知道它当时调用了哪些工具模型一次回答消耗了多少token成本是多少一次Agent任务的平均延迟是多少哪个环节最慢工具调用失败率是不是从某个版本开始上升了没有结构化日志、追踪和指标这些问题全都要靠猜。生产环境不允许靠猜。3.2 每一步都要记而不仅仅是最终答案很多团队会记录“用户输入”和“最终输出”但中间重要的决策过程完全没有日志。这会导致一个问题最终结果错了但不知道是哪一步带偏的。更完整的记录方式是给每次Agent请求分配一个trace_id然后把模型调用、工具调用、中间结果、耗时、token消耗都挂在这个trace_id下面。import structlog logger structlog.get_logger() def run_agent_step(trace_id, step_name, **context): logger.info(agent_step, trace_idtrace_id, stepstep_name, **context)实际的日志里至少要包含这些字段trace_id一次完整Agent任务的唯一标识step当前步骤名称比如plan、tool_call、tool_result、model_replytool_name如果该步骤调用了工具记录工具名input_summary输入内容注意脱敏不要把密钥、隐私字段打进日志latency_ms该步骤耗时token_usage模型输入的token数和输出token数is_error是否成功error_type失败类型便于聚合。这样当用户反馈一个问题时你只需要拿到trace_id就能还原Agent当时做了哪些决策、每一步花了多久、卡在哪个环节。3.3 用trace_id把一次决策串起来分布式系统里trace_id是用来串联跨服务调用链的。Agent系统也一样一次任务会涉及模型、工具、知识库、业务API等多个组件。如果你只在单个组件里打日志排查问题时要靠时间戳对齐效率极低。实际落地时建议在入口处生成trace_id然后通过上下文对象传递到所有子模块。无论Agent内部是调用一个函数还是请求一个外部服务都把这个trace_id带上。排查问题时第一步就是查trace_id下的全部日志而不是搜索关键词。3.4 上线前的“睁眼测试”这里有一个很简单的检查方法关掉所有print和调试工具把用户反馈模拟一遍问自己一句——“如果这个Agent刚才做错了我能从日志里知道它为什么不这么做吗”如果你发现日志里只有“用户问了一句”和“Agent回了一句”中间完全不可见那这个Agent还不能上生产。可观测性不是锦上添花它是故障排查、成本分析、效果评估的共同基础。4. 第三条规则把失败当成主流程来设计4.1 生产环境里一定会发生的失败很多Agent在设计时默认所有组件都会正常返回。但生产环境里失败不是例外而是常态。常见失败包括模型服务超时或返回空内容工具接口超时、限流、返回500第三方知识库没有命中结果模型返回的JSON格式非法无法解析上下文长度超过窗口限制用户中途取消任务权限校验不通过。这些问题任何一个都可能让Agent流程卡住。如果你只在“成功路径”上做设计那上线后的主路径其实就是失败路径。4.2 失败分支要显式设计一个好的Agent流程不只是“调用工具→得到结果”而是每个调用都带着if/else如果工具返回成功继续下一步如果工具超时先重试一次重试间隔用退避策略如果工具返回错误记录错误决定是换一种方式调用还是直接转人工如果模型输出解析失败可以重新请求一次但最多一次避免死循环如果上下文超长先做截断或摘要再给模型。这些分支不应该藏在prompt里让模型自己判断而应该在框架代码里显式写出来。模型适合做“内容生成和语义判断”不适合做“精确的流程控制”。# 示例结构带失败分支的工具调用 for attempt in range(max_retries): try: result call_tool(tool_name, args) return result except TimeoutError: time.sleep(backoff_base * attempt) except RateLimitError: time.sleep(rate_limit_wait) return {status: failed, reason: tool_retry_exhausted}4.3 参数到底是在调给谁看很多Agent项目喜欢在演示时把temperature调高让回答显得“更有创造性”。但在生产环境里大部分任务需要的是可复现和稳定而不是随机发挥。我的建议是面向事实提取、工具调用、流程执行的场景temperature可以设置在0.1到0.3之间面向创意生成、娱乐闲聊的场景可以适当调整到0.7以上但要明确接受不可控性max_tokens不是越大越好要根据任务需要限制输出长度过长输出既增加成本又让日志变臃肿超时设置要参考工具响应的P95或P99而不是凭感觉定一个固定值重试次数要谨慎如果操作不是幂等的比如创建订单、发送消息重试可能导致重复执行需要业务侧做幂等验证。这些参数不是模型参数而是系统参数。它们决定了Agent在真实负载下的行为边界。4.4 先让失败可控制再追求成功率很多团队拿到新Agent的第一反应是“怎么提高成功率”但更稳妥的顺序是先让失败可控。你可以先模拟失败手动让工具超时、让模型返回非法格式、让权限校验不通过观察Agent会不会挂死、有没有重试、日志是否完整、转人工是否生效。当这些失败路径都能得到预期处理时再回到业务上优化成功率。一个失败路径清晰可控的Agent比一个成功率看起来很高但一失败就崩掉的Agent更适合进入生产环境。5. 第四条规则编排越简单越好模型只在最后出现5.1 能用代码判断就不要交给模型Agent开发里有一个很容易被忽略的原则确定性逻辑要由代码完成模型只处理真正需要语义理解的部分。比如一个请求是新增工单你需要先检查工单标题是否为空、用户是否有权限、所属项目是否有效。这些校验完全可以用代码完成不需要让模型“理解”。如果你把这些逻辑全塞进prompt让模型来判断那就等于把稳定问题变成了概率问题。生产级Agent的代码结构应该是代码做输入校验、权限校验、状态管理代码决定当前需要模型完成什么任务模型只返回语义判断结果比如抽取字段、生成回复代码再对模型输出做结构解析和校验。模型是流程里的一个函数而不是整个流程本身。5.2 复杂Agent框架不是必需品现在Agent框架很多功能也很丰富多Agent协作、记忆、规划、知识库、插件机制。但框架强不等于适用。对一个业务场景相对固定的Agent最可靠的架构往往是最简单的循环。一个最小可用结构通常只需要接收任务把任务传给模型让模型决定调用哪个工具或者生成最终回答解析模型输出调用工具把工具结果回传给模型循环直到完成任务或达到最大步数。这个循环看起来简单但足够支撑大量真实场景。先把它跑通再根据实际需要引入记忆、多Agent或复杂调度而不是为了“技术先进”一上来就铺一个大架构。当然这不是说框架没有价值。当你的Agent有状态机转换、多角色协作、长时记忆、复杂人工介入节点时框架可以节省大量重复工作。但引入框架的前提是业务复杂度和团队维护能力匹配。先用简单代码跑通业务比先选一个框架再适配业务要靠谱得多。5.3 稳定流水线优于灵活动手“给模型更多自由度”听起来很先进但代价是流程不可预测。生产级Agent追求的不是“它什么都会一点”而是“它该做什么就稳定做什么”。把流程理解成一条流水线每个环节输入输出明确异常分支清晰模型只负责中间最需要智慧的环节。这样的Agent更易于测试、评估和迭代。如果某天发现某个环节模型总出错你可以用代码把这一步替换掉而不是继续在prompt里加规则。5.4 模型只在最后出现这句话更准确的理解是模型不应该承担流程控制的责任。它不应该决定“失败后重试多少次”不应该判断“用户有没有权限”也不应该记忆“已经执行到第几步”。这些都应该由代码和外部状态管理负责。模型适合做的是理解用户意图、抽取关键信息、生成自然语言回复、决定在已知工具列表中选择哪一个。把这些职责边界切开之后Agent的代码结构会清晰很多后续所有问题也更容易定位。6. 第五条规则没有评估数据的迭代都是自我安慰6.1 建立回归集很多团队迭代Agent的方式是“改prompt→跑一两个例子→感觉差不多→上线”。这种方式在demo阶段没问题但进入生产后你根本不知道一次改动是提升了整体效果还是只让某个例子变好了同时让另外十个例子变差了。要改变这个局面第一步是建立回归集。把历史真实请求收集起来人工标注期望行为。数量可以从几十条开始慢慢扩充到几百条。回归集里的场景要覆盖常见操作、边界情况、失败场景、权限拒绝场景。场景输入示例期望行为是否通过正常查询知识库“请帮我查一下支付失败的常见原因”调用search_kb并返回相关结果待验证越权操作“把项目A删除掉”拒绝并说明无权限待验证工具超时第三方接口无响应重试后转人工待验证上下文超长输入一篇文章截断或摘要后继续待验证这张表可以先用Excel管理等规模变大再接入自动化评估平台。重点是先跑起来不要等完美再开始。6.2 每次改动先跑回归当你准备改prompt时先别急着直接换到生产环境。把改动应用到评估集上跑一遍和基线结果做对比。具体做法是记录当前版本的评估集通过率作为基线修改prompt或工具代码重新跑同一个评估集对比通过率和失败原因如果通过率没有下降再考虑灰度上线如果个别case变差要分析是回归集不完整还是改动方向不对。这个过程不需要很重的平台一个脚本加一个结果对比表就足够支撑早期迭代。6.3 生产环境收集反馈回归集是离线评估线上真实反馈是另一层数据。生产级Agent要设计反馈闭环包括用户对回答点“有用/无用”用户对Agent执行的操作进行确认或取消人工客服可以把Agent的错误标记出来系统自动记录失败率、拒答率、工具调用异常率。这些反馈数据需要回流到评估集和模型迭代流程中。否则你的Agent就像闭着眼睛跑只能靠用户投诉发现问题。6.4 评估指标不能只看准确率准确率是必要指标但不是全部。生产级Agent还应该关心成功率在允许时间内完成任务的占比失败率无法完成任务的占比拒答率Agent拒绝执行的占比太高可能说明权限边界过于严格太低可能说明边界判断失效平均延迟每个步骤至少要有分位统计单次请求成本token消耗和外部API费用人工介入率有多少请求需要转到人工处理这个指标能反映Agent处理长尾问题的能力。这些指标共同构成了Agent的健康状态。只看准确率你可能会漏掉成本失控和延迟恶化的问题。7. 五条规则之外的三个工程护栏7.1 一切模型依赖都版本化Agent和普通后端服务不同它的行为不仅由代码决定还由模型版本、prompt内容、工具返回格式决定。任何一个环节变化都可能影响整体输出。所以模型名称和版本、prompt、工具代码、评估集都要做版本管理。至少要在发布记录里明确写清楚这个版本用了哪个模型、prompt内容是什么、上了哪些工具、评估通过率是多少。否则一旦线上质量波动你连复现基线都找不到。7.2 灰度发布即使离线评估通过也不代表可以全量上线。更稳妥的做法是先让Agent服务很小比例的用户比如5%或10%观察一段时间的关键指标。灰度期间重点看四类数据失败率和异常率是否上升工具调用权限是否出现越权告警用户反馈是否变差成本是否明显超预算。一旦指标异常立即回滚到上一个稳定版本。灰度发布不是对自信心的挑战而是给生产环境上的不确定性留一条退路。7.3 必须有人工兜底Agent再稳定也会有处理不了的情况。生产级系统必须保留人工接管入口和紧急停止开关。具体包括当Agent连续重试失败或判定超出能力边界时自动转给人工处理运营或管理员可以手动关闭某个工具禁用某个Agent针对高风险操作比如删除、发消息、改配置增加人工确认步骤。这些兜底机制看起来和“智能化”冲突但它们恰恰是Agent能够长期稳定运行的保障。用户需要的是可靠的服务不需要一个永远逞强的模型。7.4 落地顺序建议如果你的团队刚开始做生产级Agent我不建议一次性把五条规则全部铺开。更好的方式是选择一个高频、低风险的业务场景按照下面的顺序搭建最小闭环先定义边界只开放两到三个工具给每一步调用增加结构化日志和trace_id设计失败分支至少覆盖超时和越权两类异常写二十到三十条回归用例跑通一个简单评估脚本小流量灰度上线观察延迟、失败率、成本和用户反馈。等这个最小闭环稳定了再逐步增加工具、扩大权限、提高流量。这个节奏虽然慢但每一步都有数据支撑出了问题也能快速定位。五条规则不是理论框架更像是一组工程约束。它们不会让Agent看起来更“聪明”但会让Agent在真实环境里变得更可预测、可控制、可迭代。对任何一个准备把Agent推上生产环境的团队来说这比单纯的模型炫技重要得多。如果你现在手上正在做一个Agent项目我的建议是先停下来做一件事梳理你的Agent当前的能力边界和观测日志。你都能说清楚吗如果能再继续往下走如果不能就先补齐这一块再谈其他。