Skip to main content
The gateway now ships in the praisonai-bot package. praisonai serve gateway still works exactly as documented here; for a standalone install see praisonai-bot Migration.
Trigger an agent run from any external HTTP event — Gmail, GitHub, Stripe, CI, forms, IoT — by POSTing JSON to /hooks/<path>.
The user POSTs JSON to /hooks/<path>; the gateway verifies auth, runs the mapped agent, and delivers the reply on the configured channel.

Quick Start

1

YAML — simplest form

Create gateway.yaml:
Start the gateway:
Fire a test event:
Response:
2

Python — register programmatically

3

CLI — manage hooks at runtime


How It Works


Two Actions: agent vs wake

Choose based on whether the external event carries new content for the agent. action: agent (default) — runs a full agent turn on the templated message. Use when the external event carries new content the agent should process. action: wake — nudges an existing session’s _last_activity without a new user message. Use when the external event means “this session is still alive / re-deliver any pending work”.

Templating

Both placeholder styles work and render the same payload fields: Rules:
  • A leading payload. is optional — {{ payload.from }} and {{ from }} both work.
  • Dotted paths resolve nested keys: {{ payload.user.email }}{user: {email: "x"}}.
  • Missing keys render as empty strings — templates never raise.
  • Substitution is single-pass — payload values containing {...} are not re-expanded (prevents key-corruption via payload injection).
Worked example: Payload:
Template config:
Resolved values:
  • session_key"hook:gmail:abc123"
  • idempotency_key"abc123"
  • message"New email from alice@example.com: Hello"

Idempotency & Retries

  • idempotency_key is a template; the rendered value is hashed (sha256) and scoped by path so the same id on different hooks never collide.
  • If omitted, the entire payload is hashed deterministically (canonical JSON).
  • Store is bounded (10,000 entries) with a 24h TTL — pruned lazily on each delivery.
  • Key is only recorded on success — transient failures stay retryable.
  • Concurrent identical deliveries are deduplicated atomically (in-flight reservation prevents TOCTOU between seen-check and record).
  • Duplicate response: 200 {"ok": true, "deduplicated": true}.

Authentication

  • Per-hook bearer: set auth: to a literal token or ${ENV_VAR} in YAML.
  • Falls back to the gateway’s auth_token when no hook-specific secret is set.
  • Bearer header only?token= query params are rejected by design (prevents secret leakage into access logs).
  • Compared in constant time (secrets.compare_digest).
  • 401 if no token provided, 403 if token is wrong.

Delivery

  • deliver_to: "channel:target" — e.g. "telegram:123456789", "discord:987654321", "slack:U12345".
  • Reuses the same channel-bot send path as scheduled delivery (hooks and scheduler route outbound identically).
  • If the channel bot is not registered, delivery is logged as failed and the hook returns {"ok": false} so the sender retries.
  • Omit deliver_to to skip outbound delivery entirely — the agent still runs.

Config Locations & Hot-Reload

YAML hooks can live at the top level (hooks:) or nested under gateway: (for grouping with other gateway settings):
Both locations are picked up at startup and at reload_config — a config reload clears and re-registers the entire hook table, so removed hooks and rotated secrets take effect without a process restart. See Gateway Hot-Reload.

Real User-Interaction Flow

Gmail received a new email. Zapier POSTs the parsed message to /hooks/gmail. The gateway deduplicates by message_id, runs the assistant agent on a templated summary, and Telegram chat 123456789 gets a notification with the agent’s reply. If Zapier retries the same delivery, the gateway returns {"ok": true, "deduplicated": true} instantly without re-running the agent.

Common Patterns

GitHub Issue Triage

Webhook POSTs arrive, the triage agent classifies the issue, and a Slack notification lands in #triage.

Stripe Payment Event

Payment events nudge the billing-support session for that customer without generating a new agent turn.

CI Failure Ping

The ops agent investigates and the reply goes directly to the on-call Telegram chat.

Best Practices

Use the provider’s native delivery id (Gmail message_id, GitHub X-GitHub-Delivery, Stripe event id). Never rely on time of receipt — providers retry with identical ids.
A separate auth: token per integration means a leaked secret isolates to one source, not your entire webhook surface.
Derive the session key from a stable entity id (customer, repo, user) so related events thread through the same conversation and the agent has full context.
If the webhook just signals “still alive” or “payment completed” without carrying content the agent should read, action: wake saves an LLM call.

Gateway Overview

Gateway architecture and how channels, agents, and routing connect.

Gateway CLI

Full CLI reference including the praisonai gateway hooks subcommand.

Bot Lifecycle Hooks

In-process outbound hooks (GATEWAY_START, SESSION_START, SCHEDULE_TRIGGER) — the counterpart to inbound HTTP triggers.

Gateway Hot-Reload

How hook changes and rotated secrets take effect without a process restart.