做生产级智能体平台,说白了就是三件事:任务编排、工具管理、运行监控。我见过太多团队冲着“大模型”去搭平台,最后都烂在这三件事上——业务没跑几个,代码全堆在链式调用里;工具越接越多,密钥散落在各个服务;线上用户一问就崩,连日志都不知道去哪翻。今天这篇文章就以我实际落地过的方案为例,把这三块拆开讲透,适合正在做智能体平台、或者准备把智能体从Demo推向生产的架构师和后端同学参考。
你可能已经看过不少关于Dify这类智能体开发平台的介绍,但生产级平台和低代码工具的核心差异,恰恰不在“画流程图”,而在编排引擎的健壮性、工具接入的规范化、以及监控体系能否跟上模型的不可控。我后续所有的内容都会围绕这两个字:“落地”。不聊太虚的架构图,直接说怎么设计、怎么选型、怎么填坑。
1. 先想清楚再动手:生产级智能体平台的设计骨架
1.1 为什么任务编排、工具管理和运行监控是三大命脉
很多人一开始做智能体平台,重点都放在“模型选型”上:GPT系列、Claude系列、开源中文模型挨个测,觉得只要模型够聪明,平台就能成。但真跑起来你会发现,一个简单的客服智能体,从用户提问到返回答案,中间可能涉及意图识别、查库存、下订单、发通知四个环节。这四个环节一旦有一个挂了,整个任务就卡住,用户感知就是“机器人今天不正常”。
这就是任务编排要解决的问题。它不是把Prompt拼起来完事,而是要支撑复杂的工作流:条件分支、并行执行、人工审批、超时重试、任务补偿。我在生产环境里见过最典型的翻车案例,是团队用简单的链式调用来写订单流程:查库存成功了才下订单,下订单成功后发通知。结果通知服务偶发超时,订单已经创建成功,但整条链直接报错退出,用户在界面上看到的是“下单失败”,实际上订单已经生成,后续对账一团糟。这就是缺少编排层事务思维导致的业务事故。
工具管理是第二层命脉。智能体的能力边界基本等于工具接入的边界,但工具不是把API地址配上去就能用的。生产环境里要面对的是几十上百个工具,谁有权限调用、调用哪个版本、密钥怎么安全下发、工具返回格式不统一怎么办。这些全是实打实的问题。我在一个项目里接过四个外部API,每个API的超时时间、鉴权方式、错误码含义都不一样,如果用硬编码方式接,每接一个工具就得改一次平台代码,平台很快就变成一团乱麻。
运行监控则是第三层,也是最容易被拖延的一层。模型有不确定性,工具会超时,队列会积压,Token成本会失控,这些现象在测试环境里都不明显,一上生产就集中爆发。没有监控数据,出了问题只能拍脑袋猜,运气好猜对了,运气不好折腾俩小时。所以我把监控和编排、工具放同一个优先级去设计,而不是等上线以后再说。
1.2 平台的分层架构与技术选型策略
我习惯把智能体平台拆成五层来设计,每一层职责清晰,不越界:
- 接入层:负责API网关、Webhook、SDK接入,把外部请求统一转成平台内部的任务请求。
- 编排层:负责任务流程的定义、状态管理、调度执行,是整个平台的中枢。
- 执行层:负责真正跑智能体逻辑,包括模型调用、工具调用、代码执行。
- 工具层:负责工具注册、发现、调用、权限控制和版本管理。
- 观测层:负责指标、日志、链路追踪、告警,以及成本数据采集。
技术选型上,我的原则是:核心编排引擎尽量可控。开源的东西可以借鉴,但不要直接套。比如LangChain能帮你快速做复杂链,但它的抽象非常重,出问题排查链路长;Dify的编排可视化做得好,适合做产品和运营侧的智能体搭建,但生产级平台如果完全基于它定制,后续性能和权限扩展会受限。
我更推荐自研一套轻量编排引擎,底层可以借助成熟的队列或工作流引擎。比如用Redis Stream或RabbitMQ做任务队列,用状态表维护任务状态,用Worker池执行节点。这套方案的优点是问题边界清晰,节点逻辑可以完全自己控制,也很容易接入Prometheus监控。后面我会详细说这块的落地设计。
2. 任务编排:让智能体不再是一条简单的“链”
2.1 从线性链到DAG:编排模型怎么选
我在团队里问过一个很基础的问题:“智慧体流程到底是什么?”不少人会回答“Prompt组成的链”。这在原型阶段没错,但生产级平台面临的流程要复杂得多。
线性链是最容易理解的模式:A节点完成后执行B节点,B完成后执行C。这种模式适合简单的固定流程,比如“文本分类→调用对应工具→生成回复”。但缺点是逻辑一旦复杂,比如要做“判断用户意图→按意图分流到不同处理分支→其中一支还要并行查两个数据源”,线性链就没法表达了。
生产环境我更倾向用DAG(有向无环图)模型。每个任务流程由图节点和边组成,节点定义动作,边定义依赖关系,支持并行、分支、汇聚。实现DAG的方式有很多,你可以用现成的workflow引擎,比如Temporal、Airflow,也可以自研图执行器。关键看团队技术栈和部署环境。
我个人的建议是:如果平台规模不大、团队对分布式工作流引擎不够熟悉,自研一个中等复杂度的DAG执行器完全可行。核心就是拿到Flow定义后做一次拓扑排序,然后按入度为零的节点开始执行,每完成一个节点就更新下游节点状态,循环直到所有节点终态。这套逻辑自己写不复杂,但能完全掌控错误处理和状态恢复。
2.2 编排引擎选型:从自己写到用Temporal
写下这节标题的时候,我得诚实说一句:现在让我再选一次,我很可能在自研和Temporal之间犹豫。
自研的好处是简单直接,技术栈好维护。我之前在一个项目里用Python FastAPI写过一个轻量编排执行器,节点类型分模型调用节点、工具调用节点、代码节点、HTTP请求节点。每个节点是一个数据类,Flow是一个带依赖关系的节点列表。执行时用asyncio.gather跑并行的节点,每次节点完成后把结果写入任务上下文里。这个方案在单机规模下完全够用,部署也简单。
但当你需要处理大量并发任务、节点执行时间跨度长、需要历史活动回溯时,自研就会开始吃紧。Temporal这类持久化工作流引擎能解决这些问题:它会把工作流的状态持久化,服务重启后任务可以恢复,不需要自己维护“任务执行到一半”的状态。这个优势在生产环境里极大,尤其智能体任务动不动要几分钟,中间夹杂模型调用、人工审批,会话还不能丢。
如果选择自研,我建议你一定要提前实现这些能力:
- 节点执行状态持久化,写入数据库,方便断点恢复。
- 节点输入输出定义成JSON Schema,方便校验和版本兼容。
- 每个节点有独立的超时设置,避免模型卡死拖垮整个流程。
- 节点间通过统一的Event消息传递上下文,不直接共享内存变量。
如果你选Temporal,我不拦,但你要知道Temporal的运维成本不低,而且团队的运维意识得跟上。我用过一段时间后最大的体会是:很好的引擎,但版本兼容和升级需要谨慎,测试环境一定要完全模拟生产部署方式。
2.3 状态机、幂等与重试:生产环境必须抓住的细节
编排引擎听起来高大上,但落到具体实现,最难的都是细节。我在设计任务状态机时,没有一上来就搞复杂的五态、七态,而是先定义了最基础的四态:pending、running、succeeded、failed。跑一阵后发现不够用,因为模型调用超时了,任务到底是“失败”还是“等待重试”?工具调用被限流了,任务要不要在队列里排一会儿?后来我把状态扩展成:pending、running、waiting_retry、succeeded、failed、cancelled。每次状态变更记录到任务事件表中,事后回溯就像看账本一样清楚。
幂等性是另一个大坑。模型或工具调用超时,重试机制启动,但如果重试时又执行了“下单”这种非幂等操作,就会产生重复订单。解决思路是在平台层面做两层处理:第一层,每个节点执行前都分配一个全局唯一的执行ID,下游工具接口接收这个ID并以其作为幂等键;第二层,平台内部用一个去重表记录已经成功执行过的节点执行ID,如果同一个执行ID重复进入,直接返回上一次的结果,不再调用工具。
重试策略也要分节点类型来设计。模型调用节点可能偶发超时,线性退避重试三次可行;但数据库写入类节点不能盲目重试,得先判断错误类型。我经常和团队说一句话:重试不是无脑喊“再来一次”,而是要有“快失败、慢恢复”的节奏。快失败是指可预见的业务错误(比如参数校验不通过)直接返回,不要浪费资源;慢恢复是指对瞬时故障(连接池满、模型服务过载)先等待一段指数退避时间,再逐步恢复尝试。
2.4 一段可落地的编排配置示例
光说理论没意思,我给一个实际用过的编排定义示例。这个Flow描述的是“客服智能体处理售后单”的场景:先判断用户意图,如果包含“退款”关键字就进入退款分支并同时调用用户订单查询和用户历史工单查询,两个查询都完成后生成处理建议;否则进入通用问答分支。
flow: id: after_sale_handler name: 售后处理流程 start: intent_classify nodes: - id: intent_classify type: model model: qwen-plus prompt_template: "判断用户意图,输出 refund 或 faq" next: - condition: output == "refund" target: query_order_and_ticket - condition: output == "faq" target: general_qa - id: query_order_and_ticket type: parallel branches: - query_user_order - query_user_ticket - id: query_user_order type: tool tool: order_query timeout: 10s retry: max_attempts: 3 backoff: 2s - id: query_user_ticket type: tool tool: ticket_query timeout: 10s retry: max_attempts: 3 backoff: 2s - id: generate_suggestion type: model model: qwen-plus depends_on: [query_user_order, query_user_ticket] input_from: "$.query_order_and_ticket.results" - id: general_qa type: model model: qwen-plus prompt_template: "基于知识库回答通用问题"注意到这个流程里的几个关键点:
parallel节点表示并行执行多个子节点,执行完后再汇合。- 每个工具节点都设置了独立的超时和重试。
depends_on显式声明了依赖关系,而不是靠全局上下文隐式传递。- 模型节点和工具节点的输入输出都会自动写入任务上下文,方便后续节点引用。
这套配置放在JSON里也行,但YAML的可读性对业务方友好得多。我的建议是编排定义一定要做版本管理,因为线上的流程不可能永远是同一个版本,你改了流程以后,老任务可能还在执行,新老版本的行为差异需要能看到。
3. 工具管理:智能体的“手”和“权限”都要管好
3.1 工具的注册、发现与统一调用协议
智能体平台里,工具就是模型之外的能力补充。但工具的形态五花八门:有的挂在内部REST API上,有的是GraphQL接口,有的是gRPC服务,还有些是Python包直接封装成的函数。如果不做统一协议,编排层每接一个新工具就要写一段定制代码,平台就废了。
我在平台上定义了一套统一工具协议,最小字段包括:工具名(tool_name)、版本(version)、输入参数JSON Schema、输出JSON Schema、鉴权方式、超时配置、错误码映射。工具接入的时候,开发者先按这个协议注册一个工具描述文件,平台自动生成调用入口,调用时统一通过工具网关转发。
其实很多开源智能体平台已经往这个方向走了。Dify工具生态里的Agent Tool就是类似的思路,它把HTTP请求封装成标准化工具,你只需要填API地址、Header、Body和输出字段映射。我们自研的协议本质上和它一样,只不过更关注内部多种协议的支持,所以做了适配器层:
- HTTP适配器:把平台内工具ID映射到具体REST端点。
- Python适配器:允许上传一个Python文件,平台通过沙箱执行该文件暴露的函数。
- MCP适配器:如果工具已经按MCP标准实现了服务发现,可以直接接入。
MCP这个概念现在越来越常见,简单理解就是给AI工具定了一套“即插即用”的接口标准。如果团队的工具生态还比较封闭,不建议一开始就全面拥抱MCP,但建议预留好接入空间,看到工具方提供MCP端点时,至少能快速接入。
3.2 工具密钥、权限与审批流
工具管理里最敏感的不是代码,是密钥。我见过最粗暴的做法是把密钥直接写在工具配置里,前端都能看到明文;稍微好一点的是写在环境变量里,但所有工具共用一把密钥,权限上根本没法隔离。
生产级平台的做法应该是工具密钥和服务密钥分开管理。平台内部服务之间的访问用服务身份,工具调用时下发的密钥由密钥管理服务动态签发,并且可以设置临时有效期。具体落地时,我用HashiCorp Vault存储密钥,工具注册的时候引用Vault里的路径,比如secret/tools/order_query,平台调用工具前从Vault读取临时凭证,用完即关短时间有效期。
同一个工具还要区分“谁有权限调用”。我的分法是三层数据模型:
- 工具目录:所有已注册工具的技术描述,开发者可以查看。
- 工具授权:一个工具可以被哪些应用/工作流调用,由平台管理员分配。
- 工具审批:当某个业务方申请开通一个高风险工具(比如对外发短信、转移订单)时,必须进入审批流,指定审批人,审批通过后自动开通权限。
工具权限和业务权限不要混在一起。业务权限管“用户能干什么”,工具权限管“智能体能干什么”。两者是独立的,否则当你希望一个智能体只处理某类用户的订单查询时,会非常痛苦。
3.3 工具配置与源码的版本管理:为什么我弃用SVN
工具除了业务逻辑,还有配置和Prompt模板。配置改坏了要能回滚,工具升级了要能追溯历史版本,这让“版本管理”成为工具管理里绕不开的话题。
说到版本管理,很多老团队还在用SVN。我不能说SVN不行,它确实简单、稳,集中式模型在某些小团队里也够用。但智能体平台里的工具配置、Flow定义、Prompt模板经常需要跨团队并行修改,SVN的“锁文件”模式会阻碍协作。而且在Web端操作和做代码评审时,SVN的整体体验确实差点意思。
除SVN之外,我更推荐用带Web端的Git托管工具,比如GitLab、Gitea、Gitee。它们都支持在浏览器里查看不同版本的源码差异,也都能做分支管理和合并请求。实际用下来,GitLab对CI/CD和权限管理的集成很强,适合中等以上团队;Gitea轻量,内存占用小,一个小团队自己部署很舒服;Gitee国内访问体验好,但和自建系统集成的自由度不如前两者。
这里不是要搞“Git vs SVN”的宗教辩论,而是想强调一个点:智能体平台的配置本质上是代码,应该走代码的治理方式。我们把所有Flow定义、工具描述文件、Prompt模板放在一个agent-platform-config仓库里,任何修改走Merge Request流程,有评审记录、有历史版本,出问题能一键回滚。这套流程比用SVN时期乱改配置爽太多了。
工具的代码版本还要和工具运行时版本做关联。工具升级了,线上跑的智能体不能全部立刻切到新版,因为模型已经习惯老工具的输出结构。我们让工具注册表里同时存在多个版本,平台管理员决定某个工作流具体绑定哪个工具版本,避免“升级即全体受影响”。
3.4 工具测试沙箱与灰度发布
把工具接进平台容易,但保证这个工具在真实场景下的表现是另一回事。我强烈建议平台必须有一个“工具测试沙箱”,在里面开发者可以用预置的测试凭证调用工具,平台记录调用输入输出,方便比对。
沙箱要能模拟生产工具的返回,最重要的还有“故障注入”。我搞过一个很土但有效的做法:沙箱里的HTTP适配器可以配置响应延迟和错误码,比如测试时故意把订单查询接口调成50%概率超时,观察编排层重试逻辑是否正常。这些场景不提前做,上了生产就变成事故。
工具上线也要灰度。我们的做法是:新版本工具先挂到测试工作流,再挂到低流量生产工作流,观察成功率、延迟、Token费用等指标,达到阈值后再全量。这段路径依赖监控数据,所以下一章的内容和工具管理其实是联动的。
4. 运行监控:把可观测性从“锦上添花”变成“保命稻草”
4.1 该监控哪些指标:从LLM调用到队列积压
提到监控,很多人第一反应是看CPU、内存,这个没错,但对智能体平台来说远远不够。平台的核心指标有三类:模型调用指标、工具调用指标、任务流程指标。
模型调用指标包括:每次调用的延迟、Token数、模型返回错误率、输入输出长度。这里特别提一句,Token费用是智能体平台运行成本的最大头,把Token消耗按工作流维度聚合,才能知道哪个业务线烧钱最快。
工具调用指标包括:工具调用次数、成功率、超时率、限流次数。工具成功率低不一定是工具本身挂了,也可能是编排层传的输入参数模型生成得不对,所以看这类指标时要能下钻到具体任务。
任务流程指标包括:任务吞吐量、队列积压数、各节点执行耗时、失败任务数、平均恢复时间。队列积压数尤其重要,智能体任务比普通Web请求慢得多,一个任务几十秒甚至几分钟很正常,队列积压一多,用户等待时间就失控。
我还建议加一类“业务结果类指标”,比如智能体一次会话里成功调用了工具的次数、最终回复被用户点赞或点击“有用”的比例。这类指标贴近业务价值,但也最难采集,量力而行。
4.2 Prometheus采集配置:让指标先跑起来
监控界现在基本被Prometheus + Grafana这套组合统治。我见过最多的问题不是工具不好用,而是不会设计指标暴露方式。Prometheus是拉取模式,也就是说需要每个服务提供一个/metrics端点,让Prometheus定时来抓。
我给编排执行器暴露的指标大致是这些:
# 任务维度 agent_task_total = Counter("agent_task_total", "总任务数", ["flow_id", "status"]) agent_task_duration = Histogram("agent_task_duration_seconds", "任务耗时", ["flow_id"], buckets=[1, 5, 10, 30, 60, 120]) agent_queue_depth = Gauge("agent_queue_depth", "任务队列深度", ["queue"]) # 模型调用维度 model_call_total = Counter("model_call_total", "模型调用次数", ["model", "flow_id", "status"]) model_call_duration = Histogram("model_call_duration_seconds", "模型调用耗时", ["model"], buckets=[0.5, 1, 2, 5, 10, 30]) model_token_total = Counter("model_token_total", "Token消耗", ["model", "type"]) # 工具维度 tool_call_total = Counter("tool_call_total", "工具调用次数", ["tool", "version", "status"]) tool_call_duration = Histogram("tool_call_duration_seconds", "工具调用耗时", ["tool"], buckets=[0.1, 0.5, 1, 2, 5, 10])在FastAPI服务里,我直接用了prometheus_client库,初始化/metrics路由,项目里的Counter、Histogram、Gauge都是全局对象,业务逻辑里采样即可。
Prometheus采集配置方面,可以参考下面的体系:
global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: "agent-platform" metrics_path: /metrics static_configs: - targets: ["agent-executor:8000", "agent-tool-gateway:8001"]15秒的采集间隔对绝大多数智能体平台都够用,如果任务量非常大,再考虑降到10秒。但要注意Prometheus本身也是资源消耗者,别把采集间隔调得过密,未必值得。
Prometheus的数据量也要心里有数。卡片级指标像model_token_total这种会按模型和业务标签无限增长,聚合查询多了容易慢。我一般会对这类高基数指标做分层聚合,或用VictoriaMetrics替代存储,不过初期用Prometheus就够了。
4.3 Grafana看板与告警:100%展示不是目的,止损才是
Grafana的价值不在看板好看,而在于把数据变成决策。跑通一个仪表盘也就一下午的功夫,关键是你能不能定义出真正有意义的告警规则。
我最常用的告警规则有这几个:
- 任务失败率五分钟内超过20%,触发
Warning;超过50%,触发Critical。 - 某个工作流下模型调用平均延迟连续三分钟超过30秒,触发告警。
- 工具调用成功率低于90%且持续五分钟,触发告警。
- 任务队列积压数超过500且持续两分钟,触发告警。
- Token消耗异常增加,比如某个工作流半小时Token消耗比同时段上涨5倍,需要人工关注。
Grafana里一条和Prometheus告警规则长这样:
groups: - name: agent-platform-alerts rules: - alert: HighTaskFailureRate expr: | sum(rate(agent_task_total{status="failed"}[5m])) / sum(rate(agent_task_total[5m])) > 0.2 for: 5m labels: severity: warning annotations: summary: "任务失败率超过20%"这个规则的意思是:五分钟内失败任务占总任务的比率超过20%,并且持续五分钟,才算告警。for: 5m这个参数很重要,它避免偶发波峰频繁打扰,生产环境建议都用上。
还要强调告警必须分级。我团队里定了一条规矩:P0告警直接电话通知值班人,比如核心工作流完全不可用;P1告警钉钉群提醒,比如失败率持续偏高;P2告警只进告警列表,比如Token消耗异常,每天下班前review一次。没有分级的告警发多了,人会麻,关键告警反而被忽略。
4.4 链路追踪与日志:定位“这一轮为什么失败”
指标能告诉你“坏了”,但定位“为什么坏”要靠日志和链路追踪。很多智能体平台的问题是:一个任务涉及多个节点,每个节点都会调用模型和工具,出问题时你需要在“任务ID”这个维度把所有节点日志串起来。
我现在的做法是基于OpenTelemetry做全链路Trace。任务启动时生成trace_id,每一个节点执行都生成一个span,记录节点ID、模型名称、工具名、输入输出摘要(脱敏后的)。Elasticsearch负责日志检索,Jaeger或者Grafana Tempo负责Trace查询。
日志规范上有一点必须养成习惯:不要直接打印完整Prompt和工具返回原文。Prompt里可能包含用户敏感信息,工具返回原文可能包含业务数据,一旦日志泄露就是资安事故。我们在日志里只记录字段级摘要,比如输入长度、输出长度、Token数、响应码,以及脱敏后的关键字段。
4.5 成本监控与配额治理
大模型平台的钱烧起来是真的快,如果不做成本治理,月底账单会让你怀疑人生。成本监控不是只看总量,要看分摊。
我们会在Token指标上打三个标签:flow_id(工作流)、model(模型)、tenant(租户/业务线)。这样每天早上能从Grafana拉出各业务线前一天的Token消耗排行。对异常消耗,我们设置一个“模型每日消耗上限”,比如某个测试工作流每天最多消耗100万Token,超过就自动熔断,不再继续调用模型,直接返回降级提示。
成本和限流其实是双生的。平台还要对模型调用做配额管理:每个工作流每分钟最多调用多少次模型、每天最多多少Token。这里需要注意,限流不能只挡“用户”,智能体任务的模型调用量是波动的,配额太死会影响体验,所以我用令牌桶,允许短时突发,但长时间平均值被限制。你在Prometheus里也能看配额剩余,调起来方便。
5. 评测、压测与踩坑实录:把平台推到生产边缘
5.1 参考《大模型智能体开发平台技术能力综合测试报告》做评测
年前看了一份《大模型智能体开发平台技术能力综合测试报告》,虽然不同报告侧的评测维度略有差异,但基本都逃不开这几项:任务编排能力、工具生态兼容性、模型接入灵活性、可观测性、安全与权限、性能与稳定性。
我把这些维度整理成一张内部清单,每次大版本上线前都会跑一遍,也推荐你参考来做评测:
- 编排能力:是否支持并行/分支/循环?任务能否中断恢复?失败重试是否可配置?
- 工具生态:接入一个新HTTP工具平均需要多久?是否需要改平台代码?是否支持MCP?
- 模型接入:添加一个新模型服务商需要多少配置?切换模型是否影响Flow运行?
- 可观测性:能否按任务ID串起日志和Trace?指标能否按工作流维度下钻?
- 安全和权限:工具密钥是否加密存储?是否最小权限分配?日志是否脱敏?
- 性能:100并发任务下模型调用成功率如何?200并发时任务耗时是否线性恶化?
- 稳定性:Pod重启后正在执行的任务能否恢复?重复执行是否会重复下单?
对照这份清单测下来,大部分平台在“编排能力”和“可观测性”上分数低,这两个恰恰就是生产级和Demo级的核心分水岭。
5.2 压测中暴露的典型问题
我做压测时最常看到的几个问题,基本可以当“前车之鉴”:
第一是任务并发上来后,模型调用全部打到同一个模型网关,导致网关线程池打满。这个问题在测试环境根本发现不了,因为量太小。解决办法是给模型网关做连接池隔离,或者对接模型服务商时配置足够的超时上限,按工作流分流。
第二是工具调用慢,但编排层默认超时时间设得太短。工具实际需要8秒,平台超时却设的是5秒,结果很多任务是“成功调用但主动放弃等待”,浪费了工具消耗,用户还看到失败。这个问题的根因是超时配置没有针对具体工具做精细化设值,所以工具注册协议里一定要把超时时间作为必填项,不是平台全局统一。
第三是重试风暴。某个下游工具抖动,编排层同时触发几十个任务的重试,导致下游系统被放大了几十倍的流量打挂。这个我在生产里踩过,后来强制要求重试必须带随机抖动,而且重试总次数不能超过3次。随机抖动就是在退避时间上加减一个随机值,比如退避2秒,实际等待1.8到2.2秒之间,避免同一时刻一起重试。
5.3 常见问题速查表
我把高频问题整理成一张速查表,放在了监控告警入口旁边,非常实用:
- 任务卡在
pending状态不动:看队列消费者是否存活,Worker是否发生OOM重启。 - 任务
failed但日志没报错:看节点是否有“静默吞错”,比如Python函数里except后没抛出。 - 模型调用超时但模型服务正常:看平台侧调用模型用的HTTP连接池是否耗尽。
- 工具调用成功但任务失败:看工具返回的Schema是否与节点定义不匹配。
- 任务重复执行产生重复订单:检查幂等键是否传到了工具接口。
- Grafana查不出数据:先看Prometheus Target里服务是否Up,再看指标名是否有拼写错误。
- 告警频繁但任务正常:检查
for持续时间,以及指标标签是否过度聚合。
速查表最大的价值是让值班同学不用每次从头查起。排查耗时从平均半小时降到十分钟,这种感觉非常好。
5.4 我踩过的一些坑和经验
最后聊几个印象深刻的坑,希望能帮你少走弯路。
第一个坑是“没有事先约定模型输出格式”。我们曾经有个Flow让模型输出JSON格式,结果模型偶尔在JSON前面加Markdown代码块,导致解析失败,整条流程成功率只有75%。后来我们强制在Prompt里做few-shot示例,并且解析阶段增加了“提取第一个平衡JSON块”的容错逻辑,成功率才稳定到98%左右。
这里多说一句,想靠Prompt保证100%的JSON格式是不现实的,平台层必须做兼容。
第二个坑是“工具网关成了单点”。刚开始工具网关功能不多,部署上只开了一个实例。某次工具网关服务发布,平台所有任务卡在调用工具阶段,用户侧反馈“机器人罢工了”。后来再忙也要保证工具网关至少两个副本,并且和编排层弱依赖:工具网关不可用时,编排流程能快速失败,而不是无限挂起。
第三个坑是“监控告警做了,但没人看”。这里的问题不在技术,在流程。告警推到群里,如果没人响应,告警等于白做。我后来专门排了值班表,并把告警升级路径写清楚:P0发到电话,五分钟不回自动上报给技术负责人。这套流程看似简单,但真的能给平台兜底。
第四个经验是“Flow版本和模型版本一起锁”。你可能会遇到这种情况:线上业务跑得很好,某天改了模型的temperature或者换了个新版本模型,结果任务表现明显变差,但代码没变。所以Flow定义里必须记录使用的模型版本和推理参数,否则线上出了质量问题,连“什么模型跑的”都查不出来。
收尾的个人体会
做智能体平台这几年,我越来越觉得,它的难点不在“智能”,而在“工程”。模型再聪明,编排不严谨会出错;工具再丰富,权限管不住会出事;监控再华丽,告警没人盯也白搭。生产级这三个字,本质上是用工程化的确定性去对抗模型和外部服务的天然不确定性。如果你正准备做这块,我建议先从任务编排最小闭环搭起,一个流程跑通、一个工具接入、一屏监控看住,再逐步扩展。把每一层的基本功做扎实,比一开始就追求宏大架构靠谱得多。