Skip to content

Webhook ​

Cloud Only

Webhook は Cloud バージョン でのみ利用可能です。

Webhook を使うと、ADHDev Cloud がマシンおよびエージェントのイベントを、あなた自身の HTTP エンドポイントにプッシュできます。

現在の重要な動作:

  • Webhook API は稼働中です。
  • 専用の /webhooks ダッシュボードページは、現在は安定した標準ナビゲーションサーフェスではありません。
  • ペイロード、イベント、配信履歴の構造の正式な契約としては、REST API リファレンス を使ってください。
  • Webhook の作成/切り替え/削除/テストのアクションは、最近のログインによって保護されたクラウドアカウントの操作であり、API キーではなく新鮮なダッシュボードセッションの JWT が必要です。

Webhook の作成 ​

現在サインインしているクラウドダッシュボードセッションから Webhook を作成してください。基盤となるリクエストボディは次のとおりです:

json
{
  "url": "https://example.com/hooks/adhdev",
  "events": ["agent:status", "agent:approve_request"]
}

古いブラウザセッションから、または API キーで、変更を伴う Webhook エンドポイントを呼び出すと、サーバーはフックをプロビジョニングする代わりに 403 RECENT_LOGIN_REQUIRED を返します。

作成レスポンスは次を返します:

  • Webhook レコード
  • 署名検証のために一度だけ表示される secret

events は自由形式ではなく許可リストです: 以下の名前(および "*")のみが受け付けられ、それ以外は黙って無視されます。個別に購読できない細かいイベントも含めてすべて受け取るには ["*"] を使ってください。

イベント ​

個別に購読可能(events で受け付けられる):

イベントトリガー
daemon:connectデーモンがサーバーに接続した
daemon:disconnectデーモンの接続が失われた
agent:statusエージェントのステータスが変化した(スロットル済み、デーモンごとに10秒あたり最大1回)
agent:approve_request予約済み — 許可リストにはあるが、サーバーは現在発行していない

サーバーは発行するが "*" で購読した Webhook にのみ配信される(個別購読不可):

イベントトリガー
agent:generating_startedエージェントが応答の生成を開始した
agent:generating_completedエージェントが生成を完了した
agent:waiting_approvalエージェントが承認を待っている
agent:waiting_choiceエージェントが複数選択のプロンプトを待っている
agent:stoppedエージェントセッションが停止した
monitor:no_progressエージェントが進行なしで停滞しているように見える(レガシーエイリアス: monitor:long_generating)
webhook:testPOST /webhooks/{id}/test による明示的なテスト配信 — 購読フィルタリングを完全にバイパスし、テスト対象の Webhook 1件にのみ配信される

ペイロード形式 ​

各配信は、トップレベルに event・payload・timestamp(サーバーが配信を送った時刻、エポックミリ秒)の 3 フィールドを持つ JSON 本文です。エージェント/モニターのイベント(agent:status を除く agent:* と monitor:no_progress)のペイロードは次のとおりです:

json
{
  "event": "agent:generating_completed",
  "payload": {
    "daemonId": "8e1f4c2a9b7d3e5f6a0c1b2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f",
    "daemonType": "adhdev-daemon",
    "event": "agent:generating_completed",
    "timestamp": 1714000000000,
    "targetSessionId": "9b2d7c4e-1f3a-4b5c-8d6e-0a1b2c3d4e5f",
    "providerType": "claude-cli",
    "providerSessionId": "3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f",
    "workspaceName": "/home/dev/projects/myproject",
    "duration": 42,
    "surfaceHidden": false,
    "muted": false
  },
  "timestamp": 1714000000215
}
フィールド含まれる条件
daemonId常に — イベントを報告したデーモン接続
event, timestamp常に — イベント名と、デーモンがそれを観測した時刻(エポックミリ秒)
targetSessionId特定のエージェントセッションに関するイベントのとき — agent:generating_completed と agent:stopped には常に含まれる
providerTypeデーモンがセッションを解決できた場合。エージェントのプロバイダー(例: claude-cli、cursor)。解決できなければフィールドは含まれず、デーモン種別が入ることはありません
daemonType常に。イベントを送信したデーモンの種別。現在は adhdev-daemon
providerSessionIdプロバイダーが独自の会話 ID を公開しているとき
workspaceNameセッションにワークスペースがあるとき — CLI エージェントの作業ディレクトリ、または IDE のワークスペース
durationagent:generating_completed のみ。デーモンがターン開始を観測したとき、整数秒で
elapsedSecmonitor:no_progress — 進捗が見られなかった秒数
modalMessage, modalButtonsagent:waiting_approval / agent:waiting_choice — 承認プロンプトの文言とボタンのラベル
surfaceHidden, mutedデーモンがセッションをホストしているとき — ダッシュボードで非表示/ミュートかどうか

daemon:connect、daemon:disconnect、agent:status、webhook:test はそれぞれ別の形のペイロードを送ります。modalMessage の承認プロンプト文言を除き、ペイロードにチャットメッセージ、チャットタイトル、エージェントの応答が含まれることはありません。

署名の検証 ​

各 Webhook リクエストには次が含まれます:

  • X-ADHDev-Signature
  • X-ADHDev-Event

署名の形式:

text
X-ADHDev-Signature: t=1714000000000,v1=a3f9c2b1...

生のリクエストボディ に対して検証してください。

js
import crypto from 'crypto'

function verifySignature(body, signature, secret) {
  const parts = Object.fromEntries(signature.split(',').map((p) => p.split('=')))
  const timestamp = parts.t
  const received = parts.v1
  const payload = `${timestamp}.${body}`
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')

  return crypto.timingSafeEqual(
    Buffer.from(received),
    Buffer.from(expected)
  )
}

// Express の例
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-adhdev-signature']
  const body = req.body.toString('utf8')
  if (!verifySignature(body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }
  const event = JSON.parse(body)
  // イベントを処理...
  res.sendStatus(200)
})
python
import hmac
import hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    parts = dict(p.split('=', 1) for p in signature.split(','))
    timestamp = parts.get('t', '')
    received = parts.get('v1', '')
    payload = f"{timestamp}.{body.decode('utf-8')}".encode()
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(received, expected)

# Flask の例
@app.route('/webhook', methods=['POST'])
def webhook():
    sig = request.headers.get('X-ADHDev-Signature', '')
    if not verify_signature(request.data, sig, WEBHOOK_SECRET):
        return 'Invalid signature', 401
    event = request.get_json()
    # イベントを処理...
    return '', 200

Webhook のシークレットは、Webhook の作成時に一度だけ表示されます — 安全に保管してください。

管理エンドポイント ​

text
GET    /api/v1/webhooks
POST   /api/v1/webhooks
PATCH  /api/v1/webhooks/{webhookId}
DELETE /api/v1/webhooks/{webhookId}
GET    /api/v1/webhooks/{webhookId}/deliveries?limit=20
POST   /api/v1/webhooks/{webhookId}/test

GET エンドポイントが最も安全な自動化サーフェスです。変更を伴うエンドポイント(POST、PATCH、DELETE、test)は、最近のログインによって保護されたダッシュボードセッションの操作です。

リトライポリシー ​

失敗した配信は、指数バックオフで最大 3 回リトライされます。

プラン制限 ​

プラン最大 Webhook 数
Free2
Pro10
Ultra50
Enterprise無制限

ホスティングされたクラウドのドキュメントはこちらです。オープンソースおよびセルフホストのドキュメントは OSS リポジトリにあります。