配置体系¶
设计目标¶
插件有大量可调参数:并发上限、权限名单、MCP 服务器、看板条数、润色开关。这些参数散落在各功能模块里,如果每个模块各自读配置,用户要改一处行为就得翻多个文件。配置体系要解决的就是这个问题:把全部可调项收拢到一个地方,统一声明、统一校验、统一暴露。
设计目标有三条:
- 开箱即用。所有配置项都有默认值,Runner 启动时自动生成
config.toml,用户不编辑任何文件也能跑起来。 - 强类型校验。配置错误在加载时暴露,而不是等运行时才炸。字段类型由 Pydantic 保证,插件内部拿到的是校验后的强类型对象。
- WebUI 可编辑。MaiBot WebUI 根据配置模型自动生成表单,用户改配置不用手写 TOML。
设计方案¶
Pydantic 数据模型¶
配置模型全部定义在 config.py,共 13 个 Pydantic 类,分三层:
- 11 个配置节类,对应
config.toml的 11 个节:PluginSection(config.py:32)、PermissionConfig(:56)、TaskConfig(:109)、PlannerBoardConfig(:153)、PolishConfig(:184)、SplitterConfig(:201)、SendConfig(:238)、MCPConfig(:324)、SearchConfig(:393)、SubAgentConfig(:410)、ShellConfig(:456)。 - 1 个嵌套模型
MCPServerConfig(config.py:256),描述单个 MCP 服务器,作为MCPConfig.servers列表的元素。 - 1 个根模型
MaibotAgentConfig(config.py:493),聚合上述 11 节,是插件对外声明的完整配置。
每个类继承 maibot_sdk.PluginConfigBase。字段用 Field(default=..., description=...) 声明默认值和中文描述,json_schema_extra 提供 WebUI 表单的中文 label / hint(无 label 时 WebUI 回退显示英文字段名),__ui_label__ 提供 WebUI 表单的分组名。Literal[...] 类型(如 transport)会让 WebUI 渲染成下拉框。
config.toml 生成与校验¶
plugin.py:68 将 MaibotAgentConfig 声明为插件的 config_model。Runner 启动时读取该模型,做三件事:
- 若
config.toml不存在,用模型默认值补齐生成; - 校验已有文件的字段类型和结构;
- 把字段的
description和__ui_label__暴露给 WebUI 生成表单。
插件内部通过 self.config 访问校验后的 MaibotAgentConfig 实例,字段类型由 Pydantic 保证。
热更新¶
配置变更无需重启插件。SDK 在调用 on_config_update(plugin.py:94)前已刷新 plugin.config,插件侧由 apply_config_update(lifecycle.py:161-217)把新值传播到运行时组件:
- 重建
PermissionResolver,权限变更立即生效; scheduler.update_config更新并发上限与超时参数;task_manager.update_config刷新配置引用;reload_mcp_if_changed按需重启 MCP 客户端;- 重建
PlannerBoard,清空 hash 去重状态。
任一步失败只记日志,不向 SDK 抛出,避免影响插件整体运行。
使用与配置¶
13 节配置项详解¶
以下按 13 个配置节列出全部字段。配置键与 config.py 字段一一对应。
[plugin] — 插件¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
bool |
true |
是否启用插件 |
config_version |
str |
"0.1.0" |
配置文件版本号 |
[permission] — 权限¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
admins |
list[str] |
[] |
管理员列表(按人),格式 platform:user_id |
admin_groups |
list[str] |
[] |
管理群列表(按群),格式 platform:group:group_id |
users |
list[str] |
[] |
用户列表(按人),格式 platform:user_id |
user_groups |
list[str] |
[] |
用户群列表(按群),格式 platform:group:group_id |
admin_in_group_chats |
bool |
false |
按人配置的 admin 在群聊中是否生效(私聊无条件生效) |
权限判定顺序:admin(人/群)> user(人/群)> guest(未匹配)。详见 权限模型。
[task] — 任务¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
max_concurrent_tasks |
int |
4 |
并发任务上限,超出部分按优先级排队 |
max_runtime_min |
int |
0 |
agent 任务总时长兜底(分钟),0 = 不限 |
default_timeout_min |
int |
10 |
ask_user 无回复挂起等待时间(分钟),已声明但当前未执行 |
persist_history |
bool |
true |
是否持久化完整任务历史(当前实现始终持久化,未读取该开关) |
scheduled 状态任务创建不受并发限制,但触发运行时仍计入并发计数。详见 调度器。
[planner_board] — Planner 看板¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
bool |
true |
是否向 Planner 注入插件简介与待办看板 |
max_waiting |
int |
5 |
待用户回复任务条数上限(等待最久的优先展示) |
看板只推送「需要 Planner 主动介入」的待办(waiting_input),不再注入运行中/定时/已完成等状态快照;每会话首次请求还会注入一次插件能力简介。详见 Planner 看板。
[polish] — 润色¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
use_jargon |
bool |
true |
润色时机械匹配黑话(复刻 MaiBot jargon_context_matcher) |
其他润色参数(消息条数、黑话条数上限等)直接跟随 MaiBot 全局配置,不提供插件级覆盖。
[splitter] — 回复分割¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enable |
bool |
true |
是否把长回复拆成多条消息发送(复刻 MaiBot response_splitter 思路的确定性版本) |
max_length |
int |
1000 |
单条消息目标最大长度(字符),无标点的超长句会被硬切(ge=50) |
max_messages |
int |
5 |
一次回复最多拆成几条消息,超过时尾部合并进最后一条(ge=1) |
分割在润色之后进行(ReplySender 的 _split),两级策略确定性切分,保留原文不丢内容:含换行时按行分割为主(行是打包的基本单元,段边界只在行边界,仅当单行超过 max_length 时才在行内按句号切分),无换行(单段长文)时整段按句号分割;所有发送路径(instant 任务、agent 完成回复、send_message 工具、失败通知、命令回复)统一跟随本配置生效,不再提供按消息覆盖参数。详见 回复润色。
[send] — 发送¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
max_retries |
int |
3 |
消息发送最大重试次数(指数退避 1s→2s),超过后放弃发送并抛异常(ge=1) |
[mcp] — MCP¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
bool |
true |
是否启用 MCP 工具 |
fetch_enabled |
bool |
true |
是否启用内置 fetch MCP 服务器 |
fetch_user_agent |
str |
浏览器 UA(Chrome/126 Windows) | 内置 fetch 出站请求的 User-Agent;默认浏览器 UA 规避反爬验证码,留空退回 mcp-server-fetch 自带 UA |
fetch_block_internal |
bool |
true |
是否拦截内置 fetch 抓取内网/云元数据地址(SSRF 缓解,默认开启):拦截回环、私有网段、链路本地(含 169.254.169.254)、CGNAT 等地址,域名先解析再逐 IP 判定;内网文档抓取场景需设为 false |
exa_enabled |
bool |
true |
是否启用内置 exa.ai MCP 服务器 |
servers |
list[MCPServerConfig] |
[](自定义追加;内置 exa/fetch 预设见 08-mcp.md) |
MCP 服务器列表 |
插件内置 exa(远程 web 搜索,http)与 fetch(本地网页抓取,stdio)两个预设 MCP 服务器,
由 fetch_enabled / exa_enabled 开关控制,开箱即用;servers 默认空列表,仅用于自定义
追加,与预设同名的条目会替代预设连接。详见 MCP 工具集成。servers 列表中的
每个元素为 MCPServerConfig(config.py 的 MCPServerConfig),字段如下:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name |
str |
"" |
MCP 服务器名称(标识用) |
transport |
Literal["stdio", "http", "sse"] |
"stdio" |
传输协议 |
command |
str |
"" |
启动命令(transport="stdio" 时使用) |
args |
list[str] |
[] |
命令行参数列表 |
env |
dict[str, str] |
{} |
环境变量键值对 |
url |
str |
"" |
服务器 URL(transport="http" / "sse" 时使用) |
headers |
dict[str, str] |
{} |
HTTP 请求头 |
MCP 工具进入 Agent 工具集的 Discoverable 层,按权限过滤。不支持运行时动态增删服务器。详见 MCP 工具集成。
[search] — 搜索¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
max_results |
int |
20 |
search_users 返回条数上限 |
[subagent] — 子 Agent¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
bool |
true |
是否启用子 Agent 工具(ask_subagent / ask_subagents),false 时两个工具都不注册 |
max_rounds |
int |
10 |
子 Agent 最大执行轮数(ge=1) |
max_result_chars |
int |
8000 |
子 Agent 答案最大字符数,超长截断 |
max_parallel_subagents |
int |
3 |
ask_subagents 单次批量派发的子 Agent 数量上限(ge=1) |
子 Agent 由主 Agent 通过工具调用触发,结果回传主 Agent 上下文继续判断;配置经 config_getter 热更新,无需重注册。详见 子 Agent。
[plugin_api] — 跨插件 API 工具¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
allowlist |
list[str] |
[] |
允许包装为 Agent 工具(call_*)的插件 API 名;留空(默认)不暴露任何跨插件 API 工具 |
Agent 侧跨插件 API 工具采用显式允许名单:仅名单内的插件 API 会被包装为
call_{api} 工具,且最低角色固定为 ADMIN(不可配置降低);本插件自身 6 个
任务端点(create / list / get / cancel / inject / history)永远排除在包装
之外——Agent 操作任务请用原生 owner 隔离工具(list_my_tasks / create_subtask /
inject_task / cancel_task)。详见 跨插件 API 与
权限模型。
[shell] — 命令执行¶
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
bool |
true |
是否注册 run_command 命令执行工具;false 时 TaskManager.setup() 不注册 |
timeout_seconds |
int |
60 |
命令默认超时(秒,ge=1);超时后强制终止整个进程树 |
max_output_chars |
int |
8000 |
stdout/stderr 单侧最大返回字符数(ge=100),超长截断 |
run_command 仅对 admin 可见(min_role + role_provider 双重门控),子 Agent 允许集排除该工具;配置经 config_getter 热更新,timeout_seconds / max_output_chars 修改后无需重注册立即生效。详见 命令执行。
已知限制¶
default_timeout_min已配置但未执行(config.py:133)。TaskConfig.default_timeout_min声明了ask_user无回复挂起等待时间的意图,但调度器未读取该值:waiting_input状态的任务不因超时而自动取消或推进,而是永久挂起直到用户回复或手动取消。- 跨插件 API 信任模型(无身份时按 ADMIN)。SDK 的
api.call通道不携带调用方身份,6 个跨插件端点对无身份参数的调用按 ADMIN 执行,owner 校验被有意旁路——跨插件调用面向受信任插件。Agent 侧 call_* 工具已收紧:显式允许名单(默认空)+ 最低角色 ADMIN + 自身端点排除,见 [plugin_api] 配置节与 10-cross-plugin-api。