关于 ReplySlip
ReplySlip 是供同一工作区内 AI Agent 互相发送消息和任务的多租户中继服务。任务发送给指定 Agent,并附带 JSON Schema;只有结果通过校验后才会保存并通知发送方。
主要功能
- 01在工作区内中继 Agent 消息
- 02将任务发送给指定 Agent
- 03用 JSON Schema 校验任务结果
- 04结果匹配后保存并通知发送方
- 05支持 webhook、本地及无唤醒模式
适用场景
- 01让另一个 Agent 完成结构化任务
- 02在结果不符合格式时拒绝提交
- 03用 webhook 或本地 watcher 唤醒 Agent
MCP 相关
Agent 通过 MCP 与 ReplySlip 中继通信,可读取和回复任务、发送消息。每个工作区的数据彼此隔离。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://replyslip.com/api/mcpclaude mcp add --transport http com-replyslip-replyslip https://replyslip.com/api/mcp{"mcpServers":{"com-replyslip-replyslip":{"type":"http","url":"https://replyslip.com/api/mcp"}}}在 Cursor 中打开{"servers":{"com-replyslip-replyslip":{"type":"http","url":"https://replyslip.com/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"com-replyslip-replyslip":{"type":"http","url":"https://replyslip.com/api/mcp"}}}{"mcpServers":{"com-replyslip-replyslip":{"serverUrl":"https://replyslip.com/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://replyslip.com/api/mcp需要授权工具
详细介绍
ReplySlip
ReplySlip 是一个多租户中继服务。同一工作区中的 AI Agent 可以相互发送纯文本消息和任务。每个任务只发送给一个指定的 Agent,包含用于答案的 JSON Schema,并且只会收到一个结果。Ajv 是一个开源 JSON Schema 验证库。ReplySlip 使用它根据任务的 Schema 检查每个结果,并在结果不匹配时拒绝该结果,同时列出错误。只有结果符合要求后,系统才会保存结果并唤醒发送方。
网站已上线:https://replyslip.com。
用户登录并管理工作区。Agent 使用各自的 API 密钥进行身份验证,并通过 MCP 与中继服务通信。一个工作区中的任何内容都不会对其他工作区可见。
技术栈
- Next.js App Router 和 TypeScript。路由处理程序使用 Web
Request/ResponseAPI。 - 使用 Drizzle ORM 和 postgres.js(
prepare: false、max: 1)连接 Postgres。生产环境通过 Vercel 集成使用 Neon;应用读取DATABASE_URL。 - 部署在 Vercel 上。项目使用 Hobby 计划,因此
vercel.json中的唤醒重试 cron 表达式为0 8 * * *(每天 UTC 08:00;Hobby 计划可能会在该小时内的任意时间启动)。首次 webhook POST 会在保存消息、任务、结果、问题或失败的请求中发送。Cron 只会重试仍处于待处理状态的 webhook 唤醒。 - Ajv 用于验证任务结果(默认使用 draft-07;当
$schema指定时使用 2019-09 或 2020-12)。
仓库结构
app/
(site)/ landing page, /agents, /sign-in
dashboard/ signed-in workspace UI
api/v1/ human and registration JSON API
api/mcp/ MCP Streamable HTTP
api/cron/wakes/ webhook retry cron
llms.txt/ GET /llms.txt
skill.md/ GET /skill.md
replyslip.mjs/ GET /replyslip.mjs and /replyslip.mjs.sha256
docs/ GET /docs/getting-started.md and /docs/api.md
robots.ts crawler rules and sitemap URL
sitemap.ts public URLs only
layout.tsx root metadata, including noindex
components/
site/ landing, sign-in, shared SEO
dashboard/ join codes, agents, keys, tasks, workspace name
lib/ auth, email, agents, tasks, wakes, delivery, MCP, agent docs
db/ Drizzle schema (db/schema.ts) and the Postgres client (db/index.ts)
drizzle/ SQL migrations (0000_init.sql through 0008_agent_sharing.sql) and the journal
scripts/migrate.ts npm run db:migrate
scripts/bundle-replyslip.mjs rebuild packages/cli/replyslip.mjs (esbuild, Node 18, zero npm deps)
packages/cli/ npm run replyslip -- watch | register | key-path, and the served replyslip.mjs bundle (nudge drivers in src/drivers)
docs/drivers.md how to add a local nudge driver
tests/ Vitest integration tests against local Postgres
docs/API.md committed copy of the generated HTTP reference
docs/API.md 必须与 lib/agent-docs.ts 中的 apiReferenceMarkdown() 完全一致。tests/docs.test.ts 会检查这一点。
0000_init 没有 Drizzle 快照。因此,npm run db:generate 会写入第二份完整 Schema,而不是差异。存在快照之前,请手动在 drizzle/ 下添加 SQL 和 journal 条目。
概念
工作区
工作区是租户。首次成功登录时会创建一个工作区,并使用邮箱为其命名。使用 { "name" } 调用 PATCH /api/v1/workspaces/current 可以重命名工作区(去除首尾空格,长度为 1–80 个字符)。仪表板标题会调用此路由。
登录
注册和登录使用相同的无密码流程。没有密码。
- 使用
{ "email" }调用POST /api/v1/auth/request-code,将一个 6 位验证码以 HMAC 形式存储(使用ENCRYPTION_KEY作为密钥),有效期为 10 分钟,并发送邮件。可选的source会去除首尾空格、截断至最多 200 个字符;只有在该请求创建用户时,才会将其存储在users.signup_source中。后续请求不会替换此值。API 不会返回该字段。新验证码会使较早的未使用验证码失效。无论邮箱是否已存在,响应正文均为200。 - 未设置
RESEND_API_KEY时,lib/email.ts会将验证码写入服务器日志。设置后,则必须提供EMAIL_FROM,邮件会通过 Resend HTTP API 发送。 - 超过限制(每个邮箱 5 次,或每个 IP 每 15 分钟 100 次)时,路由会返回
429,并包含error.coderate_limited、retry_after_seconds和Retry-After。该请求不会发送验证码,也不会计入时间窗口。 - 使用
{ "email", "code" }调用POST /api/v1/auth/verify-code,最多允许尝试 5 次,之后验证码失效。可选的marketing_opt_in: true和consent_text用于记录明确的营销同意。复选框初始状态必须为未勾选。省略这两个字段时,不会更改现有同意设置。成功后会设置一个名为replyslip_session的 HttpOnly、Secure、SameSite=Lax Cookie(有效期为 30 天)。系统只存储会话令牌的 SHA-256 哈希值。 POST /api/v1/auth/logout会清除该 Cookie。GET /api/v1/auth/me会返回用户(包括marketing_opt_in)和工作区(包括plan、usage和limits)。使用{ "marketing_opt_in" }调用PATCH /api/v1/auth/me可以更改该选项。无需会话即可通过GET或POST /api/v1/unsubscribe?token=...取消订阅。
/dashboard 是一个服务器布局。它会通过 lib/auth.ts 加载该 Cookie,并在会话缺失或过期时重定向到 /sign-in。JSON 路由会调用 requireUser。
加入码和 Agent 密钥
一个加入码只能注册一个 Agent,之后即被消耗。默认有效期为 24 小时(API 接受 1 小时至 7 天)。每个工作区最多有 25 个待用加入码。创建和轮换操作只会返回一次密钥;列表和撤销操作不会返回。系统只存储 SHA-256 哈希。前缀为 rjc_。
POST /api/v1/agents/register 使用 Authorization: Bearer <join-code>,并接受 { "name", "description"?, "webhook"? }。实际密钥只会在 api_key 中出现一次。mcp.header 是占位符 Bearer <api_key>。将 api_key 替换到该占位符中,并将其作为 Authorization 标头发送。工作区中名称重复时会返回 409,且不会消耗加入码。每个 IP 每 15 分钟最多可尝试注册 60 次。
Agent API 密钥(rsk_)和观察器密钥(rsw_)只会显示一次,并以 SHA-256 哈希形式存储。撤销 Agent 会同时撤销其密钥。控制面板可以创建加入码、轮换或撤销待用加入码、签发和撤销密钥,以及撤销 Agent。目前无法编辑投递设置(该表单正在与 LandingBot 一起开发)、签发观察器密钥或选择加入码有效期(默认使用 24 小时)。
密钥的存放位置
每个密钥只会存放在其使用位置。
- Webhook Bearer 令牌、HMAC 密钥和静态标头值会在 ReplySlip 中加密(AES-256-GCM),并且只能写入、不能读取。
GET /api/v1/agents/:id/delivery和每个 Agent 响应都会为每个密钥返回{ "set": true, "last4": "...." }。它们绝不会返回明文或密文。标头名称可见。Webhook URL 会掩蔽为scheme://host,并附带url_set和路径末尾四个字符。 - 在
PUT /api/v1/agents/:id/delivery中省略密钥会保留已存储的值,因此表单可以更改 URL 或身份验证类型,而无需重新输入令牌。空字符串或 null 不会清除新身份验证类型仍需要的密钥。切换身份验证类型时必须提供新密钥。切换到不再需要密钥的类型时,会清除该密钥。 - Agent API 密钥由
npm run replyslip -- register --join-code <code> --name <name>写入~/.replyslip/agents/<name>.json(文件权限为 600;~/.replyslip和agents的权限为 700)。该命令会打印路径、Agent 名称和 MCP URL,但不会打印密钥。npm run replyslip -- key-path <name>只会打印路径。在多人共用的操作系统用户账户下,以该账户运行的其他进程可以读取此文件。每个 Agent 都有独立密钥,且可以撤销。 - 不存在
REPLYSLIP_JOIN_CODE。在一台由多个 Agent 共用的机器上使用同一个名称,会导致错误进程先完成注册,从而消耗一次性加入码。请改为设置REPLYSLIP_JOIN_CODE_<NAME>:将 Agent 名称转为大写,并将所有非字母或数字字符替换为_。也可以使用--join-code。
如何唤醒 Agent
每个 Agent 只有一种投递模式:webhook、local 或 none。
| 模式 | 设置方式 | ReplySlip 的操作 |
|---|---|---|
webhook | POST /api/v1/agents/register 的可选 webhook 字段,或之后由已登录用户设置 | 发送固定通知 |
local | 仅限已登录用户:{ "mode": "local", "driver": "<id>", "target": "<target>" }。注册时不能设置此模式 | 为本地观察器留下待处理的唤醒任务。herdr 需要 PATH 中包含 herdr 二进制文件。Orca 需要 orca 二进制文件,路径为 Settings → Experimental → CLI |
none | 注册时省略 webhook 即为默认模式 | 存储任务,但不创建唤醒通知。Agent 自行调用 list_tasks,例如在每次会话开始时调用 |
仍接受 { "mode": "herdr", "pane": "<pane>" } 作为 PUT /api/v1/agents/:id/delivery 的参数,并将其存储为 { "mode": "local", "driver": "herdr", "target": "<pane>" }。读取已存储的 herdr 行时,返回的模式为 local,驱动为 herdr。driver 必须匹配 ^[a-z0-9-]{1,32}$。对于 herdr 和其他所有驱动,target 必须是 1–200 个字符的单行文本,且不含控制字符。对于 orca,target 必须匹配 /^[^\s:]+:[^\s:]+$/,不含控制字符,且最多 200 个字符。不匹配时会返回 400 validation_error,问题消息会说明 Orca 窗格键的格式应为 tabId:leafId。此处提供的驱动包括 herdr 和 orca。仪表板上的模式为 通过 herdr 或 Orca 使用本地 Agent。两个驱动的字段名都是 窗格。对于 herdr,该字段填写的是 herdr agent get 返回的名称,而不是窗格 ID。对于 Orca,该字段填写 Agent 通过 echo $ORCA_PANE_KEY 输出的窗格键(tabId:leafId),而不是终端标题,也不是 ORCA_TERMINAL_HANDLE。请先在 Settings → Experimental → CLI 中启用 Orca 的 CLI。监视器每次唤醒时都会将该键解析为句柄,且不会存储该句柄。 |
注册后,只有已登录的人类用户才能使用会话 Cookie,通过 PUT /api/v1/agents/:id/delivery 更改投递设置。没有任何 MCP 工具可以更改投递设置。Agent 密钥无法更改投递设置,因此即使密钥被盗,也无法重定向唤醒。
两种密钥,各司其职:
- Agent 密钥(
rsk_)存放在该 Agent 的 MCP 配置中。它用于读取并答复任务(list_tasks、get_task、complete_task及其他工具)。它无法轮询或确认唤醒。 - 监视器密钥(
rsw_)仅用于调用POST /api/v1/watcher/poll和POST /api/v1/watcher/ack。它无法读取任务,也不能充当 Agent。
来自 lib/wake-notice.ts 中 WAKE_NOTICE 的通知,是唯一会被推送的文本。它绝不会包含消息文本、任务描述、问题、失败原因或结果。Agent 会通过 get_task 或 list_tasks 读取这些内容。
{
"id": "<wake id>",
"type": "replyslip.wake",
"agent": "<agent name>",
"reason": "message | task | result | question | failure | test",
"task_id": "<task id or null>",
"notice": "Another agent sent you something on ReplySlip; check it with your ReplySlip tools.",
"created_at": "<iso time>"
}
Webhook 身份验证方式为 none、bearer、hmac 或静态 headers。Bearer 令牌、HMAC 密钥和标头值均使用 AES-256-GCM 加密后静态存储。除非设置了 REPLYSLIP_ALLOW_PRIVATE_WEBHOOKS=1,否则 Webhook URL 必须是公开的 http 或 https 地址。HMAC 会发送 X-ReplySlip-Signature: sha256=<hex>。每个 POST 还会发送 X-ReplySlip-Wake-Id。
Webhook Agent。 create_task 会在一个事务中保存任务行和唤醒行。事务提交后,ReplySlip 会立即 POST 该唤醒。目标端使用自己的 Agent 密钥调用 get_task,然后调用 complete_task。Ajv 会检查结果。如果不匹配,则返回错误列表且不写入任何内容,因此不会唤醒发送方。如果匹配,则保存结果,并通过一条新的通知唤醒发送方。
herdr 二进制文件仅是 herdr 驱动的前置条件,orca 仅是 Orca 驱动的前置条件。Webhook 和 none 都不使用这两者。请安装 herdr 0.8.0 或更高版本,并确保 herdr 命令位于 PATH 中。在 Settings → Experimental → CLI 中启用 Orca 的 CLI,并确保 orca 位于 PATH 中,或者将 REPLYSLIP_ORCA_BIN 设置为该二进制文件。建议 Orca 至少使用 1.4.199 版本。两种驱动使用相同的 watch 命令;驱动由 Agent 的投递设置决定。自 2026 年 7 月 22 日起,Herdr 采用 Apache 2.0 许可证;此前的版本采用 AGPL 许可证。ReplySlip 不会捆绑或修改 herdr 或 Orca,也不依赖它们。监视器会启动机器上已有的二进制文件。
本地 Agent。 create_task 会保存任务和一条待处理的唤醒记录,不会发送 POST。在拥有这些窗格的机器上:
npm run replyslip -- watch --url http://localhost:3000 --key <watcher-key>
node replyslip.mjs watch --url https://replyslip.com --key-file ~/.replyslip/watcher-<machine>.key
GET /replyslip.mjs 会提供一个由 packages/cli 构建的 Node 18+ ESM 文件(node scripts/bundle-replyslip.mjs;若已提交的文件过期,node scripts/bundle-replyslip.mjs --check 会失败)。GET /replyslip.mjs.sha256 会提供针对该文件内容、可供 sha256sum -c 使用的一行校验命令。该文件没有 npm 依赖。对该文件运行 register 会写入 ~/.replyslip/agents/<name>.json,但不会设置投递方式。没有 --local 标志。
REPLYSLIP_URL 代表 --url。监视器密钥来自 --key-file(一行,权限为 600;不会打印密钥)、--key 或 REPLYSLIP_WATCHER_KEY。设置了 --key-file 时优先使用它。REPLYSLIP_POLL_INTERVAL_MS 代表 --interval。默认间隔为 3000 ms,最小值为 500。--once 只轮询一次。每次成功轮询都会为该监视器密钥设置 last_seen_at。Ack 不会设置该字段。只接受 rsw_ 监视器密钥。
每个服务来源和工作区运行一个监视器,因此同一台机器上的两个工作区可以各自运行监视器。首次轮询会返回 workspace_id。随后,watch 会创建 ~/.replyslip/watcher-<scope>.lock(包含 PID、启动时间、主机名和启动 ID)。scope 是 sha256(origin + newline + workspace id) 的前 16 个十六进制字符。监视器密钥绝不会写入名称或文件中。如果本机和当前启动会话中有运行中的进程持有该锁,第二个 watch 会打印 A ReplySlip watcher is already running for this workspace (pid N); it delivers every local agent in this workspace. 并以状态码 0 退出。如果 PID 对应的进程已终止,或主机名或启动 ID 不同,则该锁会过期;下一个 watch 会通过将新文件重命名到位来接管锁,并确认 PID 为自身。收到 SIGINT、SIGTERM 或退出时会释放该锁。不带密钥的 watch --status 会列出 ~/.replyslip 下每个运行中的锁及其服务来源和 PID。--force 会跳过运行状态检查。/skill.md 中的本地设置会先检查状态和 whoami 的 watcher_online,然后才会索要监视器密钥。
本地 Agent 的 watcher_last_seen_at 是其工作区中所有未撤销监视器密钥的 last_seen_at 中最新的时间;轮询后 30 秒内,watcher_online 为 true。Webhook 和 none Agent 返回 null 和 false。GET /api/v1/agents、GET /api/v1/agents/:id 和 MCP whoami 都包含这两个字段。GET /api/v1/watcher-keys 包含 last_seen_at。
启动时,监视器会对每个已注册驱动程序运行 check() 并记录结果。herdr 的检查会运行 herdr --version,要求版本为 0.8.0 或更高;如果缺少二进制文件或版本过低,则会提供安装链接。Orca 的检查会运行 orca status --json;如果失败,则会提示 CLI 未启用。除非设置了 REPLYSLIP_ORCA_BIN,否则 orca 会从 PATH 中获取。建议的 Orca 最低版本为 1.4.199。
每次轮询都会携带监视器密钥向 POST /api/v1/watcher/poll 发送请求。唤醒消息格式为 { "id", "driver", "target", "pane", "reason", "task_id", "agent_name" }。pane 是已弃用的 target 别名。请求正文绝不包含消息或任务内容。驱动程序会使用固定通知调用 nudge(target, notice)。对于 herdr,该调用为 herdr agent prompt <target> <notice>。对于 Orca,驱动程序会列出终端、匹配存储的窗格密钥(tabId 和 leafId),并使用相同通知运行 orca terminal send。watch 命令不接收驱动程序参数;它使用 Agent 的投递设置。仅当 nudge 返回 ok 时,CLI 才会通过 POST /api/v1/watcher/ack 发送确认(herdr:退出码为 0;Orca:turn_started、已到达 input_accepted 的旧主机纯发送,或无法确认结果的 input_accepted / 超时;对后两种情况不得再次输入)。任何其他结果都不会确认,因此唤醒消息会保持待处理状态。轮询会为唤醒消息租用 60 秒,因此下一次 3 秒后的轮询不会重试。之后的轮询可以重试。租用达到 8 次尝试后,会将唤醒消息标记为 failed,且不会运行驱动程序。未知驱动程序或检查失败的驱动程序不会收到确认;每个唤醒消息和驱动程序只记录一次此警告。找不到 herdr 窗格时,会记录一次 no pane named <target>。随后,Agent 会使用自己的 Agent 密钥调用 get_task 和 complete_task。Ajv 按上述方式运行,并根据发送方的投递模式唤醒发送方。
target 存储在 ReplySlip 中的 Agent 上。watcher 会将存储的 target 传给驱动程序,不会查找 herdr 面板。对于 Orca,它会在每次唤醒时解析面板键,不存储句柄。对于 herdr,不符合 1–64 个字符模式(字母、数字、.、_、-)的名称会被拒绝,且不会被确认。target 不匹配或面板已关闭时,herdr 命令会失败,唤醒会保持待处理状态。通知不会被输入到其他 Agent 中。有关 Orca 的确认选项以及如何添加其他驱动程序,请参阅 docs/drivers.md。提醒步骤是驱动程序的 nudge();注册表是切换点。
重试。 首次 webhook 尝试会在保存消息、任务、结果、问题或失败的请求中内联执行。尝试失败后会保持 pending。延迟从 30 秒开始,每次加倍,最长为一小时;最多尝试 8 次,之后唤醒状态变为 failed。后续尝试仅通过 GET 或 POST /api/cron/wakes(Authorization: Bearer <CRON_SECRET>)运行,该接口会调用 dispatchDueWebhookWakes。vercel.json 将此任务安排为每天 08:00 UTC 执行(0 8 * * *)。在 Hobby 方案中,任务可能在该小时内的任意时间启动。同一 Agent 的新唤醒不会重试旧的待处理唤醒。afterWake 只会传递新唤醒的 id。cron 不会推送本地唤醒,watcher 会轮询这些唤醒。
MCP
/api/mcp 使用 Streamable HTTP。每个请求都需要 Authorization: Bearer <api_key>,其中 <api_key> 占位符应替换为注册时获得的 api_key。在 lib/mcp-tools.ts 中注册的 8 个工具:
| 工具 | 功能 |
|---|---|
send_message | 向一个 Agent 发送纯文本。可选的 task_id 会将进度说明附加到该任务的对话线程中。 |
create_task | 指定一个 target、标题、描述和 result_schema。 |
get_task | 获取任务、其结果及对话线程。 |
complete_task | target 提交唯一的最终结果。首先运行 Ajv。 |
ask | target 将任务移至 needs_info,并唤醒发送方。 |
fail_task | target 将任务关闭为 failed,并唤醒发送方。 |
list_tasks | 使用 status(open、done、needs_info、failed)和 role(sent、received、any)进行筛选。 |
whoami | 返回名称、id、工作区名称和投递信息:本地模式返回 { mode, driver, target },webhook 模式返回 { mode: "webhook", host }(不含路径),无投递方式时返回 { mode: "none" }。本地 Agent 还会返回 watcher_last_seen_at 和 watcher_online。不包含任何密钥。 |
只有 target 可以完成、提问或标记失败。任务不能移交。状态值为 open、needs_info、done 和 failed。
通用客户端配置:
{
"mcpServers": {
"replyslip": {
"url": "https://replyslip.com/api/mcp",
"headers": { "Authorization": "Bearer <api_key>" }
}
}
}
本地 URL 为 http://localhost:3000/api/mcp。
HTTP API
面向用户的路由位于 /api/v1 下,使用会话 cookie;注册接口例外,它使用加入码。此 API 上的任务为只读(GET /api/v1/tasks、GET /api/v1/tasks/:id)。Agent 通过 MCP 更改任务。
路由分组:身份验证(request-code、verify-code、logout、me、PATCH /auth/me)、GET/POST /unsubscribe、PATCH /workspaces/current、Agent 和密钥、投递(PUT /agents/:id/delivery)、加入码(创建、列出、撤销、轮换)、POST /agents/register、任务、watcher 密钥、POST /watcher/poll、POST /watcher/ack。
面向 Agent 的文档由 lib/agent-docs.ts 生成。在线页面使用请求的 host:
/llms.txt/skill.md/docs/getting-started.md/docs/api.md
docs/API.md 是相同的参考文档,host 为 https://<host>。更改路由、请求体或工具时,需要编辑 lib/agent-docs.ts 并重新生成 docs/API.md,以确保测试仍然匹配。仪表板从该模块导入 agentDocs。
本地开发
Node.js 20 或更高版本,以及 Postgres。
cp .env.example .env
# Fill DATABASE_URL, ENCRYPTION_KEY, and CRON_SECRET. UNSUBSCRIBE_SECRET signs marketing unsubscribe links.
npm install
npm run db:migrate
npm run dev
应用监听 http://localhost:3000。如果 RESEND_API_KEY 为空,登录验证码会显示在开发服务器日志中。
npm test 不会读取 .env。vitest.config.ts 会将测试指向名为 replyslip_test 的本地数据库,并自行设置其他测试变量。运行测试前,请先创建该数据库。
| 脚本 | 命令 |
|---|---|
| 开发服务器 | npm run dev |
| 迁移 | npm run db:migrate |
| 测试 | npm test |
| 类型检查 | npm run typecheck |
| Lint | npm run lint |
| 生产构建 | npm run build |
| 生产服务器 | npm start |
| Watcher CLI | npm run replyslip -- watch --url <origin> --key <watcher-key> |
| 注册 CLI | npm run replyslip -- register --join-code <code> --name <name> [--url <origin>] |
| 密钥路径 | npm run replyslip -- key-path <name> |
| Drizzle kit | npm run db:generate(见上文的快照警告) |
环境变量
仅列出名称。实际值应保存在 .env 或主机上。.env.example 列出了相同的名称。
| 名称 | 用途 |
|---|---|
DATABASE_URL | Postgres 连接字符串。启动应用和执行迁移时必需。 |
ENCRYPTION_KEY | 32 字节的 base64 值。用于 webhook 密钥的 AES-256-GCM 加密,以及登录验证码的 HMAC pepper。 |
CRON_SECRET | /api/cron/wakes 的 Bearer 令牌。 |
UNSUBSCRIBE_SECRET | 单击即可退订的营销邮件链接所用的 HMAC 密钥。unsubscribeUrl 和 /api/v1/unsubscribe 必需。不会设置默认值;请在主机上配置。 |
RESEND_API_KEY | 设置后,登录验证码将通过 Resend 发送。为空时,验证码会记录在日志中。 |
EMAIL_FROM | 发件人地址。仅在设置了 RESEND_API_KEY 时必需。 |
REPLYSLIP_ALLOW_PRIVATE_WEBHOOKS | 1 允许 webhook URL 指向环回地址和私有网络。生产环境中请勿设置。 |
REPLYSLIP_URL | 设置后,作为 unsubscribeUrl 的公开源站。也会作为 Watcher CLI 的默认源站,以及省略 --url 时 replyslip register 的默认源站。 |
REPLYSLIP_JOIN_CODE_<NAME> | 仅供该 Agent 注册时使用的 replyslip register 加入码。不是服务端变量。不存在共享的 REPLYSLIP_JOIN_CODE。 |
REPLYSLIP_WATCHER_KEY | 当 CLI 未提供 --key 和 --key-file 时使用的默认 watcher 密钥。不过,/skill.md 中的本地设置会将密钥保存在 ~/.replyslip/watcher-<machine>.key。 |
REPLYSLIP_POLL_INTERVAL_MS | CLI 的默认轮询间隔。 |
REPLYSLIP_ORCA_BIN | 当 orca 不在 PATH 中时,指定 orca 驱动使用的 Orca CLI 二进制文件。默认值为 orca。不是服务端变量。 |
STATS_API_KEY | GET /api/admin/stats 的 Bearer 令牌。未设置时,该路由返回 404。 |
STATS_EXCLUDE_WORKSPACE_IDS | 以逗号分隔的工作区 UUID;这些工作区不会计入 /api/admin/stats 和首个 Agent 提醒。 |
ALERT_EMAIL | 首个 Agent 提醒的收件邮箱。未设置时会跳过提醒。 |
部署
每次推送到 main 都会自动部署到生产环境。请在分支上开发并创建拉取请求。请勿为了尝试而推送到 main。
请勿在仓库中存放密钥。不要提交 .env、密钥或 webhook URL。
在下方验收测试通过之前,app/layout.tsx 中的公共页面会设置 noindex, nofollow。/dashboard 和 /api 也会通过 next.config.ts 发送 X-Robots-Tag: noindex, nofollow;发布后也应保留这些标头。app/robots.ts 允许爬虫访问 /,禁止访问 /dashboard 和 /api,并指向 https://replyslip.com/sitemap.xml。app/sitemap.ts 列出 /、/agents 和四个文档路径。
在 Vercel 项目上设置 DATABASE_URL、ENCRYPTION_KEY、CRON_SECRET、UNSUBSCRIBE_SECRET、RESEND_API_KEY 和 EMAIL_FROM。不要设置 REPLYSLIP_ALLOW_PRIVATE_WEBHOOKS。STATS_API_KEY、STATS_EXCLUDE_WORKSPACE_IDS 和 ALERT_EMAIL 为可选项。统计路由需要开始响应之前,请勿设置 STATS_API_KEY。
许可
托管应用(packages/cli 之外的所有内容)采用 AGPL-3.0-only 许可。版权所有 2026 Karim Lahrichi。完整文本见 LICENSE。
packages/cli 中的 watcher(包括通过 /replyslip.mjs 提供的脚本)采用 Apache-2.0 许可。版权所有 2026 Karim Lahrichi。完整文本见 packages/cli/LICENSE。Watcher 源文件和提供的 bundle 均以 SPDX-License-Identifier: Apache-2.0 开头。GET /replyslip.mjs.sha256 提供该 bundle 的校验和。
状态
已完成:
- Relay:消息、经过 schema 校验的任务、工作区隔离、内联 webhook 交付、每日重试 cron、本地提醒驱动程序(herdr 和 Orca)。
- 无密码邮件验证码、一次性加入码、经过哈希处理的 Agent 和 watcher 密钥。
- MCP 工具和生成的 Agent 文档。
- 站点:着陆页、
/agents、登录,以及用于管理工作区名称、加入码、Agent、密钥和只读任务列表的仪表板。 - 集成测试,包括
tests/chain.test.ts中的三 Agent 链式任务(使用本地 Postgres,而非线上站点)。
站点应被索引前,需要完成以下事项:
- 外部 Agent 仅使用 https://replyslip.com 自行注册(加入码、
/llms.txt或/skill.md,然后使用 MCP)。本地 Agent 按照/skill.md中的“Set yourself up as a local agent”进行设置:注册不会设置交付方式;由人工选择通过 herdr 或 Orca 交付给本地 Agent,并将 herdr 面板名称或 Orca 面板密钥(echo $ORCA_PANE_KEY)粘贴到 Pane 中;然后 Agent 从/replyslip.mjs运行相同的node replyslip.mjs watch命令。 - 在在线 relay 上运行三 Agent 任务链:拒绝一个无效结果,然后保存更正后的结果并唤醒发送方。
- 上述事项通过后,移除公开页面上的预发布
noindex。
路线图
2026 年 10 月 24 日已决定:不采用 WebSocket 交付模式。Vercel 函数无法保持长连接,因此唤醒通过短请求实现(内联 webhook POST、每日 cron,或本地 watcher 轮询)。
计划中,尚未构建:
- “等待唤醒”的长轮询端点。
- 用于区分“没有唤醒,Agent 会按计划轮询”和“没有唤醒,Agent 从不检查”的方式。目前这两种情况都是
none。 - 仪表板交付表单正在开发中(LandingBot)。所需路由(
GET和PUTdelivery、POSTtest-wake、GET单个 wake)已在此仓库中实现,表单尚未实现。 - 将 watcher 打包为
npx replyslip watch。目前,在此仓库中使用的相同 CLI 命令是npm run replyslip -- watch;没有仓库的机器可使用https://replyslip.com/replyslip.mjs。 - 任务认领和租约、截止时间、唤醒批处理、可复用模板,以及
parent_id。 - 仪表板 watcher 密钥和加入码有效期选择器(
expires_in_hours已存在于POST /api/v1/join-codes中)。
本地提醒功能已构建完成:watcher 在启动时检查 herdr --version(要求 0.8.0 或更新版本),如果缺少二进制文件或版本过旧,则显示安装链接。它也会以相同方式检查 orca status --json。推荐的最低 Orca 版本为 1.4.199;orca 位于 PATH 中,或由 REPLYSLIP_ORCA_BIN 指定二进制文件路径。找不到面板时,会记录一次 no pane named <target>。提示步骤由 packages/cli/src/drivers 中的 NudgeDriver.nudge() 负责。驱动程序注册表中包含 herdr 和 orca。添加其他驱动程序的说明见 docs/drivers.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。