关于 Webhooks by Wakeshift
Webhooks by Wakeshift 为 AI Agent 提供可监听的 webhook URL,适合需要让 Agent 响应外部事件的开发者。它通过 MCP 工具订阅事件,并在收到 POST、PUT 或 PATCH 请求时唤醒对话。
主要功能
- 01创建 webhook 链接与接收 URL
- 02订阅或取消订阅 webhook 事件
- 03查看近期请求与 webhook 信息
- 04支持 GitHub、Stripe 和 Linear 签名校验
- 05提供实时事件页面与状态
适用场景
- 01GitHub 工作流失败时唤醒 Agent
- 02收到 Stripe 付款事件后启动处理
- 03将 Linear 更新通知发送给 Agent
MCP 相关
提供采用 Streamable HTTP 的 MCP 服务,含 watch、unwatch、recent_posts 和 webhook_info 工具。MCP 客户端可订阅 webhook.received 事件,并在新请求到达时唤醒对话。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://try.wakeshift.ai/t/{link}/mcpclaude mcp add --transport http ai-wakeshift-webhooks https://try.wakeshift.ai/t/{link}/mcp{"mcpServers":{"ai-wakeshift-webhooks":{"type":"http","url":"https://try.wakeshift.ai/t/{link}/mcp"}}}在 Cursor 中打开{"servers":{"ai-wakeshift-webhooks":{"type":"http","url":"https://try.wakeshift.ai/t/{link}/mcp"}}}在 VS Code 中打开{"mcpServers":{"ai-wakeshift-webhooks":{"type":"http","url":"https://try.wakeshift.ai/t/{link}/mcp"}}}{"mcpServers":{"ai-wakeshift-webhooks":{"serverUrl":"https://try.wakeshift.ai/t/{link}/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
Webhooks
一个能唤醒 Agent 的 webhook URL:获取链接,将其添加到你的 Agent(Claude Code、Codex、Cursor、Antigravity、opencode、Copilot CLI 或任何 MCP 客户端)中,让 Agent 监听;每当有人向你的 webhook URL 发送 POST 请求(来自 curl、Postman、GitHub、Stripe、Linear 或你自己的应用),它就会唤醒 Agent。Wakeshift 在 try.wakeshift.ai 上运行。基于 TypeScript SDK @wakeshift/sdk 构建。
工作原理
- 无状态链接。 链接的代码使用
TRY_SECRET签名,并包含一个随机 webhook ID 及其创建时间。MCP URL(/t/<code>/mcp)、页面(/l/<code>)、webhook URL(/in/<token>,每种签名检查对应一个 token)和签名密钥都由此派生。不会存储任何内容。链接在 7 天未使用后过期;上次使用时间保存在数据库中(每个实例最多每 5 分钟写入一次)。链接过期时,会要求 Wakeshift 忘记该 webhook(使用 webhook ID 调用forgetUser,该 ID 是它在应用中的用户):包括其工作区、监听它的对话、这些对话的订阅和投递记录。清理任务会在删除链接自身数据的事务中将其加入数据库队列,每个实例每 10 分钟处理一次队列;失败时会按退避策略重试(从 1 分钟开始,每次加倍,最长 6 小时),直到 Wakeshift 确认完成。 - SDK 用户就是 webhook;帖子是一种事件。
webhook.received(参数:webhook 的 ID;只有 webhook 自身的 SDK 用户,也就是持有其链接的人,才能订阅)会携带发布的内容:summary(说明发生了什么的一行文字),然后是解析后的正文和用于标明发送者的标头。每个工具都由attached.events(wake.attach返回的句柄)包装,并通过attached.inputs接收 Wakeshift 的参数。watch使用call.subscribe订阅调用它的对话;unwatch使用call.unsubscribe结束订阅。包装器会在每个工具的结果中添加一个 Wakeshift 区块:订阅后如何唤醒该对话;否则显示待处理消息和 Codex 线程的信标。调用失败时会结束它创建的订阅。支持 MCP Events 的客户端(ChatGPT)不会创建对话订阅:该区块会提示它自行订阅webhook.received。帖子会变成event.emit。wake.attach会添加subscribe_events、unsubscribe_events和list_subscriptions。 - MCP: 使用带会话的 Streamable HTTP,无需登录(URL 中的代码就是凭据)。实例不保存任何会话数据:初始化时的客户端名称、版本和能力会存储在
Mcp-Session-Id下,每个请求都会根据这些信息,在其到达的任意实例上重新构建 MCP 服务(SDK 的无状态模式传输;此处会检查会话 ID,若未知或属于其他链接则返回 404)。因此会话可以跨重启保留,也无需会话亲和性;客户端名称和能力(它们决定如何唤醒 Cursor、opencode 等客户端,以及客户端是否自行订阅)在每个实例上都准确无误:重建的服务会根据存储的初始化信息回答getClientVersion和getClientCapabilities,包装器也会读取这些信息。闲置 7 天的会话会被删除(客户端需要重新初始化)。工具:watch、unwatch、recent_posts、webhook_info。 - Webhooks:
POST、PUT或PATCH/in/<token>,正文最多 64 KB。事件的text用来说明发生了什么:对于 GitHub(来自X-GitHub-Event),内容为GitHub workflow_run completed: failure on main (tests) in acme/api;对于 Stripe,内容为Stripe invoice.payment_failed: in_…, USD 49.00, open (evt_…, test mode);对于 Linear,内容为Linear Issue create: ENG-123 Checkout page 500s;其他情况则为POST to your webhook,若正文为空则加上(empty body),因为其余信息都在data中:text不会重复正文,因此小型帖子的数据可以完整地显示在 Monitor 的一行中(480 字节)。其data包含解析后的正文(body或body_base64)、请求方法、内容类型、用于标明发送者的若干标头(包括Linear-Event和Linear-Delivery;绝不包含 Authorization、cookie 或签名),以及 Stripe 和 Linear 请求中的source(事件类型和 ID)。重试会合并为一次发布:依据Idempotency-Key、X-GitHub-Delivery、Linear-Delivery或 Stripe 事件的evt_ID 去重。对于 GitHub、Stripe 或 Linear URL,只有该服务自身的 ID 才有效(Idempotency-Key未签名,因此使用新 ID 重放被截获的投递会再次唤醒 Agent);Stripe URL 只使用已签名正文中的evt_ID。GET会说明如何发布;正文超过上限 256 KB 时,会直接断开连接,而不会读取正文。 - 签名检查: 页面中的标签页会为每项检查提供一个 URL,每个 URL 都有自己的 token,因此经过检查的 URL 无法变成开放 URL;开放 URL 会继续对持有者有效,直到用户将其替换(见下文)。GitHub 的
X-Hub-Signature-256和Authorization: Bearer使用按 webhook 和检查项分别派生的密钥(try_gh_…、try_bearer_…)。Stripe 和 Linear 使用各自的密钥:用户将密钥粘贴到页面中,密钥会被封装进该 URL 的 token(使用由TRY_SECRET派生的密钥进行 AES-256-GCM 加密)。密钥仅以这种形式存储:URL 会作为 webhook 的已检查 URL 保存(见下文),直到链接过期。Stripe 的Stripe-Signature(t=…,v1=…,对t.body计算 HMAC-SHA256)必须在 5 分钟内;Linear 的Linear-Signature(正文的十六进制 HMAC-SHA256)要求webhookTimestamp在 1 分钟内。 - 新的开放 URL: 开放标签页中的“获取新 URL”(
POST /l/<code>/rotate)会替换开放 URL。此后,该 URL 的 token 会携带 webhook 的开放 URL 代数,该代数按 webhook 保存在数据库中(hooks.open_gen);向任何其他代数的开放 URL 发帖或发送 GET 请求都会得到 410(replaced),并立即在所有实例上生效。Webhook ID(即 SDK 用户,其订阅也因此保留)、链接和 MCP URL、历史记录以及已检查 URL 都保持不变,实时视图会显示 URL 已更改的一行消息。只有链接代码可以发起此操作(webhook URL 是另一种能力,无法发起此操作),且请求必须来自本站页面:若请求中的Origin或Sec-Fetch-Site表示请求来自其他站点,则返回 403。每个 webhook 每小时最多 10 次(超过后返回 429)。 - Agent 会获知哪个 URL:
watch和webhook_info会提供用户最近选择的已检查 URL(用户打开的 GitHub 或 bearer 标签页、用户创建的 Stripe 或 Linear URL,或服务最近发布到的 URL),并说明使用的是哪项检查。只要链接有效,该信息就会保留。 - 限制(在数据库中原子计数,因此在所有实例间统一生效;采用固定时间窗口:小时和 UTC 日):每个 webhook 的每个 URL 每小时最多 60 次、每天最多 500 次(返回带有
Retry-After的 429),因此持有开放 URL 的人无法耗尽已检查 URL 的配额。被拒绝的帖子(401、413)不计数;重试会计数(每次仍然是向 Wakeshift 发出的请求,因此重复使用Idempotency-Key不能绕过限制)。所有 webhook 合计每小时最多 20,000 次;每个地址每小时最多创建 30 个新链接(IPv6 地址按其 /64 网段计;该小时内以地址的 HMAC 保存)。TRY_PER_HOUR、TRY_PER_DAY、TRY_GLOBAL_PER_HOUR和TRY_LINKS_PER_HOUR可用于更改这些限制;服务条款和隐私政策会说明当前生效的限制。 - 过载: 每个实例最多处理 256 个并发请求(帖子最多占其中四分之三,为页面和工具调用留出一些余量),以及 900 条打开的流(实时视图、MCP GET 和监听流);对于单个 webhook,实时视图最多 20 条,此外 Agent 流也最多 20 条,避免 Agent 占满连接,导致页面无法打开;单个 MCP 会话最多允许 2 条 GET 流(超出时,实时视图返回 429,GET 流返回 405)。超过限制,或数据库不可用、连接耗尽时,服务会返回带有
Retry-After的 503 和纯文本消息(webhook 返回 JSON,MCP 返回 JSON-RPC,页面返回页面),绝不返回 500。即使数据库缓慢,链接页面仍会显示,只是不会显示历史记录;实时视图会重试并说明情况(见下文)。Wakeshift 自身在发布时返回的 429 或 503,会转换为带有Retry-After的 503 返回给发布者。 - 页面的实时视图通过此服务的 SSE(
/l/<code>/live)提供:每条帖子(已收到、被拒绝或被限流的帖子、所发布内容的开头,以及发布触达的监听对话数),以及每次 watch 和 unwatch。消息行保存在数据库中(每个 webhook 保留最近 50 条),并通过 webhook 的通道上的NOTIFY推送到所有实例上的页面(每个实例只对有页面打开的 webhook 执行LISTEN;连接断开后恢复时,会重放最近的消息行;每 30 秒对该连接执行一次 ping,以便检测无声断连)。每个实例对单个 webhook 的被拒绝和限流帖子每分钟最多记录 10 行,避免错误签名洪水挤掉真实帖子。其余帖子会计数;每分钟结束时(或实例停止时),每个实例都会将计数汇总到该 webhook 在该分钟对应的一行中,页面会原地更新这一行:每分钟一行,汇总所有实例的数据;每个实例对每个 webhook 每分钟最多写入一次。无法及时处理已写入数据的实时视图会被断开连接(EventSource 会重新连接)。每一行都带有对应的seq作为 SSE ID;实时视图会请求其最新一行之后的消息(?after=<seq>,或 EventSource 自动重新连接时使用Last-Event-ID),因此即使中间有消息遗漏,也会显示期间发生的情况(最近 50 条范围内)。服务器拒绝连接时(429、503),EventSource 会停止重连;页面会在 2 秒后尝试重连,之后逐渐延长间隔,最长为 30 秒(间隔会略作随机调整);连接成功后间隔重置为 2 秒;页面再次打开、网络恢复或状态轮询获得响应时会立即重试(page.ts中的liveConnection)。页面会显示谁调用了watch、每条帖子“已发送至 N 个监听对话”,以及 Agent 当前是否已连接及其连接方式(stream、hooks 或 polling):页面每 10 秒轮询一次/l/<code>/status,使用 webhook 的 ID 查询 Wakeshift 中webhook.received的状态(只读的event.status)。
自行运行
-
在 Wakeshift 控制台 中,打开 Build → New app 并复制其密钥(
wst_…)。 -
创建一个空的 Postgres 数据库。Webhooks 启动时会创建其数据表(
migrations/)。 -
从仓库根目录开始,先构建 SDK,再构建 Webhooks:
(cd third_party/wakeshift-node && npm ci && npm run build) cd webhooks && npm ci && npm run build -
将
.env.example复制为.env,填写内容并运行:变量 WAKESHIFT_KEY第 1 步中的应用密钥 WAKESHIFT_COREWakeshift 的 URL(默认为 https://app.wakeshift.ai)TRY_SECRET用于签署链接;至少需要 32 个随机字节。更改后,所有链接都会失效 TRY_DATABASE_URL第 2 步中的数据库;所有实例共用该数据库 TRY_DB_POOL每个实例的连接数(默认为 3),另加一个用于监听实时视图的连接 PUBLIC_URL你的副本的公开 URL(默认为 http://localhost:$PORT)PORT监听端口(默认为 8380) TRY_PROXY_HOPS前置代理中会将内容追加到 X-Forwarded-For的代理数量(Google 的负载均衡器为 2);0 表示使用套接字地址TRY_PER_HOUR、TRY_PER_DAY、TRY_GLOBAL_PER_HOUR、TRY_LINKS_PER_HOUR可选:上述限制 set -a; . ./.env; set +a npm start -
打开
PUBLIC_URL获取链接,然后运行 Agent 对应标签页中显示的命令。
测试
npm run lint
npm test # unit tests; needs WAKESHIFT_TEST_DATABASE_URL, a Postgres URL for a role that can create databases
端到端测试和负载测试会针对 Wakeshift 服务运行 Webhooks,因此需在 Wakeshift 自己的仓库中运行。
贡献
此仓库由 Wakeshift 主仓库生成。欢迎提交拉取请求:我们会在主仓库中应用这些更改并发布结果。请参阅 CONTRIBUTING。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。