乐于分享
好东西不私藏

开阳 Agent 插件体系详解:你的 AI 能力无限扩展

开阳 Agent 插件体系详解:你的 AI 能力无限扩展

开阳(Mizar)的核心卖点是"自举"——让 AI 自己写插件扩展自己。但插件到底能做什么?有哪些 API 可用?今天详细拆解。


插件是什么?


一个 .ts 或 .js 文件,放在 extensions/ 目录下,开阳启动时自动加载。TS 文件走内嵌 esbuild 编译(毫秒级),JS 文件免编译直接跑在 goja(Go 内嵌 JS 引擎)上。改完代码,热加载立即生效,不用重启。


插件的基本结构


一个最小的插件:


export function plugin_init(): void {

  // 插件加载后执行(可选)

  log("磁盘监控插件已加载");

}


export function plugin_cleanup(): void {

  // 插件卸载前执行(可选)

  log("磁盘监控插件已卸载");

}


plugin_init 和 plugin_cleanup 是两个可选的生命周期钩子。init 在插件加载成功后触发(包括热重载),cleanup 在插件被删除或热重载替换前触发。


宿主函数:插件能用的 Go 能力


开阳给插件暴露了一整套宿主函数,涵盖 HTTP、文件、数据库、LLM、网络、日志等。插件通过这些函数调用 Go 核心能力,不需要自己实现底层逻辑。


HTTP 客户端


http_request(method, url, body, headersJSON) → response

统一 HTTP 请求:method 支持 GET/POST/PUT/DELETE/PATCH,headers 是可选的 JSON 字符串。返回响应文本。


http_get(url) → response

薄封装:http_request("GET", url, "", "")


http_post(url, body) → response

薄封装:http_request("POST", url, body, "")


示例:调外部 API

const resp = http_post("http://127.0.0.1:3002/v1/chat/completions",

  JSON.stringify({model: "deepseek-v4-flash", messages: [{role: "user", content: "你好"}]})

);

const data = JSON.parse(resp);


文件操作


fs_read(path) → content

读取文件内容(上限 10MB,超限拒绝)。


fs_read_range(path, offset, length) → [content, totalSize, error]

有界 seek 读:大文件分片读取,单次 4MB,循环处理大文件。


fs_write(path, content) → void

写入文件(自动创建父目录)。


fs_list(path) → fileList

列出目录内容。


示例:读配置文件

const cfg = JSON.parse(fs_read("/etc/myapp/config.json"));

log("数据库地址: " + cfg.db_host);


数据库查询(内置 3 驱动)


db_query(driver, dsn, sql) → JSON

内置 SQLite/MySQL/PostgreSQL 驱动,返回 JSON 结果。


db_close(driver, dsn) → void

关闭数据库连接(显式释放)。


db_exec_batch(driver, dsn, sqlsJSON) → {"rowsAffected":N}

SQL 数组一个事务执行,失败整体回滚。写多行优先 batch(性能提升 10 倍以上)。


示例:建表+插入

db_exec_batch("sqlite3", "/data/app.db", JSON.stringify([

  "CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY, msg TEXT, ts DATETIME DEFAULT CURRENT_TIMESTAMP)",

  "INSERT INTO logs (msg) VALUES ('插件已启动')"

]));


LLM 调用(自举钥匙)


llm_chat(messagesJSON) → response

调用当前配置的 LLM,messages 格式同 OpenAI API。这是自举的核心——插件能调用 AI,AI 又能写插件。


示例:让 AI 分析日志

const resp = llm_chat(JSON.stringify([

  {role: "user", content: "分析这段日志的异常: " + log_content}

]));

log("AI 分析结果: " + resp);


MCP 工具调用


mcp_call(server, tool, argsJSON) → response

调用外部 MCP server 的工具。服务器在 config.json 的 mcp_servers 里配置。


示例:调 Redis

const result = mcp_call("redis", "get", JSON.stringify({key: "my_key"}));


日志和工具


log(message) → void

输出日志(带时间戳)。


sleep(ms) → void

异步等待(毫秒)。


count_tokens(text) → number

计算文本的 token 数量。


钩子系统:监听 Agent 事件


插件可以监听 Agent 的生命周期事件,做统计、审计、自动化。


hook_on(event, callback) → void

注册钩子回调。event 是事件名,callback 是处理函数。


当前支持的事件:

RunStart — Agent 开始处理任务

RunEnd — Agent 完成任务

ToolCall — 工具被调用(可做统计)


示例:统计工具调用次数

let toolCount = 0;

hook_on("ToolCall", (ctx) => {

  toolCount++;

  log("工具调用次数: " + toolCount);

  return ""; // 返回空字符串

});


网络能力:TCP/HTTP/FTP/WebSocket


插件可以开网络服务器或连外部服务,做分布式互联。


TCP 服务器

tcp_listen(addr, onAccept) → connID

开启 TCP 监听,onAccept 回调接入连接。


tcp_send(connID, data) → void

发送数据。


tcp_onrecv(connID, callback) → void

注册接收回调。


tcp_stop(connID) → void

停止服务器。


TCP 客户端

tcp_dial(addr) → connID

连接远程服务器。


http_listen(addr, handler) → addr

开启 HTTP 服务器,handler 是请求处理函数(接收 JSON 请求,返回 JSON 响应)。


示例:开一个 HTTP API

http_listen(":8080", (reqJSON) => {

  const req = JSON.parse(reqJSON);

  if (req.path === "/status") {

    return JSON.stringify({status: 200, body: "ok"});

  }

  return JSON.stringify({status: 404, body: "not found"});

});


WebSocket 客户端

ws_connect(url, onMessage) → connID

连接 WebSocket 服务器。


ws_send(connID, data) → void

发送消息。


ws_onmessage(connID, callback) → void

注册消息回调。


ws_close(connID) → void

关闭连接。


ws_emit(event, data) → void

向所有 WS 客户端推送事件(Server 模式用)。


FTP 客户端

ftp_connect(host, user, pass) → connID

连接 FTP 服务器。


ftp_list(connID, path) → fileList

列出目录。


ftp_upload(connID, localPath, remotePath) → void

上传文件。


ftp_download(connID, remotePath, localPath) → void

下载文件。


安全机制:防止插件搞破坏


panic 隔离:插件里的宿主函数 panic 不会拖垮主程序(defer recover 捕获)。


执行超时:单次执行默认 30 秒,goja Interrupt 打断死循环。


白名单 shell:shell_exec 只允许预定义的命令,防止执行危险操作。


文件大小限制:fs_read 上限 10MB,防止读取超大文件耗尽内存。


热重载:新版本 plugin_init 成功才生效,失败保留旧版本——改坏不丢。


自举:让 AI 自己写插件


这是开阳最酷的能力。你跟它说:


"写一个插件:每天 9 点检查磁盘占用,超过 80% 发飞书告警"


它会生成 disk_watch.ts,内容大概这样:


export function plugin_init(): void {

  hook_on("RunStart", (ctx) => {

    const resp = shell_exec("df -h /");

    if (resp.includes("80%")) {

      http_post("飞书webhook地址", JSON.stringify({msg: "磁盘告警"}));

    }

    return "";

  });

}


热加载后立即生效。你不需要手动写代码,AI 帮你写,AI 帮你扩展。


三层扩展模型


技能层:SKILL.md 纯文本,指导 AI 怎么做(不需要代码)

插件层:.ts/.js 文件,可执行的新工具/能力

工具层:MCP 服务器,任意语言实现


三层互不阻塞:技能不需要代码,插件不需要外网,MCP 不需要改二进制。


实战:一个监控插件的完整例子


假设你要监控服务器内存,超过 90% 发告警:


// extensions/mem_watch.ts


export function plugin_init(): void {

  log("内存监控插件已加载");

  hook_on("RunStart", (ctx) => {

    const resp = shell_exec("free | grep Mem | awk '{print $3/$2 * 100.0}'");

    const usage = parseFloat(resp.trim());

    if (usage > 90) {

      http_post("https://open.feishu.cn/open-apis/bot/v2/hook/xxx",

        JSON.stringify({msg: "内存使用率 " + usage + "%"}));

    }

    return "";

  });

}


export function plugin_cleanup(): void {

  log("内存监控插件已卸载");

}


保存为 extensions/mem_watch.ts,开阳热加载,监控开始工作。


总结:为什么用开阳的插件体系?


零依赖:插件是纯 TS/JS,不需要 npm、node_modules

热加载:改完代码立即生效,不用重启

自举:AI 能自己写插件,你只需要提需求

安全:panic 隔离、超时、白名单,插件搞不垮主程序

生态兼容:SKILL.md 兼容 Anthropic/Hermes 生态

网络能力:TCP/HTTP/FTP/WebSocket 都能用

数据库:内置 SQLite/MySQL/PostgreSQL 驱动

LLM 调用:插件能调 AI,形成自举闭环


一个 25MB 的二进制,一套插件系统,让你的 AI 能力无限扩展。


觉得有用给个 star,GitHub 地址:https://github.com/icefairy/mizar


作者:玄凌子