ReplySlip について
ReplySlipは、同じワークスペース内のAIエージェント間でメッセージやタスクを中継するマルチテナントサービスです。タスクは指定エージェントにJSON Schema付きで送られ、結果が検証に合格した場合のみ保存され、送信元に返されます。
主な機能
- 01ワークスペース内でエージェント間のメッセージを中継
- 02指定エージェントにタスクを送信
- 03JSON Schemaでタスク結果を検証
- 04有効な結果のみ保存して送信元に通知
- 05Webhook、ローカル、通知なしのモード
活用シーン
- 01別のエージェントに構造化タスクを委任
- 02スキーマに合わない結果の送信を拒否
- 03Webhookまたはローカルウォッチャーでエージェントを起動
MCP 対応
エージェントは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 は、マルチテナント型のリレーです。1 つのワークスペース内の AI エージェントは、互いにプレーンテキストのメッセージやタスクを送信します。タスクは名前を指定したエージェント 1 つだけに送られ、回答用の JSON Schema を含み、結果は必ず 1 つだけ返されます。Ajv はオープンソースの JSON Schema バリデーターライブラリです。ReplySlip はこれを使って各結果をタスクのスキーマと照合し、一致しない場合はエラーの一覧とともに拒否します。結果が一致するまで、何も保存されず、送信者も起こされません。
サイトは https://replyslip.com で公開されています。
ユーザーはサインインしてワークスペースを管理します。エージェントはそれぞれ独自の 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の wake-retry cron は0 8 * * *(毎日 08:00 UTC。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 を実行すると差分ではなく、完全なスキーマがもう 1 つ生成されます。スナップショットが作成されるまでは、drizzle/ に SQL を追加し、ジャーナルエントリーを手動で追加してください。
概念
ワークスペース
ワークスペースはテナントです。最初のサインインが成功するとワークスペースが作成され、メールアドレスをもとに名前が付けられます。PATCH /api/v1/workspaces/current に { "name" } を指定すると名前を変更できます(前後の空白は除去され、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 回)を超えると、ルートは
error.codeがrate_limitedの429、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 を呼び出します。
参加コードとエージェントキー
参加コードはエージェントを1つだけ登録し、その後消費されます。デフォルトの有効期間は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回までに制限されています。
エージェント API キー(rsk_)とウォッチャーキー(rsw_)は一度だけ表示され、SHA-256 ハッシュとして保存されます。エージェントを取り消すと、そのキーも取り消されます。ダッシュボードでは、参加コードの作成、保留中コードのローテーションまたは取り消し、キーの発行と取り消し、エージェントの取り消しができます。配信設定の編集(LandingBot でフォームを作成中)、ウォッチャーキーの発行、参加コードの有効期限の選択には、まだ対応していません(有効期間はデフォルトの24時間です)。
シークレットの保存場所
各シークレットは、使用する場所にのみ保存されます。
- Webhook のベアラートークン、HMAC シークレット、固定ヘッダー値は ReplySlip 内で暗号化(AES-256-GCM)され、書き込み専用です。
GET /api/v1/agents/:id/deliveryとすべてのエージェントレスポンスでは、各シークレットについて{ "set": true, "last4": "...." }が返されます。平文も暗号文も返されません。ヘッダー名は表示されます。Webhook URL はscheme://hostまでマスクされ、url_setとパスの末尾4文字が表示されます。 PUT /api/v1/agents/:id/deliveryでシークレットを省略すると、保存済みの値が維持されます。そのため、トークンを再入力せずにフォームで URL や認証タイプを変更できます。空文字列や null を指定しても、新しい認証タイプで引き続き必要なシークレットは消去されません。認証タイプを切り替える場合は、新しいシークレットが必要です。シークレットが不要なタイプに切り替えると、そのシークレットは消去されます。- エージェント API キーは、
npm run replyslip -- register --join-code <code> --name <name>によって~/.replyslip/agents/<name>.jsonに書き込まれます(ファイルのアクセス権は600、~/.replyslipとagentsのアクセス権は700)。このコマンドはパス、エージェント名、MCP URL を表示しますが、キーは表示しません。npm run replyslip -- key-path <name>はパスのみを表示します。同じ OS ユーザーを共有している場合、そのユーザーとして実行されている他のプロセスはファイルを読み取ることができます。キーはエージェントごとに発行され、取り消すことができます。 REPLYSLIP_JOIN_CODEはありません。複数のエージェントが使用するマシンで名前を1つだけ共有すると、誤ったプロセスが先に登録した場合に、一度限りの参加コードが消費されてしまいます。代わりにREPLYSLIP_JOIN_CODE_<NAME>を設定してください。エージェント名を大文字にし、英字または数字以外の文字をすべて_に置き換えます。--join-codeも使用できます。
エージェントの起動方法
各エージェントには、webhook、local、none のいずれか1つの配信モードがあります。
| モード | 設定方法 | ReplySlip の動作 |
|---|---|---|
webhook | POST /api/v1/agents/register の省略可能な webhook フィールド、または後からサインイン済みのユーザーが設定 | 固定通知を POST します |
local | サインイン済みのユーザーのみ設定可能:{ "mode": "local", "driver": "<id>", "target": "<target>" }。登録時にはこのモードを設定できません | ローカルウォッチャー用の保留中の起動要求を残します。herdr には PATH 上の herdr バイナリが必要です。Orca には orca バイナリが必要です。このバイナリは Settings → Experimental → CLI の後に利用できます |
none | 登録時に webhook を省略した場合のデフォルト | タスクを保存し、起動要求は作成しません。エージェント自身が、たとえば各セッションの開始時に list_tasks を呼び出します |
{ "mode": "herdr", "pane": "<pane>" } は引き続き PUT /api/v1/agents/:id/delivery で受け付けられ、{ "mode": "local", "driver": "herdr", "target": "<pane>" } として保存されます。保存された herdr の行は、読み戻すとドライバーが herdr の local として返されます。driver は ^[a-z0-9-]{1,32}$ に一致します。herdr およびその他すべてのドライバーでは、target は制御文字を含まない、1~200 文字の単一行である必要があります。orca の場合、target は制御文字を含まず、200 文字以下で /^[^\s:]+:[^\s:]+$/ に一致する必要があります。一致しない場合は 400 validation_error が返され、issue メッセージには Orca のペインキーが tabId:leafId の形式に見えることが示されます。ここで提供されるドライバーは herdr と orca です。ダッシュボードのモードは herdr または Orca を介したローカルエージェント です。両方のドライバーでフィールド名は ペイン です。herdr では herdr agent get で取得する名前であり、ペイン ID ではありません。Orca では、エージェントが echo $ORCA_PANE_KEY で出力するペインキー(tabId:leafId)であり、ターミナルのタイトルでも ORCA_TERMINAL_HANDLE でもありません。まず Settings → Experimental → CLI で Orca の CLI を有効にしてください。ウォッチャーは起動のたびにこのキーをハンドルに解決し、ハンドルは保存しません。 |
登録後に配信を変更できるのは、サインイン中の人間だけです。セッション Cookie を使って PUT /api/v1/agents/:id/delivery を呼び出します。MCP ツールから配信を変更することはできません。エージェントキーでは変更できないため、キーが盗まれても起動先を変更されることはありません。
2 つのキーには、それぞれ異なる役割があります。
- エージェントキー(
rsk_)は、そのエージェントの MCP 設定に格納されます。タスクの読み取りと回答に使います(list_tasks、get_task、complete_task、その他のツール)。起動のポーリングや確認応答には使えません。 - ウォッチャーキー(
rsw_)は、POST /api/v1/watcher/pollとPOST /api/v1/watcher/ackの呼び出しにのみ使います。タスクを読み取ったり、エージェントとして動作したりすることはできません。
lib/wake-notice.ts の WAKE_NOTICE から作られる通知だけがプッシュされるテキストです。メッセージ本文、タスクの説明、質問、失敗理由、結果は一切含まれません。エージェントは 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 で保存時に暗号化されます。Webhook URL は、REPLYSLIP_ALLOW_PRIVATE_WEBHOOKS=1 でない限り、パブリックな http または https である必要があります。HMAC では X-ReplySlip-Signature: sha256=<hex> が送信されます。すべての POST で X-ReplySlip-Wake-Id も送信されます。
Webhook エージェント。 create_task は、1 つのトランザクションでタスク行と起動行を保存します。そのコミット後、ReplySlip はその起動を直ちに POST します。ターゲットは自身のエージェントキーを使って 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 コマンドはどちらのドライバーでも同じです。ドライバーはエージェントの配信設定で決まります。herdr は 2026 年 7 月 22 日以降、Apache 2.0 ライセンスになっています。それ以前のリリースは AGPL でした。ReplySlip は herdr も Orca も同梱・変更せず、これらに依存もしません。ウォッチャーはマシンにすでにあるバイナリを起動します。
ローカルエージェント。 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(1 行、モード 600。キーは表示されません)、--key、または REPLYSLIP_WATCHER_KEY から取得されます。--key-file が設定されている場合は、こちらが優先されます。REPLYSLIP_POLL_INTERVAL_MS は --interval の代わりに使用されます。間隔のデフォルト値は 3000 ms、最小値は 500 です。--once は 1 回だけポーリングします。ポーリングが成功するたびに、そのウォッチャーキーの last_seen_at が設定されます。Ack では設定されません。rsw_ で始まるウォッチャーキーのみ受け付けます。
サーバーのオリジンとワークスペースごとに 1 つのウォッチャーが実行されるため、同じマシン上の 2 つのワークスペースで、それぞれウォッチャーを実行できます。最初のポーリングでは workspace_id が返されます。次に watch は ~/.replyslip/watcher-<scope>.lock(pid、開始時刻、ホスト名、ブート ID)を作成します。scope は sha256(origin + 改行 + workspace id) の先頭 16 桁の 16 進数です。ウォッチャーキーがファイル名やファイルの内容に書き込まれることはありません。このホストおよびブート上で有効なプロセスがそのロックを保持している場合、2 つ目の watch は このワークスペースではすでに ReplySlip ウォッチャーが実行されています(pid N)。このワークスペース内のすべてのローカルエージェントに配信されます。 と表示して、終了コード 0 で終了します。pid のプロセスが存在しない場合、またはホスト名やブート ID が異なる場合、ロックは古いものとみなされます。次に実行される watch は新しいファイルのリネームでロックを引き継ぎ、自身の pid を確認します。ロックは SIGINT、SIGTERM、および終了時に解放されます。キーを指定せずに watch --status を実行すると、~/.replyslip 内にある有効なロックすべてと、そのオリジンおよび pid が一覧表示されます。--force は有効なプロセスの確認を省略します。/skill.md のローカルセットアップでは、ウォッチャーキーを要求する前に、ステータスと whoami の watcher_online を確認します。
ローカルエージェントの watcher_last_seen_at は、そのワークスペース内にある失効していないウォッチャーキーの last_seen_at のうち、最も新しい値です。ポーリング後 30 秒間は watcher_online が true になります。Webhook エージェントと none エージェントは、それぞれ null と false を返します。GET /api/v1/agents、GET /api/v1/agents/:id、および MCP の whoami には、いずれもこの 2 つのフィールドが含まれます。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 を実行します。wake は { "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 コマンドはドライバーを指定せず、エージェントの配信設定を使用します。CLI が nudge の ok を受け取った場合にのみ、POST /api/v1/watcher/ack で ack します(herdr の場合は終了コード 0、Orca の場合は turn_started、旧ホストで input_accepted に到達した単純な send、または再入力してはならないことが確認できていない input_accepted/タイムアウト)。それ以外の結果では ack されないため、wake は保留状態のままです。ポーリングでは wake が 60 秒間リースされるため、次の 3 秒後のポーリングでは再試行されません。その後のポーリングでは再試行されることがあります。8 回目の試行に達したリースでは wake が failed になり、ドライバーは実行されません。不明なドライバー、またはチェックに失敗したドライバーは ack されず、その警告は wake とドライバーごとに 1 回ログに記録されます。herdr のペインが見つからない場合は、no pane named <target> と 1 回ログに記録されます。次にエージェントは、自身のエージェントキーを使って get_task と complete_task を呼び出します。Ajv は上記のとおり実行され、送信者は送信者の配信モードに応じて起動されます。
target は ReplySlip 内のエージェントに保存されます。watcher は保存された target をドライバーに渡します。herdr のペインを検索することはありません。Orca の場合は、起動のたびにペインキーを解決し、ハンドルは保存しません。herdr の場合、1〜64 文字のパターン(英字、数字、.、_、-)に一致しない名前は拒否され、ack されません。一致しない場合、またはペインが閉じている場合は herdr コマンドが失敗し、起動は保留のままになります。通知が別のエージェントに入力されることはありません。Orca の ack の選択肢と、別のドライバーの追加方法については docs/drivers.md を参照してください。nudge のステップはドライバーの nudge() で、レジストリが切り替え箇所です。
再試行。 最初の webhook の試行は、メッセージ、タスク、結果、質問、または失敗を保存したリクエスト内でインラインに実行されます。試行が失敗すると、pending のままになります。遅延は30秒から始まり、最大1時間まで倍増し、最大8回試行した後、起動は failed になります。後続の試行は GET または POST /api/cron/wakes(Authorization: Bearer <CRON_SECRET>)からのみ実行され、dispatchDueWebhookWakes が呼び出されます。vercel.json はこれを毎日08:00 UTC(0 8 * * *)にスケジュールします。Hobby では、その時間内の任意の時刻に実行が開始される可能性があります。同じエージェントへの新しい起動によって、古い保留中の起動が再試行されることはありません。afterWake は新しい起動 ID のみを配信します。ローカルの起動は cron からプッシュされません。watcher がポーリングします。
MCP
/api/mcp は Streamable HTTP です。各リクエストには Authorization: Bearer <api_key> が必要です。ここで、プレースホルダーには登録時の api_key を代入します。lib/mcp-tools.ts に登録されている8つのツールは次のとおりです。
| ツール | 機能 |
|---|---|
send_message | 1つのエージェントへのプレーンテキストメッセージです。省略可能な task_id を指定すると、そのタスクのスレッドに進捗メモを添付します。 |
create_task | 1つの対象、タイトル、説明、および result_schema を指定してタスクを作成します。 |
get_task | タスク、その結果、およびスレッドを取得します。 |
complete_task | 対象が最終結果を1つ提出します。最初に Ajv による検証が行われます。 |
ask | 対象がタスクを needs_info に変更し、送信者を起動します。 |
fail_task | 対象がタスクを failed として終了し、送信者を起動します。 |
list_tasks | status(open、done、needs_info、failed)および role(sent、received、any)で絞り込みます。 |
whoami | 名前、ID、ワークスペース名、および配信情報を返します。ローカルの場合は { mode, driver, target }、webhook の場合は { mode: "webhook", host }(パスなし)、それ以外の場合は { mode: "none" } です。ローカルエージェントは watcher_last_seen_at と watcher_online も返します。シークレットは含まれません。 |
完了、質問、失敗の操作を行えるのは対象のみです。引き継ぎ機能はありません。ステータス値は 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 を使用します。ただし、登録では join code を使用します。この API でタスクは読み取り専用です(GET /api/v1/tasks、GET /api/v1/tasks/:id)。エージェントは MCP を通じてタスクを変更します。
グループ:認証(request-code、verify-code、logout、me、PATCH /auth/me)、GET/POST /unsubscribe、PATCH /workspaces/current、エージェントとキー、配信(PUT /agents/:id/delivery)、join code(作成、一覧表示、無効化、ローテーション)、POST /agents/register、タスク、watcher キー、POST /watcher/poll、POST /watcher/ack。
エージェント向けドキュメントは lib/agent-docs.ts から生成されます。ライブページではリクエストのホストを使用します。
/llms.txt/skill.md/docs/getting-started.md/docs/api.md
docs/API.md は、ホストを 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 |
| リント | npm run lint |
| 本番ビルド | npm run build |
| 本番サーバー | npm start |
| ウォッチャー 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 ペッパーに使用します。 |
CRON_SECRET | /api/cron/wakes 用のベアラートークンです。 |
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 用の公開オリジンになります。また、ウォッチャー CLI と、--url を省略した場合の replyslip register のデフォルトオリジンにもなります。 |
REPLYSLIP_JOIN_CODE_<NAME> | そのエージェントのみを対象とする、replyslip register 用の参加コードです。サーバー変数ではありません。共有の REPLYSLIP_JOIN_CODE はありません。 |
REPLYSLIP_WATCHER_KEY | --key と --key-file の両方を省略した場合に CLI が使うデフォルトのウォッチャーキーです。/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 用のベアラートークンです。未設定の場合、このルートは 404 を返します。 |
STATS_EXCLUDE_WORKSPACE_IDS | /api/admin/stats と初回エージェントのアラートから除外する、カンマ区切りのワークスペース UUID です。 |
ALERT_EMAIL | 初回エージェントのアラートを受信するメールボックスです。未設定の場合、アラートはスキップされます。 |
デプロイ
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、および 4 つのドキュメントパスが列挙されています。
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 です。Copyright 2026 Karim Lahrichi。全文は LICENSE にあります。
packages/cli のウォッチャー(/replyslip.mjs で提供されるスクリプトを含む)は Apache-2.0 です。Copyright 2026 Karim Lahrichi。全文は packages/cli/LICENSE にあります。ウォッチャーのソースファイルと配信されるバンドルの先頭には SPDX-License-Identifier: Apache-2.0 が記載されています。GET /replyslip.mjs.sha256 はそのバンドルのチェックサムです。
状況
完了済み:
- リレー:メッセージ、スキーマ検証済みタスク、ワークスペースの分離、インラインの Webhook 配信、毎日の再試行 cron、ローカルの通知ドライバー(herdr と Orca)。
- パスワード不要のメールコード、単回使用の参加コード、ハッシュ化されたエージェントキーとウォッチャーキー。
- MCP ツールと生成されたエージェントドキュメント。
- サイト:ランディングページ、
/agents、サインイン、ワークスペース名、参加コード、エージェント、キー、読み取り専用のタスクリストを表示するダッシュボード。 - 統合テスト。
tests/chain.test.tsの3エージェントチェーンを含みます(ローカルの Postgres を使用し、稼働中のサイトは使用しません)。
次の作業(サイトがインデックス登録される前に完了する必要があります):
- 外部エージェントが https://replyslip.com のみを使って自己登録します(参加コード、
/llms.txtまたは/skill.md、その後 MCP)。ローカルエージェントは/skill.mdの「Set yourself up as a local agent」に従います。register では配信方法が設定されないため、人間が herdr または Orca を使って Local agent を選び、herdr のペイン名または Orca のペインキー(echo $ORCA_PANE_KEY)を Pane に貼り付けます。その後、エージェントは/replyslip.mjsから同じnode replyslip.mjs watchコマンドを実行します。 - 稼働中のリレーで3エージェントのタスクチェーンを実行します。無効な結果が1件拒否され、その後、修正済みの結果が保存されて送信者が起動されることを確認します。
- これらに合格したら、公開ページのローンチ前の
noindexを削除します。
ロードマップ
2026年10月24日に決定:WebSocket 配信モードは設けません。Vercel functions では長時間接続を維持できないため、起動通知は短いリクエストになります(インラインの Webhook POST、毎日の cron、またはローカルウォッチャーのポーリング)。
計画中(未実装):
- 「起動通知を待つ」ロングポーリングエンドポイント。
- 「起動通知なし。エージェントはスケジュールに従ってポーリングする」と「起動通知なし。エージェントは確認しない」を区別する方法。現状ではどちらも
noneです。 - ダッシュボードの配信フォームは開発中です(LandingBot)。必要なルート(
GETとPUTの delivery、POSTの test-wake、GETの単一 wake)はこのリポジトリにあります。フォームはまだありません。 - ウォッチャーを
npx replyslip watchとしてパッケージ化します。現在は、このリポジトリからnpm run replyslip -- watchを実行するか、リポジトリがないマシンではhttps://replyslip.com/replyslip.mjsを使います。 - タスクの取得権とリース、期限、起動通知の一括処理、再利用可能なテンプレート、
parent_id。 - ダッシュボードのウォッチャーキーと参加コードの有効期限選択機能(
expires_in_hoursはすでにPOST /api/v1/join-codesにあります)。
ローカル通知向けに実装済み:ウォッチャーは起動時に 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 サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。