Approval Engine approval plugin — Feishu card-based human-in-the-loop approval workflow engine
Project description
Hermes Approval Engine v2
飞书卡片审批工作流引擎 — 多容器编排、风险分级、人工审批、审计日志一体化。
Feishu (Lark) card-based human-in-the-loop approval workflow engine. Multi-container orchestration, risk classification, manual approval, and full audit trail.
项目概述 / Overview
Hermes Approval Engine V2 是一个基于 飞书消息卡片 的人机协同审批工作流引擎。它采用 Supervisor + Sub-Agent 多容器架构,通过 SQLite WAL 持久化、状态机校验、三级风险分级、JSONL 审计日志等能力,提供安全可控的命令审批和自动化执行。
典型场景: 小美(操作 Agent)提交命令 → 小强(审批 Supervisor)决策 → 鹏老板(管理员)终审高风险操作 → 执行并归档。
V2 核心升级: 零外部依赖(stdlib-only)、SQLite WAL 连接池、双重幂等、6 套飞书卡片模板、Docker Compose 多容器编排。
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ Docker Host │
│ │
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ Supervisor Container │ │ Sub-agent Containers │ │
│ │ (hermes-supervisor) │ │ │ │
│ │ │ │ ┌───────────────────────┐ │ │
│ │ ┌───────────────────────┐ │ │ │ finance-worker │ │ │
│ │ │ HTTP API Server │───┼───┼──│ (财务数据分析) │ │ │
│ │ │ (port 8080) │ │ │ └───────────────────────┘ │ │
│ │ └───────────────────────┘ │ │ │ │
│ │ │ │ │ ┌───────────────────────┐ │ │
│ │ ┌──────▼─────────────────┐ │ │ │ life-assistant │ │ │
│ │ │ Approval Engine Core │ │ │ │ (生活学习助理) │ │ │
│ │ │ ┌───────────────────┐ │ │ │ └───────────────────────┘ │ │
│ │ │ │ SQLite (WAL+Pool) │ │ │ │ │ │
│ │ │ │ Risk Classifier │ │ │ │ ┌───────────────────────┐ │ │
│ │ │ │ State Machine │ │ │ │ │ it-ops-worker │ │ │
│ │ │ │ Audit Logger │ │ │ │ │ (IT运维设备) │ │ │
│ │ │ │ Card Builder (×6) │ │ │ │ └───────────────────────┘ │ │
│ │ │ └───────────────────┘ │ │ │ │ │
│ │ └────────────────────────┘ │ └─────────────────────────────┘ │
│ │ │ │ │
│ │ ▲ │ │ Poll loop │
│ │ │ Feishu Card API │ ▼ (kanban/HTTP) │
│ │ ┌──────┴──────────┐ │ ┌────────────────────┐ │
│ │ │ Feishu (Lark) │◀───────┼──▶│ Shared Volume │ │
│ │ │ Message Cards │ │ │ /opt/share │ │
│ │ └─────────────────┘ │ └────────────────────┘ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
ASCII 架构简图
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Sub-Agent │◀───▶│ Supervisor │◀───▶│ Feishu Cards │
│ (operators) │ │ HTTP API:8080 │ │ (approval UI) │
└──────────────┘ └────────┬─────────┘ └──────────────────┘
│
┌────────▼─────────┐
│ approval_engine │
│ ┌─────────────┐ │
│ │ SQLite (WAL)│ │
│ │ Risk Engine │ │
│ │ State Mach. │ │
│ │ Audit Log │ │
│ │ 6 Templates │ │
│ └─────────────┘ │
└──────────────────┘
Features / 功能特性
| Category | Feature | Description | 说明 |
|---|---|---|---|
| Persistence | SQLite WAL + Pool | 64 连接池,WAL 模式,双重幂等,72h 自动过期清理 | 高并发读写不阻塞 |
| Risk | 3-Level Classification | 自动识别破坏性操作 + 可信网段降级 + SQL 无 WHERE 检测 | low / medium / high |
| State | Finite State Machine | 8 状态 + 12 条合法转换规则,非法转换自动拒绝 | 保证状态一致性 |
| Feishu | 6 Card Templates | 待审批 / 已通过 / 已驳回 / 修改重提 / 人工终审 / 归档 | 完整审批生命周期 |
| Security | Field Masking | API Key, Token, Password, Secret 自动脱敏 | 审计日志安全 |
| Audit | JSONL Full Trail | 每条操作变更都有 JSONL 格式可追溯记录 | 合规审计 |
| Timeout | Auto Reject | 1h 告警 + 6h 自动驳回,防止任务卡死 | 兜底安全 |
| Whitelist | Hot-reload | 运行时动态更新操作人白名单 | 灵活权限控制 |
| Deploy | Multi-Container | Supervisor + 3 Sub-agents, Docker Compose 编排 | 开箱即用 |
Quick Start / 快速开始
Installation
pip install hermes-approval-engine
Or install from source (editable):
git clone git@github.com:jiayoupengpeng/hermes-plugin-approval-v2.git
cd hermes-plugin-approval-v2
pip install -e .
Python Usage
from approval_engine import (
create_task, get_task, update_task,
build_approval_card, classify_risk,
TaskStatus, RISK_LOW, RISK_HIGH,
)
# 1. Create an approval task
task = create_task(
command="systemctl restart nginx",
description="Restart Nginx service",
source_ip="10.0.0.52",
)
print(f"Task ID: {task['task_id']}, Risk: {task['risk_level']}")
# Output: Task ID: TASK-0001, Risk: low
# 2. Risk classification
risk, labels = classify_risk("rm -rf /data", source_ip="10.0.0.52")
assert risk == RISK_HIGH
assert "destructive_command" in labels
# 3. Update status (approve)
updated = update_task(task['task_id'],
status=TaskStatus.APPROVED,
operator_name="Xiaoqiang",
)
print(f"Status: {updated['status']}") # approved
# 4. Build Feishu card
card = build_approval_card(task,
approve_open_id="ou_approver",
reject_open_id="ou_rejector",
)
# 5. List pending tasks
pending = list_pending_tasks()
print(f"Pending tasks: {len(pending)}")
# 6. Clean expired tasks (older than 72h)
cleaned = clean_expired_tasks()
print(f"Cleaned {cleaned} expired tasks")
Risk Classification Examples
from approval_engine import classify_risk
# High risk — destructive command
risk, reasons = classify_risk("rm -rf /data", source_ip="10.0.0.5")
assert risk == "high"
assert "destructive_command" in reasons
# High risk — cross-network request
risk, reasons = classify_risk("ls -la", source_ip="8.8.8.8")
assert risk == "high"
assert "cross_network" in reasons
# Low risk — safe command from trusted network
risk, reasons = classify_risk("df -h", source_ip="10.0.0.10")
assert risk == "low"
assert reasons == []
Docker Deployment / Docker 部署
Prerequisites
- Docker & Docker Compose v2
- Feishu App (create at open.feishu.cn)
- Network: macvlan driver configured
Step 1: Configure Environment
cd docker
cp .env.template ../.env
# Edit .env with your Feishu credentials and network settings
vim ../.env
Key variables in .env:
# Feishu credentials
FEISHU_APP_ID=cli_your_app_id
FEISHU_APP_SECRET=your_app_secret
# Personnel
FEISHU_ADMIN_ID=ou_admin_open_id # 鹏老板
COMMANDER_OPEN_ID=ou_commander_id # 小强
EXECUTOR_OPEN_ID=ou_executor_id # 小美
# Network (adjust to your environment)
MACVLAN_SUBNET=10.0.0.0/24
SUPERVISOR_IP=10.0.0.100
Step 2: Deploy Supervisor
cd docker
docker compose --env-file ../.env up -d
This starts the Supervisor container with:
- HTTP API on port 8080
- SQLite database at
/opt/share/data/ - Feishu card integration
- Health check at
/health
Step 3: Deploy Sub-agents
Build the sub-agent base image first:
docker build -t hermes-subagent:latest -f docker/subagent.Dockerfile .
Then deploy all 3 sub-agents:
docker compose -f docker/subagent-compose.yml --env-file .env up -d
Or deploy a specific sub-agent:
docker compose -f docker/subagent-compose.yml --env-file .env --profile finance up -d
Container Architecture
| Container | Role | IP | Purpose |
|---|---|---|---|
hermes-supervisor |
审批主管 | 10.0.0.100 |
API server + engine + feishu |
hermes-finance-worker |
财务数据分析 | 10.0.0.110 |
Finance domain tasks |
hermes-life-assistant |
生活学习助理 | 10.0.0.111 |
Life domain tasks |
hermes-it-ops-worker |
IT 运维设备 | 10.0.0.112 |
IT ops domain tasks |
Verification
# Check Supervisor health
curl http://localhost:8080/health
# Check sub-agent logs
docker logs hermes-finance-worker
API Quick Reference / API 速查表
| Method | Path | Description |
|---|---|---|
GET |
/health |
健康检查 |
POST |
/api/tasks |
创建审批任务 |
GET |
/api/tasks |
任务列表(支持 ?status= 过滤) |
GET |
/api/tasks/:id |
任务详情 |
POST |
/api/tasks/:id |
更新任务状态 |
POST |
/api/tasks/:id/dispatch |
下发任务至子 Agent |
POST |
/api/tasks/:id/verify |
验证执行结果 |
POST |
/api/webhook/feishu |
飞书卡片回调 |
完整 API 参考见 docs/api.md。
Development Guide / 开发指南
Project Structure
hermes-plugin-approval-v2/
├── approval_engine/ # 核心引擎包
│ ├── __init__.py # 公开 API 导出 + ApprovalEngine 类
│ ├── __main__.py # Supervisor HTTP 服务入口
│ └── approval_engine.py # 核心逻辑:CRUD / 状态机 / 风险 / 卡片 / 审计
├── agent/
│ └── poll_loop.py # 子 Agent 轮询循环
├── docker/
│ ├── Dockerfile # Supervisor 容器镜像
│ ├── subagent.Dockerfile # 子 Agent 基础镜像
│ ├── docker-compose.yml # Supervisor Docker Compose
│ └── subagent-compose.yml # 子 Agent Docker Compose
├── tests/
│ ├── test_approval_engine_smoke.py # 冒烟测试(10 项)
│ └── test_phase1_selfcheck.py # Phase 1 自测(9 项)
├── examples/
│ ├── run_trial_scenario1.py # 多任务并发 + 跨容器推送
│ ├── run_trial_scenario2.py # 场景二
│ └── run_trial_scenario3.py # 场景三
├── docs/
│ └── api.md # API 参考文档
├── .github/workflows/
│ └── test.yml # GitHub Actions CI
├── .env.template # 环境变量模板
├── pyproject.toml # 项目配置
└── README.md # 本文档
Running Tests
# Install package (editable)
pip install -e .
# Run smoke tests
python tests/test_approval_engine_smoke.py
# Run phase 1 self-check
python tests/test_phase1_selfcheck.py
# Run with pytest
cd tests
python -m pytest test_approval_engine_smoke.py -v
CI Pipeline
GitHub Actions 矩阵测试(Python 3.10-3.13),自动执行:
pip install -e .(editable install)- 包导入验证 (
from approval_engine import *) - Phase 1 自测
- 冒烟测试
- HTTP 服务启动 +
/health端点验证
CI 配置见 .github/workflows/test.yml。
Local Development
# Start Supervisor locally
APPROVAL_HOME=/tmp/hermes-dev python -m approval_engine
# Or with custom port
SUPERVISOR_PORT=9090 python -m approval_engine
# Verify health
curl http://localhost:8080/health
Environment Variables
| Variable | Default | Description |
|---|---|---|
SUPERVISOR_HOST |
0.0.0.0 |
HTTP 监听地址 |
SUPERVISOR_PORT |
8080 |
HTTP 端口 |
APPROVAL_HOME |
~/.hermes |
数据目录 |
API_SERVER_KEY |
(empty) | API 鉴权密钥 |
TRUSTED_NETWORK |
10.0.0.0/24 |
可信网段 CIDR |
LOG_LEVEL |
INFO |
日志级别 |
FEISHU_APP_ID |
— | 飞书应用 ID |
FEISHU_APP_SECRET |
— | 飞书应用密钥 |
APPROVAL_WHITELIST |
(empty) | 操作人 open_id 列表(逗号分隔) |
License
MIT License — see LICENSE.
Links
- Repository: github.com/jiayoupengpeng/hermes-plugin-approval-v2
- API Docs: docs/api.md
- Issues: github.com/jiayoupengpeng/hermes-plugin-approval-v2/issues
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_approval_engine-1.0.0.tar.gz.
File metadata
- Download URL: hermes_approval_engine-1.0.0.tar.gz
- Upload date:
- Size: 90.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
124c1cbffc4a2d3779b0fa85cbd84d5a5b18c1c7819420e9028124dcc3fcf2d6
|
|
| MD5 |
95b66a74ab6f9b5d83fd931cc381d21e
|
|
| BLAKE2b-256 |
7fa3f315347ae5374b2a9db0aa83b54a1ad76c8f06f034274d17fdc5d54ce4fe
|
Provenance
The following attestation bundles were made for hermes_approval_engine-1.0.0.tar.gz:
Publisher:
publish.yml on jiayoupengpeng/hermes-plugin-approval-v2
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_approval_engine-1.0.0.tar.gz -
Subject digest:
124c1cbffc4a2d3779b0fa85cbd84d5a5b18c1c7819420e9028124dcc3fcf2d6 - Sigstore transparency entry: 1961861745
- Sigstore integration time:
-
Permalink:
jiayoupengpeng/hermes-plugin-approval-v2@372e720e7e3d1aa627f6bf02b150c15c823e3ec4 -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/jiayoupengpeng
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@372e720e7e3d1aa627f6bf02b150c15c823e3ec4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hermes_approval_engine-1.0.0-py3-none-any.whl.
File metadata
- Download URL: hermes_approval_engine-1.0.0-py3-none-any.whl
- Upload date:
- Size: 75.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1da9e1c98ec17268e5d0a68ee451556cdf79ea99610b85967a26a1f7f0e8747
|
|
| MD5 |
e28e159cff699cc2da4e7678fd1b9bd7
|
|
| BLAKE2b-256 |
95b4016c858628740dd773dc5c00087177df146143d6eea830c4894f56354b5b
|
Provenance
The following attestation bundles were made for hermes_approval_engine-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on jiayoupengpeng/hermes-plugin-approval-v2
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_approval_engine-1.0.0-py3-none-any.whl -
Subject digest:
e1da9e1c98ec17268e5d0a68ee451556cdf79ea99610b85967a26a1f7f0e8747 - Sigstore transparency entry: 1961861801
- Sigstore integration time:
-
Permalink:
jiayoupengpeng/hermes-plugin-approval-v2@372e720e7e3d1aa627f6bf02b150c15c823e3ec4 -
Branch / Tag:
refs/tags/v2.0.0 - Owner: https://github.com/jiayoupengpeng
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@372e720e7e3d1aa627f6bf02b150c15c823e3ec4 -
Trigger Event:
push
-
Statement type: