#12635: Gateway: add inbound webhook dispatch framework
gateway
stale
Hey! I've been running OpenClaw as my daily gateway and kept finding myself wanting external services to push events directly into the agent. So I built a generic webhook framework that plugs into the existing hooks/gateway infrastructure. Figured this would be useful for the wider community too.
## Summary
- Adds a generic webhook HTTP endpoint at `/webhooks/{token}/{source}` on the gateway
- Receives POST payloads from external services and dispatches them to the agent via the cron isolated-agent system
- Uses constant-time token validation (reuses the existing hooks token)
- Pluggable transform architecture — easy to add new services
### Architecture
```
POST /webhooks/{token}/{source}
→ token validation (constant-time)
→ source lookup in enabled presets
→ transform function converts raw payload → structured message
→ dispatch to agent via isolated cron job
→ system event enqueued for visibility
```
**Files:**
- `src/gateway/webhooks-http.ts` — Core HTTP handler
- `src/gateway/server/webhooks.ts` — Gateway integration (agent dispatch)
- `src/gateway/webhook-transforms/index.ts` — Transform registry
- `src/gateway/webhook-transforms/*.ts` — Per-service transforms
- Config wiring: `server-http.ts`, `server-runtime-config.ts`, `server-runtime-state.ts`, `server-reload-handlers.ts`, `server.impl.ts`
- Schema: `types.hooks.ts`, `zod-schema.ts`
### Built-in transforms (4 services, 50 tests)
| Service | Events | Notes |
|---------|--------|-------|
| **Shopify** | Orders, customers, products, refunds | Infers event type from payload shape |
| **QuickBooks** | Entity CRUD | Supports both legacy and CloudEvents (May 2026 migration) |
| **Read.ai** | Meeting notes | Triggers on `meeting_end` only |
| **OwnerRez** | Bookings, contacts, properties | Entity insert/update/delete with embedded entity parsing |
### Configuration
```yaml
hooks:
enabled: true
token: "your-secret-token"
webhooks:
enabled: true
presets:
- shopify
- quickbooks
- readai
- ownerrez
```
## Test plan
- [x] All 50 webhook tests pass (`pnpm vitest run src/gateway/webhook-transforms/ src/gateway/webhooks-http.test.ts`)
- [x] Build passes (`pnpm build`)
- [x] Type-check and lint pass (`pnpm check` — only pre-existing `.vercel/project.json` format issue)
- [ ] Integration test: deploy and POST sample payloads to `/webhooks/{token}/{source}`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds an inbound webhook framework to the gateway: a new `/webhooks/{token}/{source}` endpoint validates the existing hooks token, selects an enabled source preset, transforms the received JSON payload into a structured agent message (Shopify / QuickBooks / Read.ai / OwnerRez), and dispatches it to the agent via an isolated cron job. Runtime/config wiring is added so the endpoint can be enabled/disabled and hot-reloaded alongside existing hooks.
The main correctness gap is around payload shape support: the HTTP handler currently coerces any non-object JSON body (including top-level arrays) into `{}`, while the QuickBooks transform includes logic to handle top-level array CloudEvents. As written, direct-array CloudEvents batches will be silently dropped and never reach the transform.
<h3>Confidence Score: 4/5</h3>
- Generally safe to merge once array-payload handling is clarified/fixed.
- Core wiring and token validation are straightforward and covered by tests, but there is a concrete behavioral mismatch: the HTTP layer normalizes non-object JSON bodies to `{}`, making the QuickBooks CloudEvents top-level array path unreachable and causing real payloads to be ignored depending on sender format.
- src/gateway/webhooks-http.ts, src/gateway/webhook-transforms/quickbooks.ts
<!-- greptile_other_comments_section -->
<sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#11788: feat: inter-agent communication via CLI scripts
by jingkang0822 · 2026-02-08
79.0%
#6974: Feature/webhook gateway token
by MC-shark · 2026-02-02
77.1%
#7771: Hooks: wire lifecycle events and tests
by rabsef-bicrym · 2026-02-03
76.3%
#6405: feat(security): Add HTTP API security hooks for plugin scanning
by masterfung · 2026-02-01
75.2%
#12234: gateway: incident tracking, recover command, and ciao ERR_SERVER_CL...
by levineam · 2026-02-09
75.0%
#10383: feat(hooks): add agentId to hook mappings
by quentintou · 2026-02-06
74.7%
#7846: feat: add agentId param to webhook agent endpoint
by Bre77 · 2026-02-03
74.5%
#20420: Telegram webhook listener to use the gateway's HTTP server instead ...
by kesor · 2026-02-18
74.4%
#23461: Gateway: add hook replay protection with timestamp and nonce
by bmendonca3 · 2026-02-22
74.4%
#9909: Gateway: add HITL approvals integration
by FletcherFrimpong · 2026-02-05
74.2%