CLI for Agents

Durable Waits

A durable wait is a condition OtterKit holds for you on the server. Arm it on a live session ("when a request matching event.type = payment.succeeded lands") and disconnect: no polling loop, no open socket, no compute burning while you wait. When a matching request arrives, whether or not any client is attached, OtterKit POSTs it to your callback URL, signed, with retries. Agents park instead of waiting.

bash
# When a matching Stripe event lands, call my CI back — then go do other work
npx otterkit wake hook-a1b2c3d4 \
  --call https://ci.example.com/hooks/resume \
  --field event.type=payment.succeeded

# Match on method and path prefix too (all clauses must hold)
npx otterkit wake hook-a1b2c3d4 --call https://... --method POST --path /stripe

Match clauses: --method (exact), --path (prefix), and --field (dot-path equality into a JSON body). Waits are one-shot, capped at 20 per session, and expire with the session (or sooner via --ttl). Manage them with otterkit waits list and otterkit waits cancel.

Verifying deliveries

Each wait gets a secret, shown once at creation. Deliveries carry X-OtterKit-Signature: sha256=<hmac>, the HMAC-SHA256 of the raw body with that secret, so your receiver can prove the callback came from OtterKit. Failed deliveries retry with backoff (1, 2, 4, 8 minutes; five attempts).

json
{
  "waitId": "…",
  "subdomain": "hook-a1b2c3d4",
  "matchedAt": "2026-07-21T18:04:11.000Z",
  "request": { "method": "POST", "path": "/stripe/webhooks", "headers": { "…": "…" }, "body": "<base64>" }
}

Approval waits

An approval wait swaps the event source for a human. otterkit approve asks a question and blocks until someone taps Approve or Deny on the endpoint's page at app.otterkit.com/webhooks (or runs otterkit waits resolve). Deterministic exit codes make it a one-line gate in any script an agent runs.

bash
npx otterkit approve hook-a1b2c3d4 "Deploy v2.1 to prod?" --timeout 1h \
  && ./deploy.sh \
  || echo "not approved"
Exit codeMeaning
0Approved
1Denied
2No decision before --timeout

Approvals resolve only through the session's connect token, never through the public URL, so a decision can't be forged by anyone who merely knows the endpoint address.

MCP clients get all of this natively: wait_create, wait_list, wait_cancel, and wait_resolve ship in otterkit mcp (CLI 0.13+), so an agent can arm a wait or request sign-off mid-task without shelling out.