三大引擎协同工作流:从用户消息到智能决策的完整链路
OpenClaw + Harness + Hermes 三驾马车如何协同工作?一条消息的完整旅程
📑 目录
- 一、引言:一条消息的旅程
- 二、端到端流程总览
- [2.1 七步全景图](#2.1 七步全景图)
- [2.2 各阶段职责速览](#2.2 各阶段职责速览)
- 三、阶段一:消息接入(OpenClaw)
- [3.1 多渠道统一入站](#3.1 多渠道统一入站)
- [3.2 消息归一化与路由](#3.2 消息归一化与路由)
- [四、阶段二:会话管理(Session Manager)](#四、阶段二:会话管理(Session Manager))
- 五、阶段三:约束校验(Harness)
- 六、阶段四:智能决策(Hermes)
- [6.1 System Prompt 三层组装](#6.1 System Prompt 三层组装)
- [6.2 Agent Loop 执行](#6.2 Agent Loop 执行)
- [七、阶段五:自改进(Hermes 学习循环)](#七、阶段五:自改进(Hermes 学习循环))
- 八、阶段六:响应返回(OpenClaw)
- 九、完整时序图
- [十、代码实现:OrchestrationService 核心编排逻辑](#十、代码实现:OrchestrationService 核心编排逻辑)
- 十一、总结
一、引言:一条消息的旅程
当用户在飞书群里发了一条消息:"帮我分析一下最近一周的营销数据,生成一份报告"------这条消息是如何被系统理解、处理、并最终返回结果的?
这个过程涉及三个引擎的协同工作:
| 引擎 | 职责 | 在链路中的位置 |
|---|---|---|
| OpenClaw | 消息接入与渠道网关 | 第一站:接收消息,归一化,路由 |
| Harness | 安全约束与校验 | 第二站:权限校验,边界检查,风控 |
| Hermes | 智能决策与自进化 | 第三站:推理决策,工具执行,学习优化 |
这三个引擎各司其职,形成了一个完整的**"感知→约束→决策→执行→学习→响应"**闭环。
本文将完整拆解一条消息从入站到出站的全链路,展示三大引擎如何协同工作。
二、端到端流程总览
2.1 七步全景图
#mermaid-svg-FDMmGiN0WXdW2Ljn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FDMmGiN0WXdW2Ljn .error-icon{fill:#552222;}#mermaid-svg-FDMmGiN0WXdW2Ljn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FDMmGiN0WXdW2Ljn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .marker.cross{stroke:#333333;}#mermaid-svg-FDMmGiN0WXdW2Ljn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FDMmGiN0WXdW2Ljn p{margin:0;}#mermaid-svg-FDMmGiN0WXdW2Ljn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .cluster-label text{fill:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .cluster-label span{color:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .cluster-label span p{background-color:transparent;}#mermaid-svg-FDMmGiN0WXdW2Ljn .label text,#mermaid-svg-FDMmGiN0WXdW2Ljn span{fill:#333;color:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .node rect,#mermaid-svg-FDMmGiN0WXdW2Ljn .node circle,#mermaid-svg-FDMmGiN0WXdW2Ljn .node ellipse,#mermaid-svg-FDMmGiN0WXdW2Ljn .node polygon,#mermaid-svg-FDMmGiN0WXdW2Ljn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .rough-node .label text,#mermaid-svg-FDMmGiN0WXdW2Ljn .node .label text,#mermaid-svg-FDMmGiN0WXdW2Ljn .image-shape .label,#mermaid-svg-FDMmGiN0WXdW2Ljn .icon-shape .label{text-anchor:middle;}#mermaid-svg-FDMmGiN0WXdW2Ljn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .rough-node .label,#mermaid-svg-FDMmGiN0WXdW2Ljn .node .label,#mermaid-svg-FDMmGiN0WXdW2Ljn .image-shape .label,#mermaid-svg-FDMmGiN0WXdW2Ljn .icon-shape .label{text-align:center;}#mermaid-svg-FDMmGiN0WXdW2Ljn .node.clickable{cursor:pointer;}#mermaid-svg-FDMmGiN0WXdW2Ljn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .arrowheadPath{fill:#333333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FDMmGiN0WXdW2Ljn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FDMmGiN0WXdW2Ljn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FDMmGiN0WXdW2Ljn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FDMmGiN0WXdW2Ljn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .cluster text{fill:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn .cluster span{color:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FDMmGiN0WXdW2Ljn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FDMmGiN0WXdW2Ljn rect.text{fill:none;stroke-width:0;}#mermaid-svg-FDMmGiN0WXdW2Ljn .icon-shape,#mermaid-svg-FDMmGiN0WXdW2Ljn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FDMmGiN0WXdW2Ljn .icon-shape p,#mermaid-svg-FDMmGiN0WXdW2Ljn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FDMmGiN0WXdW2Ljn .icon-shape .label rect,#mermaid-svg-FDMmGiN0WXdW2Ljn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FDMmGiN0WXdW2Ljn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FDMmGiN0WXdW2Ljn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FDMmGiN0WXdW2Ljn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
拒绝
阶段七:响应返回
OpenClaw Gateway
结果回传用户
阶段六:自改进
Hermes 学习循环
反馈收集→Skill优化→记忆更新
阶段五:工具执行
Tool Executor
数据查询/API调用/文件操作
阶段四:智能决策
Hermes Agent
System Prompt组装→Agent Loop→工具调用
阶段三:约束校验
Harness 约束层
认知约束·权限约束·流程约束
阶段二:会话管理
Session Manager
获取/创建会话
阶段一:消息接入
OpenClaw Gateway
多渠道统一入站
👤 用户发送消息
🚫 返回拒绝信息
记录审计日志
✅ 用户收到回复
2.2 各阶段职责速览
| 阶段 | 引擎 | 核心职责 | 关键产出 |
|---|---|---|---|
| ① 消息接入 | OpenClaw | 多渠道消息接收、验签、归一化 | UnifiedMessage |
| ② 会话管理 | Session Manager | 获取/创建会话,加载上下文 | SessionContext |
| ③ 约束校验 | Harness | 权限校验、边界检查、风控 | ConstraintResult |
| ④ 智能决策 | Hermes | System Prompt 组装、Agent Loop | 决策结果 |
| ⑤ 工具执行 | Tool Executor | 数据查询、API 调用、文件操作 | 执行结果 |
| ⑥ 自改进 | Hermes | 反馈收集、Skill 优化、记忆更新 | 学习结果 |
| ⑦ 响应返回 | OpenClaw | 结果格式化、渠道适配、推送 | 用户响应 |
三、阶段一:消息接入(OpenClaw)
3.1 多渠道统一入站
OpenClaw Gateway 作为消息接入层,负责接收来自多个渠道的 Webhook 回调。
#mermaid-svg-d6sBHRDSiD9oL3hS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d6sBHRDSiD9oL3hS .error-icon{fill:#552222;}#mermaid-svg-d6sBHRDSiD9oL3hS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d6sBHRDSiD9oL3hS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d6sBHRDSiD9oL3hS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d6sBHRDSiD9oL3hS .marker.cross{stroke:#333333;}#mermaid-svg-d6sBHRDSiD9oL3hS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d6sBHRDSiD9oL3hS p{margin:0;}#mermaid-svg-d6sBHRDSiD9oL3hS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS .cluster-label text{fill:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS .cluster-label span{color:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS .cluster-label span p{background-color:transparent;}#mermaid-svg-d6sBHRDSiD9oL3hS .label text,#mermaid-svg-d6sBHRDSiD9oL3hS span{fill:#333;color:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS .node rect,#mermaid-svg-d6sBHRDSiD9oL3hS .node circle,#mermaid-svg-d6sBHRDSiD9oL3hS .node ellipse,#mermaid-svg-d6sBHRDSiD9oL3hS .node polygon,#mermaid-svg-d6sBHRDSiD9oL3hS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d6sBHRDSiD9oL3hS .rough-node .label text,#mermaid-svg-d6sBHRDSiD9oL3hS .node .label text,#mermaid-svg-d6sBHRDSiD9oL3hS .image-shape .label,#mermaid-svg-d6sBHRDSiD9oL3hS .icon-shape .label{text-anchor:middle;}#mermaid-svg-d6sBHRDSiD9oL3hS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d6sBHRDSiD9oL3hS .rough-node .label,#mermaid-svg-d6sBHRDSiD9oL3hS .node .label,#mermaid-svg-d6sBHRDSiD9oL3hS .image-shape .label,#mermaid-svg-d6sBHRDSiD9oL3hS .icon-shape .label{text-align:center;}#mermaid-svg-d6sBHRDSiD9oL3hS .node.clickable{cursor:pointer;}#mermaid-svg-d6sBHRDSiD9oL3hS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d6sBHRDSiD9oL3hS .arrowheadPath{fill:#333333;}#mermaid-svg-d6sBHRDSiD9oL3hS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d6sBHRDSiD9oL3hS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d6sBHRDSiD9oL3hS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d6sBHRDSiD9oL3hS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d6sBHRDSiD9oL3hS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d6sBHRDSiD9oL3hS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d6sBHRDSiD9oL3hS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d6sBHRDSiD9oL3hS .cluster text{fill:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS .cluster span{color:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d6sBHRDSiD9oL3hS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d6sBHRDSiD9oL3hS rect.text{fill:none;stroke-width:0;}#mermaid-svg-d6sBHRDSiD9oL3hS .icon-shape,#mermaid-svg-d6sBHRDSiD9oL3hS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d6sBHRDSiD9oL3hS .icon-shape p,#mermaid-svg-d6sBHRDSiD9oL3hS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d6sBHRDSiD9oL3hS .icon-shape .label rect,#mermaid-svg-d6sBHRDSiD9oL3hS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d6sBHRDSiD9oL3hS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d6sBHRDSiD9oL3hS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d6sBHRDSiD9oL3hS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输出
OpenClaw Gateway
消息渠道
飞书
钉钉
企微
Telegram
Webhook Receiver
Signature Verifier
Message Normalizer
UnifiedMessage
统一消息格式
3.2 消息归一化与路由
java
@Component
@Slf4j
public class MessageRouter {
public RoutingResult route(UnifiedMessage message) {
// 1. 检查是否为系统命令
if (isSystemCommand(message.getContent())) {
return RoutingResult.systemCommand(message);
}
// 2. 检查是否为斜杠命令(快捷调用 Skill)
if (isSlashCommand(message.getContent())) {
return RoutingResult.slashCommand(message);
}
// 3. 普通对话:路由到 Agent
return RoutingResult.agent(message);
}
}
四、阶段二:会话管理(Session Manager)
会话管理负责获取或创建会话,加载用户的上下文信息。
#mermaid-svg-xjJmNWnRSMIVkDpI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xjJmNWnRSMIVkDpI .error-icon{fill:#552222;}#mermaid-svg-xjJmNWnRSMIVkDpI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xjJmNWnRSMIVkDpI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xjJmNWnRSMIVkDpI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xjJmNWnRSMIVkDpI .marker.cross{stroke:#333333;}#mermaid-svg-xjJmNWnRSMIVkDpI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xjJmNWnRSMIVkDpI p{margin:0;}#mermaid-svg-xjJmNWnRSMIVkDpI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI .cluster-label text{fill:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI .cluster-label span{color:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI .cluster-label span p{background-color:transparent;}#mermaid-svg-xjJmNWnRSMIVkDpI .label text,#mermaid-svg-xjJmNWnRSMIVkDpI span{fill:#333;color:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI .node rect,#mermaid-svg-xjJmNWnRSMIVkDpI .node circle,#mermaid-svg-xjJmNWnRSMIVkDpI .node ellipse,#mermaid-svg-xjJmNWnRSMIVkDpI .node polygon,#mermaid-svg-xjJmNWnRSMIVkDpI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xjJmNWnRSMIVkDpI .rough-node .label text,#mermaid-svg-xjJmNWnRSMIVkDpI .node .label text,#mermaid-svg-xjJmNWnRSMIVkDpI .image-shape .label,#mermaid-svg-xjJmNWnRSMIVkDpI .icon-shape .label{text-anchor:middle;}#mermaid-svg-xjJmNWnRSMIVkDpI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-xjJmNWnRSMIVkDpI .rough-node .label,#mermaid-svg-xjJmNWnRSMIVkDpI .node .label,#mermaid-svg-xjJmNWnRSMIVkDpI .image-shape .label,#mermaid-svg-xjJmNWnRSMIVkDpI .icon-shape .label{text-align:center;}#mermaid-svg-xjJmNWnRSMIVkDpI .node.clickable{cursor:pointer;}#mermaid-svg-xjJmNWnRSMIVkDpI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-xjJmNWnRSMIVkDpI .arrowheadPath{fill:#333333;}#mermaid-svg-xjJmNWnRSMIVkDpI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-xjJmNWnRSMIVkDpI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-xjJmNWnRSMIVkDpI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xjJmNWnRSMIVkDpI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xjJmNWnRSMIVkDpI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xjJmNWnRSMIVkDpI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-xjJmNWnRSMIVkDpI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-xjJmNWnRSMIVkDpI .cluster text{fill:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI .cluster span{color:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-xjJmNWnRSMIVkDpI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xjJmNWnRSMIVkDpI rect.text{fill:none;stroke-width:0;}#mermaid-svg-xjJmNWnRSMIVkDpI .icon-shape,#mermaid-svg-xjJmNWnRSMIVkDpI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xjJmNWnRSMIVkDpI .icon-shape p,#mermaid-svg-xjJmNWnRSMIVkDpI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-xjJmNWnRSMIVkDpI .icon-shape .label rect,#mermaid-svg-xjJmNWnRSMIVkDpI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xjJmNWnRSMIVkDpI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-xjJmNWnRSMIVkDpI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-xjJmNWnRSMIVkDpI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
UnifiedMessage
SessionManager.getOrCreate
是否有
已有会话?
加载会话上下文
对话历史·记忆·偏好
创建新会话
生成 Session ID
SessionContext
进入下一阶段
java
@Service
@Slf4j
public class SessionManager {
private static final String SESSION_KEY_PREFIX = "unimdp:session:";
public SessionContext getOrCreate(UnifiedMessage message) {
// 1. 优先使用已有 session_id
if (message.getSessionId() != null) {
SessionContext context = get(message.getSessionId());
if (context != null) {
context.setLastActiveAt(System.currentTimeMillis());
update(context);
return context;
}
}
// 2. 查找同一用户的活跃会话
List<SessionContext> userSessions = findActiveByUser(message.getUnifiedUserId());
if (!userSessions.isEmpty()) {
SessionContext latest = userSessions.get(0);
latest.setLastActiveAt(System.currentTimeMillis());
update(latest);
return latest;
}
// 3. 创建新会话
return create(message);
}
}
SessionContext 包含的核心信息:
| 字段 | 说明 |
|---|---|
sessionId |
会话唯一标识 |
unifiedUserId |
统一用户 ID(OneID) |
channelType |
消息渠道类型 |
status |
会话状态(INIT/ACTIVE/PAUSED/CLOSED) |
history |
对话历史(压缩后) |
memory |
用户记忆快照 |
context |
扩展上下文 |
五、阶段三:约束校验(Harness)
约束校验是 Harness 的核心职责,在 Agent 决策之前进行安全检查。
5.1 三层约束校验流程
#mermaid-svg-j4jdXuClXv9abucK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-j4jdXuClXv9abucK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-j4jdXuClXv9abucK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-j4jdXuClXv9abucK .error-icon{fill:#552222;}#mermaid-svg-j4jdXuClXv9abucK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-j4jdXuClXv9abucK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-j4jdXuClXv9abucK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-j4jdXuClXv9abucK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-j4jdXuClXv9abucK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-j4jdXuClXv9abucK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-j4jdXuClXv9abucK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-j4jdXuClXv9abucK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-j4jdXuClXv9abucK .marker.cross{stroke:#333333;}#mermaid-svg-j4jdXuClXv9abucK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-j4jdXuClXv9abucK p{margin:0;}#mermaid-svg-j4jdXuClXv9abucK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-j4jdXuClXv9abucK .cluster-label text{fill:#333;}#mermaid-svg-j4jdXuClXv9abucK .cluster-label span{color:#333;}#mermaid-svg-j4jdXuClXv9abucK .cluster-label span p{background-color:transparent;}#mermaid-svg-j4jdXuClXv9abucK .label text,#mermaid-svg-j4jdXuClXv9abucK span{fill:#333;color:#333;}#mermaid-svg-j4jdXuClXv9abucK .node rect,#mermaid-svg-j4jdXuClXv9abucK .node circle,#mermaid-svg-j4jdXuClXv9abucK .node ellipse,#mermaid-svg-j4jdXuClXv9abucK .node polygon,#mermaid-svg-j4jdXuClXv9abucK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j4jdXuClXv9abucK .rough-node .label text,#mermaid-svg-j4jdXuClXv9abucK .node .label text,#mermaid-svg-j4jdXuClXv9abucK .image-shape .label,#mermaid-svg-j4jdXuClXv9abucK .icon-shape .label{text-anchor:middle;}#mermaid-svg-j4jdXuClXv9abucK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-j4jdXuClXv9abucK .rough-node .label,#mermaid-svg-j4jdXuClXv9abucK .node .label,#mermaid-svg-j4jdXuClXv9abucK .image-shape .label,#mermaid-svg-j4jdXuClXv9abucK .icon-shape .label{text-align:center;}#mermaid-svg-j4jdXuClXv9abucK .node.clickable{cursor:pointer;}#mermaid-svg-j4jdXuClXv9abucK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-j4jdXuClXv9abucK .arrowheadPath{fill:#333333;}#mermaid-svg-j4jdXuClXv9abucK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-j4jdXuClXv9abucK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-j4jdXuClXv9abucK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j4jdXuClXv9abucK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-j4jdXuClXv9abucK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j4jdXuClXv9abucK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-j4jdXuClXv9abucK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-j4jdXuClXv9abucK .cluster text{fill:#333;}#mermaid-svg-j4jdXuClXv9abucK .cluster span{color:#333;}#mermaid-svg-j4jdXuClXv9abucK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-j4jdXuClXv9abucK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-j4jdXuClXv9abucK rect.text{fill:none;stroke-width:0;}#mermaid-svg-j4jdXuClXv9abucK .icon-shape,#mermaid-svg-j4jdXuClXv9abucK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j4jdXuClXv9abucK .icon-shape p,#mermaid-svg-j4jdXuClXv9abucK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-j4jdXuClXv9abucK .icon-shape .label rect,#mermaid-svg-j4jdXuClXv9abucK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j4jdXuClXv9abucK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-j4jdXuClXv9abucK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-j4jdXuClXv9abucK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
拒绝
警告
Harness 约束层
认知约束
行为准则检查
权限约束
工具白名单/黑名单
流程约束
执行流程校验
SessionContext + UnifiedMessage
校验结果
进入决策阶段
🚫 拒绝执行
记录审计日志
⚠️ 记录警告
继续执行
5.2 约束校验代码实现
java
package com.unimdp.orchestration;
@Component
@Slf4j
public class HarnessConstraintService {
@Autowired
private RuleEngine ruleEngine;
@Autowired
private AuditService auditService;
public ConstraintResult validate(ToolCallContext context) {
// 1. 执行认知约束检查
ConstraintResult cognitive = checkCognitiveConstraint(context);
if (!cognitive.isPassed()) {
auditService.logConstraintBlock(context, cognitive);
return cognitive;
}
// 2. 执行权限约束检查
ConstraintResult permission = checkPermissionConstraint(context);
if (!permission.isPassed()) {
auditService.logConstraintBlock(context, permission);
return permission;
}
// 3. 执行流程约束检查
ConstraintResult process = checkProcessConstraint(context);
if (!process.isPassed()) {
auditService.logConstraintBlock(context, process);
return process;
}
return ConstraintResult.pass();
}
}
六、阶段四:智能决策(Hermes)
6.1 System Prompt 三层组装
#mermaid-svg-oChAFFgP6U0mp64X{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oChAFFgP6U0mp64X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oChAFFgP6U0mp64X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oChAFFgP6U0mp64X .error-icon{fill:#552222;}#mermaid-svg-oChAFFgP6U0mp64X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oChAFFgP6U0mp64X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oChAFFgP6U0mp64X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oChAFFgP6U0mp64X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oChAFFgP6U0mp64X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oChAFFgP6U0mp64X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oChAFFgP6U0mp64X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oChAFFgP6U0mp64X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oChAFFgP6U0mp64X .marker.cross{stroke:#333333;}#mermaid-svg-oChAFFgP6U0mp64X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oChAFFgP6U0mp64X p{margin:0;}#mermaid-svg-oChAFFgP6U0mp64X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oChAFFgP6U0mp64X .cluster-label text{fill:#333;}#mermaid-svg-oChAFFgP6U0mp64X .cluster-label span{color:#333;}#mermaid-svg-oChAFFgP6U0mp64X .cluster-label span p{background-color:transparent;}#mermaid-svg-oChAFFgP6U0mp64X .label text,#mermaid-svg-oChAFFgP6U0mp64X span{fill:#333;color:#333;}#mermaid-svg-oChAFFgP6U0mp64X .node rect,#mermaid-svg-oChAFFgP6U0mp64X .node circle,#mermaid-svg-oChAFFgP6U0mp64X .node ellipse,#mermaid-svg-oChAFFgP6U0mp64X .node polygon,#mermaid-svg-oChAFFgP6U0mp64X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oChAFFgP6U0mp64X .rough-node .label text,#mermaid-svg-oChAFFgP6U0mp64X .node .label text,#mermaid-svg-oChAFFgP6U0mp64X .image-shape .label,#mermaid-svg-oChAFFgP6U0mp64X .icon-shape .label{text-anchor:middle;}#mermaid-svg-oChAFFgP6U0mp64X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oChAFFgP6U0mp64X .rough-node .label,#mermaid-svg-oChAFFgP6U0mp64X .node .label,#mermaid-svg-oChAFFgP6U0mp64X .image-shape .label,#mermaid-svg-oChAFFgP6U0mp64X .icon-shape .label{text-align:center;}#mermaid-svg-oChAFFgP6U0mp64X .node.clickable{cursor:pointer;}#mermaid-svg-oChAFFgP6U0mp64X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oChAFFgP6U0mp64X .arrowheadPath{fill:#333333;}#mermaid-svg-oChAFFgP6U0mp64X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oChAFFgP6U0mp64X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oChAFFgP6U0mp64X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oChAFFgP6U0mp64X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oChAFFgP6U0mp64X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oChAFFgP6U0mp64X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oChAFFgP6U0mp64X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oChAFFgP6U0mp64X .cluster text{fill:#333;}#mermaid-svg-oChAFFgP6U0mp64X .cluster span{color:#333;}#mermaid-svg-oChAFFgP6U0mp64X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oChAFFgP6U0mp64X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oChAFFgP6U0mp64X rect.text{fill:none;stroke-width:0;}#mermaid-svg-oChAFFgP6U0mp64X .icon-shape,#mermaid-svg-oChAFFgP6U0mp64X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oChAFFgP6U0mp64X .icon-shape p,#mermaid-svg-oChAFFgP6U0mp64X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oChAFFgP6U0mp64X .icon-shape .label rect,#mermaid-svg-oChAFFgP6U0mp64X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oChAFFgP6U0mp64X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oChAFFgP6U0mp64X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oChAFFgP6U0mp64X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🟥 Volatile 易变层
记忆快照
用户画像
时间戳/会话信息
🟨 Context 上下文层
项目规则文件
调用方传入的系统消息
🟦 Stable 稳定层
Agent 身份定义
工具使用指导
技能索引
最终 System Prompt
6.2 Agent Loop 执行
#mermaid-svg-ha3F82vjk4e5e7jw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ha3F82vjk4e5e7jw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ha3F82vjk4e5e7jw .error-icon{fill:#552222;}#mermaid-svg-ha3F82vjk4e5e7jw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ha3F82vjk4e5e7jw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ha3F82vjk4e5e7jw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ha3F82vjk4e5e7jw .marker.cross{stroke:#333333;}#mermaid-svg-ha3F82vjk4e5e7jw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ha3F82vjk4e5e7jw p{margin:0;}#mermaid-svg-ha3F82vjk4e5e7jw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ha3F82vjk4e5e7jw .cluster-label text{fill:#333;}#mermaid-svg-ha3F82vjk4e5e7jw .cluster-label span{color:#333;}#mermaid-svg-ha3F82vjk4e5e7jw .cluster-label span p{background-color:transparent;}#mermaid-svg-ha3F82vjk4e5e7jw .label text,#mermaid-svg-ha3F82vjk4e5e7jw span{fill:#333;color:#333;}#mermaid-svg-ha3F82vjk4e5e7jw .node rect,#mermaid-svg-ha3F82vjk4e5e7jw .node circle,#mermaid-svg-ha3F82vjk4e5e7jw .node ellipse,#mermaid-svg-ha3F82vjk4e5e7jw .node polygon,#mermaid-svg-ha3F82vjk4e5e7jw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ha3F82vjk4e5e7jw .rough-node .label text,#mermaid-svg-ha3F82vjk4e5e7jw .node .label text,#mermaid-svg-ha3F82vjk4e5e7jw .image-shape .label,#mermaid-svg-ha3F82vjk4e5e7jw .icon-shape .label{text-anchor:middle;}#mermaid-svg-ha3F82vjk4e5e7jw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ha3F82vjk4e5e7jw .rough-node .label,#mermaid-svg-ha3F82vjk4e5e7jw .node .label,#mermaid-svg-ha3F82vjk4e5e7jw .image-shape .label,#mermaid-svg-ha3F82vjk4e5e7jw .icon-shape .label{text-align:center;}#mermaid-svg-ha3F82vjk4e5e7jw .node.clickable{cursor:pointer;}#mermaid-svg-ha3F82vjk4e5e7jw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ha3F82vjk4e5e7jw .arrowheadPath{fill:#333333;}#mermaid-svg-ha3F82vjk4e5e7jw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ha3F82vjk4e5e7jw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ha3F82vjk4e5e7jw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ha3F82vjk4e5e7jw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ha3F82vjk4e5e7jw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ha3F82vjk4e5e7jw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ha3F82vjk4e5e7jw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ha3F82vjk4e5e7jw .cluster text{fill:#333;}#mermaid-svg-ha3F82vjk4e5e7jw .cluster span{color:#333;}#mermaid-svg-ha3F82vjk4e5e7jw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ha3F82vjk4e5e7jw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ha3F82vjk4e5e7jw rect.text{fill:none;stroke-width:0;}#mermaid-svg-ha3F82vjk4e5e7jw .icon-shape,#mermaid-svg-ha3F82vjk4e5e7jw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ha3F82vjk4e5e7jw .icon-shape p,#mermaid-svg-ha3F82vjk4e5e7jw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ha3F82vjk4e5e7jw .icon-shape .label rect,#mermaid-svg-ha3F82vjk4e5e7jw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ha3F82vjk4e5e7jw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ha3F82vjk4e5e7jw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ha3F82vjk4e5e7jw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 工具调用
最终答案
上下文超限
开始
构建 System Prompt
调用 LLM
响应类型
执行工具
追加工具结果到历史
返回结果
触发上下文压缩
结束
java
package com.unimdp.orchestration;
@Service
@Slf4j
public class HermesDecisionService {
@Autowired
private ChatClient chatClient;
@Autowired
private SystemPromptBuilder promptBuilder;
@Autowired
private ToolRegistry toolRegistry;
public DecisionResult decide(SessionContext context, UnifiedMessage message) {
// 1. 构建 System Prompt
String systemPrompt = promptBuilder.build(
context.getSessionId(),
context.getUnifiedUserId(),
message.getContent(),
context.getContext()
);
// 2. 执行 Agent Loop
String response = chatClient.prompt()
.system(systemPrompt)
.user(message.getContent())
.advisors(new ToolCallingAdvisor(toolRegistry))
.advisors(new LoggingAdvisor())
.advisors(new ValidationAdvisor())
.call()
.content();
// 3. 返回决策结果
return DecisionResult.builder()
.content(response)
.toolCalls(toolRegistry.getExecutedCalls())
.tokenUsage(chatClient.getLastTokenUsage())
.build();
}
}
6.3 工具调用执行流程
#mermaid-svg-YYXcA1rvZyWqsXyo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YYXcA1rvZyWqsXyo .error-icon{fill:#552222;}#mermaid-svg-YYXcA1rvZyWqsXyo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YYXcA1rvZyWqsXyo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YYXcA1rvZyWqsXyo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YYXcA1rvZyWqsXyo .marker.cross{stroke:#333333;}#mermaid-svg-YYXcA1rvZyWqsXyo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YYXcA1rvZyWqsXyo p{margin:0;}#mermaid-svg-YYXcA1rvZyWqsXyo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo .cluster-label text{fill:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo .cluster-label span{color:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo .cluster-label span p{background-color:transparent;}#mermaid-svg-YYXcA1rvZyWqsXyo .label text,#mermaid-svg-YYXcA1rvZyWqsXyo span{fill:#333;color:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo .node rect,#mermaid-svg-YYXcA1rvZyWqsXyo .node circle,#mermaid-svg-YYXcA1rvZyWqsXyo .node ellipse,#mermaid-svg-YYXcA1rvZyWqsXyo .node polygon,#mermaid-svg-YYXcA1rvZyWqsXyo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YYXcA1rvZyWqsXyo .rough-node .label text,#mermaid-svg-YYXcA1rvZyWqsXyo .node .label text,#mermaid-svg-YYXcA1rvZyWqsXyo .image-shape .label,#mermaid-svg-YYXcA1rvZyWqsXyo .icon-shape .label{text-anchor:middle;}#mermaid-svg-YYXcA1rvZyWqsXyo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YYXcA1rvZyWqsXyo .rough-node .label,#mermaid-svg-YYXcA1rvZyWqsXyo .node .label,#mermaid-svg-YYXcA1rvZyWqsXyo .image-shape .label,#mermaid-svg-YYXcA1rvZyWqsXyo .icon-shape .label{text-align:center;}#mermaid-svg-YYXcA1rvZyWqsXyo .node.clickable{cursor:pointer;}#mermaid-svg-YYXcA1rvZyWqsXyo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YYXcA1rvZyWqsXyo .arrowheadPath{fill:#333333;}#mermaid-svg-YYXcA1rvZyWqsXyo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YYXcA1rvZyWqsXyo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YYXcA1rvZyWqsXyo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YYXcA1rvZyWqsXyo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YYXcA1rvZyWqsXyo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YYXcA1rvZyWqsXyo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YYXcA1rvZyWqsXyo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YYXcA1rvZyWqsXyo .cluster text{fill:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo .cluster span{color:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YYXcA1rvZyWqsXyo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YYXcA1rvZyWqsXyo rect.text{fill:none;stroke-width:0;}#mermaid-svg-YYXcA1rvZyWqsXyo .icon-shape,#mermaid-svg-YYXcA1rvZyWqsXyo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YYXcA1rvZyWqsXyo .icon-shape p,#mermaid-svg-YYXcA1rvZyWqsXyo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YYXcA1rvZyWqsXyo .icon-shape .label rect,#mermaid-svg-YYXcA1rvZyWqsXyo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YYXcA1rvZyWqsXyo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YYXcA1rvZyWqsXyo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YYXcA1rvZyWqsXyo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 工具执行层
数据查询工具
查询营销数据
内容生成工具
生成报告内容
消息推送工具
推送结果
Agent 决策
执行结果
七、阶段五:自改进(Hermes 学习循环)
任务执行完成后,Hermes 的学习循环会评估是否需要将本次经验沉淀为 Skill。
7.1 学习触发条件
#mermaid-svg-8qLqPNfpyLggM2Kj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8qLqPNfpyLggM2Kj .error-icon{fill:#552222;}#mermaid-svg-8qLqPNfpyLggM2Kj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8qLqPNfpyLggM2Kj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8qLqPNfpyLggM2Kj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8qLqPNfpyLggM2Kj .marker.cross{stroke:#333333;}#mermaid-svg-8qLqPNfpyLggM2Kj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8qLqPNfpyLggM2Kj p{margin:0;}#mermaid-svg-8qLqPNfpyLggM2Kj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj .cluster-label text{fill:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj .cluster-label span{color:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj .cluster-label span p{background-color:transparent;}#mermaid-svg-8qLqPNfpyLggM2Kj .label text,#mermaid-svg-8qLqPNfpyLggM2Kj span{fill:#333;color:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj .node rect,#mermaid-svg-8qLqPNfpyLggM2Kj .node circle,#mermaid-svg-8qLqPNfpyLggM2Kj .node ellipse,#mermaid-svg-8qLqPNfpyLggM2Kj .node polygon,#mermaid-svg-8qLqPNfpyLggM2Kj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8qLqPNfpyLggM2Kj .rough-node .label text,#mermaid-svg-8qLqPNfpyLggM2Kj .node .label text,#mermaid-svg-8qLqPNfpyLggM2Kj .image-shape .label,#mermaid-svg-8qLqPNfpyLggM2Kj .icon-shape .label{text-anchor:middle;}#mermaid-svg-8qLqPNfpyLggM2Kj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8qLqPNfpyLggM2Kj .rough-node .label,#mermaid-svg-8qLqPNfpyLggM2Kj .node .label,#mermaid-svg-8qLqPNfpyLggM2Kj .image-shape .label,#mermaid-svg-8qLqPNfpyLggM2Kj .icon-shape .label{text-align:center;}#mermaid-svg-8qLqPNfpyLggM2Kj .node.clickable{cursor:pointer;}#mermaid-svg-8qLqPNfpyLggM2Kj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8qLqPNfpyLggM2Kj .arrowheadPath{fill:#333333;}#mermaid-svg-8qLqPNfpyLggM2Kj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8qLqPNfpyLggM2Kj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8qLqPNfpyLggM2Kj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8qLqPNfpyLggM2Kj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8qLqPNfpyLggM2Kj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8qLqPNfpyLggM2Kj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8qLqPNfpyLggM2Kj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8qLqPNfpyLggM2Kj .cluster text{fill:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj .cluster span{color:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8qLqPNfpyLggM2Kj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8qLqPNfpyLggM2Kj rect.text{fill:none;stroke-width:0;}#mermaid-svg-8qLqPNfpyLggM2Kj .icon-shape,#mermaid-svg-8qLqPNfpyLggM2Kj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8qLqPNfpyLggM2Kj .icon-shape p,#mermaid-svg-8qLqPNfpyLggM2Kj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8qLqPNfpyLggM2Kj .icon-shape .label rect,#mermaid-svg-8qLqPNfpyLggM2Kj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8qLqPNfpyLggM2Kj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8qLqPNfpyLggM2Kj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8qLqPNfpyLggM2Kj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 工具调用 >= 5 次
出现错误并修复
用户纠正反馈
不满足条件
学习循环
分析执行轨迹
提取可复用模式
生成 SKILL.md
保存到数据库和文件系统
任务完成
评估是否
值得学习
✅ 触发学习
✅ 触发学习
✅ 触发学习
⏭️ 跳过学习
更新记忆
7.2 学习循环代码实现
java
package com.unimdp.orchestration;
@Component
@Slf4j
public class LearningService {
@Autowired
private HermesLearningClient learningClient;
@Autowired
private SkillRepository skillRepository;
public LearningResult triggerLearning(Task task) {
// 1. 判断是否满足学习条件
if (!shouldLearn(task)) {
return LearningResult.skip("Tool calls count < 5");
}
// 2. 调用 Hermes 学习循环
LearningRequest request = LearningRequest.builder()
.sessionId(task.getSessionId())
.taskId(task.getTaskId())
.executionTrace(task.getTrace())
.build();
LearningResponse response = learningClient.triggerLearning(request);
// 3. 保存生成的 Skill
if (response.isSkillCreated()) {
SkillEntity skill = SkillEntity.builder()
.unifiedUserId(task.getUnifiedUserId())
.name(response.getSkillName())
.description(response.getSkillDescription())
.triggerKeywords(response.getTriggerKeywords())
.actionSteps(response.getActionSteps())
.examples(response.getExamples())
.source("auto_generated")
.status("active")
.build();
skillRepository.save(skill);
// 4. 同步到文件系统
skillFileSyncService.syncToFileSystem(skill);
log.info("✅ Skill created: {}", skill.getName());
return LearningResult.success(skill);
}
return LearningResult.noChange();
}
}
八、阶段六:响应返回(OpenClaw)
决策结果通过 OpenClaw Gateway 回传给用户。
#mermaid-svg-fKn1UWLqMs2y1hKP{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fKn1UWLqMs2y1hKP .error-icon{fill:#552222;}#mermaid-svg-fKn1UWLqMs2y1hKP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fKn1UWLqMs2y1hKP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fKn1UWLqMs2y1hKP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fKn1UWLqMs2y1hKP .marker.cross{stroke:#333333;}#mermaid-svg-fKn1UWLqMs2y1hKP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fKn1UWLqMs2y1hKP p{margin:0;}#mermaid-svg-fKn1UWLqMs2y1hKP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP .cluster-label text{fill:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP .cluster-label span{color:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP .cluster-label span p{background-color:transparent;}#mermaid-svg-fKn1UWLqMs2y1hKP .label text,#mermaid-svg-fKn1UWLqMs2y1hKP span{fill:#333;color:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP .node rect,#mermaid-svg-fKn1UWLqMs2y1hKP .node circle,#mermaid-svg-fKn1UWLqMs2y1hKP .node ellipse,#mermaid-svg-fKn1UWLqMs2y1hKP .node polygon,#mermaid-svg-fKn1UWLqMs2y1hKP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fKn1UWLqMs2y1hKP .rough-node .label text,#mermaid-svg-fKn1UWLqMs2y1hKP .node .label text,#mermaid-svg-fKn1UWLqMs2y1hKP .image-shape .label,#mermaid-svg-fKn1UWLqMs2y1hKP .icon-shape .label{text-anchor:middle;}#mermaid-svg-fKn1UWLqMs2y1hKP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fKn1UWLqMs2y1hKP .rough-node .label,#mermaid-svg-fKn1UWLqMs2y1hKP .node .label,#mermaid-svg-fKn1UWLqMs2y1hKP .image-shape .label,#mermaid-svg-fKn1UWLqMs2y1hKP .icon-shape .label{text-align:center;}#mermaid-svg-fKn1UWLqMs2y1hKP .node.clickable{cursor:pointer;}#mermaid-svg-fKn1UWLqMs2y1hKP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fKn1UWLqMs2y1hKP .arrowheadPath{fill:#333333;}#mermaid-svg-fKn1UWLqMs2y1hKP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fKn1UWLqMs2y1hKP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fKn1UWLqMs2y1hKP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fKn1UWLqMs2y1hKP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fKn1UWLqMs2y1hKP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fKn1UWLqMs2y1hKP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fKn1UWLqMs2y1hKP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fKn1UWLqMs2y1hKP .cluster text{fill:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP .cluster span{color:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fKn1UWLqMs2y1hKP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fKn1UWLqMs2y1hKP rect.text{fill:none;stroke-width:0;}#mermaid-svg-fKn1UWLqMs2y1hKP .icon-shape,#mermaid-svg-fKn1UWLqMs2y1hKP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fKn1UWLqMs2y1hKP .icon-shape p,#mermaid-svg-fKn1UWLqMs2y1hKP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fKn1UWLqMs2y1hKP .icon-shape .label rect,#mermaid-svg-fKn1UWLqMs2y1hKP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fKn1UWLqMs2y1hKP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fKn1UWLqMs2y1hKP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fKn1UWLqMs2y1hKP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 消息渠道
飞书
钉钉
企微
Telegram
响应适配器
格式转换
渠道适配
消息组装
决策结果
推送消息
java
@Component
@Slf4j
public class ResponseAdapter {
@Autowired
private Map<String, MessageChannel> channels;
public void send(UnifiedResponse response) {
// 1. 获取对应的渠道适配器
MessageChannel channel = channels.get(response.getChannelType());
if (channel == null) {
log.error("Channel not found: {}", response.getChannelType());
return;
}
// 2. 发送消息
try {
channel.send(response);
log.info("Response sent to channel: {}", response.getChannelType());
} catch (Exception e) {
log.error("Failed to send response", e);
// 降级:尝试发送错误通知
channel.send(UnifiedResponse.error("系统处理失败,请稍后重试"));
}
}
}
九、完整时序图
下面是完整端到端的时序图,展示各组件之间的交互顺序:
📋 Audit Service 📚 Learning Service 🔧 Tool Executor 🤖 LLM 🧠 Hermes Agent 🛡️ Harness 约束层 📋 Session Manager 🔀 Message Router 🌐 OpenClaw Gateway 📱 消息平台 👤 用户 📋 Audit Service 📚 Learning Service 🔧 Tool Executor 🤖 LLM 🧠 Hermes Agent 🛡️ Harness 约束层 📋 Session Manager 🔀 Message Router 🌐 OpenClaw Gateway 📱 消息平台 👤 用户 #mermaid-svg-3lqbP2Atn8dgHKcr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3lqbP2Atn8dgHKcr .error-icon{fill:#552222;}#mermaid-svg-3lqbP2Atn8dgHKcr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3lqbP2Atn8dgHKcr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3lqbP2Atn8dgHKcr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3lqbP2Atn8dgHKcr .marker.cross{stroke:#333333;}#mermaid-svg-3lqbP2Atn8dgHKcr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3lqbP2Atn8dgHKcr p{margin:0;}#mermaid-svg-3lqbP2Atn8dgHKcr .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-3lqbP2Atn8dgHKcr text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-3lqbP2Atn8dgHKcr .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-3lqbP2Atn8dgHKcr .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-3lqbP2Atn8dgHKcr #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-3lqbP2Atn8dgHKcr .sequenceNumber{fill:white;}#mermaid-svg-3lqbP2Atn8dgHKcr #sequencenumber{fill:#333;}#mermaid-svg-3lqbP2Atn8dgHKcr #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-3lqbP2Atn8dgHKcr .messageText{fill:#333;stroke:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-3lqbP2Atn8dgHKcr .labelText,#mermaid-svg-3lqbP2Atn8dgHKcr .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .loopText,#mermaid-svg-3lqbP2Atn8dgHKcr .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-3lqbP2Atn8dgHKcr .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-3lqbP2Atn8dgHKcr .noteText,#mermaid-svg-3lqbP2Atn8dgHKcr .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-3lqbP2Atn8dgHKcr .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-3lqbP2Atn8dgHKcr .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-3lqbP2Atn8dgHKcr .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-3lqbP2Atn8dgHKcr .actorPopupMenu{position:absolute;}#mermaid-svg-3lqbP2Atn8dgHKcr .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-3lqbP2Atn8dgHKcr .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-3lqbP2Atn8dgHKcr .actor-man circle,#mermaid-svg-3lqbP2Atn8dgHKcr line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-3lqbP2Atn8dgHKcr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt 需要工具调用 loop Agent Loop alt 满足学习条件- alt 约束检查失败 约束检查通过 发送消息 Webhook 回调 验签/解密 转发统一消息 getOrCreate(message) SessionContext validate(context) 记录约束检查 ❌ 拒绝执行 拒绝信息 推送拒绝消息 显示拒绝信息 ✅ 通过 decide(context, message) 构建 System Prompt 调用推理 返回响应 执行工具 工具结果 继续推理 最终响应 决策结果 触发学习评估 分析执行轨迹 生成 SKILL.md 持久化存储 响应结果 推送响应 显示响应
十、代码实现:OrchestrationService 核心编排逻辑
java
package com.unimdp.orchestration;
@Service
@Slf4j
public class OrchestrationService {
@Autowired
private MessageRouter messageRouter;
@Autowired
private SessionManager sessionManager;
@Autowired
private HarnessConstraintService harnessConstraintService;
@Autowired
private HermesDecisionService hermesDecisionService;
@Autowired
private LearningService learningService;
@Autowired
private ResponseAdapter responseAdapter;
@Autowired
private AuditService auditService;
/**
* 核心编排方法:处理一条消息的完整链路
*/
public OrchestrationResult process(UnifiedMessage message) {
long startTime = System.currentTimeMillis();
try {
// 1. 阶段一:消息路由
log.info("📥 [Phase 1] Message received: channel={}, userId={}",
message.getChannelType(), message.getChannelUserId());
RoutingResult route = messageRouter.route(message);
// 2. 阶段二:会话管理
log.info("📋 [Phase 2] Session management");
SessionContext sessionContext = sessionManager.getOrCreate(message);
// 3. 阶段三:约束校验(Harness)
log.info("🛡️ [Phase 3] Harness constraint validation");
ToolCallContext toolContext = buildToolCallContext(message, sessionContext);
ConstraintResult constraintResult = harnessConstraintService.validate(toolContext);
if (!constraintResult.isPassed()) {
log.warn("🔴 [Phase 3] Constraint failed: {}", constraintResult.getMessage());
auditService.logConstraintBlock(toolContext, constraintResult);
return OrchestrationResult.blocked(constraintResult.getMessage());
}
log.info("✅ [Phase 3] Constraint passed");
// 4. 阶段四:智能决策(Hermes)
log.info("🧠 [Phase 4] Hermes decision");
DecisionResult decisionResult = hermesDecisionService.decide(
sessionContext, message
);
log.info("✅ [Phase 4] Decision completed: tokens={}, toolCalls={}",
decisionResult.getTokenUsage(),
decisionResult.getToolCalls().size()
);
// 5. 阶段五:工具执行结果处理
// (工具执行已在 Agent Loop 中完成)
// 6. 阶段六:自改进(Hermes 学习循环)
log.info("📚 [Phase 5] Learning assessment");
Task task = buildTask(sessionContext, message, decisionResult);
LearningResult learningResult = learningService.triggerLearning(task);
if (learningResult.isSkillCreated()) {
log.info("✅ [Phase 5] Skill created: {}", learningResult.getSkillName());
}
// 7. 阶段七:响应返回
log.info("📤 [Phase 6] Response delivery");
UnifiedResponse response = buildResponse(decisionResult, message);
responseAdapter.send(response);
log.info("✅ [Phase 6] Response sent");
// 8. 记录审计日志
auditService.logFullChain(sessionContext, message, decisionResult, constraintResult);
long duration = System.currentTimeMillis() - startTime;
log.info("🎯 [Complete] Full chain completed: {}ms", duration);
return OrchestrationResult.success(response, duration);
} catch (Exception e) {
log.error("❌ Orchestration failed", e);
auditService.logError(message, e);
// 发送错误响应
UnifiedResponse errorResponse = UnifiedResponse.error(
"系统处理失败,请稍后重试"
);
responseAdapter.send(errorResponse);
return OrchestrationResult.error(e.getMessage());
}
}
}
十一、总结
本文完整拆解了 Uni-MDP 中三大引擎的协同工作流:
11.1 七阶段完整链路
| 阶段 | 引擎 | 核心动作 |
|---|---|---|
| ① 消息接入 | OpenClaw | 多渠道 Webhook 接收、验签、归一化 |
| ② 会话管理 | Session Manager | 获取/创建会话,加载上下文 |
| ③ 约束校验 | Harness | 认知/权限/流程三层校验 |
| ④ 智能决策 | Hermes | System Prompt 组装 → Agent Loop → 工具调用 |
| ⑤ 工具执行 | Tool Executor | 数据查询、API 调用、文件操作 |
| ⑥ 自改进 | Hermes | 反馈收集 → Skill 优化 → 记忆更新 |
| ⑦ 响应返回 | OpenClaw | 格式转换、渠道适配、消息推送 |
11.2 三大引擎的协作模式
| 引擎 | 在链路中的位置 | 对外接口 |
|---|---|---|
| OpenClaw | 入口和出口 | Webhook 接收、消息推送 |
| Harness | 决策前拦截 | 约束校验接口 |
| Hermes | 决策和优化核心 | 推理接口、学习接口 |
11.3 关键设计原则
- 责任分离:每个引擎只做自己擅长的事
- 安全优先:Harness 在决策前进行约束校验
- 可观测性:全链路审计日志,每个阶段可追溯
- 自进化闭环:每次执行都是学习的机会
下一篇预告:我们将深入营销决策场景实战,展示新客欢迎、加购催付、流失召回三个完整案例。
敬请期待!🚀
📌 本文收录于专栏 :从 OpenClaw 到 Hermes:自改进 Agent 完全指南