云猫
云猫
发布于 2026-04-01 / 8 阅读
0
0

云小猫异步审批执行系统-设计与实现

云小猫异步审批执行系统设计与实现

摘要

本文详细记录了云小猫(基于 OpenClaw 框架的运维助手 Agent)审批系统的架构改造过程。针对原有同步阻塞式审批流程存在的阻塞等待、执行时机不可控、缺乏追溯能力等问题,设计并实现了一套基于异步消息处理的审批执行系统。该系统将审批请求创建、状态管理、操作执行解耦,通过独立的服务完成审批流程,实现了审批不阻塞聊天、执行可追溯、危险操作规范化等目标。

关键词:审批系统、异步处理、Agent 安全、运维自动化、OpenClaw


1. 引言

1.1 背景

云小猫是基于 OpenClaw 框架构建的运维助手 Agent,负责处理用户的运维请求。在实际使用中,部分操作(如重启容器、停止服务)具有风险性,需要管理员审批确认后才能执行。

原有的审批流程采用同步阻塞模式:云小猫发起审批请求后,需要等待管理员确认才能继续处理后续消息。这种设计存在明显缺陷:

问题 影响
阻塞聊天 审批等待期间,云小猫无法响应用户的其他消息
执行时机不可控 审批通过后由云小猫执行,可能因等待过久而产生状态不一致
缺乏追溯能力 审批状态存储在 JSON 文件中,无法完整追溯流程
安全隐患 危险操作由 Agent 直接执行,缺乏独立的安全校验

1.2 改造目标

目标 描述
异步处理 审批请求创建后立即返回,不阻塞聊天功能
自动执行 审批通过后由独立服务自动执行操作,避免延迟
完整追溯 审批流程全程记录到数据库,支持审计查询
安全规范 定义危险指令清单,禁止操作直接拒绝,高风险操作需审批

2. 架构对比

2.1 原有架构(同步阻塞式)

用户请求 → 云小猫 → 发起审批 → 阻塞等待
                                    ↓
                            管理员审批
                                    ↓
                            云小猫继续执行
                                    ↓
                            返回结果给用户

问题:整个流程中云小猫被阻塞,无法处理其他消息。

2.2 新架构(异步执行式)

用户请求 → 云小猫 → 调用审批执行中心 → 立即返回"已提交审批"
                                        ↓
                                云小猫继续处理其他消息
                                        ↓
                                审批执行中心独立运行:
                                ├─ 管理员审批通过 → 自动执行 → 通知用户
                                ├─ 管理员审批拒绝 → 通知用户
                                └─ 审批超时 → 自动取消 → 通知用户

优势:云小猫不阻塞,审批执行由独立服务完成,流程可追溯。


3. 系统架构设计

3.1 整体架构图

┌─────────────────────────────────────────────────────────────────────┐
│                         云小猫 (OpenClaw Agent)                     │
│                    主 Agent - 仅负责聊天协调                          │
│                              ↓                                       │
│                    发起审批请求后立即返回                              │
│                    继续处理用户其他消息                                │
└─────────────────────────────────────────────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────────┐
│                    审批执行中心 (Approval Executor)                   │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐        │
│  │ 接收审批  │ → │ 存储审批  │ → │ 推送通知  │ → │ 等待决策  │        │
│  │  请求    │   │  记录    │   │ (QQ/企微) │   │ (轮询DB)  │        │
│  └──────────┘   └──────────┘   └──────────┘   └──────────┘        │
│                                                     ↓               │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐        │
│  │ 记录日志  │ ← │ 通知结果  │ ← │ 执行操作  │ ← │ 审批通过  │        │
│  │ (审计)   │   │ (用户)   │   │ (实际执行) │   │ 或超时    │        │
│  └──────────┘   └──────────┘   └──────────┘   └──────────┘        │
└─────────────────────────────────────────────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────────┐
│                      数据库 (MySQL - management_api)                 │
│  ┌──────────────────────┐  ┌──────────────────────┐                │
│  │   approval_requests   │  │ approval_execution_logs │              │
│  │   (审批请求记录)       │  │   (执行日志/可追溯)    │              │
│  └──────────────────────┘  └──────────────────────┘                │
└─────────────────────────────────────────────────────────────────────┘

3.2 核心组件说明

组件 技术栈 端口 功能描述
审批执行中心 API Flask + PyMySQL 5682 提供 RESTful API,处理审批 CRUD、执行操作、发送通知
审批状态检查器 Python 轮询脚本 - 后台服务,定时检查审批状态变更,生成通知文件
数据库 MySQL 8.0 3306 持久化审批记录和执行日志,支持审计查询
QQ 消息处理器 Python 脚本 - 解析审批确认/拒绝消息,调用 API 完成审批

3.3 数据流程详解

步骤 1: 用户发起请求
    用户在 QQ 发送: "帮我重启 MySQL 容器"
                    ↓
步骤 2: 云小猫判断风险等级
    根据操作类型判断: docker_restart = medium 风险
                    ↓
步骤 3: 调用审批执行中心
    POST /api/approval/create
    {
        "actionType": "docker_restart",
        "actionParams": {"container": "MySQL"},
        "riskLevel": "medium",
        ...
    }
                    ↓
步骤 4: 创建审批记录
    - 生成 UUID 作为审批 ID
    - 写入 approval_requests 表
    - 写入 approval_execution_logs (event: created)
                    ↓
步骤 5: 推送通知
    - 查询 subscribers 表获取订阅者
    - 发送 QQ 私信 / 企业微信通知
                    ↓
步骤 6: 立即返回用户
    "已提交审批请求!审批ID: xxx,等待管理员确认"
    云小猫继续处理其他消息(不阻塞)
                    ↓
步骤 7: 管理员审批
    管理员回复: "确认 xxx" 或 "拒绝 xxx"
                    ↓
步骤 8: 审批处理脚本解析
    - 匹配审批 ID
    - 调用 /api/approval/{id}/approve 或 reject
                    ↓
步骤 9: 执行操作(如果通过)
    - 执行 docker restart MySQL
    - 更新审批状态为 executed
    - 记录执行结果到日志
                    ↓
步骤 10: 通知用户结果
    - 审批通过: "✅ 审批已通过,容器 MySQL 已重启"
    - 审批拒绝: "❌ 审批已拒绝,操作不会执行"

4. 数据库设计

4.1 审批请求表 (approval_requests)

CREATE TABLE approval_requests (
    id VARCHAR(36) PRIMARY KEY,                    -- 审批 ID (UUID)
    action_type VARCHAR(50) NOT NULL,              -- 操作类型
    action_params JSON,                            -- 操作参数 (JSON 格式)
    risk_level ENUM('low', 'medium', 'high'),      -- 风险等级
    reason TEXT,                                   -- 审批原因/描述
    status ENUM('pending', 'approved', 'rejected', 
                'timeout', 'executed', 'failed'),  -- 审批状态
    requester_id VARCHAR(50),                      -- 请求人 ID
    requester_name VARCHAR(100),                   -- 请求人名称
    approver_id VARCHAR(50),                       -- 审批人 ID
    approver_name VARCHAR(100),                    -- 审批人名称
    source_channel VARCHAR(50),                    -- 来源渠道 (qq/wecom/api)
    source_message TEXT,                           -- 原始请求消息
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
    approved_at DATETIME,                          -- 审批时间
    executed_at DATETIME,                          -- 执行时间
    timeout_at DATETIME,                           -- 超时时间
    execution_result JSON,                         -- 执行结果 (JSON 格式)
    error_message TEXT,                            -- 错误信息
  
    INDEX idx_status (status),
    INDEX idx_created (created_at),
    INDEX idx_timeout (timeout_at),
    INDEX idx_action_type (action_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

4.2 审批执行日志表 (approval_execution_logs)

此表用于完整追溯审批流程的每一步。

CREATE TABLE approval_execution_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    approval_id VARCHAR(36) NOT NULL,              -- 关联审批 ID
    event_type VARCHAR(50) NOT NULL,               -- 事件类型
    event_data JSON,                               -- 事件详情 (JSON 格式)
    operator_id VARCHAR(50),                       -- 操作人 ID
    operator_name VARCHAR(100),                    -- 操作人名称
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP, -- 创建时间
  
    FOREIGN KEY (approval_id) 
        REFERENCES approval_requests(id) ON DELETE CASCADE,
    INDEX idx_approval (approval_id),
    INDEX idx_event_type (event_type),
    INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

4.3 事件类型定义

事件类型 触发时机 event_data 示例
created 审批请求创建 {"actionType": "docker_restart", "riskLevel": "medium"}
approved 审批通过 {"approverName": "管理员", "approverChannel": "qq"}
rejected 审批拒绝 {"approverName": "管理员", "reason": "风险太高"}
timeout 审批超时 {"auto": true}
executed 操作执行完成 {"success": true, "message": "容器已重启"}
failed 操作执行失败 {"error": "容器不存在"}

5. API 接口设计

5.1 创建审批请求

端点: POST /api/approval/create

请求头:

X-APPROVAL-TOKEN: approval-secret-token-2026
Content-Type: application/json

请求体:

{
    "actionType": "docker_restart",
    "actionParams": {"container": "MySQL"},
    "riskLevel": "medium",
    "reason": "用户请求重启 MySQL 容器",
    "requesterId": "yunmao",
    "requesterName": "云小猫",
    "sourceChannel": "qq",
    "sourceMessage": "帮我重启 MySQL",
    "timeoutMinutes": 30,
    "notifyChannels": ["qq"]
}

成功响应(需审批):

{
    "success": true,
    "approvalId": "566cf844-c583-4897-b74e-c158b163ba15",
    "status": "pending",
    "message": "审批请求已创建,等待管理员确认",
    "timeoutAt": "2026-04-01T13:25:24.137281"
}

成功响应(低风险,直接执行):

{
    "success": true,
    "approvalId": "5944f5cb-df8b-4bd4-81e1-192931dd7252",
    "status": "executed",
    "executionResult": {
        "success": true,
        "message": "容器列表获取成功",
        "output": "NAMES                 STATUS..."
    },
    "message": "低风险操作已直接执行"
}

拒绝响应(禁止操作):

{
    "success": false,
    "status": "forbidden",
    "error": "禁止执行危险操作: rm -rf /"
}

5.2 批准审批并执行

端点: POST /api/approval/{approval_id}/approve

请求体:

{
    "approverId": "admin",
    "approverName": "管理员",
    "approverChannel": "qq"
}

响应:

{
    "success": true,
    "approvalId": "566cf844-c583-4897-b74e-c158b163ba15",
    "status": "executed",
    "executionResult": {
        "success": true,
        "message": "容器 MySQL 已重启",
        "output": "MySQL\n"
    }
}

5.3 拒绝审批

端点: POST /api/approval/{approval_id}/reject

请求体:

{
    "approverId": "admin",
    "approverName": "管理员",
    "reason": "风险太高,暂不执行"
}

响应:

{
    "success": true,
    "approvalId": "a82563e9-b09e-43c8-845b-aadc3f60b45e",
    "status": "rejected",
    "message": "审批已拒绝"
}

5.4 轮询审批状态

端点: GET /api/approval/poll

响应:

{
    "success": true,
    "data": [
        {
            "id": "566cf844-c583-4897-b74e-c158b163ba15",
            "action_type": "docker_restart",
            "action_params": "{\"container\": \"MySQL\"}",
            "risk_level": "medium",
            "status": "executed",
            "requester_name": "云小猫",
            "created_at": "2026-04-01T12:55:24",
            "timeout_at": "2026-04-01T13:25:24"
        }
    ],
    "count": 1
}

5.5 获取执行日志

端点: GET /api/approval/logs/{approval_id}

响应:

{
    "success": true,
    "data": [
        {
            "id": 19,
            "approval_id": "e77a13af-e6b1-47bc-8f82-09763dc110eb",
            "event_type": "created",
            "event_data": "{\"actionType\": \"docker_restart\", \"riskLevel\": \"medium\"}",
            "created_at": "2026-04-01T13:11:43"
        },
        {
            "id": 20,
            "approval_id": "e77a13af-e6b1-47bc-8f82-09763dc110eb",
            "event_type": "approved",
            "event_data": "{\"approverName\": \"QQ用户\"}",
            "operator_name": "QQ用户",
            "created_at": "2026-04-01T13:12:02"
        },
        {
            "id": 21,
            "approval_id": "e77a13af-e6b1-47bc-8f82-09763dc110eb",
            "event_type": "executed",
            "event_data": "{\"success\": true, \"message\": \"容器 OpenResty 已重启\"}",
            "created_at": "2026-04-01T13:12:03"
        }
    ]
}

6. 风险判断机制

6.1 风险等级定义

等级 定义 操作示例 需要审批 默认超时
low 只读操作,不改变系统状态 查看容器列表、检查服务器状态 -
medium 可能暂时影响服务可用性 重启容器、启动容器 30 分钟
high 可能导致服务中断或数据丢失 停止容器、删除容器、执行命令 60 分钟
forbidden 绝对禁止执行的操作 删除根目录、格式化磁盘 - -

6.2 操作类型映射表

操作类型 风险等级 需要审批 默认超时 描述
docker_list low - 列出所有容器
docker_inspect low - 查看容器详情
docker_logs low - 查看容器日志
check_status low - 检查服务器状态
check_disk low - 检查磁盘使用情况
check_memory low - 检查内存使用情况
docker_start medium 30分钟 启动已停止的容器
docker_restart medium 30分钟 重启运行中的容器
docker_stop high 60分钟 停止运行中的容器
docker_rm high 60分钟 删除容器
docker_exec high 60分钟 在容器内执行命令
shell_command high 60分钟 在宿主机执行命令

6.3 风险判断代码实现

# 危险操作配置
DANGEROUS_PATTERNS = ['rm -rf', 'mkfs', 'dd if=', '> /dev/', 'chmod 777 /']
CRITICAL_SERVICES = ['mysql', 'nginx', 'redis', 'postgresql', 'mongodb']

# 高风险操作列表
HIGH_RISK_ACTIONS = [
    'docker_stop', 'docker_rm', 'docker_rmi', 'docker_exec',
    'shell_command', 'edit_config', 'db_delete', 'db_drop'
]

# 中风险操作列表
MEDIUM_RISK_ACTIONS = [
    'docker_start', 'docker_restart',
    'restart_service', 'db_insert', 'db_update'
]

# 禁止操作列表
FORBIDDEN_PATTERNS = [
    'rm -rf /', 'rm -rf /*', 'mkfs', 'dd if=/dev/zero',
    '> /dev/sda', 'chmod 777 /', 'chmod -R 777 /',
    ':(){ :|:& };:', 'curl | bash', 'wget | sh'
]

def determine_risk_level(action_type, params):
    """
    根据操作类型和参数判断风险等级
  
    Returns:
        tuple: (risk_level, reason, need_approval)
    """
    # 1. 检查是否为禁止操作
    if action_type == 'shell_command':
        command = params.get('command', '').lower()
        for pattern in FORBIDDEN_PATTERNS:
            if pattern.lower() in command:
                return 'forbidden', f'禁止执行危险操作: {pattern}', False
  
    # 2. Shell 命令特殊处理
    if action_type == 'shell_command':
        command = params.get('command', '')
  
        # 检查危险模式
        for pattern in DANGEROUS_PATTERNS:
            if pattern in command:
                return 'forbidden', f'禁止执行危险命令: {pattern}', False
  
        # 检查关键服务
        for service in CRITICAL_SERVICES:
            if service in command.lower():
                return 'high', f'涉及关键服务: {service}', True
  
    # 3. 根据操作类型判断
    if action_type in HIGH_RISK_ACTIONS:
        return 'high', None, True
  
    if action_type in MEDIUM_RISK_ACTIONS:
        return 'medium', None, True
  
    return 'low', None, False

6.4 禁止操作列表

以下操作会被系统直接拒绝,不进入审批流程:

命令模式 危险原因
rm -rf / 删除根目录,系统毁灭
rm -rf /* 删除根目录所有文件
mkfs 格式化磁盘,数据丢失
dd if=/dev/zero 用零覆盖磁盘数据
> /dev/sda 覆盖磁盘原始数据
chmod 777 / 设置危险的完全权限
chmod -R 777 / 递归设置危险权限
`:(){ : :& };:`
curl ... | bash 远程执行未知脚本
wget ... | sh 远程执行未知脚本

7. QQ 消息集成

7.1 消息处理优先级

当云小猫收到 QQ 消息时,按以下优先级处理:

QQ 消息
    │
    ▼
判断消息类型(优先级从高到低)
    │
    ├── 1. 审批消息?
    │       │
    │       ├── "确认 xxx" → 调用审批处理脚本 → 批准审批
    │       ├── "拒绝 xxx" → 调用审批处理脚本 → 拒绝审批
    │       └── "待审批"   → 调用审批处理脚本 → 返回审批列表
    │
    ├── 2. 帮助消息?
    │       └── 关键词: 帮助、怎么用、功能 → 返回使用帮助
    │
    ├── 3. 知识问答?
    │       └── 关键词: 知识库、文档、配置 → 调用 MaxKB 知识库
    │
    └── 4. 任务执行?
            └── 检测操作意图 → 调用审批执行中心

7.2 审批命令格式

命令格式 功能 示例
确认 {ID} 批准审批 确认 566cf844
批准 {ID} 同意审批 批准 566cf844
同意 {ID} 同意审批 同意 566cf844
拒绝 {ID} 拒绝审批 拒绝 566cf844
否决 {ID} 拒绝审批 否决 566cf844
待审批 查看审批列表 待审批

ID 简化输入:支持使用审批 ID 的前 8 位,系统自动匹配完整 ID。

7.3 审批处理脚本

脚本位置:/root/.openclaw/skills/approval-handler/approval-handler.py

核心功能

  1. 解析审批确认/拒绝消息
  2. 通过部分 ID 查找完整审批记录
  3. 调用审批执行中心 API
  4. 返回格式化的审批结果给云小猫

调用示例

# 查看待审批列表
python3 /root/.openclaw/skills/approval-handler/approval-handler.py "待审批"

# 确认审批
python3 /root/.openclaw/skills/approval-handler/approval-handler.py "确认 e77a13af"

# 拒绝审批
python3 /root/.openclaw/skills/approval-handler/approval-handler.py "拒绝 e77a13af"

8. 完整测试流程

8.1 测试场景 1:用户请求重启容器(中风险)

用户操作:在 QQ 发送消息

帮我重启 OpenResty 容器

云小猫调用审批执行中心

curl -X POST http://localhost:5682/api/approval/create \
  -H "X-APPROVAL-TOKEN: approval-secret-token-2026" \
  -H "Content-Type: application/json" \
  -d '{
    "actionType": "docker_restart",
    "actionParams": {"container": "OpenResty"},
    "reason": "用户请求重启 OpenResty 容器",
    "requesterId": "yunmao",
    "requesterName": "云小猫",
    "sourceChannel": "qq"
  }'

系统响应

{
    "success": true,
    "approvalId": "e77a13af-e6b1-47bc-8f82-09763dc110eb",
    "status": "pending",
    "message": "审批请求已创建,等待管理员确认",
    "timeoutAt": "2026-04-01T13:41:43.160238"
}

云小猫回复用户

已提交审批请求!

📋 审批ID: e77a13af...
🎯 操作: 重启容器 OpenResty
⚠️ 风险等级: 中等

已通知管理员,请等待审批结果。

8.2 测试场景 2:管理员查看待审批列表

管理员操作:在 QQ 发送消息

待审批

系统响应

### 📋 待处理审批列表

📋 审批ID: e77a13af...
🎯 操作: docker_restart
📊 参数: {"container": "OpenResty"}
⚠️ 风险: 🟡 MEDIUM
📝 原因: 用户请求重启 OpenResty 容器

回复 "确认 {ID前8位}" 或 "拒绝 {ID前8位}" 进行审批

8.3 测试场景 3:管理员确认审批

管理员操作:在 QQ 发送消息

确认 e77a13af

系统响应

✅ 审批已通过

✅ 执行成功
容器 OpenResty 已重启

详细信息:
- 操作: e77a13af...
- 结果: {"success": true, "message": "容器 OpenResty 已重启"}

8.4 测试场景 4:查看执行日志(可追溯)

API 调用

curl http://localhost:5682/api/approval/logs/e77a13af-e6b1-47bc-8f82-09763dc110eb \
  -H "X-APPROVAL-TOKEN: approval-secret-token-2026"

系统响应

{
    "data": [
        {
            "event_type": "created",
            "event_data": "{\"actionType\": \"docker_restart\", \"riskLevel\": \"medium\"}",
            "created_at": "2026-04-01T13:11:43"
        },
        {
            "event_type": "approved",
            "event_data": "{\"approverName\": \"QQ用户\"}",
            "operator_name": "QQ用户",
            "created_at": "2026-04-01T13:12:02"
        },
        {
            "event_type": "executed",
            "event_data": "{\"success\": true, \"message\": \"容器 OpenResty 已重启\"}",
            "created_at": "2026-04-01T13:12:03"
        }
    ]
}

8.5 测试场景 5:高风险操作拒绝

用户操作:请求停止容器

停止 clawith-frontend-1 容器

系统响应

{
    "success": true,
    "approvalId": "a82563e9-b09e-43c8-845b-aadc3f60b45e",
    "status": "pending",
    "riskLevel": "high"
}

管理员操作

拒绝 a82563e9

系统响应

❌ 审批已拒绝,操作不会执行

8.6 测试场景 6:低风险操作直接执行

用户操作

查看所有容器

系统响应

状态: 直接执行(无需审批)
执行结果: 容器列表获取成功

容器列表(前5个):
NAMES                 STATUS                  PORTS
clawith-backend-1     Up 2 hours (healthy)    8000/tcp
clawith-frontend-1    Up 2 hours              80/tcp, 0.0.0.0:3030->3000/tcp
clawith-postgres-1    Up 2 hours (healthy)    5432/tcp
clawith-redis-1       Up 2 hours (healthy)    6379/tcp
1Panel-ollama-CqL2    Up 22 hours             0.0.0.0:11434->11434/tcp

8.7 测试场景 7:禁止操作直接拒绝

用户操作

执行命令: rm -rf /

系统响应

状态: forbidden
错误: 禁止执行危险操作: rm -rf /

8.8 测试结果汇总

测试场景 预期结果 实际结果 状态
中风险操作请求 创建审批,状态 pending ✅ 正确 通过
查看待审批列表 返回格式化列表 ✅ 正确 通过
确认审批 执行成功,状态 executed ✅ 正确 通过
查看执行日志 返回完整事件链 ✅ 正确 通过
高风险操作 状态 pending,风险 high ✅ 正确 通过
拒绝审批 状态 rejected,不执行 ✅ 正确 通过
低风险操作 直接执行,无需审批 ✅ 正确 通过
禁止操作 状态 forbidden,直接拒绝 ✅ 正确 通过

9. 安全设计

9.1 认证机制

所有 API 请求需要携带认证 Token:

X-APPROVAL-TOKEN: approval-secret-token-2026

未认证请求返回 401 Unauthorized:

{
    "success": false,
    "error": "Unauthorized"
}

9.2 操作隔离

安全措施 说明
独立进程 审批执行服务以独立进程运行,与云小猫隔离
子进程执行 操作执行通过子进程调用,设置超时限制(60-120秒)
二次校验 危险命令在执行前进行二次模式匹配校验
权限分离 云小猫只有创建审批的权限,执行权限在审批服务

9.3 审计日志

所有审批操作记录到数据库,包含:

  • 审批请求创建时间
  • 请求人信息(ID、名称、渠道)
  • 审批人信息(ID、名称、渠道)
  • 审批决策(通过/拒绝/超时)
  • 执行结果(成功/失败、输出信息)
  • 执行时间

日志保留期限:90 天


10. 部署说明

10.1 服务管理

# 启动审批执行服务
systemctl start approval-executor

# 启动审批状态检查服务
systemctl start approval-checker

# 查看服务状态
systemctl status approval-executor
systemctl status approval-checker

# 查看日志
journalctl -u approval-executor -f
journalctl -u approval-checker -f

10.2 配置文件位置

文件 路径 用途
审批执行服务 /opt/approval-executor/app.py Flask API 服务主程序
Systemd 服务配置 /etc/systemd/system/approval-executor.service 服务启动配置
状态检查器 /opt/approval-executor/approval_checker.py 状态轮询脚本
QQ 审批处理器 /root/.openclaw/skills/approval-handler/approval-handler.py QQ 消息处理脚本
危险指令规范 /root/.openclaw/workspace/dangerous-operations.md 操作分类定义文档
云小猫工作配置 /root/.openclaw/workspace/AGENTS.md 云小猫工作流程配置
云小猫灵魂配置 /root/.openclaw/workspace/SOUL.md 云小猫核心行为定义

10.3 环境变量

# API Token(可在 systemd service 文件中配置)
APPROVAL_API_TOKEN=approval-secret-token-2026

# QQ Bot API 地址
QQ_BOT_API=http://127.0.0.1:5700

# 企业微信 Webhook(可选)
WECOM_BOT_WEBHOOK=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx

11. 总结与展望

11.1 实现成果

本次改造成功实现了以下核心目标:

目标 实现情况
异步审批 审批请求创建后立即返回,云小猫可继续处理其他消息 ✅
自动执行 审批通过后由独立服务自动执行,避免延迟 ✅
完整追溯 审批流程全程记录到数据库,支持审计查询 ✅
安全规范 定义危险指令清单,禁止操作直接拒绝 ✅
QQ 集成 支持通过 QQ 消息查看列表、确认、拒绝审批 ✅

11.2 架构优势对比

对比项 原有架构 新架构
审批等待 阻塞云小猫 不阻塞,异步处理
执行时机 不可控 审批通过立即执行
流程追溯 JSON 文件,不完整 数据库记录,完整事件链
安全性 Agent 直接执行 独立服务执行,多层校验
可用性 等待期间无法聊天 随时可聊天

11.3 后续优化方向

方向 描述
多渠道通知 集成企业微信、飞书、邮件等更多通知渠道
审批流引擎 支持多级审批、条件审批、会签等复杂流程
权限细粒度 基于角色的审批权限控制,不同管理员审批不同风险级别
操作模板 预定义常用操作模板,简化审批流程创建
定时审批 支持定时执行审批通过的操作
Web 管理界面 提供 Web 界面管理审批、查看统计
告警集成 与监控系统集成,自动创建审批请求

附录 A:API 端点完整列表

端点 方法 功能 需要认证
/health GET 健康检查
/api/approval/create POST 创建审批请求
/api/approval/<id> GET 获取审批详情
/api/approval/list GET 列出审批请求
/api/approval/<id>/approve POST 批准并执行
/api/approval/<id>/reject POST 拒绝审批
/api/approval/check-timeout POST 检查超时审批
/api/approval/logs/<id> GET 获取执行日志
/api/approval/poll GET 轮询审批状态
/api/approval/wait/<id> GET 长轮询等待结果
/api/subscriber/list GET 列出订阅者
/api/subscriber/add POST 添加订阅者
/api/subscriber/remove POST 移除订阅者
/api/actions/list GET 操作类型列表

附录 B:数据库表关系图

┌─────────────────────────┐
│   approval_requests     │
├─────────────────────────┤
│ id (PK)                 │
│ action_type             │
│ action_params (JSON)    │
│ risk_level              │
│ status                  │
│ requester_id            │
│ requester_name          │
│ approver_id             │
│ approver_name           │
│ created_at              │
│ approved_at             │
│ executed_at             │
│ timeout_at              │
│ execution_result (JSON) │
└───────────┬─────────────┘
            │
            │ 1:N
            │
┌───────────▼─────────────┐
│ approval_execution_logs │
├─────────────────────────┤
│ id (PK)                 │
│ approval_id (FK)        │
│ event_type              │
│ event_data (JSON)       │
│ operator_id             │
│ operator_name           │
│ created_at              │
└─────────────────────────┘

附录 C:状态流转图

                    ┌─────────────┐
                    │   pending   │
                    │  (等待审批)  │
                    └──────┬──────┘
                           │
           ┌───────────────┼───────────────┐
           │               │               │
           ▼               ▼               ▼
    ┌────────────┐  ┌────────────┐  ┌────────────┐
    │  approved  │  │  rejected  │  │  timeout   │
    │  (已批准)   │  │  (已拒绝)   │  │  (已超时)   │
    └─────┬──────┘  └────────────┘  └────────────┘
          │
          ▼
    ┌────────────┐
    │  executed  │
    │  (已执行)   │
    └─────┬──────┘
          │
          ▼
    ┌────────────┐
    │   failed   │
    │  (执行失败) │
    └────────────┘

文档版本: 1.0
创建日期: 2026-04-01
作者: CodeBuddy
适用对象: 运维工程师、系统架构师、后端开发者


评论