v1.4: 多租户开通 + 安全性重构 + 数据脱敏

新增:
- provision_server.py HTTP API 服务 (Bottle, 端口 5566)
- 状态持久化 (JSON, 每30秒保存, 1小时内可恢复)
- 会议室模式 (开发团队 Inbox 多 AI 路由)
- supervisor 托管, SIGTERM 优雅退出
- PUBSUB_TOKEN 三级 fallback

修复:
- 所有硬编码凭证清除 (CW_EMAIL/CW_PASSWORD 无 fallback)
- 双重 WebSocket 重连
- 内存泄漏 (无界 Set 清理)
- INBOX_CONFIG 兜底 (skip+log 不崩溃)
- PID 文件竞争, Metrics 热路径优化
- 幂等性正确实现 (存真实响应含 HTTP 状态码)

安全:
- 完整数据脱敏 (无 URL/邮箱/密码/token 硬编码)
- .env.example / chatwoot_auth.example.json / inboxes.example.json
This commit is contained in:
Chatwoot AI Agent Dev
2026-06-04 12:56:11 +00:00
parent 504b9b2e40
commit d0b20a0e14
17 changed files with 1375 additions and 868 deletions
+169 -92
View File
@@ -1,119 +1,196 @@
# Chatwoot AI Agent — Multi-Inbox Intelligent Customer Service
# Chatwoot AI Agent — 多租户 AI 自动回复系统
> A multi-tenant AI customer service platform built on self-hosted Chatwoot.
> Single WebSocket agent routes conversations to different AI agents per inbox — with seamless AI ↔ Human handoff.
基于 Chatwoot ActionCable WebSocket 的实时 AI 客服系统,支持多租户、人工/AI 无缝切换、自动开通。
## Architecture
## 架构概览
```
Customer (Web Widget / API)
Chatwoot Self-Hosted (wss://chatwoot.275763.xyz/cable)
WS Agent (chatwoot_ws_agent.py)
│ reads inboxes.json → routes by inbox_id
── Inbox 1 → sourcing-agent (EN, 采购代理)
├── Inbox 7 → halo-blog-agent (中文, 安防弱电顾问)
└── Inbox 8 → amazon-agent (EN, Amazon 客服)
┌─────────────────────────────────────────────────────┐
│ QwenPaw Agent
│ ┌─────────────────────┐ ┌──────────────────────┐ │
│ │ WS Agent │ │ Provision Server │ │
│ │ (WebSocket 长连接) │ │ (HTTP API :5566)
│ │ • 接收实时消息 │ │ • 自动开通租户 │ │
│ │ • AI 自动回复 │ │ • 创建 Inbox/Team │ │
│ │ • 人工/AI 切换 │ │ • 创建 AI Agent │ │
│ │ • 多 Inbox 路由 │ │ • 写入路由配置 │
─────────┬─────────────┘ └──────────┬───────────┘ │
│ │ │ │
└────────────┼───────────────────────────┼───────────────┘
│ WebSocket (wss) │ HTTP API
▼ ▼
┌────────────────┐ ┌──────────────────┐
│ Chatwoot │ │ FastAdmin │
│ (自托管客服系统)│◄───────│ (PHP 管理后台) │
└────────────────┘ └──────────────────┘
```
## Features
## 组件说明
| Feature | Description |
|:--------|:-----------|
| **24/7 AI Auto-Reply** | AI responds instantly, acts as human agent (uses User session, not AgentBot) |
| **AI ↔ Human Handoff** | Human replies → AI backs off. Human leaves → AI resumes after 15min timeout |
| **Multi-Inbox Routing** | Single WS agent serves multiple sites/inboxes, each with its own AI agent & knowledge base |
| **Hot-Reload Config** | `inboxes.json` — add/edit inboxes without restarting the agent (30s polling) |
| **Auto-Provision** | `provision.py` — one command to create Chatwoot inbox + AI agent + routing config |
| **Health & Metrics** | CLI: `--health`, `--metrics`, `--ws-status`, `--list-inboxes`, `--inbox-stats` |
| **Default Fallback** | Hardcoded `DEFAULT_INBOX_CONFIG` ensures demo sites work even without `inboxes.json` |
| **Private Notes** | AI auto-generates Chinese notes for human agents on each reply |
| **Zero Monthly Fee** | Self-hosted Chatwoot + QwenPaw, no SaaS subscription |
### 1. WS Agent (`chatwoot_ws_agent.py`)
## Routing Matrix
WebSocket 长连接实时 AI 客服,**1147 行**。
| Inbox | Site | Agent | Lang | Role |
|:-----:|:-----|:------|:----:|:-----|
| 1 | greatqiu.cn | sourcing-agent | EN | Global Sourcing Advisor |
| 7 | shopqiu.com | halo-blog-agent | 中文 | 安防弱电技术顾问 |
| 8 | Amazon (API) | amazon-agent | EN | Amazon Customer Service |
**核心技术:**
- **ActionCable WebSocket** — 通过 Chatwoot RoomChannel 实时接收消息事件,零轮询
- **多 Inbox 路由** — 根据 `inbox_id` 分发到不同 AI Agent,支持 30+ 租户并发
- **人工 ↔ AI 无缝切换** — 通过消息 ID 追踪 (`ai_sent_msg_ids`) + 对话 Pending 机制 (`_ai_pending_convs`) 精准区分 AI 回复和人工回复,不误判
- **15 分钟人工超时** — 人工回复后 AI 自动回避;超过 15 分钟无人工回复,AI 自动接回
- **会议模式** — 三人实时通信(开发团队 Inbox),消息同时转发多个 AI,`[SKIP]` 机制避免重复回复
- **状态持久化** — 每 30 秒保存到 JSON 文件,重启/崩溃后自动恢复(1 小时内快照安全兜底)
- **热加载配置** — `inboxes.json` 文件变化自动检测,无需重启进程
- **Metrics 监控** — 记录 WebSocket 连接状态、每个 Inbox 的 AI 回复成功率和响应时间
- **Graceful Shutdown** — SIGTERM 信号处理器,退出时保存状态和指标
- **内存保护** — `ai_sent_msg_ids``processed_ids` 定期清理,上限 10000 条
## Quick Start
**AI 回复流程:**
```
客户发消息 → WS 接收 → is_human_active? → 跳过/回复
call_qwenpaw_ai() → subprocess.qwenpaw agents chat
send_reply() → Chatwoot API (以 User 身份发送)
metrics.record_reply() 记录性能指标
```
### 2. Provision Server (`provision_server.py`)
HTTP API 服务,**555 行**,用于自动开通租户。
**端点:**
| 路径 | 方法 | 说明 |
|------|------|------|
| `/health` | GET | 健康检查 |
| `/provision` | POST | 创建租户(Inbox + 团队 + Agent + 路由配置) |
| `/suspend` | POST | 暂停租户(改名 + 清 Website URL + 关闭欢迎语) |
| `/activate` | POST | 恢复租户(恢复原名 + 重设 Website URL |
**安全性:**
- 所有 POST 端点需 `X-API-Key` 头部认证
- 幂等性支持:`Idempotency-Key` 头部,5 分钟 TTL,返回真实响应(含正确 HTTP 状态码)
- 输入验证:name/domain/email/channel 格式校验
- Session 管理:自动检测 `expiry` 过期,提前 1 小时自动续期
- Chatwoot API 401 自动重试(3 次)
**幂等性机制:**
```python
# 使用字典存储 {key: response} + 线程锁,避免竞态
# 5 分钟自动过期
_IDEMPOTENT_RESULTS: dict[str, dict] = {}
_IDEMPOTENT_LOCK = threading.Lock()
_IDEMPOTENT_TTL = 300
```
### 3. 控制脚本 (`chatwoot_ws_ctl.sh`)
进程管理脚本,包含 PID 验证(`/proc/PID/cmdline` 防复用)。
## 消息路由配置 (`inboxes.json`)
```json
{
"1": {
"name": "GreatQiu",
"type": "web_widget",
"target_agent": "sourcing-agent",
"system_prompt": "你是专业的外贸采购代理...",
"prompt_template": "客户 '{sender_name}' 发来消息:\n{customer_msg}\n\n请回复..."
},
"7": {
"name": "HALO Blog",
"type": "web_widget",
"target_agent": "halo-blog-agent",
"system_prompt": "你是安防弱电专家...",
"prompt_template": "..."
}
}
```
## 人工/AI 切换机制详解
### 核心原理
AI 使用 **User Session** 发消息(不让客户察觉是 AI),通过追踪消息 ID 区分:
1. **AI 回复追踪**`track_sent_message(msg_id)` 将 ID 存入 `ai_sent_msg_ids`
2. **竞态防护**`_ai_pending_convs` 在 API 调用前标记对话为 Pending`try/finally` 保证清理
3. **人工检测**WS 事件到达时,检查 `is_ai_sent_message(msg_id)``conv_id in _ai_pending_convs`,任一命中则忽略
4. **超时恢复**:人工最后回复后 15 分钟无响应 → AI 自动接回
5. **状态恢复**:客户将对话改为 Pending → AI 立即恢复
```
时间线:
客户发消息 ──→ AI 回复 ──→ 人工介入 ──→ 人工离开 ──→ 15分钟超时 ──→ AI 接回
↑ ↑ ↑
ai_sent_msg_ids mark_human_active() human_active 过期
加入 conv_id conv_id 加入 conv_id 被清理
```
## 快速开始
```bash
git clone https://github.com/hanmolabiqiu/chatwoot-ai-agent.git
cd chatwoot-ai-agent
# 1. 安装依赖
pip install -r requirements.txt
cp .env.example .env
# Edit .env with your Chatwoot API credentials
python3 chatwoot_ws_agent.py
# 2. 配置环境变量(详见 .env.example
export CW_BASE=https://your-chatwoot.com
export CW_EMAIL=admin@example.com
export CW_PASSWORD=your-password
# 3. 登录 Chatwoot 获取 session
python3 chatwoot_ws_agent.py --renew
# 4. 启动 WS Agent
python3 chatwoot_ws_agent.py &
# 5. (可选)启动 Provision Server
python3 provision_server.py
```
### CLI Commands
## 环境变量
```bash
python3 chatwoot_ws_agent.py # Start the WS agent
python3 chatwoot_ws_agent.py --health # Health check (JSON)
python3 chatwoot_ws_agent.py --metrics # Performance metrics (JSON)
python3 chatwoot_ws_agent.py --ws-status # WebSocket connection status
python3 chatwoot_ws_agent.py --list-inboxes # List configured inboxes
python3 chatwoot_ws_agent.py --inbox-stats # Formatted inbox statistics table
python3 chatwoot_ws_agent.py --inbox-stats-csv # Stats as CSV
python3 chatwoot_ws_agent.py --inbox-stats-one-line # One-line summary
python3 chatwoot_ws_agent.py --renew # Force session renew
python3 chatwoot_ws_agent.py --test-ws # Test WebSocket connection
```
### WS Agent 必需
| 变量 | 说明 |
|------|------|
| `CW_BASE` | Chatwoot 服务器地址 |
| `CW_EMAIL` | 管理员账号邮箱 |
| `CW_PASSWORD` | 管理员密码 |
| `CW_PUBSUB_TOKEN` | Chatwoot ActionCable pubsub token(首次运行自动获取) |
### Add a New Tenant
### Provision Server 必需
| 变量 | 说明 |
|------|------|
| `CW_BASE` | Chatwoot 服务器地址 |
| `CW_ADMIN_EMAIL` | 管理员邮箱 |
| `CW_ADMIN_PASSWORD` | 管理员密码 |
| `CW_PLATFORM_TOKEN` | Chatwoot Platform API Token |
| `CHATHUB_API_KEY` | API 密钥(默认: chathub-default-key-change-me |
```bash
python3 provision.py --name "NewSite" --type web_widget --lang en
# Output: inbox ID, agent ID, embed code
```
## File Structure
## 文件结构
```
chatwoot-ai-agent/
├── chatwoot_ws_agent.py # Core engine — WS agent with multi-inbox routing
├── inboxes.json # Hot-reloadable inbox routing config
├── provision.py # Auto-provision new tenants
├── CHANGELOG.md # Version history (v1.0 → v1.3)
├── knowledge-base.md # Knowledge base for halo-blog-agent
├── SOUL-halo-blog-agent.md # AI personality — 安防弱电 (Chinese)
├── SOUL-amazon-agent.md # AI personality — Amazon CS (English)
├── PROFILE-amazon-agent.md # Amazon agent profile
├── .env.example # Environment config template
├── requirements.txt # Python dependencies
├── README.md # This file
├── chatwoot_ws_agent.py # WebSocket AI Agent(核心,1147 行)
├── provision_server.py # HTTP 开通服务(555 行)
├── chatwoot_ws_ctl.sh # 进程管理脚本
├── start_agent.sh # 启动脚本(旧,推荐用 supervisor
├── .env.example # 环境变量模板
├── requirements.txt # Python 依赖
├── chatwoot_auth.example.json # Session 认证文件模板
├── inboxes.example.json # 路由配置模板
└── .gitignore
```
## Version History
## 版本历史
| Ver | Date | Highlights |
|:----|:-----|:-----------|
| v1.3 | 2026-06-03 | Metrics monitoring, health check CLI, default config fallback, inbox-stats cleanup |
| v1.2 | 2026-06-02 | Hot-reload `inboxes.json`, `provision.py` auto-provision |
| v1.1 | 2026-06-02 | Amazon API inbox, API inbox human detection fix |
| v1.0 | 2026-06-01 | Initial: dual inbox routing, AI↔Human handoff, knowledge base |
| 版本 | 说明 |
|------|------|
| v1.0 | 初始 WebSocket 版本,支持基本 AI 回复 |
| v1.1 | Amazon API 集成,人工/AI 切换修复 |
| v1.2 | 热加载配置架构 |
| v1.3 | 代码清理优化,Metrics 监控 |
| v1.4 | 多租户架构,Provision Server,状态持久化,安全性修复 |
## Roadmap
## 许可证
- [x] Multi-inbox routing (GreatQiu + HALO + Amazon)
- [x] Hot-reload config (`inboxes.json`)
- [x] Auto-provision script (`provision.py`)
- [x] Health check & metrics monitoring
- [ ] FastAdmin management backend (ChatHub plugin)
- [ ] Tenant self-service registration + payment
- [ ] WhatsApp Business API channel
- [ ] Chatwoot Captain AI integration
- [ ] Automated backup & alerting
## License
MIT
MIT License