A modular AI Agent runtime for TRSS-Yunzai — LLM · Tool Calling · Memory · MCP · and self-evolving tools.
基于 TRSS-Yunzai / Miao-Yunzai 的 AI Agent 插件框架 —— 不是普通插件,而是一套可演化的 Agent Runtime:多模型对话 · 工具调用 · 长期记忆 · 人设 · 多模态识图 · MCP · 群管 · 终端(E2B 沙箱) · 图片渲染,外加**工具进化(Tool Evolution)**等差异化能力。
一个插件打通:多模型对话 · 工具调用 · 长期记忆 · 人设 · 多模态识图 · MCP · 群管 · 终端(E2B 沙箱) · 图片渲染
QQ 群:960179589 | 作者 QQ:3891977697
- 🎭 表情包功能已恢复:支持自动发现(群聊被动采集 → 视觉判定+打标 → 入库)+ 手动安装(manifest 驱动)+ LLM 自主引用
[sticker:名称]。配置agent.sticker开启。- 🧪 深度搜索 / 深度研究(
#研究)为早期功能:依赖联网检索 + 多轮子代理编排,受搜索源、模型能力、token 消耗影响,效果可能不稳定甚至不可用。⚠️ 终端执行为沙箱能力:默认关闭;开启agent.sandbox.mode: e2b+apiKey(命令在 E2B 微虚机内执行)即视为自担风险。沙箱服务端二选一:E2B 云托管(只填 apiKey)或自托管(必须有 KVM——腾讯云轻量等普通云主机不行,见「自托管安装」)。- ✅ 核心对话(多模型聊天 / 工具调用 / 记忆 / 人设 / 图片渲染 / MCP / 群管)稳定可用,请以核心为主。
- 一插件打通全链路:多模型对话 · 工具调用 · 长期记忆 · 人设 · 多模态识图 · MCP · 群管 · 终端 · 图片渲染,无需东拼西凑。
- ReAct 内核 + 自我反思/自纠:最终回复交付前门控自检(完整性 / 准确性 / 一致性),发现问题自动回环修正;多层频率闸防"每条都带表情"的 AI 感。
- 双协议多模型:OpenAI / Anthropic 兼容,一行配置接 DeepSeek / Kimi / MiMo / 通义 / 智谱 / Gemini;视觉子模型让无视觉的主模型也能识图。
- 渐进式披露 + 结构化 prompt:技能按需加载、工具目录速查、分层 system prompt(执行取向 / 服务准则 / 安全护栏),兼顾能力与上下文成本。
- 文件即真相的记忆:
MEMORY.md/USER.md人可读可编辑 +memory_search主动召回,跨会话不失忆、不串档。 - 安全纵深:工具 RBAC + 主人审批 + 注入防御 + 高危执行面隔离(终端与工具进化代码跑在 E2B 沙箱,宿主无 shell 执行面),高危动作不裸奔。
- 配置热加载 + 锅巴适配:改配置即生效、免重启;锅巴 Web 面板可视化编辑。
- 回复默认渲染成精美图片:markdown → 浅色卡片图(标题 / 列表 / 代码高亮 / 表格 / 引用全支持),失败退文本。
- 🧬 工具进化(Tool Evolution):Agent 经 LLM 生成新工具 → typescript AST 静态门 → 沙箱行为验证 → 主人审批上线,形成可验证 / 可回滚 / 权限不可自扩的工具生命周期(生成→验证→晋升→淘汰闭环)。
| 能力 | 说明 | 状态 |
|---|---|---|
| 💬 多模型对话 | OpenAI / Anthropic 双协议,接 DeepSeek / Kimi / MiMo / 通义 / 智谱 / Gemini 等 | ✅ 稳定 |
| 🖼️ 图片渲染回复 | markdown → 精美浅色卡片图片(完整语法 + 代码高亮 + 底部会话/对话id),失败退文本 | ✅ 稳定 |
| 🔧 工具调用 | ReAct 内核、并行调用、RBAC + 主人审批、工具开发 SDK | ✅ 稳定 |
| 🧠 长期记忆 | MEMORY.md/USER.md 人可编辑 + memory_search 主动召回(参考 OpenClaw) |
✅ 稳定 |
| 🎭 人设系统 | 内置 6 角色 + 自建,替换身份层不缩水工具/记忆 | ✅ 稳定 |
| 🖼️ 多模态识图 | 视觉子模型(主模型无视觉时图转文) | ✅ 稳定 |
| 🔌 MCP | 完整 MCP 客户端(stdio / HTTP)、多服务端、按工具 RBAC | ✅ 稳定 |
| 👥 群聊工具 | 群信息 / 群管理 / 米游社搜索 | ✅ 稳定 |
| 📥 媒体下载 | 基于 yt-dlp 的视频/音频下载(受约束,仅主人),支持 YouTube/B站/抖音等 1000+ 站点 | ✅ 稳定 |
| 💻 终端执行 | E2B 沙箱执行(Firecracker microVM;全员可用 + 出口白名单 + 命令数/并发上限);服务端用 E2B 云或自托管(需 KVM,普通云主机不支持) | |
| 🌐 浏览器自动化 | Stagehand:goto/observe/extract/act 自然语言原语,本地或 Browserbase 云,会话跨调用保持 | 🧪 早期 |
| 🎭 表情包 | 自动发现(群聊被动采集→视觉打标→入库)+ 手动安装 + LLM 自主引用 [sticker:名称] |
✅ 稳定 |
| 🤖 伪人模式 | 群聊环境参与者:旁听→门控→Planner 决策→Replyer 自然回复(参照 MaiBot) | 🧪 早期 |
| 💬 私聊对话 | 私聊触发对话(默认关闭:agent.privateChat=false;开启后私聊任何消息直接触发,独立会话与记忆) |
✅ 稳定 |
| 🌐 代理访问 | HTTP/SOCKS 代理(国内服务器访问 GPT/Gemini 等海外 LLM) | ✅ 稳定 |
| 🔁 回退模型 | 主模型失败自动依次尝试 fallbackModels(同 provider) |
✅ 稳定 |
| 📂 日志分文件 | 按会话分文件 + 图片底部会话/对话id + #上报错误 打包发主人 |
✅ 稳定 |
| 🔍 统一搜索 | Tavily/Exa/Perplexity/Brave → SearXNG → DDG 兜底 | ✅ 稳定 |
| 📊 示意图生成 | 流程图/架构图/时序图/状态图/ER/思维导图:LLM 语义结构 → 自托管 Kroki D2 → 高清 PNG(文字/连线精确,非文生图) | ✅ 稳定 |
| 📚 深度研究 | #研究 五阶段管线(规划→检索→综合→引用→评估) |
🧪 早期 |
| 🧬 工具进化 | LLM 生成候选 → AST 门 + 隔离执行面验证 → 审批上线(版本化 / 可回滚 / 安全闸) | 🧪 早期 |
Agent 不再只从固定工具列表中选择——它能生成新工具、验证、审批上线、持续改进与淘汰,形成可演化的工具库。这是本插件相对普通 Agent 框架的核心差异点,也是搜索词
tool evolution agent的入口。
完整生命周期(安全纵深,五阶段):
#进化工具 <能力描述>
→ LLM 生成(json_schema 结构化)
→ typescript AST 静态门(禁 require / child_process / process.env / eval / 一切 import;危险候选不入库)
→ 隔离行为验证(E2B 沙箱 / 本地子进程双档 + 测试断言 + 性能/超时门)
→ #采纳工具 <id>(master 审批)→ stable + 注入 → agent 经 tool_search 调用
→ 调用埋点 → 适应度 / 失败聚类 → #工具健康 检测 → #淘汰工具 下线
安全原则(不可妥协):
- ① 生成闸:只允许
sideEffects ∈ {none, read};联网 / 发消息 / 删库等固定受信适配器永不自动生成 - ② 可信基不可被工具进化:DB / 验证器 / 沙箱 / 审批 / 审计由人维护,工具不能改
- ③ 版本不可变 + 审计 + 权限单调不增 + 安全硬否决(一票否决,非权重)
命令族(均 master):#进化工具 / #工具进化列表 / #采纳工具 / #淘汰工具 / #工具健康 + Web「工具进化」管理面板。
本插件提供终端(shell)执行能力,命令跑在 E2B 沙箱(Firecracker microVM)里:
- 命令在独立微虚机内执行:宿主文件/进程不可见,网络出口按
agent.sandbox.network.allowOut白名单收紧(默认只放行包管理器与api.openai.com)。 - terminal 全员可用(无身份门槛、无验证码认领):每个会话(群/用户/对话)独占一个沙箱、文件系统互不可见;沙箱化后不再有逐条
#确认审批与命令黑名单(破坏面已被 microVM 限制),成本由单会话命令数上限、单命令超时上限与并发沙箱上限兜底。 - 终端默认关闭(
agent.sandbox.mode默认off,此时 terminal 工具根本不注册),需自行准备 E2B(自托管或云)并填apiKey后开启。 - 连不上 E2B 时一律拒绝执行(fail-closed),绝不回退到主机执行——本插件已删除宿主 shell 执行面。
- 开启
agent.sandbox.mode: e2b即表示你已知晓上述风险、同意自行承担一切后果,与开发者无关。 沙箱逃逸类漏洞、配额/账单消耗、主人账号被盗导致的沙箱操作权,均需自行评估;开发者不作任何担保。
如不接受该风险,请保持
agent.sandbox.mode: off(默认)。此时本插件不涉及任何 shell 执行(含沙箱)。升级注意:旧配置
agent.terminal.*(enable/maxTimeout/blocklist/skipConfirm)已废弃。Config 的自愈机制只增不删,所以旧键会留在你的config/config.yaml里但不再被读取;启动时会打印一条迁移警告,请手工删除该段并改配agent.sandbox。
# Gitee(国内推荐):
git clone https://gitee.com/YunXi-67/trss-agent-plugin.git ./plugins/agents-plugin
# 或 GitHub:
git clone https://github.com/yunhai89/trss-agent-plugin.git ./plugins/agents-plugin
cd ./plugins/agents-plugin && npm install # 安装 markdown 渲染依赖(marked / highlight.js)除 markdown 渲染(marked / marked-highlight / highlight.js,需在插件目录
npm install)外,其余依赖随 Yunzai 提供。#agents更新(git pull)后若 package.json 有变动,需重跑一次npm install。 重启 Yunzai 后,首次启动自动在插件自己的plugins/agents-plugin/config/config.yaml生成配置,填入 API Key 即可使用。
机器人回复默认渲染成精美浅色卡片图片(完整 markdown + 代码语法高亮),渲染失败自动退文本。配置 agent.reply.mode:
image(默认):markdown → 浅色卡片图片(标题/列表/代码高亮/表格/引用全支持)text:纯文本回复
配置文件在插件目录内(不在 Yunzai 根)。若你之前用的是旧版
Yunzai/config/agents-plugin.yaml,首次加载会自动迁移到插件目录并删除旧文件(apiKey/masters 等全部保留)。 支持热加载:改完配置保存即可,无需重启 Yunzai——下次对话自动用新配置重建运行时(provider/model/tools/skills/mcp)。也可发#agents重载(主人)立即重建。锅巴(Guoba)适配:已支持。安装 Guoba-Plugin 后,
#锅巴登录进入 Web 面板即可图形化编辑本插件配置;保存后自动热加载。适配文件为插件根guoba.support.js。
推荐路径:打开 Web 配置中心(主人私聊 #agents登录 取访问地址),在 厂商配置 添加厂商(接口地址 + Key)→ 模型列表 在该厂商下添加模型 → 基础 / 模型 选中这两个条目。保存即热加载。
群里 @机器人 或发 #ai 你好 即可对话。
基础模型是引用式的:config.yaml 里用 providerId + modelId 指向「厂商配置 / 模型列表」的条目,不再单独填接入参数。手写配置的等价写法:
agent:
llmProviders: # 厂商配置(协议/预设/地址/Key 都在这里)
- id: pmain
name: DeepSeek
protocol: openai # 或 anthropic / gemini
preset: deepseek # 厂商预设:openai/deepseek/gemini/dashscope/zhipu/moonshot/mimo/minimax 等
baseURL: ""
apiKey: "sk-xxx" # ★必填
llmModels: # 模型列表(挂在某厂商下)
- id: mchat
name: 主力
providerId: pmain
model: "deepseek-chat"
providerId: pmain # ← 基础模型选哪个厂商
modelId: mchat # ← 基础模型选哪个模型老配置(只有
protocol/preset/baseURL/apiKey/model五个扁平字段)首次加载会自动迁移:按原接入信息生成一条厂商 + 一条模型条目,并让上面两个引用指向它们,无需手工重配。迁移后这五个字段变成只读镜像(由上层引用解析回填),手改会在下次加载被覆盖。
配置文件不含注释(保持整洁),所有字段含义在此说明。未用到的字段留空即可。
| 字段 | 说明 |
|---|---|
debug |
true 打开详细日志(工具入参/每轮 token/搜索词等),排查时开启 |
prefix |
命令前缀(保留备用) |
| 字段 | 默认 | 说明 |
|---|---|---|
trigger |
at |
触发模式:at(艾特) / command(触发词) / both |
triggerCommand |
#ai |
trigger 为 command/both 时的触发词 |
providerId |
空 | ★必填 基础模型选用哪个厂商条目(见下方 ↴ llmProviders) |
modelId |
空 | ★必填 基础模型选用哪个模型条目(须挂在上述厂商下) |
llmProviders |
[] |
厂商清单 [{ id, name, protocol, preset, baseURL, apiKey }];没有“默认厂商”,被 providerId 选中的那个就是主接入 |
llmModels |
[] |
模型清单 [{ id, name, providerId, model, temperature, maxTokens, thinking, note }];thinking/温度/maxTokens 在被主对话链路使用时覆盖全局 |
protocol / preset / baseURL / apiKey / model |
镜像 | 上面引用的解析结果,加载时自动回填;勿手改,改厂商 Key / 换模型会自动跟随 |
utilityModel |
空 | 播报等旁路小模型(留空=沿用主模型);只能在上面所选厂商的「模型列表」里选,因为旁路任务走主 provider 端点 |
reasoningFields |
[] |
推理字段归一化(如 ["reasoning_content"]),preset 通常已带 |
maxTurns |
50 |
单次对话工具调用轮次预算 |
temperature |
空 | 采样温度 |
maxTokens |
空 | 单次回复最大 token(留空=厂商默认;Anthropic 默认 4096) |
contextWindow |
空 | 模型上下文窗口 token 数(如 32000);超 80% 自动压缩历史、保留首条意图 |
maxToolResultChars |
4000 |
单条工具结果字符上限,超长截断防上下文膨胀 |
keepReasoning |
false |
是否把推理(reasoning_content)回灌历史;默认 false 省 context |
stream |
false |
逐字流式输出(依赖适配器、不稳,默认关) |
progress |
true |
工具调用时推送节流进度消息(消除"干等",默认开) |
progressRecall |
3 |
进度消息多少秒后自动撤回(适配器不支持则忽略) |
reply.mode |
image |
回复渲染:image(markdown→浅色图片,默认)/ text(纯文本) |
reply.atSender |
true |
群聊回复时艾特发言人(私聊不艾特) |
reply.narrate |
true |
中途播报:模型调工具时附带的思路/进展文本自动转发给用户(参考 OpenClaw) |
reply.renderScale |
2 |
回复图片渲染倍率(deviceScaleFactor,2=高清;越大越清晰但越耗内存/体积) |
thinking |
空 | 思考模式,如 { type: "enabled", budget_tokens: 16000 } |
memoryLimits |
空 | 声明式记忆字符上限,如 { memory: 2200, user: 1375 } |
systemPrompt |
空 | 默认身份 system prompt(留空用富默认身份;被人设覆盖时失效) |
chatPermission |
master |
#ai 命令权限:master/admin/owner/all |
privateChat |
false |
私聊是否触发对话;默认关(私聊不响应,仅群内 @/命令触发),设 true 开启 |
masters |
[] |
接收审批通知的 master QQ 号列表 |
masterSkipConfirm |
false |
#确认 直接执行(仅主人,控制台有日志不在聊天提示;denylist 仍硬拦)。注:terminal 已沙箱化,不走审批 |
confirmTimeout |
300 |
审批超时自动拒绝(秒) |
guardAction |
flag |
注入防御动作:block(拦截)/flag(隔离标注)/sanitize(脱敏) |
guardSensitivity |
medium |
防御灵敏度:low(0.95)/medium(0.7)/high(0.5) |
redactSecrets |
true |
发送前脱敏:屏蔽回复中的 API Key / token 等敏感信息 |
policy:
categoryMin:
message: 1 # 覆盖内置类别最低角色
mcp_write: 2 # 自定义类别(如 MCP 写工具需群管以上)内置类别阶梯:query:0 / personal:0 / message:1 / group_manage:2 / system:3。角色:member<admin<owner<master(99)。
| 字段 | 默认 | 说明 |
|---|---|---|
enable |
true |
多模态总开关 |
active |
true |
主动收集(消息/引用/合并转发/群文件中的图片文件) |
passive |
true |
被动工具(list_group_files/get_group_file/read_attachment) |
maxImages |
4 |
单次随消息发送最大图片数 |
maxFileBytes |
8388608 |
单文件字节上限 |
degrade |
note |
非视觉模型降级:skip/note/text |
caps |
空 | 覆盖模型能力判定(一般无需配置),如 { vision: true, file: true } |
主模型不支持视觉时,由视觉子模型识图 → 文本描述 → 主模型回答。主模型支持视觉则直发原图、不走此路径。默认复用主模型 protocol/baseURL/apiKey,只换 model。
vision:
enable: true
model: "mimo-2.5" # 视觉模型 ID(必填才启用)
# 以下可选:覆盖为独立厂商
protocol: # 如 anthropic
preset:
baseURL: ""
apiKey: "" # 空则复用主 apiKey
maxTokens: 1024
describePrompt: "" # 自定义"描述这张图"指令| 字段 | 默认 | 说明 |
|---|---|---|
builtin |
true |
启用内置工具包(群信息/群管/米游社) |
dir |
tools |
自定义工具包目录(相对插件根,自动加载) |
| 字段 | 默认 | 说明 |
|---|---|---|
cookie |
空 | 可选,提升搜索成功率/看全文;不填可匿名搜索 |
defaultGid |
2 |
默认游戏 gid(2原神/6星铁/8绝区零/1崩坏三/4未定/3崩坏学院2) |
persona:
dir: "" # 自定义人设目录(默认 data/agents-plugin/personas)🧪 搜索为早期功能,效果取决于搜索源可用性。任填一个 key 即用该源;都不填回退 SearXNG,再兜底 DDG(始终可用)。
search:
tavily: { apiKey: "" }
exa: { apiKey: "" }
perplexity: { apiKey: "" }
brave: { apiKey: "" }
searxng: { url: "" } # 如 http://localhost:8080
ddg: true # 本地 DDG 兜底(默认开)Agent 对话里说「画一下 XX 的流程图/架构图/时序图」即可生图。不用文生图模型——文字、连线、层级精确可靠: LLM 只提交语义结构(节点/连线/分组/时序消息),插件确定性编译为 D2,由自托管 Kroki 容器渲染 SVG, 经安全检查后用 resvg 转高清 PNG(默认宽 1600、2x 清晰度、内置中文字体)随回复发送。
- 支持图类型:flowchart / architecture(容器分组)/ sequence / state / class / er / mindmap
- 主题:paper-blue(默认)/ soft-pastel / technical / midnight(深色)/ sketch(手绘,仅 D2)
- 安全边界:LLM 不能提交 SVG/HTML/坐标/路径;默认禁用公共 Kroki(用户内容不出内网);SVG 输出按不可信内容检查(拒脚本/外链/实体);临时文件只写
data/diagram/(内容哈希命名 + TTL 清理)- 容错:Kroki 不可用 → 连接超时/熔断/结构化失败(可配本地
beautiful-mermaid回退),绝不挂死 Agent 或让用户无回复
部署 Kroki 容器(默认引擎依赖,一次性):
docker compose -f docs/deploy/kroki-compose.yaml up -d
# 然后保持 agent.diagram.kroki.endpoint: http://127.0.0.1:8000diagram:
enable: true
renderer: kroki # 自托管 Kroki 渲染 D2
fallbackRenderer: none # Kroki 失败的本地回退:none | beautiful-mermaid
defaultTheme: paper-blue # paper-blue | soft-pastel | technical | midnight | sketch
defaultFormat: png # png | svg(svg 以可编辑源文件发送)
timeoutMs: 15000 # 渲染总预算(编译+HTTP+栅格化)
targetWidth: 1600 # 输出宽度(px)
maxNodes: 50 # 规模上限(连线 2 倍;超出拒绝渲染并提示模型)
tempTtlMinutes: 30 # 临时图保留时长
kroki:
endpoint: "http://127.0.0.1:8000"
allowPublicEndpoint: false # ⚠️ true=允许 kroki.io 公共服务(图内容将发第三方,强制 HTTPS)
connectTimeoutMs: 2000 # 连接/响应头超时
requestTimeoutMs: 12000 # 单请求总超时(覆盖响应体读取全程)
maxResponseBytes: 4194304 # SVG 响应上限(流式字节计数)
maxConcurrency: 2
circuitBreaker: { enabled: true, failureThreshold: 3, cooldownMs: 30000 }
d2: { layout: elk } # dagre | elk(sequence 固定 dagre)
imageTag: "" # 部署镜像版本声明(进缓存 key;升级镜像后更新)使用示例:
你:用图画一下这个插件的工作流程
Bot:(流程图图片)用户消息 → Yunzai → Agent Loop → 工具调用 → 渲染回复
你:画个时序图看看工具调用过程
Bot:(时序图图片)用户/Agent/工具 三方消息序列
常见排查:
| 症状 | 原因与处理 |
|---|---|
| 回复「渲染服务不可用」 | Kroki 容器未启动/endpoint 配错:docker compose -f docs/deploy/kroki-compose.yaml up -d;或配置 fallbackRenderer: beautiful-mermaid 本地回退 |
| 连续失败每次都要等很久才回 | 熔断器生效中(连续 3 次失败短路 30s),检查容器 docker logs agents-kroki |
| 图太大被拒(output_too_large) | 减少 nodes/edges 数量,或调低 targetWidth |
| 中文显示为方框 | 理论不会发生(内置字体);若手动删除了 resources/fonts/,恢复该文件或保留系统 Noto CJK |
| 中文流程图正常但主题色不对 | Kroki 镜像版本的 D2 主题编号差异:更新 kroki.imageTag 并调整 model/diagram/themes.js 后重启 |
🧪 深度研究处于早期开发,效果可能差或不可用(见顶部「重要提示」)。受搜索源、模型能力、token 消耗影响大,仅作辅助。
| 字段 | 默认 | 说明 |
|---|---|---|
permission |
master |
master(防 token 滥用)/ all |
maxRounds |
3 |
外层 Supervisor 最大轮次 |
maxConcurrent |
3 |
子代理并发上限 |
workerModel |
空 | 子代理模型(空则用主模型;省钱可填便宜模型) |
evaluation |
true |
是否跑五维评估 |
mcp:
requestTimeout: 60000
servers:
fs: # stdio 子进程示例
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "./"]
prefix: "fs"
category: "query" # 字符串:该服务端所有工具同类;或按工具映射 { read_file: "query", write_file: "system", default: "query" }
remote: # HTTP 远程示例
transport: "http"
url: "https://example.com/mcp"
headers: { Authorization: "Bearer ..." }
listen: false
prefix: "rmt"
enabled: true
⚠️ Docker / 精简镜像没有npx?—— MCP 握手超时(ENOENT)部分 Yunzai Docker 镜像只装了
node、没有npm/npx/corepack(某些trss/miao镜像即如此)。此时上面command: "npx"会启动失败:[mcp] xxx 连接失败:传输关闭(进程退出码-2;spawn 失败:ENOENT spawn npx(npx 不在 PATH?…))(旧版本这种情况只甩一句看不懂的
request timeout: initialize;现已立即报出 ENOENT + 退出码 + stderr 末尾,便于定位。)判断:
docker exec <容器> command -v npx—— 输出为空就是容器里没装 npx。解决方案(任选其一,推荐 ①):
- 给容器补上 npm/npx(一次性脚本,推荐):仓库自带
scripts/bootstrap-npm-docker.sh,纯node + curl + tar实现、不依赖包管理器:docker cp plugins/agents-plugin/scripts/bootstrap-npm-docker.sh <容器>:/tmp/bs.sh docker exec <容器> sh /tmp/bs.sh # 装好后 npx 进入容器 PATH,上面 MCP 配置无需任何改动⚠️ 脚本装在「运行中的容器」里,容器一旦重建(重新docker run)会丢失,需重跑;想一劳永逸请把它加进镜像 entrypoint / Dockerfile。- 改用绝对路径:若容器别处有
npx/node,把command换成绝对路径(如/usr/local/bin/npx)。- 绕开 npx:容器内
npm i -g <mcp包>全局安装后,用command: "/usr/bin/node"+args: ["<全局模块入口 js 的绝对路径>"]直接跑;或改用transport: "http"连远程 MCP,本地无需任何进程。
| 指令 | 说明 |
|---|---|
@机器人 +内容 |
艾特对话(默认触发) |
#ai +内容 |
自定义触发词(trigger=command/both) |
#聊天列表 |
查看所有对话(图片) |
#进入聊天 +id |
切换对话 |
#new |
新建对话 |
| 指令 | 说明 |
|---|---|
#人设 / #人设列表 |
查看人设列表(图片) |
#人设 +id |
切换人设 |
#人设详情 +id |
查看人设内容 |
#新建人设 +名称 +内容 |
创建自定义人设并切换 |
#删除人设 +id |
删除(仅创建者/master) |
#重置人设 |
恢复默认 |
| 指令 | 说明 |
|---|---|
#研究 +主题 |
🧪 早期功能:深度研究(结果 PDF→高清图→文本),效果可能不稳定 |
| 指令 | 说明 |
|---|---|
#记忆 |
查看长期记忆 |
#忘掉 +关键词 |
按关键词遗忘 |
#我的提醒 / #取消提醒 +id |
提醒管理 |
#清空所有记录 |
清空自己的对话历史/记忆/笔记/提醒/人设绑定(不含配置;2 步确认) |
| 指令 | 说明 |
|---|---|
#模型切换 +id |
切换 LLM 模型 |
#启用mcp +名 / #停止mcp +名 |
MCP 服务端启停 |
#添加mcp +JSON |
按标准 mcpServers JSON 添加 MCP(连接验证+持久化)。私聊发 #添加mcp(不带 JSON)进入交互式添加:直接粘贴 JSON 即自动测试并应用。如 { "mcpServers": { "zai": { "type":"stdio", "command":"npx", "args":[...], "env":{...} } } } |
#mcp |
MCP 连接状态 |
#确认 +id / #拒绝 +id / #待确认 |
审批待执行危险动作 |
#agents帮助 / #agents状态 |
帮助图 / 运行状态 |
#agents重载 |
热重载配置并立即重建运行时(model/tools/skills/mcp,无需重启框架) |
#agents更新 / #agents强制更新 |
git pull 拉取最新代码(强制=reset 后 rebase),有代码改动时自动重启 Yunzai 生效 |
#agents版本 / #agents更新日志 |
最近提交时间 / 本次更新日志 |
本插件支持两种扩展,详细的开发文档(完整 API 参考 + 示例)已独立到 开发指南.md:
- 工具(Tool):给模型新增"动作",模型可直接调用执行。放
tools/目录自动加载,用defineToolPack/defineTool/paramSDK 编写。 - 技能(Skill):渐进式披露的"说明书",不新增动作、只教模型"什么场景用哪些工具、按什么顺序"。放
skills/目录自动加载,写SKILL.md。
👉 完整的 SDK API(defineTool / param.* / getGroup / ok / fail…)、运行时 ctx 字段、meta 选项(审批 / 串行 / 结果截断)、category 与 RBAC、多组完整示例与常见陷阱,见 开发指南.md。
两层记忆,互补:
- 声明式记忆(
MEMORY.md/USER.md):Agent 的个人笔记 / 用户画像,Markdown 文件、人可读可编辑(位于Yunzai/data/agents-plugin/memories/)。每条一行-bullet,有字符预算(memory 2200 / user 1375)。模型用memory工具 add/replace/remove 维护,自动注入 system prompt。旧版memory.json/user.json首次加载自动迁移为.md。可直接编辑文件,重启后生效。 - 召回式记忆(
memory_search工具):跨会话的长期记忆(偏好/身份/事实/近期事项),相似度×时间衰减召回。模型主动检索——回答涉及用户先前说过的偏好、历史决策、待办前,先调memory_search(query)核实,不要凭印象作答(移植 OpenClaw "Mandatory recall step" 语义)。结果带类型与日期引用。
指令:#记忆 查看、#忘掉 <关键词> 遗忘。
⚠️ 高危:见上方「安全声明」。terminal默认不注册,需agent.sandbox.mode: e2b+apiKey单独开启;开启即视为你知晓风险并自担后果。
terminal 工具让 Agent 在 E2B 微虚机里执行 shell 命令。宿主上没有任何 shell 执行面(旧主机执行路径已删除),拿不到沙箱就拒绝执行。
接入准备(二选一,详见仓库内 e2b-infra-nodejs-安全shell接入开发文档.md):
- E2B 云:只填
sandbox.apiKey(注意:命令与文件会送往第三方)。 - 自托管 Embed:仅限有 KVM 的机器(自家物理机 / 裸金属实例)。腾讯云轻量服务器、普通 CVM/ECS 虚拟机、容器都不行,请用上面的云托管。详见下方「自托管安装」。
说明:插件依赖的
e2bnpm 包只是 SDK(客户端),不含任何沙箱服务端。沙箱由e2b-dev/runtime(Firecracker 基础设施)提供,云托管由 E2B 运营,自托管需自己部署。
硬前提(不满足就不要尝试,装了也跑不起来):
| 项 | 要求 | 为什么 |
|---|---|---|
| KVM | /dev/kvm 存在且可读写 |
每个沙箱是一台 Firecracker microVM,没有硬件虚拟化就无从创建 |
| CPU 虚拟化 | /proc/cpuinfo 含 vmx(Intel)或 svm(AMD) |
没暴露虚拟化扩展的客机=嵌套虚拟化未开启,客机内部无法自行开启 |
| 内存 | 宿主可用内存 ≥ 20 GiB(PF_MIN_FREE_GIB) |
embed 会为沙箱预留大块内存 |
| 磁盘 | 空闲 ≥ 30 GiB | 7 个镜像 + Firecracker + 内核 + 模板 |
| 系统 | Linux x86-64/arm64,4 KiB 页内核,glibc ≥ 2.34,可写 /etc |
官方以 Ubuntu/Debian 验证;不支持 macOS/Windows 宿主与 Container-Optimized OS |
E2B 的每个沙箱是一台 Firecracker microVM,靠 CPU 硬件虚拟化(Intel VT-x / AMD-V)隔离。 因此自托管要求机器上真的有
/dev/kvm——普通云服务器(虚拟机)一律没有:
机器类型 能自托管吗 原因 自家物理机 / 裸金属服务器 ✅ 可以(需 BIOS 开 VT-x/AMD-V) 真机有硬件虚拟化 腾讯云轻量应用服务器 ❌ 不行 本身是虚拟机,不提供嵌套虚拟化,无 /dev/kvm腾讯云 CVM 标准型 / 阿里云 ECS 共享型·通用型(常见规格) ❌ 基本不行 同上,默认不开嵌套虚拟化(个别规格需工单开通且仍受限) 裸金属实例 / 专属宿主机(腾讯云黑石、阿里云神龙裸金属等) ✅ 可以 直通硬件虚拟化 明确标注「支持嵌套虚拟化」的实例 ✅ 可以(需单独开通) 如 GCE --enable-nested-virtualization各种容器 / Docker 内 / WSL2 ❌ 不行 没有独立的 KVM 设备 结论:如果你用的是腾讯云轻量服务器(以及绝大多数普通云主机、容器),自托管这条路走不通——请直接用 E2B 云托管(只填
agent.sandbox.apiKey,命令与文件会送往 E2B 云,请自行评估数据敏感度)。想在云上自托管,只能换到裸金属 / 专属宿主机这类有硬件虚拟化的实例。
不确定?在目标机器上跑体检(不改系统):
scripts/install-e2b-selfhost.sh --check。 典型失败输出:/dev/kvm 不存在+CPU 未向本机暴露虚拟化扩展。另注:除 KVM 外还需 可用内存 ≥ 20 GiB / 空闲磁盘 ≥ 30 GiB——轻量服务器这类小规格即使有 KVM 也不够。
一键部署脚本(推荐,内置上述前提检查,不满足会直接拒绝而不是"装一半"):
# ① 只做前提检查(可先在候选机器上跑,不改系统)
scripts/install-e2b-selfhost.sh --check
# ② 安装(交互式;-y 无人值守;--write-config 装完直接写进插件配置)
scripts/install-e2b-selfhost.sh -y --write-config
# ③ 卸载(停栈 + 官方 host-teardown 还原宿主参数)
scripts/install-e2b-selfhost.sh --uninstall脚本会:检查前提 → apt 装 docker/compose v2/依赖 → 克隆 e2b-dev/runtime 到 /opt/e2b-runtime → 执行官方 host-setup.sh(hugepages/nbd/sysctl)→ docker compose up -d --wait → 跑官方 smoke 自检 → 用控制面 curl 实证创建沙箱 → 导出 sdk.env 三要素并给出配置片段(--write-config 会备份后直接改写 config/config.yaml)。
可调环境变量:E2B_REF(锁定 runtime 版本,生产建议锁 CalVer tag)、E2B_DIR、PF_MIN_FREE_GIB、MIN_DISK_GIB、SKIP_SMOKE。
手工步骤(想自己掌控每一环节时):
sudo apt-get install -y git make docker.io docker-compose-v2 qemu-kvm
git clone https://github.com/e2b-dev/runtime.git && cd runtime/embed/compose
bash scripts/host-setup.sh # hugepages / nbd / sysctl
docker compose up -d --wait
docker compose --profile test run --rm smoke # 冒烟:栈内跑官方 JS SDK + 端口连通性
eval "$(docker compose exec ready cat /run/e2b/sdk.env)" # E2B_API_URL / E2B_SANDBOX_URL / E2B_API_KEY把三要素填进 agent.sandbox.apiUrl / sandboxUrl / apiKey:
agent:
sandbox:
mode: e2b
apiKey: "<sdk.env 里的 E2B_API_KEY>"
apiUrl: "http://<host>:3000" # 控制面
sandboxUrl: "http://<host>:3002" # 数据面(无通配 DNS 时**必须填**,SDK 会自动附路由头)
template: base排障:
| 症状 | 定位 |
|---|---|
--check 报无 /dev/kvm |
见上表:换支持 KVM 的机器/实例规格,或改用云托管 |
控制面 401 / Unauthorized |
apiKey 取错,重读 /run/e2b/sdk.env |
fetch failed 或连 :3002 失败 |
sandboxUrl 未填或 client-proxy 未起:docker compose ps 看服务 |
TemplateError: You need to update the template |
模板的 envd 版本过旧,栈内重跑 base 模板构建脚本 |
| 沙箱跑到一半消失 | TTL 到期;长任务用续期(插件侧 sandboxTtlMs + 半衰续期已内置) |
| smoke 失败 | docker compose logs 逐个服务看;常见是内存/磁盘不足或内核参数未生效 |
部署完成后验证插件侧链路:
E2B_INTEGRATION=1 node model/sandbox/e2b.integration.test.mjs
# 自托管会从插件配置读 apiUrl/sandboxUrl;环境变量优先,便于临时指向别处访问控制:
- 全员可用(无身份门槛):不再有「terminal 主人」验证码认领。安全边界完全由 E2B microVM 承担:每个会话(群/用户/对话)独占一个沙箱,文件与进程互不可见。
- 无审批、无命令黑名单:破坏性命令被限制在会话沙箱内(独立 VM/独立 FS/独立网络命名空间),不再靠字符串规则。
- 成本闸:
maxCommandsPerSession(单会话命令数上限)、maxTimeout(单命令超时)、maxSandboxes(全局并发)+ 闲置回收,防任何用户(含被注入诱导的会话)把配额/账单打爆。
关键配置(agent.sandbox):
| 键 | 默认 | 说明 |
|---|---|---|
mode |
off |
off=terminal 不注册(toolEvo 走本地 fork 档)| e2b=沙箱执行 |
apiKey |
空 | E2B 云或自托管团队 key(★敏感,已接入回复脱敏) |
apiUrl / domain / sandboxUrl |
空 | 自托管控制面 / 沙箱域名 / 数据面(client-proxy)地址;云托管留空 |
template |
base |
沙箱模板(CPU/内存/预装依赖由模板承载) |
maxTimeout |
600 |
单命令超时上限(秒) |
defaultCwd |
/home/user |
沙箱内默认工作目录(宿主路径在沙箱内无意义) |
idleMs / sandboxTtlMs |
300000 / 600000 |
闲置回收阈值 / 沙箱 TTL(毫秒,命中时自动续期) |
maxSandboxes / concurrencyWaitMs |
4 / 15000 |
全局并发上限 / 等名额超时(超时按配额失败) |
maxCommandsPerSession |
50 |
单会话命令数上限(0=不限) |
network.allowOut / denyOut |
包管理器 + api.openai.com / 全拒绝 |
出口白名单(allow 恒优先于 deny);留空白名单=完全断网 |
audit |
true |
每条命令写审计日志(会话键/退出码/命令前 200 字符,不含密钥) |
沙箱会话按「群 + 用户 + 会话」绑定:同一会话内文件与进程状态连续(可先装依赖再跑脚本)。群共享模式(
isolation: false)下同群共用一个沙箱。
搜索(web_search/#研究)若无 Tavily/Exa 等 key,可自建 SearXNG(免费、无 key、隐私):
docker run -d --name searxng --restart=always -p 8080:8080 \
-e SEARXNG_BASE_URL=http://localhost:8080 \
docker.m.daocloud.io/searxng/searxng:latest配置里填:
search:
searxng: { url: "http://localhost:8080" }生产建议给 SearXNG 加 reverse proxy + auth(见 SearXNG 文档)。插件按其 JSON API 调用,无需额外适配。
基于 @browserbasehq/stagehand v4。Agent 用自然语言驱动真实浏览器:打开页面、点击、填表、抽取动态渲染后的结构化数据(弥补 web_crawl 不执行 JS 的不足)。
4 个工具(category:'system',仅框架主人;stagehand__act 写动作额外需 #确认):
stagehand__goto({url})— 打开 URL(多步任务起点,页面跨调用保持)stagehand__observe({instruction?})— 列出可交互元素(只读)stagehand__extract({instruction, schema})— 按自然语言 + JSON Schema 抽结构化数据stagehand__act({instruction})— 点击/输入/提交(写动作,需#确认)
会话:per-scopeUserId 懒启动 + 5min idle 自动关;同一会话复用同一页面,支持"打开 A 站→登录→抓数据"多步任务。
配置(agent.stagehand,默认关):
stagehand:
enable: true
mode: local # local(本地 Playwright+chromium,默认) | cloud(Browserbase)
headless: true
executablePath: "" # 本地 chrome 路径(空=默认/CHROME_PATH;可填复用已装 chrome)
browserbaseApiKey: ""# 云模式必填
modelName: "" # Stagehand 原生模型(如 google/gemini-2.5-flash);空=复用插件 provider(仅 OpenAI 兼容);云模式空=自动选
modelApiKey: ""
idleTimeoutMs: 300000- LLM:Stagehand 每次原语调用要一次 LLM 推理。
modelName留空时复用插件已配的 OpenAI 兼容 provider(deepseek/openai/mimo 等,走 json_schema 结构化输出);插件协议为 anthropic 或想用更强模型,填modelName(五大 provider:openai/anthropic/google/groq/cerebras)。 - 依赖:
@browserbasehq/stagehand+zod(云崽根pnpm install随 workspace 装入插件);本地模式另需 chromium + 系统库(libnss3 libatk-bridge2.0-dev libgtk-3-dev libxss1 libasound2)。 - 云模式(Browserbase)不在主机跑浏览器、无需本地 chromium,但需 apiKey + 外网。
模型在回复中自主判断并内嵌表情包,增强拟人感——模型在文本里写 [sticker:名称],插件在发送层解析替换为对应表情包图片:
- 图片模式(默认):表情包内嵌进渲染出的整张回复图片(文字 + 表情合成一张图)。
- 文本模式:文本段 + 表情图片段混排发出。
ℹ️ 表情资源仅来自自动发现(MaiBot 式):被动采集群内图片 → 视觉判定+打标 → 入库;不再从远端仓库克隆/更新。功能默认关闭;未开启或库为空 → 不注入清单、模型看不到该功能,零影响。
开启 sticker.enable + sticker.autoDiscover 且已配视觉模型(agent.vision.model)后,群内图片会被:
- sha256 去重 → 2. 视觉判定(拒绝照片/普通图片/文档,只收表情包)→ 3. 打标(名称/标签/语义描述)→ 4. 存
resources/stickers/images/discovered/并写入index.json。
入库条目上限 maxDiscovered(超限按 usageCount 升序淘汰冷门);单张大小上限 discoverMaxSizeMB;采集群白名单 discoverGroups(空=所有群)。
四层叠加,保证偶发而非每条都蹦:① prompt 强约束(偶尔/严肃场景不用);② 概率闸 sendRate(门控通过后仅按概率真正带图);③ 冷却 cooldown(同会话最小间隔);④ 防连发(上一条带过则本条不带)。
| 指令 | 说明 |
|---|---|
#表情包状态 |
总数 / 体积 / 高频 Top5 |
#表情包开启 / #表情包关闭 |
热开关 |
关键配置(agent.sticker,enable 默认关):
sticker:
enable: false # 总开关
sendRate: 0.25 # 概率闸:门控通过后实际带图概率
cooldown: 300 # 同会话两次带图最小间隔(秒)
maxPerReply: 2
antiConsecutive: true # 防连发
autoDiscover: false # 自动发现总开关(需 enable + agent.vision.model)
discoverGroups: [] # 采集群白名单(空=所有群都采集)
maxDiscovered: 200 # 自动发现条目上限
discoverMaxSizeMB: 5 # 单张采集大小上限 MB合规:自动发现只采集群内公开图片,经视觉判定过滤照片/文档;发送侧只发本地
images/内物理存在的文件。
apps/ 事件分发与回复编排(agent 对话 / research 研究 / help / render)
model/
├─ render 统一浅色主题 + markdown→图片渲染(marked/highlight.js)
├─ openai · anthropic 协议传输层(流式/重试/熔断/failover)
├─ llm 模型能力注册表 + 熔断器 + 连接池 + embedding
├─ agent ReAct 内核 + 工具/会话/记忆/防护/策略/审批
├─ prompt 分层 system prompt 构建(执行取向/工具目录/技能/安全)
├─ evolution GEPA 提示词自我进化引擎
├─ mcp Model Context Protocol 客户端(多服务端)
├─ multiagent 编排器-工人 / pipeline / parallel / router
├─ search · tavily 统一搜索(多源路由 + DDG 兜底)
├─ research 深度研究五阶段管线 + 报告渲染
├─ media 多模态文件收集/解析/协议转换
├─ vision 视觉子模型识图
├─ miyoushe 米游社帖子搜索
├─ group 群信息 + 群管理工具
├─ persona 人设库 + 激活绑定
└─ toolkit 工具开发 SDK + 自动加载器
tools/ 自定义工具包(自动加载)
skills/ 技能说明书(SKILL.md,自动加载)
utils/ Config 配置读写(插件目录 + 热加载) · Log 分级日志
每个 model/* 模块均有离线自检(node model/<模块>/test.mjs),合计 960+ 断言全绿。
分级日志(utils/Log.js):mark(里程碑)/ info(研究进度)/ debug(工具入参·每轮 token)/ warn / error。开启 debug: true 可看到 AI 每次调用工具的名称、入参、结果与每轮 token 用量,深度研究的迭代轮次与搜索词,便于排查。
一次典型对话会在控制台打出五行 mark 日志,各字段含义如下(以实际输出为例):
[trigger] user=3891977697 gid=960179589 mode=at inputLen=83
[chat] user=3891977697 gid=960179589 conv=3 model=mimo-v2.5-pro persona=default vision=off thinking=off ctx=1116字
[agent] run start ... inputLen=83 msgs=21 tools=39 maxTurns=50
[agent] run end turns=1 stop=stop usage={in:14816,out:808} replyLen=1098 totalMs=19188
[chat] reply turns=1 stop=stop usage=in:14816/out:808 replyLen=1098
[trigger] —— 收到消息、判定触发方式时:
| 字段 | 含义 |
|---|---|
user |
触发者 QQ |
gid |
群号(私聊显示 -) |
mode |
触发方式:at(艾特)/ cmd(触发词命令) |
inputLen |
用户输入字符数 |
[chat] —— 单轮装配完成、调模型前(本轮上下文快照):
| 字段 | 含义 |
|---|---|
conv |
会话 id(#进入聊天 / #new 切换;隔离多轮历史) |
model |
当前主模型 id |
persona |
当前人设 id(default = 内置默认身份) |
vision |
主模型视觉能力:on = 直发原图 / off = 走视觉子模型图转文 |
thinking |
模型深度思考(reasoning)开关:on = 已启用 agent.thinking / off = 未启用 |
ctx |
注入 system 的「情境感知」文本长度(字):含时间/发言者/运行能力盘点/近期群聊等;为空则不显示 |
[agent] run start —— ReAct 主循环开始:
| 字段 | 含义 |
|---|---|
msgs |
发给模型的历史消息条数(会话窗口裁剪后,含本轮 user) |
tools |
注册给模型的工具总数(内置 + 自定义 + MCP) |
maxTurns |
工具调用轮次预算上限(agent.maxTurns,默认 50) |
[agent] run end / [chat] reply —— 循环结束 / 回复发出后:
| 字段 | 含义 |
|---|---|
turns |
实际执行的模型轮次数(1 = 一次性回复,未调工具) |
stop |
终止原因:stop/end_turn = 正常回复结束;clarify = 澄清短路退出;max_turns = 轮次耗尽;blocked = 被注入防御拦截 |
usage |
token 用量:run end 的 {in,out} 与 reply 的 in:../out:.. 是同一份累计值(多轮累加) |
replyLen |
最终回复字符数 |
totalMs |
本轮总耗时(毫秒),仅 run end 有 |
排查要点:
turns很大 /stop=max_turns→ 多步任务卡住或工具反复失败;usage.in持续偏高 → 上下文/记忆膨胀,考虑设contextWindow开压缩;ctx字数 → 判断情境注入量是否过大。
MCP 连不上时先看报错措辞:request timeout: initialize = 服务端进程起来了但没在超时内响应握手(npx 首次下载慢 / 网络不通 / 命令错误);ENOENT spawn npx / 进程退出码-2 = 容器里压根没有 npx(精简 Docker 镜像常见)—— 解决方案见上文 agent.mcp 章节的 进程退出码 N + stderr = 服务端启动即崩溃(缺 API Key / 依赖 / Node 版本,看 stderr 末尾)。
本站在开发过程中参考/借鉴了以下开源项目与研究的思想与实现,谨致谢意:
框架基座
- TRSS-Yunzai —— 插件运行的基座框架
- Miao-Yunzai —— Yunzai 生态前身
- NapCat —— OneBot 协议端(QQ 对接)
伪人模式(核心参考)
- MaiBot(MaiMai-with-u)—— 伪人模式的全程参照:对话关系链与指代消解(回复链解析、被引原文注入、防止认错说话对象)、回复必要性评分体系(强相关分/内容分/压力分/存在感惩罚/指数退避的骨架与参数)、Planner 工具调用式决策(
planner_no_tool_end、wait 连续上限)、记忆命中作用域白名单(_is_hit_allowed:只允许活跃人物命中)、目标消息块防混淆措辞、表情包[sticker:名称]标记式发送、回复编排(chat/utils)。我们在其思路上做了自研增强:Conversation Grounding 层(三对象拆分 + 实体白名单 + 生成校验重生成)、对象纠错识别与情绪冲销、bot↔bot 闭环熔断。
记忆与记忆体系
- OpenClaw 「文件即真相」记忆设计(
MEMORY.md/USER.md人可读可编辑 + 主动召回) - MaiBot 心意/记忆架构 —— 伪人独立记忆库的「睡眠整合」三层记忆设计(短时缓冲 → 每日整合 → 遗忘衰减)
管理面板
- Guoba-Plugin —— 配置热加载与可视化面板思路(本插件自带 Web 面板)
学术研究(GroupWorld × SelfState 设计文档引用)
- Gratch & Marsella — A Domain-independent Framework for Modeling Emotion / EMA: A Process Model of Appraisal Dynamics(情绪评价理论 OCC/EMA)
- Steunebrink et al. — A Formal Model of Emotions: An Analysis and Formalization of the OCC Model
- Park et al. — Generative Agents: Interactive Simulacra of Human Behavior(记忆流与社会仿真)
- Cai et al. — From Triggers to Emotions: A CPM-Grounded Appraisal Multi-Agent(情绪触发→评价多智能体)
若列举有遗漏或表述不当,欢迎指正,将及时补充修正。
- QQ 群:960179589
- 作者 QQ:3891977697
问题反馈、功能建议、工具包分享欢迎进群交流。