A couple quick things to separate here:
-
For WhatsApp self-chat mode, you normally don’t need a Flask webhook at all. Once WhatsApp Web is linked and channels.whatsapp.selfChatMode: true is set, OpenClaw should receive messages through the WhatsApp channel listener directly. /hooks/agent is for external systems that want to trigger an isolated agent turn.
-
A 400 from /hooks/agent usually means the Gateway did receive the request but rejected the payload. The response body should say why, e.g. message required, channel must be ..., agentId is not allowed..., bad JSON/content-type, or sessionKey not allowed.
Minimal known-good hook test:
curl -i -X POST http://127.0.0.1:18789/hooks/agent \
-H 'Authorization: Bearer YOUR_HOOK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"message":"ping from hook","channel":"whatsapp","to":"+15551234567"}'
If that fails, paste the HTTP status + JSON response body from curl. That’s the fastest clue.
- If Gateway logs “aren’t updating”, you may be tailing the wrong process/log. Check: