Webhook Verification
Fail-closed HMAC signature verification for inbound bot webhooks
from praisonaiagents import Agent
agent = Agent(name="webhook-agent", instructions="Verify and process incoming webhooks.")
agent.start("Verify the HMAC signature on this incoming webhook from GitHub.")Inbound webhooks are verified by default — misconfigured secrets return HTTP 401 instead of silently accepting unsigned traffic.
export LINEAR_WEBHOOK_SECRET=your-linear-signing-secret
export LINEAR_OAUTH_TOKEN=your-linear-token
praisonai bot linear --token "$LINEAR_OAUTH_TOKEN"The user posts a webhook; HMAC verification runs before the agent handles the payload.
Quick Start
- Set your signing secret
bash export LINEAR_WEBHOOK_SECRET=your-linear-secret # or for AgentMail: export AGENTMAIL_WEBHOOK_SECRET=your-agentmail-secret - Run the bot — verification is on by default
bash praisonai bot linear --token $LINEAR_OAUTH_TOKEN - Local dev without a real platform
bash PRAISONAI_INSECURE_WEBHOOKS=true praisonai bot linear --token $LINEAR_OAUTH_TOKEN
Which mode am I in?
How It Works
| accepts_webhooks | Verifier configured | PRAISONAI_INSECURE_WEBHOOKS | Outcome |
|---|---|---|---|
| false | — | — | No verification gate |
| true | yes | unset | Verify; 401 on failure |
| true | no | unset | 401 (fail-closed) |
| true | — | true | Skip with warning |
Configuration Options
| Variable | Purpose |
|---|---|
PRAISONAI_INSECURE_WEBHOOKS | Set to true / 1 / yes to disable verification globally (local dev only) |
LINEAR_WEBHOOK_SECRET | HMAC secret for Linear webhooks |
AGENTMAIL_WEBHOOK_SECRET | HMAC secret for AgentMail webhooks (required in production; API token is not a fallback) |
WHATSAPP_APP_SECRET | Meta app secret for Cloud-mode WhatsApp webhooks |
| PlatformCapabilities field | Default | Meaning |
|---|---|---|
accepts_webhooks | False | Channel receives inbound HTTP webhooks |
verifies_webhook_signature | False | Adapter exposes a verifier implementation |
Common Patterns
Built-in adapter, secret only — set the platform env var and run the bot; no code required.
Custom adapter with HmacWebhookVerifier:
from praisonai.bots.webhook_security import HmacWebhookVerifier
verifier = HmacWebhookVerifier(
secret="your-secret",
signature_headers=["X-Hub-Signature-256"],
prefix="sha256=",
)Custom ingress with the shared gate:
from praisonai.bots.webhook_security import enforce_webhook_verification
ok = enforce_webhook_verification(
accepts_webhooks=True,
verifier=verifier,
headers=dict(request.headers),
raw_body=await request.body(),
platform="mychat",
)
if not ok:
return Response(status_code=401)Best Practices
Never set PRAISONAI_INSECURE_WEBHOOKS in production
The override logs a warning on every request and disables all signature checks.
Use the shared helper instead of rolling your own HMAC
verify_hmac and HmacWebhookVerifier fail closed on missing secrets, unknown digest algorithms, and verifier exceptions.
Rotate signing secrets with the platform
Update both the platform webhook config and your env var at the same time.