@partme.ai/openclaw-gotify
v2026.5.20
Published
OpenClaw Gotify channel plugin — REST delivery, WebSocket stream inbound, bootstrap helpers, and config validation
Maintainers
Readme
OpenClaw Gotify
OpenClaw 插件:Gotify 渠道桥接 — REST API 推送 + WebSocket 流接收 + 多账号会话隔离
@partme.ai/openclaw-gotify 是为 OpenClaw 开发的 Gotify 渠道插件:通过 REST API 发送消息,通过 WebSocket /stream 实时接收消息,并完整支持 Application 和 Client 的 生命周期管理。
📖 简介
OpenClaw Gotify(@partme.ai/openclaw-gotify)基于 Gotify 官方 REST API 和 WebSocket Stream API,将自托管的 Gotify 推送服务器桥接到 OpenClaw Agent 系统。插件按照官方文档使用 defineChannelPluginEntry + ChannelPlugin 实现。
🎯 核心能力
- REST 消息发送 — 通过 Gotify Message API (
POST /message) 发送 Agent 回复 - WebSocket 流接收 — 通过 Gotify Stream API (
GET /stream) 实时接收入站消息 - Application 管理 — 完整的 CRUD:创建、更新、删除、上传图标
- Client 管理 — 完整的 CRUD:创建、更新、删除
- 消息管理 — 获取消息列表(游标分页)、按 ID 删除、批量删除
- 多账号多智能体 —
accounts映射支持多个 Gotify 实例,按dmScope粒度隔离会话 - 会话隔离 — 完全遵循 OpenClaw 全局
session.dmScope配置(main/per-peer/per-channel-peer/per-account-channel-peer) - 幂等去重 — 30 秒窗口内相同消息 ID 不会重复派发
生命周期
- WebSocket 监听器在 Gateway 对 Gotify 渠道执行
startAccount时启动 - 账号级并发锁确保同一 Gotify 实例的请求串行化,防止触发限流
- HTTP
GET /gotify/status、/gotify/health、/gotify/doctor在入口的registerFull中注册 - 会话键粒度遵循 OpenClaw 全局
session.dmScope配置 package.json→openclaw.setupEntry指向dist/setup-entry.js,通过defineSetupPluginEntry导出轻量入口
前置要求
- 已安装 OpenClaw(
>=2026.4.0,见package.json中peerDependencies与openclaw.compat/openclaw.build) - Node.js 22+(与官方 Building plugins 前置要求一致)
- 一个运行中的 Gotify 服务器(v2.x+)
安装
1. 使用 OpenClaw CLI(推荐)
openclaw plugins install @partme.ai/openclaw-gotify然后在 channels.gotify 中填写配置(见下文)。
2. 使用 npm(手动 / 高级)
npm install @partme.ai/openclaw-gotify再按你所用版本的规则,通过 openclaw.plugin.json、plugins.entries 等将包接入 OpenClaw。
配置
最小配置(单账号)
{
"channels": {
"gotify": {
"serverUrl": "https://gotify.example.com",
"appToken": "Axxxxxxxxxxxxx",
"clientToken": "Cxxxxxxxxxxxxx",
"defaultPriority": 5,
"inbound": {
"enabled": true
}
}
}
}多账号多智能体
{
"channels": {
"gotify": {
"defaultAccount": "ops",
"accounts": {
"ops": {
"serverUrl": "https://ops-gotify.example.com",
"appToken": "A_ops_token",
"clientToken": "C_ops_client",
"defaultPriority": 5,
"inbound": { "enabled": true }
},
"alert": {
"serverUrl": "https://alert-gotify.example.com",
"appToken": "A_alert_token",
"clientToken": "C_alert_client",
"defaultPriority": 9,
"inbound": { "enabled": true }
}
}
}
},
"agents": {
"ops-agent": {
"channels": { "gotify": { "accounts": ["ops"] } }
},
"alert-agent": {
"channels": { "gotify": { "accounts": ["alert"] } }
}
},
"session": {
"dmScope": "per-account-channel-peer"
}
}配置说明
顶级配置(单账号兼容模式)
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| enabled | boolean | true | 是否启用渠道 |
| name | string | — | 账号显示名称 |
| serverUrl | string | — | Gotify 服务器地址(如 https://gotify.example.com) |
| appToken | string | — | 应用 Token,用于发送消息(前缀 A) |
| clientToken | string | — | 客户端 Token,用于接收消息和管理 API(前缀 C) |
| defaultPriority | number | 5 | 默认消息优先级(0–10) |
| defaultAccount | string | — | 多账号模式下的默认账号 ID |
| accounts | object | — | 多账号配置映射 |
inbound — WebSocket 流配置
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| enabled | boolean | false(有 clientToken 时为 true) | 是否启用 WebSocket 流监听 |
| reconnectDelayMs | number | 2000 | 初始重连延迟(毫秒) |
| maxReconnectDelayMs | number | 30000 | 最大重连延迟(指数退避上限) |
| maxReconnectAttempts | number | 10 | 最大重连尝试次数 |
环境变量声明
以下环境变量在 openclaw.plugin.json 的 channelEnvVars 中声明,供 OpenClaw 的 setup 发现机制在插件加载前通告给用户。插件代码不直接读取 process.env — 所有配置均从 channels.gotify 配置节解析(参见上面的配置章节)。
| 变量 | 用途 |
|------|------|
| GOTIFY_SERVER_URL | Gotify 服务器地址 — 等同于配置 channels.gotify.serverUrl |
| GOTIFY_APP_TOKEN | 应用 Token — 等同于配置 channels.gotify.appToken |
| GOTIFY_CLIENT_TOKEN | 客户端 Token — 等同于配置 channels.gotify.clientToken |
🏗️ 消息处理流程
┌──────────────────────────────────────────────────────────┐
│ Gotify Server │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐ │
│ │ Message API │ │ Stream API │ │ App/Client API │ │
│ │ POST /msg │ │ WS /stream │ │ CRUD │ │
│ └──────┬──────┘ └──────┬───────┘ └───────┬────────┘ │
└─────────┼────────────────┼──────────────────┼───────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────┐
│ openclaw-gotify Plugin │
│ │
│ Outbound: mapOutbound → sendGotifyMessage → Message API │
│ Inbound: WebSocket → dedup → dmScope session → Agent │
│ Admin: list/create/update/delete Apps & Clients │
│ Health: GET /health → latency check │
└──────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ OpenClaw Gateway │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ Agent │ │ Session │ │ Channel Reply │ │
│ │ Routing │ │ Store │ │ Pipeline │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
└──────────────────────────────────────────────────────────┘- Gotify 应用或外部系统发送消息到 Gotify 服务器
- 插件通过 WebSocket
/stream实时接收消息 - 幂等去重(30 秒窗口)
- 解析对端标识(
extras.openclaw.peerId→appid→title) - 按
session.dmScope构造会话键 - 路由到对应 Agent 处理
- Agent 回复通过
POST /message(App Token)发送回 Gotify
🧭 dmScope 会话隔离
插件完全遵循 OpenClaw 全局 session.dmScope 配置,无需额外自定义隔离配置。
| dmScope | 会话键格式 | 隔离粒度 |
|---------|-----------|----------|
| main | agent:<agentId>:main | 所有消息共享同一会话 |
| per-peer | agent:<agentId>:direct:<peerId> | 按对端隔离 |
| per-channel-peer | agent:<agentId>:gotify:direct:<peerId> | 按渠道+对端隔离 |
| per-account-channel-peer | agent:<agentId>:gotify:<accountId>:direct:<peerId> | 按账号+渠道+对端隔离(推荐多账号) |
对端标识解析优先级:extras.openclaw.peerId → appid → title → "gotify"
🧪 测试
# 单元测试
npm test
# 类型检查
npm run typecheck
# 构建
npm run build🤖 GitHub Actions
| 工作流 | 触发方式 | 作用 |
|--------|----------|------|
| ci.yml | push / PR 到 main | 安装、类型检查、构建、测试 |
| release.yml | v* 标签 | 构建、测试并发布 npm 包 |
📦 发版
npm version patch
git push origin main --follow-tags📁 项目结构
openclaw-gotify/
├── src/
│ ├── index.ts # defineChannelPluginEntry + registerFull(HTTP 路由)
│ ├── setup-entry.ts # defineSetupPluginEntry 轻量入口
│ ├── channel.ts # ChannelPlugin 定义 + dispatchInboundMessage
│ ├── gotify-api.ts # Gotify REST API 全量封装(Message/Application/Client/Health)
│ ├── config.ts # 配置解析(多账号合并、默认值补齐)
│ ├── channel-config.ts # ChannelConfigSchema(Zod + JSON Schema)
│ ├── dm-scope.ts # dmScope 解析 + 会话键构造
│ ├── message-mapper.ts # 入站/出站消息映射
│ ├── outbound.ts # ChannelOutboundAdapter
│ ├── ws-listener.ts # WebSocket 流监听器(指数退避重连)
│ ├── setup.ts # Bootstrap + Doctor
│ ├── runtime.ts # 运行时状态管理
│ ├── config-wizard.ts # 配置向导
│ ├── gotify-client.ts # GotifyClient 类封装
│ └── types.ts # 类型定义
├── docs/
│ ├── Gotify-Complete-Reference_CN.md # Gotify 服务端完整技术参考
│ └── OpenClaw-Plugin-Mechanism-Complete-Reference_CN.md # OpenClaw 插件机制参考
├── scripts/
│ └── test-client.ts # 集成测试客户端
├── openclaw.plugin.json # 插件清单
├── package.json
└── README.md / README_CN.md📚 OpenClaw 官方文档
📚 Gotify 参考
❓ 常见问题
必须同时配置 appToken 和 clientToken 吗?
如果只需要发送消息(出站),仅配置 appToken 即可。如果需要实时接收消息(入站 WebSocket 流),则需要 clientToken。对于完整的双向通信,两者都需要。
WebSocket 连接断开后会自动重连吗?
是的。插件使用指数退避重连策略:初始延迟 reconnectDelayMs(默认 2000ms),每次失败翻倍,上限 maxReconnectDelayMs(默认 30000ms),最多重试 maxReconnectAttempts(默认 10)次。
如何实现多智能体隔离?
通过 session.dmScope 配置会话隔离粒度。推荐多账号场景使用 "per-account-channel-peer",这样不同 Gotify 应用的消息分配到独立的会话。
Gotify 消息如何路由到不同的 Agent?
入站消息通过 extras.openclaw.peerId 字段指定对端标识,或根据发送方 Application ID 自动识别。然后通过 OpenClaw 的 Agent 路由配置确定目标 Agent。
📄 开源协议
本项目采用 MIT License 协议。
🙏 致谢
如果这个项目对你有帮助,请给我们一个 ⭐️
Made with ❤️ by PartMe
