<div align="center">
  <h1>miobot: 超轻量级个人 AI 助手 / Ultra-Lightweight Personal AI Assistant</h1>
  <p>
    <a href="https://pypi.org/project/miobot/"><img src="https://img.shields.io/pypi/v/miobot/" alt="PyPI"></a>
    <img src="https://img.shields.io/badge/python-≥3.11-blue" alt="Python">
    <img src="https://img.shields.io/badge/license-MIT-green" alt="License">
  </p>
</div>

</div>

> 📂 本项目 fork 自 [nanobot](https://github.com/HKUDS/nanobot)，后更名为 miobot。

👾 **miobot** 是一个受 [OpenClaw](https://github.com/openclaw/openclaw) 启发的 **超轻量级 (ultra-lightweight)** 个人 AI 助手

⚡️ 核心 Agent 功能仅需 **~4,000** 行代码 — 比 Clawdbot 的 430k+ 行小 99%

📏 实时代码行数：**3,935 行**（运行 `bash core_agent_lines.sh` 可随时验证）


## miobot 核心特性 / Core Features:

🪶 **超轻量 (Ultra-Lightweight)**: 仅约 4,000 行核心代码 — 比 Clawdbot 小 99%

🔬 **研究友好 (Research-Friendly)**: 代码清晰易读，易于理解、修改和扩展研究

⚡️ **闪电快速 (Lightning Fast)**: 最小占用空间意味着更快的启动、更低的资源消耗和更快的迭代

💎 **易于使用 (Easy to Use)**: 一键部署，立即可用

## 🏗️ 架构 / Architecture

<p align="center">
  <img src="miobot_arch.png" alt="miobot architecture" width="800">
</p>

## ✨ 功能 / Features

<table align="center">
  <tr align="center">
    <th><p align="center">📈 24/7 实时市场分析</p></th>
    <th><p align="center">🚀 全栈软件工程师</p></th>
    <th><p align="center">📅 智能日程管理器</p></th>
    <th><p align="center">📚 个人知识助手</p></th>
  </tr>
  <tr>
    <td align="center"><p align="center"><img src="case/search.gif" width="180" height="400"></p></td>
    <td align="center"><p align="center"><img src="case/code.gif" width="180" height="400"></p></td>
    <td align="center"><p align="center"><img src="case/scedule.gif" width="180" height="400"></p></td>
    <td align="center"><p align="center"><img src="case/memory.gif" width="180" height="400"></p></td>
  </tr>
  <tr>
    <td align="center">发现 • 洞察 • 趋势</td>
    <td align="center">开发 • 部署 • 扩展</td>
    <td align="center">日程 • 自动化 • 整理</td>
    <td align="center">学习 • 记忆 • 推理</td>
  </tr>
</table>

## 📦 安装 / Installation

**从源码安装 (Install from source)** (最新功能，推荐用于开发)

```bash
git clone https://github.com/HKUDS/miobot.git
cd miobot
pip install -e .
```

**使用 [uv](https://github.com/astral-sh/uv) 安装** (稳定版，快速)

```bash
uv tool install miobot-ai
```

**从 PyPI 安装 (Install from PyPI)** (稳定版)

```bash
pip install miobot-ai
```

## 🚀 快速开始 / Quick Start

> [!TIP]
> 在 `~/.miobot/config.json` 中设置您的 API Key。
> 获取 API Key：[OpenRouter](https://openrouter.ai/keys)（全球）· [Brave Search](https://brave.com/search/api/)（可选，用于网页搜索）

**1. 初始化 (Initialize)**

```bash
miobot onboard
```

**2. 配置 (Configure)** (`~/.miobot/config.json`)

Add or merge these **two parts** into your config (other options have defaults).

将以下**两部分**添加或合并到您的配置中（其他选项使用默认值）。

*设置您的 API key* (例如 OpenRouter，推荐用于全球用户):
```json
{
  "providers": {
    "openrouter": {
      "apiKey": "sk-or-v1-xxx"
    }
  }
}
```

*设置您的模型* (可选择固定一个 provider — 默认自动检测):
```json
{
  "agents": {
    "defaults": {
      "model": "anthropic/claude-opus-4-5",
      "provider": "openrouter"
    }
  }
}
```

**3. 聊天 (Chat)**

```bash
miobot agent
```

完成！2 分钟内拥有一个可用的 AI 助手。

## 💬 聊天应用 / Chat Applications

将 miobot 连接到您喜欢的聊天平台。

Connect miobot to your favorite chat platform.

| 频道 (Channel) | 需要 (Requires) |
|---------|---------------|
| **Telegram** | Bot token from @BotFather |
| **Discord** | Bot token + Message Content intent |
| **WhatsApp** | QR code scan (扫描二维码) |
| **Feishu** (飞书) | App ID + App Secret |
| **Mochat** | Claw token (auto-setup available) (自动配置可用) |
| **DingTalk** (钉钉) | App Key + App Secret |
| **Slack** | Bot token + App-Level token |
| **Email** (邮箱) | IMAP/SMTP credentials |
| **QQ** | App ID + App Secret |

<details>
<summary><b>Telegram</b> (推荐 / Recommended)</summary>

**1. 创建机器人 (Create a bot)**
- 打开 Telegram，搜索 `@BotFather`
- 发送 `/newbot`，按照提示操作
- 复制 token

**2. 配置 (Configure)**

```json
{
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "YOUR_BOT_TOKEN",
      "allowFrom": ["YOUR_USER_ID"]
    }
  }
}
```

> 您可以在 Telegram 设置中找到您的 **User ID**。它显示为 `@yourUserId`。
> 复制此值**不带 `@` 符号**，然后粘贴到配置文件中。

**3. 运行 (Run)**

```bash
miobot gateway
```

</details>

<details>
<summary><b>Mochat (Claw IM)</b></summary>

默认使用 **Socket.IO WebSocket**，并有 HTTP polling 备用方案。

**1. 让 miobot 为您设置 Mochat**

只需发送此消息给 miobot（将 `xxx@xxx` 替换为您的真实邮箱）:

```
Read https://raw.githubusercontent.com/HKUDS/Mo聊天/refs/heads/main/skills/miobot/skill.md and register on Mo聊天. My Email account is xxx@xxx Bind me as your owner and DM me on Mo聊天.
```

miobot 将自动注册、配置 `~/.miobot/config.json` 并连接到 Mochat。

**2. 重启网关 (Restart gateway)**

```bash
miobot gateway
```

就是这样！miobot 会处理剩下的事情！

<br>

<details>
<summary>手动配置 (Manual configuration) (高级 / Advanced)</summary>

如果您更喜欢手动配置，请将以下内容添加到 `~/.miobot/config.json`:

> 请保密 `claw_token`。它应该只发送到您的 Mochat API 端点的 `X-Claw-Token` 请求头中。

```json
{
  "channels": {
    "mochat": {
      "enabled": true,
      "base_url": "https://mochat.io",
      "socket_url": "https://mochat.io",
      "socket_path": "/socket.io",
      "claw_token": "claw_xxx",
      "agent_user_id": "6982abcdef",
      "sessions": ["*"],
      "panels": ["*"],
      "reply_delay_mode": "non-mention",
      "reply_delay_ms": 120000
    }
  }
}
```



</details>
</details>

<details>
<summary><b>Discord</b></summary>

**1. 创建机器人 (Create a bot)**
- 访问 https://discord.com/developers/applications
- 创建应用 → Bot → 添加机器人
- 复制 bot token

**2. 启用 intents**
- 在 Bot 设置中，启用 **MESSAGE CONTENT INTENT**
- （可选）如果您计划使用基于成员数据的允许列表，请启用 **SERVER MEMBERS INTENT**

**3. 获取您的 User ID**
- Discord 设置 → 高级 → 启用 **开发者模式**
- 右键点击您的头像 → **复制用户 ID**

**4. 配置 (Configure)**

```json
{
  "channels": {
    "discord": {
      "enabled": true,
      "token": "YOUR_BOT_TOKEN",
      "allowFrom": ["YOUR_USER_ID"]
    }
  }
}
```

**5. 邀请机器人 (Invite the bot)**
- OAuth2 → URL 生成器
- Scopes: `bot`
- Bot Permissions: `Send Messages`, `Read Message History`
- 打开生成的邀请 URL 并将机器人添加到您的服务器

**6. 运行 (Run)**

```bash
miobot gateway
```

> [!TIP]
> Discord 音频附件（如 `.ogg/.mp3/.wav`）支持自动语音转文字（取决于语音转写 provider 配置）。

</details>

<details>
<summary><b>Matrix (Element)</b></summary>

首先安装 Matrix 依赖:

```bash
pip install miobot-ai[matrix]
```

**1. 创建/选择一个 Matrix 账户**

- 在您的 homeserver 上创建或重用 Matrix 账户（例如 `matrix.org`）。
- 确认您可以使用 Element 登录。

**2. 获取凭据**

- 您需要:
  - `userId` (例如: `@miobot:matrix.org`)
  - `accessToken`
  - `deviceId` (推荐，以便在重启时恢复同步 token)
- 您可以从 homeserver 登录 API (`/_matrix/client/v3/login`) 或客户端的高级会话设置中获取这些信息。

**3. 配置 (Configure)**

```json
{
  "channels": {
    "matrix": {
      "enabled": true,
      "homeserver": "https://matrix.org",
      "userId": "@miobot:matrix.org",
      "accessToken": "syt_xxx",
      "deviceId": "miobot01",
      "e2eeEnabled": true,
      "allowFrom": ["@your_user:matrix.org"],
      "groupPolicy": "open",
      "groupAllowFrom": [],
      "allowRoomMentions": false,
      "maxMediaBytes": 20971520
    }
  }
}
```

> 保持持久的 `matrix-store` 和稳定的 `deviceId` — 如果这些在重启时改变，加密会话状态将丢失。

| 选项 (Option) | 说明 (Description) |
|--------|-------------|
| `allowFrom` | 允许交互的用户 ID。空 = 所有发送者。 |
| `groupPolicy` | `open`（默认）, `mention`, 或 `allowlist`。 |
| `groupAllowFrom` | 房间允许列表（当策略为 `allowlist` 时使用）。 |
| `allowRoomMentions` | 在 mention 模式下接受 `@room` 提及。 |
| `e2eeEnabled` | E2EE 支持（默认 `true`）。设为 `false` 仅使用纯文本。 |
| `maxMediaBytes` | 最大附件大小（默认 `20MB`）。设为 `0` 阻止所有媒体。 |




**4. 运行 (Run)**

```bash
miobot gateway
```

</details>

<details>
<summary><b>WhatsApp</b></summary>

需要 **Node.js ≥18**。

**1. 链接设备 (Link device)**

```bash
miobot channels login
# 使用 WhatsApp → 设置 → 已关联的设备 扫描二维码
```

**2. 配置 (Configure)**

```json
{
  "channels": {
    "whatsapp": {
      "enabled": true,
      "allowFrom": ["+1234567890"]
    }
  }
}
```

**3. 运行 (Run)** (两个终端 / two terminals)

```bash
# Terminal 1
miobot channels login

# Terminal 2
miobot gateway
```

> [!TIP]
> WhatsApp 语音转写依赖 bridge 透传音频文件路径（`mediaPath`）。若 bridge 未提供该字段，将回退为“语音消息未转写”提示。

</details>

<details>
<summary><b>Feishu (飞书)</b></summary>

使用 **WebSocket** 长连接 — 不需要公网 IP。

**1. 创建飞书机器人**
- 访问 [飞书开放平台](https://open.feishu.cn/app)
- 创建新应用 → 启用 **Bot** 功能
- **权限**: 添加 `im:message`（发送消息）和 `im:message.p2p_msg:readonly`（接收消息）
- **事件**: 添加 `im.message.receive_v1`（接收消息）
  - 选择 **长连接** 模式（需要先运行 miobot 以建立连接）
- 从"凭据与基础信息"获取 **App ID** 和 **App Secret**
- 发布应用

**2. 配置 (Configure)**

```json
{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxx",
      "appSecret": "xxx",
      "encryptKey": "",
      "verificationToken": "",
      "allowFrom": ["ou_YOUR_OPEN_ID"]
    }
  }
}
```

> 长连接模式下 `encryptKey` 和 `verificationToken` 是可选的。
> `allowFrom`: 添加您的 open_id（在与机器人消息时在 miobot 日志中找到）。使用 `["*"]` 允许所有用户。

**3. 运行 (Run)**

```bash
miobot gateway
```

> [!TIP]
> 飞书使用 WebSocket 接收消息 — 不需要 webhook 或公网 IP！

</details>

<details>
<summary><b>QQ (QQ单聊)</b></summary>

使用 **botpy SDK** 和 WebSocket — 不需要公网 IP。目前仅支持**私聊**。

**1. 注册并创建机器人**
- 访问 [QQ 开放平台](https://q.qq.com) → 注册为开发者（个人或企业）
- 创建新的机器人应用
- 转到 **开发设置** → 复制 **AppID** 和 **AppSecret**

**2. 设置沙箱用于测试**
- 在机器人管理控制台中，找到 **沙箱配置**
- 在 **消息列表配置** 下，点击 **添加成员** 并添加您自己的 QQ 号
- 添加后，使用手机 QQ 扫描机器人的二维码 → 打开机器人资料 → 点击"发消息"开始聊天

**3. 配置 (Configure)**

> - `allowFrom`: 添加您的 openid（在 miobot 日志中与机器人消息时找到）。使用 `["*"]` 允许公开访问。
> - 生产环境：在机器人控制台提交审核并发布。详见 [QQ 机器人文档](https://bot.q.qq.com/wiki/)。

```json
{
  "channels": {
    "qq": {
      "enabled": true,
      "appId": "YOUR_APP_ID",
      "secret": "YOUR_APP_SECRET",
      "allowFrom": ["YOUR_OPENID"]
    }
  }
}
```

**4. 运行 (Run)**

```bash
miobot gateway
```

现在从 QQ 发送消息给机器人 — 它应该会回复！

</details>

<details>
<summary><b>DingTalk (钉钉)</b></summary>

使用 **Stream Mode** — 不需要公网 IP。

**1. 创建钉钉机器人**
- 访问 [钉钉开放平台](https://open-dev.dingtalk.com/)
- 创建新应用 → 添加 **Robot** 功能
- **配置**:
  - 开启 **Stream Mode**
- **权限**: 添加发送消息所需的必要权限
- 从"凭据"获取 **AppKey** (Client ID) 和 **AppSecret** (Client Secret)
- 发布应用

**2. 配置 (Configure)**

```json
{
  "channels": {
    "dingtalk": {
      "enabled": true,
      "clientId": "YOUR_APP_KEY",
      "clientSecret": "YOUR_APP_SECRET",
      "allowFrom": ["YOUR_STAFF_ID"]
    }
  }
}
```

> `allowFrom`: 添加您的员工 ID。使用 `["*"]` 允许所有用户。

**3. 运行 (Run)**

```bash
miobot gateway
```

</details>

<details>
<summary><b>Slack</b></summary>

使用 **Socket Mode** — 不需要公网 URL。

**1. 创建 Slack 应用**
- 访问 [Slack API](https://api.slack.com/apps) → **创建新应用** → "从零开始"
- 选择名称并选择您的工作区

**2. 配置应用 (Configure the app)**
- **Socket Mode**: 开启 → 生成具有 `connections:write` 范围的 **App-Level Token** → 复制它 (`xapp-...`)
- **OAuth & Permissions**: 添加 bot scopes: `chat:write`, `reactions:write`, `app_mentions:read`
- **Event Subscriptions**: 开启 → 订阅 bot events: `message.im`, `message.channels`, `app_mention` → 保存更改
- **App Home**: 滚动到 **Show Tabs** → 启用 **Messages Tab** → 勾选 **"允许用户从消息选项卡发送斜杠命令和消息"**
- **Install App**: 点击 **Install to Workspace** → 授权 → 复制 **Bot Token** (`xoxb-...`)

**3. 配置 miobot (Configure miobot)**

```json
{
  "channels": {
    "slack": {
      "enabled": true,
      "botToken": "xoxb-...",
      "appToken": "xapp-...",
      "allowFrom": ["YOUR_SLACK_USER_ID"],
      "groupPolicy": "mention"
    }
  }
}
```

**4. 运行 (Run)**

```bash
miobot gateway
```

直接 DM 机器人或在频道中 @mention 它 — 它应该会回复！

> [!TIP]
> - `groupPolicy`: `"mention"`（默认 — 仅在 @mention 时回复），`"open"`（回复所有频道消息），或 `"allowlist"`（限制特定频道）。
> - DM 策略默认开放。设置 `"dm": {"enabled": false}` 禁用 DM。

</details>

<details>
<summary><b>Email (邮箱)</b></summary>

给 miobot 一个专属邮箱账户。它通过 **IMAP** 轮询接收邮件并通过 **SMTP** 回复 — 就像一个个人邮件助手。

**1. 获取凭据 (Gmail 示例)**
- 为您的机器人创建一个专属 Gmail 账户（例如 `my-miobot@gmail.com`）
- 启用两步验证 → 创建[应用密码](https://myaccount.google.com/apppasswords)
- 对 IMAP 和 SMTP 使用此应用密码

**2. 配置 (Configure)**

> - `consentGranted` 必须为 `true` 以允许访问邮箱。这是一个安全门 — 设为 `false` 完全禁用。
> - `allowFrom`: 添加您的邮箱地址。使用 `["*"]` 接受来自任何人的邮件。
> - `smtpUseTls` 和 `smtpUseSsl` 默认分别为 `true` 和 `false`，这对 Gmail 是正确的（端口 587 + STARTTLS）。无需显式设置。
> - 如果您只想阅读/分析邮件而不发送自动回复，请设置 `"autoReplyEnabled": false`。

```json
{
  "channels": {
    "email": {
      "enabled": true,
      "consentGranted": true,
      "imapHost": "imap.gmail.com",
      "imapPort": 993,
      "imapUsername": "my-miobot@gmail.com",
      "imapPassword": "your-app-password",
      "smtpHost": "smtp.gmail.com",
      "smtpPort": 587,
      "smtpUsername": "my-miobot@gmail.com",
      "smtpPassword": "your-app-password",
      "fromAddress": "my-miobot@gmail.com",
      "allowFrom": ["your-real-email@gmail.com"]
    }
  }
}
```


**3. 运行 (Run)**

```bash
miobot gateway
```

</details>

## 🌐 Agent 社交网络 / Agent Social Network

👾 miobot 能够链接到 agent 社交网络（agent 社区）。**只需发送一条消息，您的 miobot 就会自动加入！**

| 平台 (Platform) | 如何加入 (How to Join)（发送此消息给您的机器人） |
|----------|-------------|
| [**Moltbook**](https://www.moltbook.com/) | `Read https://moltbook.com/skill.md and follow the instructions to join Moltbook` |
| [**Clawd聊天**](https://clawdchat.ai/) | `Read https://clawdchat.ai/skill.md and follow the instructions to join Clawd聊天` |

只需通过 CLI 或任何聊天频道将上述命令发送给您的 miobot，它会处理剩下的事情。

## ⚙️ 配置 / Configuration

配置文件 (Config file): `~/.miobot/config.json`

### 语音转写 / Speech-to-Text

miobot 支持统一语音转写层，适用于 Telegram / Discord / WhatsApp（当渠道提供音频文件时）。

可用 provider：
- `groq`：云端 Whisper（需要 `GROQ_API_KEY`）
- `vosk`：本地离线识别（需要安装 `vosk` 和本地模型）
- `auto`：优先 `groq`，否则尝试本地 `vosk`（默认）
- `none`：关闭语音转写

环境变量：

```bash
export MIOBOT_TRANSCRIPTION_PROVIDER=auto   # auto|groq|vosk|none
export GROQ_API_KEY=gsk_xxx                 # 使用 groq 时需要
export MIOBOT_VOSK_MODEL_PATH=~/.miobot/models/vosk-model-small-cn-0.22
```

也可以直接在 `~/.miobot/config.json` 中配置（推荐）：

```json
{
  "tools": {
    "transcription": {
      "enabled": true,
      "provider": "faster_whisper",
      "fasterWhisperModel": "small",
      "fasterWhisperComputeType": "int8",
      "voskModelPath": "~/.miobot/models/vosk-model-small-cn-0.22"
    }
  }
}
```

说明：
- `enabled=true`：启用语音转写
- `enabled=false`：关闭语音转写
- `enabled=null`（或不填）：兼容旧行为，按环境变量自动选择

本地 Vosk 安装示例：

```bash
pip install vosk
mkdir -p ~/.miobot/models
# 下载并解压 vosk-model-small-cn-0.22 到：
# ~/.miobot/models/vosk-model-small-cn-0.22
```

设置后重启网关：

```bash
systemctl --user restart miobot-gateway
```

### Provider (模型提供商)

> [!TIP]
> - **Groq** 通过 Whisper 提供语音转录。配置后 Telegram/Discord（音频附件）可自动转录；WhatsApp 需 bridge 提供 `mediaPath`。
> - **智谱编程计划**: 如果您在智谱的编程计划中，请在您的 zhipu provider 配置中设置 `"apiBase": "https://open.bigmodel.cn/api/coding/paas/v4"`。
> - **MiniMax (中国大陆)**: 如果您的 API key 来自 MiniMax 的中国大陆平台 (minimaxi.com)，请在您的 minimax provider 配置中设置 `"apiBase": "https://api.minimaxi.com/v1"`。
> - **火山引擎编程计划**: 如果您在火山引擎的编程计划中，请在您的 volcengine provider 配置中设置 `"apiBase": "https://ark.cn-beijing.volces.com/api/coding/v3"`。

| Provider | 用途 (Usage) | 获取 API Key |
|----------|---------|-------------|
| `custom` | 任何 OpenAI 兼容端点（直接，无 LiteLLM） | — |
| `openrouter` | LLM（推荐，可访问所有模型） | [openrouter.ai](https://openrouter.ai) |
| `anthropic` | LLM (Claude 直接) | [console.anthropic.com](https://console.anthropic.com) |
| `openai` | LLM (GPT 直接) | [platform.openai.com](https://platform.openai.com) |
| `deepseek` | LLM (DeepSeek 直接) | [platform.deepseek.com](https://platform.deepseek.com) |
| `groq` | LLM + **语音转录** (Whisper) | [console.groq.com](https://console.groq.com) |
| `gemini` | LLM (Gemini 直接) | [aistudio.google.com](https://aistudio.google.com) |
| `minimax` | LLM (MiniMax 直接) | [platform.minimaxi.com](https://platform.minimaxi.com) |
| `aihubmix` | LLM（API 网关，可访问所有模型） | [aihubmix.com](https://aihubmix.com) |
| `siliconflow` | LLM (SiliconFlow/硅基流动) | [siliconflow.cn](https://siliconflow.cn) |
| `volcengine` | LLM (VolcEngine/火山引擎) | [volcengine.com](https://www.volcengine.com) |
| `dashscope` | LLM (Qwen) | [dashscope.console.aliyun.com](https://dashscope.console.aliyun.com) |
| `moonshot` | LLM (Moonshot/Kimi) | [platform.moonshot.cn](https://platform.moonshot.cn) |
| `zhipu` | LLM (智谱 GLM) | [open.bigmodel.cn](https://open.bigmodel.cn) |
| `vllm` | LLM（本地，任何 OpenAI 兼容服务器） | — |
| `openai_codex` | LLM (Codex, OAuth) | `miobot provider login openai-codex` |
| `github_copilot` | LLM (GitHub Copilot, OAuth) | `miobot provider login github-copilot` |

<details>
<summary><b>OpenAI Codex (OAuth)</b></summary>

Codex 使用 OAuth 而不是 API key。需要 ChatGPT Plus 或 Pro 账户。

**1. 登录 (Login):**
```bash
miobot provider login openai-codex
```

**2. 设置模型 (Set model)** (合并到 `~/.miobot/config.json`):
```json
{
  "agents": {
    "defaults": {
      "model": "openai-codex/gpt-5.1-codex"
    }
  }
}
```

**3. 聊天 (Chat):**
```bash
miobot agent -m "Hello!"
```

> Docker 用户：使用 `docker run -it` 进行交互式 OAuth 登录。

</details>

<details>
<summary><b>Custom Provider (任何 OpenAI 兼容 API)</b></summary>

直接连接到任何 OpenAI 兼容端点 — LM Studio、llama.cpp、Together AI、Fireworks、Azure OpenAI 或任何自托管服务器。绕过 LiteLLM；模型名称按原样传递。

```json
{
  "providers": {
    "custom": {
      "apiKey": "your-api-key",
      "apiBase": "https://api.your-provider.com/v1"
    }
  },
  "agents": {
    "defaults": {
      "model": "your-model-name"
    }
  }
}
```

> 对于不需要 key 的本地服务器，将 `apiKey` 设为任何非空字符串（例如 `"no-key"`）。

</details>

<details>
<summary><b>vLLM (本地 / OpenAI 兼容)</b></summary>

使用 vLLM 或任何 OpenAI 兼容服务器运行您自己的模型，然后添加到配置：

**1. 启动服务器 (示例) (Start the server):**
```bash
vllm serve meta-llama/Llama-3.1-8B-Instruct --port 8000
```

**2. 添加到配置 (部分 — 合并到 `~/.miobot/config.json`) (Add to config):**

*Provider (key 对于本地可以是任何非空字符串):*
```json
{
  "providers": {
    "vllm": {
      "apiKey": "dummy",
      "apiBase": "http://localhost:8000/v1"
    }
  }
}
```

*Model:*
```json
{
  "agents": {
    "defaults": {
      "model": "meta-llama/Llama-3.1-8B-Instruct"
    }
  }
}
```

</details>

<details>
<summary><b>添加新的 Provider (开发者指南)</b></summary>

miobot 使用 **Provider Registry** (`miobot/providers/registry.py`) 作为单一事实来源。
添加新 provider 只需 **2 步** — 无需触碰 if-elif 链。

**第 1 步。** 在 `miobot/providers/registry.py` 的 `PROVIDERS` 中添加 `ProviderSpec` 条目:

```python
ProviderSpec(
    name="myprovider",                   # 配置字段名
    keywords=("myprovider", "mymodel"),  # 模型名关键词用于自动匹配
    env_key="MYPROVIDER_API_KEY",        # LiteLLM 的环境变量
    display_name="My Provider",          # 在 `miobot status` 中显示
    litellm_prefix="myprovider",         # 自动前缀: model → myprovider/model
    skip_prefixes=("myprovider/",),      # 不要双重前缀
)
```

**第 2 步。** 在 `miobot/config/schema.py` 的 `ProvidersConfig` 中添加字段:

```python
class ProvidersConfig(BaseModel):
    ...
    myprovider: ProviderConfig = ProviderConfig()
```

就是这样！环境变量、模型前缀、配置匹配和 `miobot status` 显示都将自动工作。

**常用 `ProviderSpec` 选项:**

| 字段 (Field) | 说明 (Description) | 示例 (Example) |
|-------|-------------|---------|
| `litellm_prefix` | 自动为 LiteLLM 添加模型名前缀 | `"dashscope"` → `dashscope/qwen-max` |
| `skip_prefixes` | 如果模型已以此开头则不添加前缀 | `("dashscope/", "openrouter/")` |
| `env_extras` | 要设置的其他环境变量 | `(("ZHIPUAI_API_KEY", "{api_key}"),)` |
| `model_overrides` | 每个模型的参数覆盖 | `(("kimi-k2.5", {"temperature": 1.0}),)` |
| `is_gateway` | 可以路由任何模型（如 OpenRouter） | `True` |
| `detect_by_key_prefix` | 通过 API key 前缀检测网关 | `"sk-or-"` |
| `detect_by_base_keyword` | 通过 API base URL 检测网关 | `"openrouter"` |
| `strip_model_prefix` | 在重新添加前缀前去除现有前缀 | `True`（用于 AiHubMix） |

</details>


### MCP (Model Context Protocol / 模型上下文协议)

> [!TIP]
> 配置格式与 Claude Desktop / Cursor 兼容。您可以直接从任何 MCP server 的 README 中复制 MCP server 配置。

miobot 支持 [MCP](https://modelcontextprotocol.io/) — 连接外部工具服务器并将它们用作原生 agent 工具。

将 MCP servers 添加到您的 `config.json`:

```json
{
  "tools": {
    "mcpServers": {
      "filesystem": {
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
      },
      "my-remote-mcp": {
        "url": "https://example.com/mcp/",
        "headers": {
          "Authorization": "Bearer xxxxx"
        }
      }
    }
  }
}
```

支持两种传输模式:

| 模式 (Mode) | 配置 (Config) | 示例 (Example) |
|------|--------|---------|
| **Stdio** | `command` + `args` | 通过 `npx` / `uvx` 的本地进程 |
| **HTTP** | `url` + `headers` (可选) | 远程端点 (`https://mcp.example.com/sse`) |

使用 `toolTimeout` 覆盖慢速服务器的默认每次调用 30 秒超时:

```json
{
  "tools": {
    "mcpServers": {
      "my-slow-server": {
        "url": "https://example.com/mcp/",
        "toolTimeout": 120
      }
    }
  }
}
```

MCP 工具在启动时自动发现和注册。LLM 可以与内置工具一起使用它们 — 无需额外配置。




### Security (安全)

> [!TIP]
> 对于生产部署，请在配置中设置 `"restrictToWorkspace": true` 以沙箱化 agent。
> **来源 / post-`v0.1.4.post3` 的变更:** 在 `v0.1.4.post3` 及更早版本中，空的 `allowFrom` 意味着"允许所有发送者"。在更新版本（包括从源码构建）中，**空的 `allowFrom` 默认拒绝所有访问**。要允许所有发送者，请设置 `"allowFrom": ["*"]`**。

| 选项 (Option) | 默认 (Default) | 说明 (Description) |
|--------|---------|-------------|
| `tools.restrictToWorkspace` | `false` | 当 `true` 时，限制**所有** agent 工具（shell、文件读写/编辑、列表）到工作区目录。防止路径遍历和超出范围访问。 |
| `tools.exec.pathAppend` | `""` | 运行 shell 命令时附加到 `PATH` 的额外目录（例如 `/usr/sbin` 用于 `ufw`）。 |
| `channels.*.allowFrom` | `[]` (允许所有) | 用户 ID 白名单。空 = 允许所有人；非空 = 只有列出的用户可以交互。 |


## CLI 参考 / CLI Reference

| 命令 (Command) | 说明 (Description) |
|---------|-------------|
| `miobot onboard` | 初始化 config 和 workspace |
| `miobot agent -m "..."` | 与 agent 聊天 |
| `miobot agent` | 交互式聊天模式 |
| `miobot agent --no-markdown` | 显示纯文本回复 |
| `miobot agent --logs` | 聊天时显示运行时日志 |
| `miobot gateway` | 启动网关 |
| `miobot status` | 显示状态 |
| `miobot provider login openai-codex` | OAuth 登录 provider |
| `miobot channels login` | 链接 WhatsApp（扫描二维码） |
| `miobot channels status` | 显示频道状态 |

交互模式退出: `exit`, `quit`, `/exit`, `/quit`, `:q`, 或 `Ctrl+D`。

<details>
<summary><b>Heartbeat (定时任务 / Periodic Tasks)</b></summary>

网关每 30 分钟唤醒一次，检查您 workspace 中的 `HEARTBEAT.md`（`~/.miobot/workspace/HEARTBEAT.md`）。如果文件中有任务，agent 会执行它们并将结果发送到您最近活跃的聊天频道。

**设置:** 编辑 `~/.miobot/workspace/HEARTBEAT.md`（由 `miobot onboard` 自动创建）:

```markdown
## Periodic Tasks / 定时任务

- [ ] 查看天气预报并发送摘要
- [ ] 扫描收件箱中的紧急邮件
```

agent 也可以自己管理这个文件 — 问它"添加一个定时任务"，它会为您更新 `HEARTBEAT.md`。

> **注意:** 网关必须运行（`miobot gateway`），并且您至少需要与机器人聊天一次，这样它才知道要发送到哪个频道。

</details>

## 🐳 Docker

> [!TIP]
> `-v ~/.miobot:/root/.miobot` 标志将您的本地配置目录挂载到容器中，这样您的配置和 workspace 在容器重启后仍然保留。

### Docker Compose

```bash
docker compose run --rm miobot-cli onboard   # 首次设置
vim ~/.miobot/config.json                     # 添加 API keys
docker compose up -d miobot-gateway          # 启动网关
```

```bash
docker compose run --rm miobot-cli agent -m "Hello!"   # 运行 CLI
docker compose logs -f miobot-gateway                   # 查看日志
docker compose down                                      # 停止
```

### Docker

```bash
# 构建镜像
docker build -t miobot .

# 初始化 config（仅首次）
docker run -v ~/.miobot:/root/.miobot --rm miobot onboard

# 在主机上编辑 config 添加 API keys
vim ~/.miobot/config.json

# 运行网关（连接到已启用的频道，如 Telegram/Discord/Mochat）
docker run -v ~/.miobot:/root/.miobot -p 18790:18790 miobot gateway

# 或运行单个命令
docker run -v ~/.miobot:/root/.miobot --rm miobot agent -m "Hello!"
docker run -v ~/.miobot:/root/.miobot --rm miobot status
```

## 🐧 Linux 服务 / Linux Service

将网关作为 systemd 用户服务运行，使其自动启动并在失败时重启

**1. 找到 miobot 二进制文件路径:**

```bash
which miobot   # 例如 /home/user/.local/bin/miobot
```

**2. 创建服务文件** 在 `~/.config/systemd/user/miobot-gateway.service`（如需要则替换 ExecStart 路径）:

```ini
[Unit]
说明=miobot Gateway
After=network.target

[Service]
Type=simple
ExecStart=%h/.local/bin/miobot gateway
Restart=always
RestartSec=10
NoNewPrivileges=yes
ProtectSystem=strict
ReadWritePaths=%h

[Install]
WantedBy=default.target
```

**3. 启用并启动:**

```bash
systemctl --user daemon-reload
systemctl --user enable --now miobot-gateway
```

**常用操作:**

```bash
systemctl --user status miobot-gateway        # 检查状态
systemctl --user restart miobot-gateway       # 配置更改后重启
journalctl --user -u miob  <br>
bot-gateway -f        # 跟踪日志
```

如果您编辑了 `.service` 文件本身，请在重启前运行 `systemctl --user daemon-reload`。

> **注意:** 用户服务只在您登录时运行。要在注销后保持网关运行，请启用 lingering:
>
> ```bash
> loginctl enable-linger $USER
> ```

## 📁 项目结构 / Project Structure

```
miobot/
├── agent/          # 🧠 核心 Agent 逻辑 (Core Agent Logic)
│   ├── loop.py     #    Agent 循环（LLM ↔ 工具执行）
│   ├── context.py  #    提示构建器
│   ├── memory.py   #    持久化记忆
│   ├── skills.py   #    技能加载器
│   ├── subagent.py #    后台任务执行
│   └── tools/      #    内置工具（包括 spawn）
├── skills/         # 🎯 捆绑技能（github, weather, tmux...）
├── channels/       # 📱 聊天频道集成 (Chat channel integrations)
├── bus/            # 🚌 消息路由 (Message routing)
├── cron/           # ⏰ 定时任务 (Scheduled tasks)
├── heartbeat/      # 💓 主动唤醒 (Proactive wake-up)
├── providers/      # 🤖 LLM Provider（OpenRouter 等）
├── session/        # 💬 对话会话 (Conversation sessions)
├── config/         # ⚙️ 配置 (Configuration)
└── cli/           # 🖥️ 命令行 (Commands)
```
