Coding agents write webhook handlers well. They can't receive webhooks at all. The handler needs a public URL, the URL needs infrastructure, and the infrastructure needs a human - so the agent writes the code, and then you personally click around a provider dashboard, trigger a test event, copy the payload out of a log, and paste it back into the chat. The agent is autonomous; you're its network stack.
OtterKit's CLI ships an MCP server that closes exactly this gap: tunnels, webhook endpoints, capture history, await, and replay as native tools the agent calls itself. The agent provisions its own URL, waits for the event, and iterates on the handler - end to end, unattended.
Setup: one command, one login
For Claude Code:
claude mcp add otterkit -- npx otterkit mcpFor Cursor and other MCP clients, add it to the client's MCP config (e.g. .cursor/mcp.json):
{
"mcpServers": {
"otterkit": {
"command": "npx",
"args": ["otterkit", "mcp"]
}
}
}Log in once with npx otterkit login and every agent on the machine is authorized with the same account and credits. Headless boxes and CI set OTTERKIT_TOKEN instead - create a token in the console under API Tokens.
The loop
Four tool calls turn webhook development into something an agent can drive without help:
webhook_create provisions an always-on endpoint and returns its URL - the endpoint is answered server-side, so it keeps capturing even if the agent's process dies. request_await is the assertion primitive: it blocks until a matching request arrives, then returns the full payload. request_replay re-sends any captured request to localhost with optional JSON body edits, which is how the agent iterates on a handler against a real payload it caught once.
No provider account yet? event_send fires a correctly-signed synthetic Stripe, GitHub, Shopify, or Slack event at the local handler, so the agent can develop and test verification logic before any real integration exists.
The inbox trick: OTPs and confirmation emails
Agents also get stuck on email - signup confirmations, verification codes, magic links. Endpoints can carry an inbox, and request_await catches mail the same way it catches webhooks:
webhook_create { "subdomain": "signup-test", "email": true }
→ [email protected]
request_await { "subdomain": "signup-test", "method": "EMAIL" }
→ { "subject": "Your verification code", "text": "Code: 481-923", ... }No MCP? The CLI speaks agent anyway.
Every provision and read command takes --json, errors come back as JSON with exit code 1, and await has deterministic exit codes - 0 when the expected request arrived, 2 on timeout. A shell-only agent (or a plain CI script) gets the same loop:
npx otterkit webhook --daemon --subdomain agent-hooks --json
# ... hand the URL to the service under test ...
npx otterkit await agent-hooks --count 1 --timeout 120s --jsonThere's also an installable skill that teaches coding agents the whole toolkit up front - npx skills add useotterkit/skill -g - and llms.txt / llms-full.txt for any agent that can read a URL.
When the provider changes the payload
Agent-built handlers rot the same way human-built ones do: the provider adds a field, retires one, changes a type - silently. On cloud endpoints, Drift Watch baselines the payload shapes the endpoint actually receives and turns changes into findings. The schema_drift tool hands the agent the same machine-readable diff: notice the drift, read a sample, patch the handler. The maintenance loop closes too.