
1. 从 Demo 到生产中间隔着一整条工程化鸿沟做过 Agent 项目的人大概都有过这种体验花一个周末用 Open WebUI 接上本地模型再挂两个 Skill跑通一个能查天气、能总结文档的智能体截图发群里大家都说“牛”。然后老板说那咱们下周上线吧给全公司用。你突然就笑不出来了。Demo 和生产之间的差距不是把模型换大一点、把提示词写长一点就能填上的。它是一整条工程化鸿沟涉及运行时稳定性、Skill 生命周期管理、多用户隔离、可观测性、错误恢复、权限边界、成本控制等一大堆在 Demo 阶段根本不会暴露的问题。标题里问“企业 Agent 平台真正缺少的是什么”我的答案是缺的不是模型能力缺的是把 Agent 当成一个长期运行的生产系统来对待的那套工程基础设施。这篇文章面向的是已经跑通过 Agent Demo、正准备往生产环境推进的开发者或者正在选型企业 Agent 平台的技术负责人。我会围绕 Agent、Runtime、Open WebUI、Hermes、Skill 这几个核心关键词把从 Demo 到生产这条路上真正会踩的坑、真正需要补的能力一层一层拆开讲。不讲虚的讲我实际趟过的和见过的。先说一个基本判断Agent 平台的核心竞争力从来不在模型那一层而在 Runtime 那一层。模型是租来的、可以换的但 Runtime 是你自己的它决定了你的 Agent 能不能稳定跑、能不能被观测、能不能被治理。下面我从整体设计思路开始拆。2. Agent 平台的整体设计与 Runtime 选型思路2.1 为什么 Runtime 才是企业 Agent 平台的真正底座很多人把 Agent 理解成“大模型 提示词 几个工具调用”这是 Demo 视角。生产视角下Agent 是一个有状态、长生命周期、需要被调度和治理的计算单元。它要处理并发请求要在工具调用失败时重试要在上下文超长时做压缩要在多个 Skill 之间做路由还要把每一步执行轨迹记录下来供审计。这些全部落在 Runtime 身上。Runtime 这个词在热词里出现频率极高从codemeter runtime到webview2 runtime再到container runtime is not running本质上都在说同一件事任何需要长期稳定运行的东西都必须有一个专门的运行时来托管它的生命周期。Agent 也不例外。一个合格的 Agent Runtime 至少要负责会话状态管理、工具/Skill 的注册与发现、执行编排、超时与重试、资源隔离、日志与追踪。缺了任何一块你的 Agent 在 Demo 里能跑在生产里就会以各种诡异的方式挂掉。我见过太多团队把编排逻辑直接写死在业务代码里用一堆 if-else 判断该调哪个工具。Demo 阶段三个工具还行生产阶段三十个 Skill、上百种意图组合这套逻辑立刻变成不可维护的意大利面。正确的做法是把编排下沉到 Runtime业务层只负责声明“我有哪些 Skill、它们的输入输出是什么”由 Runtime 去决定怎么组合、怎么调度。2.2 Open WebUI 在平台里的定位入口而非全部Open WebUI 是这两年被讨论最多的 Agent 前端之一热词里open webui 下载、绿联nas dxp4800 pro docker 部署 ollama open webui这类搜索量一直很高。它的价值在于用极低的成本给你一个可用的对话入口并且原生支持接入本地模型和工具。对个人开发者和小团队来说它是从零到一最快的路径。但这里有个认知陷阱很多人把 Open WebUI 当成了整个 Agent 平台。它不是。Open WebUI 是交互层负责把用户输入送进去、把结果渲染出来。它不负责 Skill 的版本管理不负责多租户隔离不负责执行链路的可观测性。你在 Open WebUI 里挂一个 Skill 跑通了不代表这个 Skill 能在生产环境被一百个人同时调用还不出问题。我的建议是把 Open WebUI 当作平台的“前门”但门后面必须有一套独立的 Runtime 和 Skill 管理层。Open WebUI 通过标准接口比如 OpenAI 兼容的 API 格式去调用你的 Runtime这样前端可以随时替换后端能力沉淀下来。这种分层的好处是哪天你想换成自研前端或者接入企业 IM后端一行不用改。2.3 Hermes 这类 Agent 框架带来的编排范式热词里hermes、hermes agent、deepseek hermes、hermes desktop出现得非常密集说明这类 Agent 框架正在成为主流选择。Hermes 这类框架的核心贡献是把 Agent 的执行抽象成了一套可组合的编排范式任务分解、工具选择、结果聚合、循环控制。它让开发者不用从零手写 ReAct 循环而是用声明式的方式描述 Agent 的行为。选这类框架的时候我关注三个点。第一它是否把 Runtime 和框架解耦也就是说框架挂了我的 Skill 和会话状态还在不在。第二它的 Skill 注册机制是否标准化能不能做到热插拔、版本回滚。第三它的执行轨迹是否可导出出了问题我能不能复盘每一步。这三点决定了你是把它当玩具还是当生产组件。harness 和 agent 区别这个搜索词其实点到了一个关键概念Harness 是“挽具”是承载和约束 Agent 的那套外壳包括 Runtime、权限、观测Agent 是“马”是真正干活的那部分。企业平台缺的往往不是马是那套能驾驭马的挽具。2.4 Skill 体系从“能调用”到“可治理”的跨越Skill 是 Agent 能力的载体热词里skill、agent skill、skill 插件、skill 脚本、codex skill、仓颉 skill、数学建模 skill一大堆说明大家都在往这个方向堆能力。但 Demo 阶段的 Skill 和生产阶段的 Skill要求完全不同。Demo 阶段一个 Skill 就是一个函数能返回结果就行。生产阶段一个 Skill 需要考虑输入参数的校验和清洗、超时和熔断、失败重试策略、调用频次限制、权限校验、版本管理、依赖隔离、执行成本核算。我见过一个查数据库的 SkillDemo 时直接拼 SQL上线后被人用注入的方式拖走了整张表。这不是模型的问题是 Skill 治理缺失的问题。所以 Skill 体系的设计目标应该是让每一个 Skill 都成为可注册、可发现、可授权、可观测、可回滚的标准单元。下面我会专门用一章讲怎么落地。3. 核心细节解析Runtime、Skill 与执行链路的工程化要点3.1 Runtime 的会话状态管理别把状态塞进提示词Demo 阶段最常见的做法是把所有上下文都塞进提示词里每轮对话把历史全量拼进去。这在单用户、短会话下没问题一旦上生产就崩上下文窗口撑爆、成本飙升、响应变慢而且多用户之间状态会串。正确的做法是会话状态外置。Runtime 维护一个会话存储可以是 Redis、Postgres甚至本地 SQLite 起步每个会话有独立的 ID状态包括对话历史、当前任务栈、已调用过的 Skill 及其结果、用户偏好。提示词里只放当前这一步真正需要的信息历史通过检索或摘要的方式按需注入。这里有个实操细节状态要分冷热。最近几轮对话是热状态直接进上下文更早的历史是冷状态做摘要或向量化存储需要时再召回。我一般把热窗口控制在 6 到 10 轮超过的部分自动摘要。这样既控制了 token 成本又保留了长期记忆能力。注意会话状态里千万不要存敏感明文比如用户的原始凭证、密钥。Skill 需要用到凭证时通过 Runtime 的凭证管理模块按需注入用完即焚不要让它进入对话历史。3.2 Skill 的注册、发现与版本管理Skill 要能被治理第一步是标准化它的描述。我推荐每个 Skill 至少声明这些元数据唯一标识、版本号、功能描述、输入 schema、输出 schema、超时时间、是否需要授权、依赖的外部服务、成本等级。这些元数据注册到 Runtime 的 Skill Registry 里Runtime 才能做路由和治理。版本管理这块很多人忽略。Skill 是会迭代的今天改个参数明天换个实现如果没有版本概念线上行为会莫名其妙地变。我的做法是Skill 标识 语义化版本比如query_order1.2.0。Runtime 在调用时锁定版本新版本发布后先灰度确认没问题再切流量。出问题时一键回滚到旧版本而不是手忙脚乱改代码。发现机制上Skill 多了以后不能靠把所有 Skill 描述都塞进提示词让模型选那样 token 爆炸且准确率下降。更好的做法是两阶段路由先用轻量检索关键词或向量从 Skill Registry 里召回 Top-K 个候选 Skill再把候选的详细描述给模型做最终选择。这样既控制了上下文长度又提升了选择准确率。3.3 执行编排超时、重试与熔断的实战参数Agent 执行链路里最容易被低估的就是失败处理。工具调用会超时、会返回错误、会返回格式不对的结果。Demo 阶段你可能直接让它报错生产阶段必须有一套完整的容错策略。超时设置上我的经验值是单个 Skill 调用超时 10 到 30 秒具体看 Skill 类型。查询类 10 秒生成类 30 秒涉及外部 API 的按对方 SLA 加缓冲。整个 Agent 任务的总超时控制在 2 到 5 分钟超了就中断并返回部分结果不要让用户无限等。重试策略上只对幂等的、瞬时失败的调用重试。查询类可以重试写操作类绝对不能盲目重试否则会重复下单、重复扣款。重试次数 2 到 3 次采用指数退避比如 1 秒、2 秒、4 秒。连续失败达到阈值就熔断把这个 Skill 标记为不可用一段时间避免雪崩。失败类型处理策略参数建议网络超时指数退避重试重试 2 次间隔 1s/2s参数校验失败不重试返回模型让其修正最多让模型修正 1 次外部服务 5xx重试 熔断连续 5 次失败熔断 60s写操作失败不自动重试转人工确认记录状态提示用户结果格式错误让模型重新解析最多 2 次3.4 可观测性没有追踪的 Agent 等于黑盒生产环境的 Agent 出问题时最怕的就是“它就是不工作了但不知道为什么”。可观测性是刚需至少要覆盖三层请求级追踪、Skill 级指标、模型级日志。请求级追踪给每个用户请求分配一个 trace ID贯穿整个执行链路每一步的输入输出、耗时、状态都记下来。这样出问题时能完整复盘。Skill 级指标统计每个 Skill 的调用次数、成功率、平均耗时、P99 耗时用来发现性能瓶颈和异常。模型级日志记录每次模型调用的 token 消耗、延迟、返回内容用来做成本核算和效果分析。我一般用 OpenTelemetry 这套标准来做埋点后端接 Jaeger 或类似工具看链路。如果团队小起步阶段用结构化日志JSON 格式打到文件配合简单的查询脚本也能顶一阵。但千万别省这一步省了后面排查问题的时间成本会十倍百倍地还回来。4. 实操过程从 Open WebUI Demo 到可治理 Agent 平台的落地路径4.1 第一步用 Docker Compose 搭起最小可运行环境从 Demo 起步最省事的方式是用 Docker Compose 把 Open WebUI 和本地模型服务拉起来。热词里绿联nas dxp4800 pro docker 部署 ollama open webui 的 compose.yml 脚本这类需求很典型说明大家都在找可复现的部署方案。下面是一个我常用的最小 compose 结构做了简化重点是分层清晰。services: ollama: image: ollama/ollama:latest volumes: - ollama_data:/root/.ollama ports: - 11434:11434 restart: unless-stopped open-webui: image: ghcr.io/open-webui/open-webui:main depends_on: - ollama environment: - OLLAMA_BASE_URLhttp://ollama:11434 - WEBUI_SECRET_KEYchange_me_in_production volumes: - webui_data:/app/backend/data ports: - 3000:8080 restart: unless-stopped volumes: ollama_data: webui_data:这套跑起来你就有对话入口和模型服务了。但注意这只是 Demo 环境。WEBUI_SECRET_KEY一定要改restart: unless-stopped保证容器挂了能自动拉起这是生产化的第一步意识。4.2 第二步把 Skill 从业务代码里抽出来做成独立服务Demo 阶段 Skill 往往直接写在 Open WebUI 的 Function 里或者写在一个大 Python 文件里。生产化改造的第一步是把每个 Skill 抽成独立的、有标准接口的服务。我推荐用 HTTP 或 gRPC 暴露输入输出都是 JSONRuntime 通过标准协议调用。抽出来之后每个 Skill 服务自己负责参数校验、业务逻辑、错误码定义、超时控制。Runtime 只负责编排和治理不关心 Skill 内部怎么实现。这样 Skill 可以独立部署、独立扩容、独立回滚团队之间也能并行开发。举个实际例子一个“查询订单”的 Skill接口定义大概长这样{ skill_id: query_order, version: 1.2.0, description: 根据订单号查询订单状态和详情, input_schema: { type: object, properties: { order_id: {type: string, pattern: ^[A-Z0-9]{10,20}$} }, required: [order_id] }, output_schema: { type: object, properties: { status: {type: string}, amount: {type: number}, created_at: {type: string} } }, timeout_ms: 10000, requires_auth: true, cost_level: low }这份元数据注册到 Runtime 后路由、鉴权、超时、成本核算全都有了依据。这就是从“能调用”到“可治理”的关键一步。4.3 第三步接入 Runtime 编排层实现两阶段 Skill 路由Skill 服务化之后Runtime 要做的事情就清晰了接收用户请求做意图理解召回候选 Skill让模型选择执行调用处理结果维护会话状态。这里面最关键的是两阶段路由的落地。第一阶段是召回。把所有 Skill 的description做向量化存进向量库。用户请求进来后先做一次向量检索召回 Top-8 候选。这一步不涉及大模型速度快、成本低。第二阶段是精排把候选 Skill 的完整 schema 和用户请求一起给模型让模型输出该调用哪个 Skill、参数是什么。模型输出用结构化格式JSONRuntime 解析后执行。这样做的好处是即使你有几百个 Skill每次进模型的也只有 8 个候选token 可控准确率还比全量塞进去高。实测下来两阶段路由在 Skill 数量超过 20 个之后优势非常明显。4.4 第四步加上会话存储和状态管理会话存储我一般用 Redis 做热状态Postgres 做冷状态和审计。Redis 里存最近 10 轮对话和当前任务栈设置合理的过期时间比如 24 小时。Postgres 里存完整会话记录、Skill 调用日志、执行轨迹用于审计和复盘。状态管理有个容易踩的坑并发请求下的状态竞争。同一个用户可能同时发起多个请求如果状态更新没有加锁会互相覆盖。我的做法是给每个会话加一个轻量锁Redis 的 SETNX 实现同一会话的请求串行处理不同会话并行。这样既保证了状态一致性又不影响整体吞吐。4.5 第五步补齐可观测性和告警最后一步是把可观测性补上。每个请求分配 trace ID每一步执行打结构化日志关键指标上报到监控系统。告警规则我一般设这几条Skill 成功率低于 95% 告警、P99 耗时超过阈值告警、模型调用失败率超过 5% 告警、单会话 token 消耗异常告警。这些告警不是摆设是生产环境的生命线。我经历过一次线上事故某个外部 API 悄悄改了返回格式导致一个 Skill 静默失败用户以为 Agent 在思考其实早就卡住了。后来加了结果格式校验和失败告警这类问题才能第一时间发现。5. 常见问题与排查技巧实录5.1 Agent 执行中断类问题的排查思路热词里agent execution terminated due to error和container runtime is not running这类报错很常见本质上是执行链路某一环断了。排查时我遵循从外到内、从下到上的顺序先确认容器和 Runtime 是否在运行再确认模型服务是否可达再确认 Skill 服务是否健康最后看编排逻辑和提示词。could not find the webview2 runtime这类问题属于桌面端 Agent 的运行时缺失解决方式是补装对应运行时组件。unable to locate the codex cli binary or required runtime components则是 CLI 类 Agent 的依赖缺失检查 PATH 和安装完整性即可。这类问题的共性是运行时依赖没装全生产环境部署时一定要把依赖清单固化到镜像里别指望手动装。5.2 Skill 调用失败的常见原因速查现象可能原因排查动作Skill 不被调用描述太模糊召回没命中优化 description加关键词参数格式错误schema 定义不严补 pattern、required 校验调用超时外部依赖慢或死锁看 Skill 内部日志加超时结果解析失败返回格式和 schema 不符加输出校验让模型重试权限被拒凭证过期或未注入检查凭证管理和注入链路重复执行重试策略不当写操作禁用自动重试5.3 我踩过的几个坑和对应的避坑技巧第一个坑把 Skill 描述写得太技术化。模型选 Skill 靠的是语义匹配你写“调用 order_service 的 query 方法”模型不一定懂。改成“根据订单号查询订单状态和物流信息”召回准确率立刻上去。描述要用人话写清楚“什么时候用这个 Skill”。第二个坑上下文无限增长。早期没做摘要一个长会话跑到后面每轮请求 token 都上万成本和延迟都爆炸。后来加了热窗口 自动摘要token 消耗降了七成响应也快了。第三个坑Skill 之间共享状态没隔离。两个 Skill 都往同一个全局变量写数据并发时互相污染。解决方式是 Skill 服务无状态化所有状态通过参数传入传出需要持久化的走 Runtime 的会话存储。第四个坑没有做成本核算。上线一个月才发现某个 Skill 因为逻辑问题被反复调用烧了不少模型费用。后来给每个 Skill 加了成本等级Runtime 统计每个会话的累计成本超阈值就告警。提示Skill 的 description 里最好包含“适用场景”和“不适用场景”两部分模型选择时会参考这些边界信息能显著减少误调用。5.4 关于 Hermes 类框架的选型建议如果你在选 Agent 框架我的建议是优先选那些把 Runtime 和框架解耦的。框架可以换Runtime 和 Skill 资产要能沉淀。评估时重点看三点Skill 注册是否标准化、执行轨迹是否可导出、是否支持多租户。hermes desktop 安装对接本地部署 api这类需求说明大家希望框架能灵活对接本地模型这一点在数据敏感的企业场景里很重要。另外别被框架的 Demo 效果迷惑。Demo 里跑得顺是因为场景简单、并发低、没有异常。选型时一定要做压力测试和故障注入看看框架在 Skill 超时、模型返回异常、并发上来之后的表现。这才是生产视角的评估。6. 我个人在 Agent 生产化路上的几点体会做 Agent 平台这两年我最大的体会是Demo 拼的是想象力生产拼的是工程纪律。一个能跑的 Demo 和一个能用的生产系统之间差的不是某个黑科技而是把每一件小事做扎实——状态管理、错误处理、可观测性、权限边界这些听起来不性感的东西才是决定成败的。另一个体会是别急着堆 Skill。我见过团队一口气接了五十个 Skill结果路由准确率暴跌用户根本用不明白。正确的节奏是先把核心的 5 到 10 个 Skill 打磨到生产级把 Runtime 和治理体系跑顺再逐步扩展。Skill 的质量和治理水平比数量重要得多。最后分享一个实用的小技巧给每个 Skill 加一个“干跑模式”也就是只返回它将要执行的操作和参数不真正执行。上线新 Skill 或者改路由逻辑时先用干跑模式观察一段时间确认模型选择正确、参数构造合理再开启真实执行。这个习惯帮我避免了好几次线上事故。Agent 这个方向还在快速演进Runtime、Skill 治理、多智能体协作这些话题都还有很大的探索空间。但不管技术怎么变把系统当生产系统来对待的工程思维是不会过时的。