Tutorial

How to Receive a Webhook on a Local AI Agent (7 Ways, Honest)

Akshay Sarode
Direct answer

If you want zero-config + free: Hookdeck CLI. If you want a stable URL on your domain: Cloudflare Tunnel. If you want the lightest possible: localhost.run (just SSH). If you want it baked into your agent infra: Ujex Ingress. If you want capture-and-replay for testing: ThunderHooks / HookListener.

OpenAI added webhooks in 2024. Stripe always had them. GitHub, Slack, Linear, every modern API. The challenge for local agents: your laptop has no public URL.

Here are the seven ways I've used. None of them is wrong; they're suited to different things.

1. Hookdeck CLI

Free, open-source, purpose-built for webhook development. GitHub. Has an MCP server for AI agents.

hookdeck listen 3000 my-source
# → https://hkdk.events/abc123 forwards to localhost:3000

Pros: Event inspection, replay, filtering. 10k events/month free. Cons: The URL changes per session.

2. Cloudflare Tunnel

Free, persistent. Your machine outbounds to Cloudflare; they reverse-proxy. Best for stable URLs on your domain.

cloudflared tunnel create agent-webhook
cloudflared tunnel route dns agent-webhook hooks.mydomain.dev
cloudflared tunnel run --url http://localhost:3000 agent-webhook

Pros: Stable URL, free, CGNAT-friendly. Cons: Cloudflare account needed.

3. ngrok

The original. Easy to start, paid for non-trivial use.

ngrok http 3000
# → https://abc-123.ngrok-free.app

Pros: Mature, simple. Cons: Free tier limits; URL changes; paid plans get expensive.

4. localhost.run

SSH-based, zero install.

ssh -R 80:localhost:3000 nokey@localhost.run
# → https://abc.lhr.life

Pros: Single command. Cons: Free tier random URLs.

5. localtunnel

Open-source npm package. Zero account.

npx localtunnel --port 3000
# → https://abc.loca.lt

Pros: Truly anonymous. Cons: Reliability varies.

6. Capture-and-replay services (ThunderHooks, HookListener)

Different shape — they capture incoming webhooks, store them, you replay. Good for testing without your agent running.

// ThunderHooks gives you a URL.
// Webhooks land there. You inspect / replay later.

Pros: Decouples webhook receipt from agent uptime. Cons: Not real-time.

7. Ujex Ingress

The ingress subsystem of Ujex — three-tier tunnels (Quick / Standard / Stable) via embedded bore + cloudflared. Authentication and audit baked in.

ujex ingress run --expose 3000 --stable hooks.myagent.dev

Pros: Same auth surface as the rest of your agent infra (Postbox / Recall / Audit). Auditable. Free tier. Cons: Tied to Ujex.

Side-by-side

Stable URLCustom domainAccount?Free tier
Hookdeck CLI~stable10k/mo
Cloudflare Tunnel✓ (Cloudflare)
ngrokPaid onlyPaid onlyLimited
localhost.runPaid onlyPaid only
localtunnelPaid onlyPaid only
ThunderHooksn/a (capture)n/a
Ujex Ingress✓ (stable tier)✓ Ujex

What about webhook security?

Every option above gives you a URL. Verifying that the request actually came from OpenAI / Stripe / GitHub is your job. Use HMAC verification with the provider's signing secret. Don't skip this — public URLs receive a non-trivial amount of probe traffic.

FAQ

Why not just open a port on my router?

You can. You then own DNS, dynamic IP, TLS cert renewal, and any DDoS that hits the URL. Tunnels offload all of that to a CDN.

Does Hookdeck's MCP server work with Claude Code?

Yes — Hookdeck shipped MCP support for AI agents specifically. The agent can list events, replay, and inspect headers via MCP tools.

How do I keep the URL stable across machine reboots?

Cloudflare Tunnel: yes by default. ngrok: paid plans. Hookdeck: persistent endpoints on paid plans. Ujex Ingress: stable tier.

What's the latency cost of going through a tunnel?

30–80ms typical for Cloudflare Tunnel (your laptop → CF edge → recipient). Comparable for the others. For webhooks, this is invisible (webhooks are fire-and-forget on the sender side).