# 🐈 echobot - 轻量级 AI 助手

一个轻量级的个人 AI 助手框架，支持多 LLM 提供商、多平台集成。

## 特性

- 🪶 **超轻量** - 核心约 3000 行代码
- ⚡ **快速启动** - 即开即用
- 🔌 **多 LLM 支持** - OpenRouter、Anthropic、OpenAI、MiniMax 等
- 💬 **多平台** - Telegram、WebUI
- 🛠️ **工具调用** - 文件操作、Shell 命令、Web 搜索等
- 🔒 **边界保护** - 文件与命令工具默认限制在工作区内执行
- ⏰ **定时任务** - 周期性任务执行
- 💾 **会话管理** - 持久化对话历史
- 🤖 **多 Agent 协作** - 多个 Agent 协同工作，支持 Agent 间调用

---

## 🚀 5分钟快速开始

### 步骤 1: 创建 Telegram Bot

1. 搜索 `@BotFather` 并发送 `/newbot`
2. 按提示设置名称和用户名
3. 复制 Bot Token

### 步骤 2: 安装

```bash
# 克隆项目
git.com/your-repo/echobot.git
cd echobot clone https://github

# 或使用安装脚本
chmod +x install.sh
./install.sh
```

### 步骤 3: 配置

```bash
# 复制并编辑配置
cp config/agents.example.json ~/.echobot/agents.json
nano ~/.echobot/agents.json  # 填入你的 Bot Token
```

或使用交互式向导：
```bash
echobot agents init
```

### 步骤 4: 设置 API Key

编辑 `~/.echobot/.env` 或设置环境变量：
```bash
export NANOBOT__ANTHROPIC__API_KEY=sk-ant-xxx
# 或 DeepSeek
export NANOBOT__DEEPSEEK__API_KEY=sk-xxx
```

### 步骤 5: 启动

```bash
# 单 Agent 模式
echobot gateway

# 多 Agent 模式
echobot gateway --multi
```

### Docker 部署

```bash
# 1. 复制配置
cp config/agents.example.json config/agents.json
# 2. 编辑 config/agents.json 填入你的 Bot Token
# 3. 创建 .env 文件并设置 API Key
# 4. 启动
docker-compose up -d
```

---

## 详细配置

### 1. 安装（高级）

```bash
uv pip install -e .
```

### 2. 配置

```json
{
  "agents": {
    "defaults": {
      "model": "MiniMax-M2.1"
    }
  },
  "providers": {
    "openai": {
      "apiKey": "sk-xxx",
      "apiBase": "https://api.minimaxi.com/v1"
    }
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "YOUR_BOT_TOKEN",
      "allowFrom": ["YOUR_USER_ID"]
    },
    "webui": {
      "enabled": true,
      "token": "YOUR_WEBUI_TOKEN",
      "allowRoles": ["orchestrator", "coder"]
    }
  }
}
```

> 安全建议：请不要把 API Key 写入仓库文件，统一使用本地配置或环境变量。

### 3. 启动

```bash
# 启动 Gateway（默认后台运行，支持 Telegram）
echobot gateway

# 前台运行（用于调试）
echobot gateway --foreground --verbose

# 后台运行并启用 WebUI
echobot gateway --webui --webui-port 8000
```

后台模式会输出 `PID`、日志路径和 `PID file`。可用以下命令查看/停止：

```bash
# 查看日志
tail -f ~/.echobot/logs/gateway.log

# 停止默认实例后台进程
echobot gateway --stop

# 停止指定实例后台进程
echobot gateway --instance admin --stop
```

### 4. 使用

```bash
# 发送单条消息
echobot agent -m "你好！"

# 交互模式
echobot agent
```

## 架构

```
echobot/
├── agent/          # 🧠 核心 Agent 逻辑
│   ├── loop.py    #    Agent 循环（LLM ↔ 工具执行）
│   ├── context.py #    上下文管理
│   ├── memory.py  #    持久化记忆
│   └── tools/     #    工具集
├── channels/       # 💬 平台集成
│   └── telegram/   #    Telegram Bot
├── webui/         # 🌐 Web 界面（FastAPI + HTMX）
├── bus/           # 🚌 消息总线
├── cron/          # ⏰ 定时任务
├── providers/     # 🤖 LLM 提供商
├── session/       # 💬 会话管理
├── config/        # ⚙️ 配置
└── cli/           # 🖥️ 命令行
```

## WebUI

启动 Gateway 时添加 `--webui` 参数：

```bash
echobot gateway --webui --webui-port 8000
```

然后访问 http://localhost:8000

### WebUI API（Gateway 内置）

当 Gateway 运行时，会挂载以下接口：

- `POST /api/webui/chat` - 发送聊天消息
- `GET /api/webui/health` - 健康检查
- `GET /api/webui/status` - WebUI 开关状态
- `GET /api/webui/roles` - 获取可用角色（可按 allowRoles 过滤）
- `POST /api/webui/clear?session_id=...` - 清空指定会话历史
- `GET /api/webui/approvals/pending` - 查看待审批工具调用
- `POST /api/webui/approvals/{request_id}/approve` - 通过审批
- `POST /api/webui/approvals/{request_id}/reject` - 拒绝审批
- `GET /api/webui/webhooks/subscriptions` - 列出 webhook 订阅
- `POST /api/webui/webhooks/subscriptions` - 新建 webhook 订阅
- `DELETE /api/webui/webhooks/subscriptions/{id}` - 删除 webhook 订阅
- `POST /api/webui/webhooks/inbound` - 接收入站 webhook（签名校验）

> 入站 webhook 需要配置环境变量 `ECHOBOT_WEBHOOK_SECRET` 用于验签。
> 若配置了 `channels.webui.token`（或环境变量 `ECHOBOT_WEBUI_TOKEN`），除 `/health` 与入站 webhook 外需携带 `Authorization: Bearer <token>` 或 `X-Echobot-Token`。

### 安全审批与上下文压缩配置（可选）

可在 `~/.echobot/config.json` 中配置：

```json
{
  "agents": {
    "defaults": {
      "approvalTtlSeconds": 900,
      "approvalRequiredTools": ["exec", "write_file", "edit_file", "run_skill_script"],
      "deniedExecPatterns": [
        "(^|[;&|])\\s*rm\\s+-rf\\s+/\\s*($|[;&|])",
        "curl\\s+[^|]*\\|\\s*(sh|bash)"
      ],
      "contextCompressionEnabled": true,
      "contextHistoryMaxMessages": 40,
      "contextKeepRecentMessages": 16,
      "contextSummaryMaxChars": 2000,
      "webhookSecret": ""
    }
  }
}
```

说明：
- `approvalRequiredTools` 设为 `[]` 可关闭“工具级审批”（仍可通过 `deniedExecPatterns` 做硬阻断）。
- `deniedExecPatterns` 支持正则，命中后直接拒绝，不进入审批队列。
- `webhookSecret` 可直接配置在 `config.json`；若留空会回退读取环境变量 `ECHOBOT_WEBHOOK_SECRET`。
- `run_skill_script` 是技能脚本执行工具，默认纳入审批列表（可按需移除以实现全自动）。

### 技能脚本自动执行说明

`echobot` 新增工具：`run_skill_script`，用于执行技能目录下的脚本：
- 工作区技能：`<workspace>/skills/<skill_name>/scripts/...`
- 内置技能：`echobot/skills/<skill_name>/scripts/...`

安全约束：
- 仅允许执行 `scripts/` 子目录内文件（禁止越界路径）。
- 支持 `.py` / `.sh` / `.js`（或可执行文件）。

示例（对话触发）：
- “请用 xlsx 技能脚本运行 recalc.py，参数为 report.xlsx”
- 模型会调用：
  - `skill_name="xlsx"`
  - `script="recalc.py"`
  - `args=["report.xlsx"]`

### 审批链路快速示例

1) 触发一个可能需要审批的请求（示例消息中明确要求执行命令）：

```bash
curl -s -X POST http://localhost:18790/api/webui/chat \
  -H "content-type: application/json" \
  -H "Authorization: Bearer YOUR_WEBUI_TOKEN" \
  -d '{"message":"请执行 `ls -la` 并告诉我结果","session_id":"webui:demo","role":"coder"}'
```

2) 查看待审批列表并拿到 `request_id`：

```bash
curl -s http://localhost:18790/api/webui/approvals/pending \
  -H "Authorization: Bearer YOUR_WEBUI_TOKEN"
```

3) 通过审批（将 `<request_id>` 替换为实际值）：

```bash
curl -s -X POST "http://localhost:18790/api/webui/approvals/<request_id>/approve" \
  -H "content-type: application/json" \
  -H "Authorization: Bearer YOUR_WEBUI_TOKEN" \
  -d '{"approver":"ops-admin"}'
```

4) 重新发送同一请求，Agent 会消费已批准令牌并继续执行：

```bash
curl -s -X POST http://localhost:18790/api/webui/chat \
  -H "content-type: application/json" \
  -H "Authorization: Bearer YOUR_WEBUI_TOKEN" \
  -d '{"message":"请再次执行 `ls -la` 并告诉我结果","session_id":"webui:demo","role":"coder"}'
```

### Webhook 订阅管理示例

新增订阅（监听工具执行前后事件）：

```bash
curl -s -X POST http://localhost:18790/api/webui/webhooks/subscriptions \
  -H "content-type: application/json" \
  -d '{
    "url":"http://localhost:9999/hook",
    "events":["before_tool","after_tool"],
    "secret":"outbound-signing-secret",
    "headers":{"X-App":"echobot"},
    "max_retries":2,
    "enabled":true
  }'
```

查看订阅：

```bash
curl -s http://localhost:18790/api/webui/webhooks/subscriptions
```

删除订阅（将 `<id>` 替换为实际订阅 ID）：

```bash
curl -s -X DELETE "http://localhost:18790/api/webui/webhooks/subscriptions/<id>"
```

### 入站 Webhook 验签示例（HMAC-SHA256）

验签算法：`signature = HMAC_SHA256(secret, "{timestamp}.{raw_body}")`  
请求头要求：
- `X-Echobot-Timestamp`：Unix 秒级时间戳
- `X-Echobot-Signature`：hex 小写摘要（不带 `sha256=` 前缀）
- `X-Echobot-Event-Id`：可选，建议传，便于防重放

```bash
export ECHOBOT_WEBHOOK_SECRET="replace-with-your-secret"

BODY='{"event":"message","content":"你好，请回复一句话","session_id":"webhook:demo"}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" \
  | openssl dgst -sha256 -hmac "$ECHOBOT_WEBHOOK_SECRET" -binary \
  | xxd -p -c 256)

curl -s -X POST http://localhost:18790/api/webui/webhooks/inbound \
  -H "content-type: application/json" \
  -H "X-Echobot-Timestamp: $TS" \
  -H "X-Echobot-Signature: $SIG" \
  -H "X-Echobot-Event-Id: evt-demo-001" \
  -d "$BODY"
```

## 多实例与 Cron

echobot 支持实例隔离（配置、会话、定时任务分别存储）。

```bash
# 启动 admin 实例
echobot gateway --instance admin

# 查看 admin 实例的定时任务
echobot cron list --instance admin

# 给 admin 实例添加定时任务（每 10 分钟）
echobot cron add --instance admin --name ping --message "状态检查" --every 600
```

## 多 Agent 协作模式

echobot 支持多 Agent 协作，类似于 OpenClaw 的架构：
- 多个独立的 Agent 实例（每个有独立的 Telegram Bot token）
- 部署到同一个群聊中相互协作
- 通过配置定义 Agent 行为和协作规则

### 快速开始

```bash
# 交互式创建多 Agent 配置
echobot agents init

# 启动多 Agent 模式
echobot gateway --multi
```

### 命令行管理

```bash
# 查看已配置的 Agent
echobot agents list

# 添加新 Agent
echobot agents add --id coder --token "BOT_TOKEN" --role coder

# 添加群聊 @mention 绑定
echobot agents bind coder --mention coder

# 启用/禁用 Agent
echobot agents enable coder
echobot agents disable coder

# 移除 Agent
echobot agents remove coder

# 管理协作权限
echobot agents collaboration --enable --add coder,reviewer
```

### 配置文件

配置文件位于 `~/.echobot/agents.json`：

```json
{
  "agents": [
    {
      "id": "coder",
      "name": "Coder",
      "token": "YOUR_BOT_TOKEN",
      "role": "coder",
      "workspace": "~/.echobot/agents/coder",
      "enabled": true
    },
    {
      "id": "reviewer",
      "name": "Reviewer",
      "token": "YOUR_BOT_TOKEN",
      "role": "default",
      "workspace": "~/.echobot/agents/reviewer",
      "enabled": true
    }
  ],
  "collaboration": {
    "enabled": true,
    "allowCalls": ["coder", "reviewer"]
  },
  "bindings": [
    {
      "agentId": "coder",
      "match": {
        "channel": "telegram",
        "chatType": "private"
      }
    },
    {
      "agentId": "coder",
      "match": {
        "channel": "telegram",
        "chatType": "group",
        "mention": "coder"
      }
    },
    {
      "agentId": "reviewer",
      "match": {
        "channel": "telegram",
        "chatType": "group",
        "mention": "reviewer"
      }
    }
  ]
}
```

### 配置说明

| 字段 | 说明 |
|------|------|
| `agents` | Agent 实例列表 |
| `agents[].id` | Agent 唯一标识 |
| `agents[].name` | 显示名称 |
| `agents[].token` | Telegram Bot Token（每个 Agent 独立） |
| `agents[].role` | 使用的角色 |
| `agents[].workspace` | 工作区目录 |
| `agents[].enabled` | 是否启用 |
| `collaboration.enabled` | 是否允许 Agent 间调用 |
| `collaboration.allowCalls` | 允许被调用的 Agent ID 列表 |
| `bindings` | 消息路由规则 |
| `bindings[].agentId` | 目标 Agent ID |
| `bindings[].match.channel` | 消息渠道（如 telegram） |
| `bindings[].match.chatType` | 聊天类型（private/group/supergroup） |
| `bindings[].match.mention` | @mention 标识 |

### 消息路由优先级

1. **@mention** - 群聊中 `@coder` 会直接路由到 coder Agent
2. **bindings** - 根据绑定规则匹配
3. **默认** - 路由到第一个启用的 Agent

### Agent 间调用

当 `collaboration.enabled: true` 时，Agent 可以使用以下工具：

- `call_agent` - 调用其他 Agent 执行任务
- `list_agents` - 列出可用的 Agent

示例对话：
```
@Coder 写一个快速排序，然后让 reviewer 审查一下
```

## Telegram Bot

1. 创建 Bot：搜索 `@BotFather`，发送 `/newbot`
2. 配置 token 到 `config.json`
3. 启动 `echobot gateway`

## 角色系统

echobot 支持多角色配置，每个角色可以有不同的技能、工具集和行为风格。

### 配置默认角色

在 `~/.echobot/config.json` 中设置默认角色：

```json
{
  "agents": {
    "defaults": {
      "model": "MiniMax-M2.1",
      "default_role": "default"
    }
  }
}
```

### 命令行指定角色

```bash
# 使用指定角色运行 agent
echobot agent -m "帮我写代码" --role coder

# 列出所有可用角色
echobot roles
```

### 创建自定义角色

在项目根目录创建 `roles/` 目录，添加角色文件夹：

```
roles/
├── coder/
│   ├── SKILL.md      # 角色技能定义
│   └── config.yaml   # 角色配置
└── tester/
    ├── SKILL.md
    └── config.yaml
```

**config.yaml 示例：**

```yaml
display_name: Coder
description: 专业编程助手，擅长代码编写和调试
priority: 10
trigger_keywords:
  - 代码
  - 编程
  - bug
tools:
  default:
    - read_file
    - write_file
    - bash
  exclusive:
    - grep
style:
  language: zh
  format: code
```

**SKILL.md 示例：**

```markdown
# 角色设定

你是一个专业编程助手，擅长：
- Python、TypeScript、Go 等语言开发
- 代码审查和优化
- Bug 调试和修复
- 架构设计和最佳实践

请始终：
1. 提供清晰的代码示例
2. 解释实现原理
3. 给出最佳实践建议
```

## License

MIT
