业务系统集成 OpenClaw 多 Agent 方案:从架构到落地的完整指南

本文基于一个已完成的生产级项目,系统梳理业务系统与 OpenClaw 的集成方案。核心思路:一个用户一个 Agent,通过 REST API 打通业务数据,支持多端消息通道和主动 AI 问询


一、架构全景

scss 复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        消息通道 (Channels)                       │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────────┐   │
│  │  飞书     │  │ 微信公众号 │  │ Web 前端  │  │  更多渠道...  │   │
│  │ (Feishu)  │  │ (WeChat) │  │ (Nuxt 3) │  │              │   │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └──────┬───────┘   │
│       │              │              │               │           │
│       └──────────────┼──────────────┼───────────────┘           │
│                      │              │                           │
│                      ▼              ▼                           │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │              OpenClaw Gateway (:18789)                   │    │
│  │  ┌──────────────────────────────────────────────────┐   │    │
│  │  │        Agent Binding & Routing                   │   │    │
│  │  │  channel + accountId → agentId 映射              │   │    │
│  │  └──────────────────────────────────────────────────┘   │    │
│  │  ┌──────────────────────────────────────────────────┐   │    │
│  │  │        HTTP Endpoints                            │   │    │
│  │  │  POST /v1/responses     (Responses API)          │   │    │
│  │  │  POST /v1/chat/completions (Chat Completions)    │   │    │
│  │  └──────────────────────────────────────────────────┘   │    │
│  │  ┌──────────────────────────────────────────────────┐   │    │
│  │  │        Model Router                              │   │    │
│  │  │  主模型 → fallback 链 → 自动切换                 │   │    │
│  │  └──────────────────────────────────────────────────┘   │    │
│  └──────────────────────┬──────────────────────────────────┘   │
│                         │                                      │
│  ┌──────────────────────┼──────────────────────────────────┐   │
│  │            Agent 隔离沙箱 (Per-User Workspace)           │   │
│  │                                                          │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐              │   │
│  │  │ user_21  │  │ user_144 │  │ user_149 │  ...更多     │   │
│  │  │ ─────── │  │ ─────── │  │ ─────── │              │   │
│  │  │ SOUL.md  │  │ SOUL.md  │  │ SOUL.md  │              │   │
│  │  │ AGENTS.md│  │ AGENTS.md│  │ AGENTS.md│              │   │
│  │  │ TOOLS.md │  │ TOOLS.md │  │ TOOLS.md │              │   │
│  │  │ skills/  │  │ skills/  │  │ skills/  │              │   │
│  │  │ Docker沙箱│  │ Docker沙箱│  │ Docker沙箱│              │   │
│  │  └────┬─────┘  └────┬─────┘  └────┬─────┘              │   │
│  └───────┼─────────────┼─────────────┼─────────────────────┘   │
│          │              │              │                        │
│          └──────────────┼──────────────┘                        │
│                         ▼                                       │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                   业务 REST API 层                       │   │
│  │  meeting-api │ task-api │ project-api │ report-api      │   │
│  │  member-api  │ document-api │ workspace-api │ ...       │   │
│  └─────────────────────────────────────────────────────────┘   │
│                         │                                       │
│                         ▼                                       │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    业务数据库 (Agent 不可直接访问)        │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

关键原则 :Agent 禁止直接访问数据库,所有业务数据必须通过 REST API 获取。这保证了权限控制、审计追踪和数据安全。


二、用户与 Agent 的关系模型

这是整个方案的核心设计决策:每个用户拥有独立的 Agent 实例

2.1 为什么要一对一?

方案 优势 劣势
多用户共享 Agent 资源开销小 会话隔离困难,上下文混乱,权限不可控
一用户一 Agent(本方案) 天然隔离,独立上下文,独立沙箱 需要管理多个 Agent 实例

在一个多租户业务系统中,每个用户的数据可见性不同(项目 A 的用户不该看到项目 B 的数据),Agent 级别的隔离是最安全的方案。

2.2 Agent ID 命名与映射

typescript 复制代码
// 每个用户对应一个唯一的 Agent ID
export function getUserAgentId(userId: number): string {
  return `user_${userId}`  // 例如: user_21, user_144
}

// 支持显式指定 agent,未指定时使用 user_xxx
export function resolveOpenClawAgentId(userId: number, agentId?: string): string {
  return agentId?.trim() || getUserAgentId(userId)
}

命名规则user_{userId} --- 简单清晰,与业务系统用户 ID 直接对应。

2.3 多 Agent 实例示例

json 复制代码
// openclaw.json 中的 agents.list(运行时自动创建,这里展示生成的快照)
{
  "agents": {
    "list": [
      { "id": "main" },              // 默认主 Agent
      { "id": "user_144" },          // 用户 144 的专属 Agent
      { "id": "user_21" },           // 用户 21 的专属 Agent
      { "id": "user_149" }           // 用户 149 的专属 Agent
    ]
  }
}

Agent 由代码懒创建------当用户首次发送消息时,自动检查是否存在对应 Agent,不存在则创建。


三、Session 会话管理

3.1 Session Key 设计

typescript 复制代码
export function generateSessionKey(
  userId: string | number,
  sessionId: string,
  agentId = 'main'
): string {
  return `agent:${agentId}:user_${userId}:session_${sessionId}`
}
// 生成示例: "agent:user_21:user_21:session_a1b2c3d4"

Session Key 同时包含了 Agent 归属用户归属会话标识 ,作为 OpenAI Responses API 中 user 参数的值传入,实现会话级别的对话连续性。

3.2 请求上下文传递

每次请求注入的运行时上下文:

typescript 复制代码
const requestBody = buildOpenClawResponsesRequestBody({
  model: `openclaw/${agentId}`,  // 指定目标 Agent
  message,                         // 用户消息
  sessionKey,                      // 会话标识
  systemMessage,                   // 动态系统指令
  metadata: {                      // 业务上下文
    userId: String(userId),
    apiHost,                       // 业务 API 地址
    authToken,                     // 用户鉴权 Token
  },
})

metadata 中的 authToken 是关键------它来自用户登录时的 JWT Token,有时效性。Agent 每次调用业务 API 都携带此 Token,既保证了安全性,也天然实现了用户级权限隔离。


四、Agent 自动创建机制

用户首次对话时,系统自动创建 Agent 并初始化 Workspace:

typescript 复制代码
async function ensureOpenClawAgent(agentId: string): Promise<void> {
  // 1. 幂等保护:同一 Agent 不会重复创建
  if (agentCreationPromises.has(agentId)) {
    return agentCreationPromises.get(agentId)!
  }

  // 2. 列出已有 Agent,新建才创建
  const { stdout } = await execWithNodePath('openclaw agents list --json')
  const agents = JSON.parse(stdout)

  if (!agents.some((a: any) => a.id === agentId)) {
    // 3. 拷贝 Skills 到 Workspace(每次都会执行)
    await fs.cp(skillsSrc, skillsDst, { recursive: true, force: true })

    // 4. 写入 Agent 行为文件
    // SOUL.md  --- 角色定位
    // AGENTS.md --- 操作指令
    // TOOLS.md  --- 工具使用说明

    // 5. 创建 Agent
    await execWithNodePath(`openclaw agents add ${agentId} --workspace "${workspace}"`)
  }
}

Agent 行为文件

SOUL.md --- 定义 Agent 的核心能力和行为边界:

markdown 复制代码
你是用户的个人中文助手,专注于项目管理、任务、会议、报告、风险建议等查询和数据分析。

核心能力:
- 通过 REST API 查询任务、项目和会议数据
- 汇总待办事项并按优先级展示
- 提供数据分析和可视化建议

重要规则:
- 必须基于真实数据回答,不要编造数据
- 如果接口返回为空或报错,要明确说明

AGENTS.md --- 操作级指令:

markdown 复制代码
当用户询问任务、报告、会议、数据等内容时,必须通过 REST API 获取真实数据。

数据访问原则:
- 启动时优先阅读运行时注入的 instructions 和 metadata
- 所有 API 接口信息已包含在 instructions 中
- 禁止直接访问数据库,所有数据必须通过 REST API 获取

TOOLS.md --- 工具使用约定:

markdown 复制代码
所有业务数据查询均通过 REST API 完成。
优先使用 curl 调用接口,Header 中携带 Authorization: Bearer {token}
如 curl 不可用,使用 web_fetch 工具
token 从运行时 instructions 或 metadata 中获取

每次请求都重新同步 skills 到 workspace,确保 Agent 始终使用最新的业务 API 定义。


五、系统指令注入(核心机制)

每次请求都动态生成 System Message,注入业务上下文:

typescript 复制代码
export function buildOpenClawSystemMessage({
  apiHost, userId, projectId, authToken, doubaoApiKey,
}: BuildOpenClawSystemMessageOptions): string {
  return `你是用户的个人助手,专注于项目管理、任务、会议、知识库检索等。

当前操作用户 ID: ${userId}
当前项目ID: ${projectId}

## 数据获取方式
使用 curl 或 web_fetch 工具调用 REST API,在请求头中携带 Authorization: Bearer {token}。

- 后端地址: ${apiHost}
- 鉴权方式: Authorization: Bearer ${authToken}
- 豆包图片生成 API Key: ${doubaoApiKey || '未配置'}

## 鉴权失效处理
如果接口返回 401 或提示 token 失效,说明 authToken 已过期。
此时不要反复重试,应明确告知用户"登录已过期,请提供用户名和密码重新登录",
然后调用 /api/user/login.do 获取新的 authToken。

## 可用 API 接口
- meeting-api:会议管理
- task-api:任务管理
- project-api:项目管理
- report-api:报告管理
- member-api:成员管理
- document-api:文档管理
- workspace-api:工作台
- proactive-interaction-api:主动问询

## 重要约束
缺少必要参数时必须向用户确认,禁止自行填补默认值。
创建/更新/删除等写操作,执行前向用户确认操作内容。
查不到数据时明确说明你查了什么、结果如何。`
}

为什么用 System Message 而不是 Skill?

方式 适合场景
System Message 运行时动态数据(userId, projectId, authToken 每次不同)
Skill 文件 静态 API 文档(接口地址、参数、示例不常变)

两者配合:System Message 注入动态上下文,Skill 提供静态 API 知识


六、Skills 体系 --- 业务 API 的知识层

6.1 业务 Skills 清单

每个业务模块对应一个 Skill 文件(SKILL.md),包含完整的 API 文档:

ruby 复制代码
~/.openclaw/skills/
├── meeting-api/SKILL.md        # 会议管理(30+ 接口)
├── task-api/SKILL.md           # 任务管理(CRUD + 确认 + 导入)
├── project-api/SKILL.md        # 项目管理
├── report-api/SKILL.md         # 报告管理
├── member-api/SKILL.md         # 成员管理
├── document-api/SKILL.md       # 文档与知识库
├── workspace-api/SKILL.md      # 工作台(待办/通知/建议)
├── proactive-interaction-api/SKILL.md  # 主动问询
├── zhiqiu-creative/SKILL.md    # 结果可视化
├── meeting-summary-indented-tree-html/  # 会议纪要树形 HTML
├── meeting-summary-mixed-html/          # 会议纪要混合 HTML
├── frontend-design/SKILL.md    # 前端设计
└── ...(开发类 Skills: nuxt, vue, tailwind 等)

6.2 Skill 文件结构示例(task-api)

markdown 复制代码
---
name: task-api
description: 任务管理 API --- 查询、创建、更新、删除任务,导入任务,确认任务等
---

# 任务管理 API

所有接口需在 Header 中携带 `Authorization: Bearer {token}`。
**apiHost** 和 **token** 从运行时 instructions 或 metadata 中获取。

## 1. 查询任务列表
```bash
curl -X GET "{apiHost}/api/project/issueList.do?projectIdList=123&pageNum=1&pageSize=20" \
  -H "Authorization: Bearer {token}"
参数 类型 必填 说明
projectIdList List 项目ID列表
statusIdList List 任务状态ID列表
assignedToId Integer 指派人用户ID
pageNum Integer 页码,默认1
pageSize Integer 每页条数

出参{ code: 200, data: { total, rows: IssueListRow[] } }

2. 创建任务

bash 复制代码
curl -X POST "{apiHost}/api/project/issueCreate.do" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {token}" \
  -d '{"projectId": 123, "subject": "完成前端开发", ...}'
csharp 复制代码
**Skill 设计原则**:
- 每个接口包含完整的 cURL 示例------Agent 可以直接复制执行
- `{apiHost}` 和 `{token}` 是占位符,Agent 从运行时上下文替换
- 参数说明表格标注必填/可选和数据类型
- 出参格式让 Agent 知道如何解析响应

---

## 七、OpenClaw 配置详解

以下是 `~/.openclaw/openclaw.json` 的关键配置项说明。

### 7.1 模型路由配置

```jsonc
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "deepseek/deepseek-chat",     // 主模型
        "fallbacks": [                            // 自动降级链
          "ollama/qwen2.5:7b",                   // 本地 Ollama(快速但能力弱)
          "modelstudio/qwen3.5-plus",            // 阿里百炼
          "qwen/qwen3-max-2026-01-23",           // 通义千问 Max
          "qwen/qwen3-coder-next",               // 千问 Coder
          "qwen/qwen3-coder-plus",               // 千问 Coder Plus
          "qwen/MiniMax-M2.5",                   // MiniMax
          "qwen/glm-5",                          // 智谱 GLM-5
          "qwen/kimi-k2.5"                       // Moonshot Kimi
        ]
      }
    }
  }
}

Fallback 机制:当主模型不可用时,Gateway 自动按顺序尝试下一个模型。优先使用本地 Ollama(零成本),再尝试云端 API。

7.2 多 Provider 配置

jsonc 复制代码
{
  "models": {
    "mode": "merge",  // 合并多个 provider 的模型列表
    "providers": {
      "deepseek": {                     // DeepSeek 官方 API
        "baseUrl": "https://api.deepseek.com",
        "api": "openai-completions",
        "models": [{ "id": "deepseek-chat", "contextWindow": 131072, "maxTokens": 8192 }]
      },
      "qwen": {                         // 阿里云百炼(兼容 OpenAI API)
        "baseUrl": "https://coding.dashscope.aliyuncs.com/v1",
        "api": "openai-completions",
        "models": [                     // 8+ 模型,详见配置文件
          { "id": "qwen3.5-plus", "contextWindow": 1000000, "maxTokens": 65536 },
          { "id": "qwen3-max-2026-01-23", "contextWindow": 262144, "maxTokens": 65536 }
        ]
      },
      "ollama": {                        // 本地 Ollama 服务
        "baseUrl": "http://<your-ollama-host>:11434",
        "api": "ollama",
        "models": [                      // Gemma, Qwen, GLM 等本地模型
          { "id": "qwen2.5:7b", "contextWindow": 32768 },
          { "id": "qwen3.5:latest", "contextWindow": 262144 }
        ]
      }
    }
  }
}

关键参数说明

参数 说明
mode: "merge" 合并所有 provider 的模型,统一调度
contextWindow 上下文窗口大小(Token 数)
maxTokens 单次最大输出 Token 数
cost 成本配置($/百万 Token),用于成本追踪
reasoning 是否为推理模型(带思维链)
input 支持的输入类型:["text"]["text","image"]

7.3 Gateway 配置

jsonc 复制代码
{
  "gateway": {
    "mode": "local",             // 本地模式(非远程/云端)
    "port": 18789,               // Gateway 监听端口
    "bind": "loopback",          // 仅本地回环(127.0.0.1)
    "auth": {
      "mode": "token",           // Token 鉴权模式
      "token": "your-gateway-token-here"
    },
    "http": {
      "endpoints": {
        "chatCompletions": { "enabled": true },  // 兼容 OpenAI Chat API
        "responses": { "enabled": true }          // OpenAI Responses API
      }
    },
    "controlUi": {
      "allowInsecureAuth": true  // 允许 HTTP(非 HTTPS)鉴权
    }
  }
}

安全注意事项

  • bind: "loopback" 确保 Gateway 只监听本地,不暴露到公网
  • Token 鉴权防止未经授权的请求
  • 生产环境建议使用反向代理(Nginx)+ HTTPS

7.4 沙箱配置

jsonc 复制代码
{
  "sandbox": {
    "mode": "non-main",           // 非 main agent 启用沙箱
    "scope": "agent",             // 每个 Agent 独立沙箱
    "workspaceAccess": "rw",      // 工作区可读写
    "docker": {
      "image": "openclaw-sandbox-common:bookworm-slim",
      "network": "bridge"         // 桥接网络(可访问业务 API)
    }
  }
}

non-main 策略下,user_xxx 这类用户 Agent 运行在 Docker 沙箱中,而 main Agent 不隔离。这保证了:

  • 用户 Agent 的执行环境隔离,互不影响
  • 沙箱内可安装依赖、执行脚本,不影响宿主机
  • workspaceAccess: "rw" 让 Agent 可以读写自己的 workspace

7.5 消息通道绑定

jsonc 复制代码
{
  "bindings": [
    {
      "type": "route",
      "agentId": "user_21",
      "match": { "channel": "openclaw-weixin", "accountId": "user_21" }
    },
    {
      "type": "route",
      "agentId": "user_149",
      "match": { "channel": "openclaw-weixin", "accountId": "user_149" }
    }
  ]
}

路由规则channel + accountId → agentId。微信用户 user_21 的消息自动路由到 Agent user_21

多通道配置:

jsonc 复制代码
{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxxx",
      "appSecret": "xxxx",
      "connectionMode": "websocket",     // 飞书使用 WebSocket 长连接
      "dmPolicy": "allowlist",           // 白名单模式
      "allowFrom": ["ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
    },
    "openclaw-weixin": {
      "enabled": true,
      "dynamicAccount": true,            // 动态账号模式,自动按 user_xxx 分配
      "accountPrefix": "user_"
    }
  }
}

微信通道的特殊设计dynamicAccount: true + accountPrefix: "user_" 意味着每新增一个微信用户,自动创建一个对应的账号和绑定。这与 user_{userId} 的 Agent 命名规则天然对应。

7.6 其他关键配置

jsonc 复制代码
{
  "compaction": { "mode": "safeguard" },   // 上下文压缩保护
  "tools": {
    "profile": "coding",                   // 工具配置文件(coding = 开发场景)
    "web": { "search": { "provider": "tavily", "enabled": true } },  // 网络搜索
    "exec": { "security": "full", "host": "auto" }  // 命令执行安全策略
  },
  "session": { "dmScope": "per-account-channel-peer" },  // 会话隔离策略
  "plugins": {
    "entries": {
      "memory-core": { "config": { "dreaming": { "enabled": true } } }  // 长期记忆
    }
  }
}

八、Nuxt 3 服务端集成

8.1 运行时配置

typescript 复制代码
// nuxt.config.ts
{
  openclawGatewayUrl: process.env.OPENCLAW_GATEWAY_URL || 'ws://127.0.0.1:18789',
  openclawGatewayToken: process.env.OPENCLAW_GATEWAY_TOKEN || '',
}

8.2 SSE 流式 API 端点

前端调用 POST /napi/ai/chat-stream,后端转发到 OpenClaw Gateway 并代理 SSE 流:

typescript 复制代码
// server/routes/napi/ai/chat-stream.post.ts
export default defineEventHandler(async (event) => {
  const { userId, sessionId, query, context, agentId } = await readBody(event)

  // 1. 从请求头提取用户 JWT Token(有时效性,不持久化)
  const authToken = getHeader(event, 'authorization')?.replace('Bearer ', '')

  // 2. 生成 Session Key 和 Agent ID
  const resolvedAgentId = resolveOpenClawAgentId(Number(userId), agentId)
  const sessionKey = generateSessionKey(userId, sessionId, resolvedAgentId)

  // 3. 设置 SSE 响应头
  setHeader(event, 'Content-Type', 'text/event-stream')

  // 4. 创建可读流,内部调用 OpenClaw
  const stream = new ReadableStream({
    async start(controller) {
      await sendOpenClawMessage({
        userId, projectId, sessionKey, message, agentId, authToken,
        callbacks: {
          onDelta: (data) => sendSSE({ content: data.content, ... }),
          onCompleted: (data) => { sendSSE({ finishReason: ... }); closeStream() },
          onError: (error) => { sendSSE({ content: error.message }); closeStream() },
        },
      })
    },
  })

  return sendStream(event, stream)
})

流程:前端 SSE → Nuxt API Route → OpenClaw Gateway HTTP → Agent 处理 → 流式返回。

8.3 与 OpenClaw Gateway 通信

typescript 复制代码
export async function sendOpenClawMessage(options) {
  // 1. 确保 Agent 已创建(首次自动创建)
  await ensureOpenClawAgent(agentId)

  // 2. 构建请求体(Responses API 格式)
  const requestBody = {
    model: `openclaw/${agentId}`,   // 模型名称 = openclaw/ + Agent ID
    input: message,                  // 用户输入
    instructions: systemMessage,     // 动态系统指令
    stream: true,                    // 启用流式输出
    user: sessionKey,                // 会话标识
    metadata,                        // 业务上下文
  }

  // 3. POST 请求,携带 Gateway Token + Agent ID + Session Key
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${gatewayToken}`,
      'x-openclaw-agent-id': agentId,
      'x-openclaw-session-key': sessionKey,
    },
    body: JSON.stringify(requestBody),
    signal: AbortSignal.timeout(10 * 60 * 1000),  // 10 分钟超时
  })

  // 4. 读取 SSE 流并解析
  const reader = response.body.getReader()
  while (true) {
    const { done, value } = await reader.read()
    if (done) break
    // 解析 data: {...}\n\n 格式的 SSE 事件
    // → 提取 content / reasoning_content / finishReason
  }
}

关键 Header

Header 说明
Authorization: Bearer {gatewayToken} Gateway 层鉴权
x-openclaw-agent-id 指定目标 Agent
x-openclaw-session-key 会话标识,用于上下文连续性

8.4 SSE 流解析

模型返回的事件有多种格式,需要统一解析:

typescript 复制代码
export function parseOpenClawStreamChunk(json: Record<string, any>) {
  // OpenAI Responses API 格式:response.output_text.delta
  if (json.type === 'response.output_text.delta') {
    return { content: json.delta }
  }
  // 推理内容增量
  if (json.type?.startsWith('response.reasoning') && json.type.endsWith('.delta')) {
    return { reasoning_content: json.delta }
  }
  // 完成事件
  if (json.type === 'response.completed') {
    return { finishReason: json.response?.status === 'incomplete' ? 'length' : 'stop', done: true }
  }
  // 兼容 OpenAI Chat Completions 格式(其他 Provider)
  const choice = json.choices?.[0]
  if (choice?.delta?.content) return { content: choice.delta.content }
  if (choice?.delta?.reasoning_content) return { reasoning_content: choice.delta.reasoning_content }
  if (choice?.finish_reason) return { finishReason: choice.finish_reason, done: true }
  return {}
}

兼容两种流式格式 :OpenAI Responses API(response.output_text.delta)和 Chat Completions API(choices[0].delta.content),因为不同 Provider 可能返回不同格式。


九、主动问询 --- Agent 主动触达用户

这是业务系统的特色功能:AI Agent 不只是被动应答,还能主动向用户发起问询。

9.1 触发时机

在 System Message 中约定了使用场景:

  • AI 发现了需要用户关注的问题(任务逾期、数据异常)
  • 用户要求 "主动跟我沟通"、"有问题通知我"
  • AI 需要用户做出决定或提供更多信息

9.2 API 调用

bash 复制代码
curl -X POST "{apiHost}/api/task/proactive/process/v2/requireInteraction" \
  -H "Content-Type: application/json" \
  -d '{
    "taskName": "任务逾期提醒",
    "from": "openclaw",
    "userId": ${userId},
    "projectId": ${projectId},
    "interaction": {
      "interactionType": "openclaw",
      "interactionUserId": ${userId},
      "messages": [{
        "role": "assistant",
        "content": "您有 3 个任务已逾期超过 3 天,需要确认是否延期或关闭..."
      }]
    }
  }'

9.3 用户回复后的上下文拼接

当用户在业务系统前端回复了 Agent 的问询,服务端会自动拼接对话历史:

typescript 复制代码
// chat-stream.post.ts 中的上下文拼接逻辑
if (context?.interactionType === 'openclaw' && Array.isArray(context?.messages)) {
  const historyParts = context.messages.map(msg =>
    `${msg.role === 'assistant' ? '你之前的留言' : '用户'}: ${msg.content}`
  )
  contextualMessage = `【对话上下文 - 主动问询】
  ${historyParts.join('\n')}
  【用户的最新回复】
  ${query}

  请结合上述对话历史理解上下文,回复用户的这条消息。
  如果用户已经充分回复了你的问题,并且你也没有其他要追问的,
  请在回复完本条消息后,调用主动问询的完成接口,将本次交互标记为已完成。`
}

这个设计解决了 Agent 的 "失忆"问题------不同 Session 之间 Agent 不记得之前的对话,通过拼接历史消息来恢复上下文。


十、完整请求链路

以一个 "查看我的待办任务" 为例:

css 复制代码
1. 用户在 Web 前端输入 "帮我看看我有哪些待办任务"
   ↓
2. 前端 POST /napi/ai/chat-stream
   Body: { userId: 21, sessionId: "abc", query: "帮我看看我有哪些待办任务",
           context: { projectId: 123 } }
   Headers: { Authorization: "Bearer <user_jwt>" }
   ↓
3. Nuxt API Route 提取 JWT token,生成 sessionKey
   构建 System Message(注入 apiHost, userId, projectId, authToken)
   ↓
4. POST http://127.0.0.1:18789/v1/responses
   Body: {
     model: "openclaw/user_21",
     input: "帮我看看我有哪些待办任务",
     instructions: "<System Message>",
     stream: true,
     user: "agent:user_21:user_21:session_abc",
     metadata: { userId: "21", apiHost: "https://api.xxx.com", authToken: "<jwt>" }
   }
   Headers: {
     Authorization: "Bearer <gateway_token>",
     x-openclaw-agent-id: "user_21",
     x-openclaw-session-key: "agent:user_21:user_21:session_abc"
   }
   ↓
5. OpenClaw Gateway 路由到 Agent user_21
   注入 instructions 和 metadata 到 Agent 上下文
   ↓
6. Agent 识别意图:查询任务
   自动加载 task-api skill
   执行 curl 命令:
   curl "https://api.xxx.com/api/project/issueList.do?projectIdList=123&assignedToId=21" \
     -H "Authorization: Bearer <jwt>"
   ↓
7. 业务 API 返回用户 21 在项目 123 的任务列表
   ↓
8. Agent 分析数据,生成自然语言回复,流式返回
   ↓
9. Nuxt API Route 解析 SSE 流 → 转发给前端
   ↓
10. 前端实时渲染 AI 回复

十一、部署架构

scss 复制代码
┌─────────────────────────────────────────────────────┐
│                    服务器                            │
│                                                     │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────┐  │
│  │  Nuxt 3   │  │ OpenClaw │  │  Docker Engine   │  │
│  │  (Node)   │  │ Gateway  │  │  ┌────────────┐  │  │
│  │  :3000    │  │ :18789   │  │  │ sandbox_21  │  │  │
│  └─────┬─────┘  └────┬─────┘  │  ├────────────┤  │  │
│        │              │        │  │ sandbox_144 │  │  │
│        └──────┬───────┘        │  ├────────────┤  │  │
│               │                │  │ sandbox_149 │  │  │
│               │                │  └────────────┘  │  │
│               │                └──────────────────┘  │
│               │                        │             │
│               ▼                        ▼             │
│  ┌────────────────────────────────────────────────┐  │
│  │              业务 REST API                      │  │
│  └────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘
         │                    │
         ▼                    ▼
┌────────────┐    ┌──────────────────┐
│ Ollama      │    │  云端模型 API    │
│ (本地 GPU)  │    │  阿里百炼/DeepSeek │
│ :11434      │    │  通义千问/Kimi   │
└────────────┘    └──────────────────┘

资源规划建议

  • OpenClaw Gateway 本身轻量,1-2 核即可
  • 每个 Agent Sandbox 运行在 Docker 容器中,内存按 512MB-1GB 预估
  • 本地 Ollama 服务建议独立部署在有 GPU 的机器上
  • Nuxt 服务和 Gateway 可以部署在同一台机器上,通过 loopback 通信

十二、总结

核心设计决策

决策 选择 理由
Agent 粒度 一用户一 Agent 数据隔离、上下文独立、权限可控
数据访问 仅通过 REST API 安全审计、权限复用、禁止直连 DB
鉴权机制 JWT Token 透传 用户级权限隔离、时效性保证
知识注入 System Message + Skill 动态上下文 + 静态 API 文档分工
多通道 binding 路由映射 channel+accountId → agentId 自动分发
模型策略 主模型 + Fallback 链 保证可用性,成本可控
会话管理 结构化 SessionKey 同时编码 agent/user/session 信息

关键文件清单

文件 作用
~/.openclaw/openclaw.json OpenClaw 全局配置(模型、通道、沙箱)
server/utils/openclaw.ts Nuxt 侧集成代码(消息发送、流解析、Agent 管理)
server/routes/napi/ai/chat-stream.post.ts SSE 流式 API 端点
~/.openclaw/skills/*/SKILL.md 业务 API Skill 定义
nuxt.config.ts Gateway URL / Token 环境变量

扩展方向

  • 定时巡检:让 Agent 定时检查任务逾期、风险异常,触发主动问询
  • 多 Agent 协作:复杂任务拆分给多个 Agent 并行处理
  • Agent 能力进化 :基于用户反馈和使用数据,自动优化 Agent 行为(Skill 中已有 self-improving-agent 的种子)中间省略的部分,都是这个方案中已经验证落地的模块。
相关推荐
小码哥0686 小时前
一套可复用的打车系统模板,微服务版网约车系统|类似滴滴的打车平台
微服务·云原生·架构·滴滴·打车
元智启6 小时前
企业AI如何开发:智能体时代的安全治理架构与合规管控实践
人工智能·安全·架构
老毛肚7 小时前
微服务网关整合授权中心实现单点登录
运维·微服务·架构
沪漂阿龙7 小时前
Dify 面试题详解:开源 LLM 应用开发平台、RAG 知识库、Workflow 工作流、Agent 智能体一文讲透
人工智能·架构
一枝小雨7 小时前
RISC-V架构的中断与异常处理机制学习笔记
单片机·架构·嵌入式·risc-v·内核原理·中断与异常
沪漂阿龙8 小时前
面试题详解:多模态大模型全攻略——ViT 架构、扩散模型、U-Net、VAE、CLIP、Prompt 图像对齐一次讲透
人工智能·架构·prompt
REDcker8 小时前
Playwright详解 Web自动化与E2E测试 架构原理与实战入门
前端·架构·自动化
phltxy8 小时前
Redis Sentinel:主从架构的自动保镖详解
redis·架构·sentinel
百珏8 小时前
[灰度发布]:灰度流量如何匹配与识别:从特征补全到网关命中引擎
java·后端·架构