本文讨论如何把通用 Agent 收敛为面向单一业务场景的生产级智能体,并通过可信会话、Skill、Action Tool 和受控后端划清推理、权限与执行边界。

背景

大语言模型已经能让通用 Agent 听懂需求、规划步骤、调用工具。做一个演示不难,难的是把它放进真实业务里,并且让人敢用。

到了生产环境,问题很快会从“模型够不够聪明”变成另一组更麻烦的事:用户身份从哪里来?模型可以执行哪些动作?谁来校验权限?流程中断后怎么接着跑?路径、凭据和基础设施信息又该如何藏在边界以内?

下文把基于 Hermes Agent、面向单一业务场景收敛出来的生产级智能体称为 ScenarioAgent。这里不讨论某个具体功能,而是拆解它从通用 Agent 走向生产环境时需要的分层架构:

用户负责表达目标,ScenarioAgent 负责理解与编排,Skill 按需提供流程提示词,Action Tool 收窄动作,CLI/API 受控后端负责可信执行。


总体分层架构

图中画的是一次业务请求的调用链,不是 Hermes Agent 内部模块的代码归属。ScenarioAgent 先判断意图并加载对应 Skill。Skill 只补充当前任务需要的提示词,并规定该调用哪个 Action Tool。Action Tool 再把开放式请求压缩成有限动作和有限参数,交给 CLI/API 后端执行。

结果按原路返回。Action Tool 接收后端给出的结构化状态和安全用户投影,再通过 Tool Result 交还给 ScenarioAgent。后端不会绕开 Tool,直接回调 ScenarioAgent

这套分层有一条很直观的规律:越靠近用户,越要理解开放的自然语言;越靠近基础设施,越要确定、可验证、可审计。Skill 避免上下文被全部场景规则塞满,Action Tool 卡住能力边界,受控后端则把简单业务动作翻译成经过校验的底层操作。


用户只说目标,不填写系统参数

用户只需要描述想完成什么,不该替系统填写底层参数。

例如,用户可以表达:

  • 创建一项业务任务;
  • 继续上一次流程;
  • 查询当前状态;
  • 对某个业务对象执行允许的操作。

但普通用户不应该直接提供:

  • 宿主机路径;
  • 容器名;
  • 内部端口;
  • 服务地址;
  • API 密钥;
  • 任意 Shell 命令;
  • 可以改变安全策略的配置片段。

这里要守住一条线:自然语言用来表达业务意图,不能直接穿透成系统控制参数。

消息平台不只是聊天界面,也是认证链路的一部分。它把用户输入和平台确认过的会话身份一起交给下一层。用户当然可以在聊天里说“我是谁”,但系统只能信任通道提供的身份上下文,不能把这句话当作身份证明。

具体接入飞书、企业微信、Slack、Web 应用还是内部 API,并不影响这条原则:

用户提供意图,可信通道提供身份。


Hermes Gateway 建立可信会话上下文

Hermes Gateway 连接消息平台和 Agent Runtime。它接收消息、管理会话,并把平台已经认证的信息带入 Agent 的执行上下文。

Gateway 不负责理解业务。它先把请求边界钉牢:

  • 消息来自哪个平台;
  • 当前会话属于哪个用户;
  • 请求发生在哪个会话中;
  • 哪些上下文由平台提供、不能由模型修改;
  • 当前入口允许装配哪些工具。

可信会话上下文需要与普通模型参数分开。模型可以使用这些信息发起动作,却不能伪造或覆盖它们。

如果先让模型从聊天内容里提取用户名,再拿这个名字做权限判断,身份校验就退化成了概率问题。Gateway 应该提供经过认证、对模型只读的身份上下文,最后仍由受控后端校验。

Gateway 还决定当前入口能看到哪些工具。普通用户入口只装配业务必需的能力,管理员维护入口与普通会话隔离。安全不能靠提示词里一句“请勿使用危险工具”,更可靠的办法是运行时根本不提供这些工具。


ScenarioAgent 理解意图、编排流程,也负责把话说清楚

ScenarioAgent 运行在 Hermes Agent Runtime 中。Gateway 把消息和可信会话上下文交给它,它再按当前意图选择 Skill,并依照 Skill 调用 Action Tool。它站在自然语言与确定性系统之间,处理传统后端不擅长的开放式工作。

它主要做三件事。

意图理解

同一个目标,不同用户可能有完全不同的说法。ScenarioAgent 结合当前消息、会话上下文和场景 Skills,把这些表达归一成有限的业务意图。

流程编排

流程跨越多个阶段时,ScenarioAgent 根据后端返回的当前状态和允许动作选择下一步。模糊表达、重复请求、中途离开后再回来,这些都由它消化,用户不必理解后端状态机。

用户沟通

后端返回稳定的结构化事实,ScenarioAgent 把事实说成人话:已经完成了什么、还在等什么、用户现在要做什么。

ScenarioAgent 不证明身份,不决定权限,也不直接操作基础设施。它可以判断“下一步想做什么”,但不能自己认定“现在实际上走到哪一步”。

两边的分工可以浓缩成一句话:

ScenarioAgent 负责智能判断,受控后端负责事实判断。

这不意味着要把所有场景规则长期塞进系统提示词。ScenarioAgent 先从简短的 Skill 索引里找到相关能力,再按需读取详细流程,最后选择 Action Tool。有限的上下文因此能留给眼前的任务,无关规则也不容易干扰判断。

ScenarioAgent 的上下文从哪里来

一个能长期运行的 ScenarioAgent,需要几类来源不同、边界清楚的上下文:

  • SOUL.md 提供长期身份、职责边界和表达风格上下文,让 ScenarioAgent 在不同会话中保持一致的角色判断。
  • AGENTS.md 提供当前工作目录的项目规则和文件纪律上下文,让 ScenarioAgent 知道在这个环境中应该如何工作、哪些边界不能越过。
  • Skill 提供按需加载的场景流程上下文,让 ScenarioAgent 只在任务相关时读取详细步骤,避免把所有规则一次性塞进模型窗口。
  • Memory 提供跨会话的用户偏好、稳定环境事实和长期经验上下文,让 ScenarioAgent 不必每次重新询问或重新发现,但不用于保存短期任务状态。
  • Session 提供当前对话的消息历史和本轮任务上下文,让 ScenarioAgent 能理解指代、承接多轮交流并维持当前目标。
  • config.yaml 提供模型、toolset 和 runtime 策略上下文,.env 提供运行所需的秘密输入,使能力装配和凭据来源由部署控制而不是由用户文本决定。
  • Profile 把 SOUL、配置、Skills、Memory、Session、插件和平台连接状态组合成独立运行上下文,使不同职责的 ScenarioAgent 可以在同一机器上相互隔离。
  • Docker 可以进一步固定依赖、系统工具、文件系统、网络和运行用户上下文,使 ScenarioAgent 的环境更可复现、更容易限制和回滚。

不过,ScenarioAgent 本身并不总该放进 Docker。本文所依据的 Creator 场景就需要创建和管理下游 Docker Agent。如果 Creator 也在容器里运行,就不得不额外处理宿主机 Docker socket、挂载、权限以及服务生命周期,边界反而更复杂。这个场景更适合让 ScenarioAgent 作为受控的 Hermes Agent Profile 运行,严格收窄普通用户的能力面,再由 CLI/API 后端创建和管理下游 Docker 实例。

可以用下面几条来判断:

  • 如果 ScenarioAgent 主要消费外部 API 或处理普通文件任务,可以优先考虑整体容器化;
  • 如果 ScenarioAgent 本身要管理宿主级容器、系统服务或其他高权限运行时,先用 Profile、toolset 白名单和受控后端收窄能力,再谨慎决定是否容器化;
  • 不论是否容器化,身份、权限、状态机、资源派生和审计都仍应放在确定性后端,而不是交给 Prompt 或 Skill。

Skill 按需补充场景知识

Skill 回答的是“ScenarioAgent 应该怎样完成这类任务”。系统先给模型一份精简的 Skill 索引,只包含名称和用途。确认与当前任务相关后,ScenarioAgent 才加载详细目标、步骤、判断规则、工具选择、沟通方式和异常恢复说明。

比起一次性注入所有规则,按需加载更省上下文,也更容易控制:

  • 只为当前任务占用上下文;
  • 减少无关指令之间的干扰;
  • 场景流程可以独立维护、测试和复用。

生产环境不该默认加载所有内置 Skill。更稳妥的做法是使用白名单,只装配当前 ScenarioAgent 确实需要的 Skill,并让 Skill 来源随部署版本一起受控。这样既能减少无关能力对模型路由的干扰,也能防止通用 Skill 把流程带出场景边界。

在本文所依据的实际场景里,ScenarioAgent 只装配两个与职责直接相关的项目 Skill。其他 Hermes bundled、profile-local 或外部 Skill 都不进入活动集合。

但 Skill 不是权限边界。归根结底,它只是提供给模型的流程知识:

  • Skill 可以说明何时调用某个动作;
  • Skill 可以要求先查询状态再继续;
  • Skill 可以约束用户回复中应展示什么;
  • Skill 不能证明调用者身份;
  • Skill 不能授予资源权限;
  • Skill 不能绕过后端执行系统操作。

Skill 位于 ScenarioAgent 和 Action Tool 之间。它告诉 ScenarioAgent 该走哪条流程、何时调用哪个 action,但不执行动作,也不做最终授权。白名单缩小的是模型的认知和路由空间,真正的执行权限仍由 Action Tool 与受控后端决定。


Action Tool 只暴露有限业务动作

Action Tool 决定模型究竟能对生产系统表达哪些动作。这比在 Prompt 里写“不要使用危险工具”可靠得多:没有装配到当前入口的 Tool,模型就调用不了。

Hermes Runtime 仍需保留少量基础工具,用于发现和读取 Skill、查询工具目录,但这些工具不承载业务副作用:

  • Skill 使用工具:用于发现和读取受控 Skill,包括 skills_listskill_viewskill_manage
  • Tool Search 基础工具:用于查询按需加载的工具目录,包括 tool_searchtool_describetool_call

真正能产生生产业务副作用的只有一个类型化 Action Tool:cri_hermes_action。Skill 规定调用时机,这个 Tool 只接受预先定义的 action 和低风险业务参数。

通用高权限工具则明确禁用或不装配,不会出现在普通用户所用的 ScenarioAgent 能力面中:

  • terminal
  • file,包括任意文件读取、写入和修改;
  • code_execution
  • 通用飞书文档和云盘工具;
  • Docker、computer use 和系统服务操作能力。

“Hermes Agent 里存在某个工具”和“当前 ScenarioAgent 能看到这个工具”是两回事。Hermes Agent 可以有丰富的基础能力,生产场景则应通过 platform_toolsetsdisabled_toolsets 等装配边界,为每个入口生成最小工具集合。实际工具 schema 中没有高权限能力,才是真正的安全边界,不能指望模型自觉不用。

Tool Search 也不意味着放开全部能力。它只是 Hermes 的按需发现机制。某项工具能否被发现、描述和调用,仍受当前 Profile、插件注册、平台 toolset 和禁用策略限制。所有业务副作用依旧只能通过 Action Tool 进入后端。

Action Tool 是这套架构的执行窄腰。它把模型依据 Skill 作出的开放判断,收敛成有限、结构化、可校验的业务动作。

危险往往来自过于通用的接口:

1
execute(command, arguments)

这种接口把“做什么”和“怎样操作系统”都交给模型。只要参数拼错,或把用户文本直接带进命令,业务边界就可能被突破。

生产环境更适合这样的接口:

1
2
3
create_task(task_type, description)
continue_workflow(resource_ref)
query_status(resource_ref)

类型化工具至少要满足这些要求:

  • 动作集合是有限的;
  • 每个动作具有明确 schema;
  • 参数只表达业务含义;
  • 身份不由模型填写;
  • 系统路径和资源名称不由模型指定;
  • 未知字段和越界值默认拒绝;
  • 每个动作映射到固定的后端能力;
  • 返回值是稳定、结构化的业务状态。

Action Tool 不只是 API 包装。它定义了模型影响生产系统的最大范围:Skill 告诉 ScenarioAgent 怎么走流程,Action Tool 决定副作用可以携带哪些动作和参数。

设计新场景时,应该先枚举模型需要哪些业务动作,再为每个动作设计最小参数。不要先开放通用工具,然后靠 Prompt 提醒模型谨慎使用。


CLI / API 后端掌管可信事实和副作用

CLI/API 后端是安全边界的最终执行者。Action Tool 只表达简单、有限的业务动作,后端再把它们翻译成针对 Docker、Profile、飞书 API、SMB 或其他系统的复杂指令。凡是需要系统信任的判断,都要在这一层完成。

身份校验

后端从可信会话上下文中取得调用者身份,不接受模型或普通用户自报身份。拿不到可信身份,就直接拒绝动作。

权限与资源归属

资源引用只能说明“要操作哪个对象”,不能证明调用者有权访问。后端每次都要重新校验资源归属、当前状态和允许的操作。

持久状态机

对话历史可以帮助模型理解上下文,却不能充当业务事实源。跨步骤流程要由后端持久化状态,并明确合法转换、幂等语义、超时和恢复规则。

用户换了一个会话,ScenarioAgent 也能重新查询后端状态并继续,不必指望模型记住之前发生过什么。

资源派生

模型只接触业务对象,后端负责把它派生为真实的基础设施资源。运行单元、Profile、外部 API 目标和文件空间,都不需要出现在模型参数里。

这样既守住了安全边界,也保留了迁移空间。底层部署方式可以变化,上层业务动作不必跟着改。

幂等、事务与补偿

网络、进程和外部系统都可能让生产流程失败。后端需要明确提交点,避免重复调用产生重复副作用,并在跨系统操作失败时执行补偿。

无法证明安全时就 Fail Closed:停下来,不猜测缺失的身份、路径、配置或状态。

审计

后端需要记录谁从哪个可信入口发起了什么动作、结果如何、是否触发恢复或补偿。日志要留下足够的诊断证据,同时对身份标识、凭据和内部资源脱敏。

安全结果投影

后端不能把原始异常、内部路径和基础设施信息直接扔给模型。它应先生成一份安全结果投影,只包含:

  • 当前业务阶段;
  • 已满足的条件;
  • 仍在等待的条件;
  • 是否需要用户操作;
  • 是否可以重试;
  • 下一项允许动作。

ScenarioAgent 再根据这些受控事实组织回复。脱敏由确定性程序完成,不留给模型临场发挥。


底层复杂指令只能由后端派生和执行

Docker、Profile、飞书 API、SMB 和其他业务系统位于架构最底层。它们常常涉及复杂命令、路径、凭据、调用顺序和恢复逻辑。这些细节不能直接暴露给普通用户、ScenarioAgent、Skill 或 Action Tool。

这里有三条硬约束。

模型不直接访问

ScenarioAgent 不需要知道容器名、宿主路径、内部端口、凭据位置和服务拓扑,只需要读取后端返回的业务状态。

用户不直接指定

普通用户不能通过自然语言提交底层资源参数。后端根据可信身份、业务对象和部署策略派生真实资源。

基础设施差异不向上泄漏

底层可以运行在容器、虚拟机或云任务中,也可以使用本地文件、对象存储或网络文件系统。只要后端保持同一份业务契约,上层 Hermes Agent 和 Skills 就不用跟着基础设施重写。

复用也由此变得实际:上层沿用智能编排方式,中间保留安全边界,底层按场景替换具体系统。


这套架构如何复用到其他垂类场景

这套架构不是靠削弱模型换安全,而是把不同职责放回合适的位置。

模型仍然有足够的发挥空间:

  • Hermes Agent 理解自然语言;
  • ScenarioAgent 处理多轮上下文和流程编排;
  • 白名单 Skill 提供可组合、按需加载的场景提示词;
  • Action Tool 提供明确的能力窄腰;
  • 模型可以在合法动作空间中自主选择下一步。

系统的稳定性则来自:

  • 业务状态由后端持久化;
  • 动作具有幂等和恢复语义;
  • 资源由系统确定性派生;
  • 外部事实可以重新验证;
  • 基础设施变化不会直接影响上层交互。

安全边界包括:

  • 身份由可信通道提供;
  • Skill 与 Action Tool 都采用白名单装配;
  • terminal、file、code execution 等通用高权限 toolset 不进入普通用户能力面;
  • Action Tool 只允许有限动作和参数;
  • 后端执行权限、归属和状态校验;
  • 模型与用户只看到安全结果投影;
  • 所有关键副作用都可以审计。

目的不是把 ScenarioAgent 改造成固定脚本,而是给它一个边界清楚的业务世界。模型仍可理解和组合用户意图,但越不过系统允许的动作空间。

复用方法

迁移到新的垂类场景时,可以按下面的顺序设计:

  1. 明确用户通过哪个可信通道进入系统。
  2. 明确 Gateway 能提供哪些不可伪造的会话上下文。
  3. 定义 ScenarioAgent 需要理解和编排的业务流程。
  4. 只装配当前场景需要的有限 Skill。
  5. 以白名单定义当前入口可见的 Action Tool,并禁用通用高权限 toolset。
  6. 枚举有限的业务动作,不暴露底层命令。
  7. 为每个动作设计最小、类型化参数。
  8. 把身份、权限、状态和资源派生放入受控后端。
  9. 将跨步骤流程建模为持久状态机。
  10. 为每个副作用定义幂等、提交和补偿语义。
  11. 先设计安全结果投影,再设计用户回复。
  12. 让基础设施只能通过受控后端访问。

换一个场景,需要调整的是 ScenarioAgent 的业务流程、Skill、Action Tool 的动作集合以及底层资源适配。主调用链不用变:

1
2
3
4
5
6
可信通道
→ ScenarioAgent
→ Skill 渐进式提示词
→ Action Tool 能力窄腰
→ CLI / API 受控后端
→ 底层复杂指令

比如:

  • 知识管理场景:ScenarioAgent 理解内容需求,后端负责文档归属、审批和发布;
  • 数据分析场景:ScenarioAgent 拆解分析目标,后端负责数据权限和作业提交;
  • 研发协作场景:ScenarioAgent 收集需求,后端负责资源配额和生命周期;
  • 部署场景:ScenarioAgent 解释变更,后端负责审批、发布和回滚;
  • 合规场景:ScenarioAgent 辅助审阅,后端负责材料范围、签署状态和审计。

给模型自由,但只在受控世界里

生产级 Agent 不该同时承担推理、授权、状态存储和基础设施安全。把所有能力直接交给模型,看似灵活,其实是把系统正确性押在一次次概率生成上。

更可靠的做法,是让每一层只承担自己擅长的职责:

  • 用户表达目标;
  • Hermes Gateway 提供可信会话上下文;
  • ScenarioAgent 负责理解、编排和沟通;
  • 有限 Skill 提供渐进式披露的场景提示词;
  • Action Tool 定义模型能够表达的有限动作边界;
  • CLI / API 受控后端证明身份、权限、状态和资源;
  • 底层复杂指令只由受控后端派生和执行。

模型不需要拥有整个系统。给它足够理解业务和编排流程的自由,再把身份、权限、状态与副作用交给确定性后端,这样的 Agent 才能真正进入生产环境。