Skip to main content

HTTP Webhook Adapter

The webhook adapter registers HTTP POST endpoints that accept JSON payloads (e.g. GitHub, custom integrations). Each request is validated, optionally HMAC-verified, filtered by event type, then handed to an Agentix run using a prompt template that includes the JSON body.

Typical use: configure everything in gateway.yaml — you rarely construct WebhookAdapter in Python.


1. Enable the channel

The gateway skips the webhook channel unless the environment says so:

VariableRequiredPurpose
WEBHOOK_ENABLEDYesSet to true (case-insensitive) or the webhook adapter is not registered.
WEBHOOK_PORTNoWhen a webhook channel is present, the HTTP server listens on this port (default 8644), overriding gateway.port in YAML.
WEBHOOK_SECRETNoDefault HMAC secret for routes that omit secret (see Secrets).
WEBHOOK_MAX_BODY_SIZENoMax POST body size in MB when a route omits max_body_size_mb (default 2).
WEBHOOK_RATE_LIMITNoRequests per minute when a route omits rate_limit_per_min (default 60).

Put these in the process environment or a project .env file (loaded when the gateway starts).


2. Minimal gateway.yaml shape

Under channels, add a single entry (the key is arbitrary, e.g. webhook or integrations):

channels:
webhook:
adapter: webhook
routes:
<route_name>:
# required — see §3
...
agents:
<name>:
# optional named AgentixAgentOptions (subset) — see §4
  • adapter must be webhook.
  • routes is a map: each key becomes the URL segment /webhooks/<key>.
  • agents defines named agent configs; routes reference them via agent: <name>.

3. Route configuration (routes.<route_name>)

Each route must include:

FieldRequiredDescription
eventsYesNon-empty list of event type strings allowed for this route. Incoming requests are matched against the resolved event type (see Event type). Others get HTTP 400.
agentYesName of an entry under agents: that should run this webhook. If that name is missing, the gateway default agent client is used.
promptYesText template; {payload} is replaced with a JSON string of the request body (truncated if very large). This text is what the agent receives as the user message.

Optional fields:

FieldDefaultDescription
secretPer-route HMAC secret. If unset, see WEBHOOK_SECRET. If no secret applies, HMAC is not required.
deliverlogWhere the agent result goes after the run finishes: log (structured logs) or http_callback (POST JSON to callback_url).
callback_urlRequired when deliver: http_callback.
max_body_size_mbenv / 2Max body size for this route.
rate_limit_per_minenv / 60Per-route rate limit.

HTTP behavior (important): The handler responds 202 Accepted with {"status":"accepted","event_id":...} right after enqueueing work. The agent runs asynchronously; the HTTP client does not wait for the LLM. Use deliver: http_callback if a downstream system must receive the result.


4. Named agents (agents)

Optional. Each key under agents becomes a dedicated AgentixClient with its own AgentixAgentOptions (same fields you use under the top-level agent: section: name, provider, model, system_prompt, allowed_tools, etc.).

Routes point to a name with agent: default (or any key you defined). If the name is missing, the gateway’s default agent is used.


5. Full example (GitHub-style)

channels:
webhook:
adapter: webhook
routes:
github_pr:
events: ["pull_request"]
secret: "${GITHUB_WEBHOOK_SECRET}"
agent: default
prompt: |
A GitHub event was received. Handle it appropriately.

Payload:
{payload}
deliver: log
agents:
default:
name: webhook-agent
provider: anthropic
model: null
system_prompt: "Process incoming webhook events and take appropriate action."
permission_mode: default
max_tokens: 4096
max_iterations: 20
tool_timeout: 120.0
conversation_summarization_enabled: true
persistence_enabled: false
allowed_tools: []
disallowed_tools: []
cwd: null
env: {}
llm_options: {}

Sender URL: POST https://<your-gateway>/webhooks/github_pr


How event type is resolved

The adapter resolves a single string event_type from, in order:

  1. Headers X-Event-Type or X-GitHub-Event (case variants supported), or
  2. JSON body fields event_type or action.

That string must appear in the route’s events list, or the request fails with 400 (invalid_event_type).

GitHub: sends X-GitHub-Event: pull_request — include "pull_request" in events.


Secrets and HMAC

When a secret applies (per-route secret or WEBHOOK_SECRET), the adapter expects HMAC-SHA256 over the raw request body, in the X-Hub-Signature-256 header, GitHub-style: sha256=<hex>.

Missing or bad signature → 401.


Other HTTP responses (short)

StatusMeaning
404Unknown route_name in the URL.
400Invalid JSON, or event type missing / not in events.
413Body larger than allowed.
429Rate limited.
200Same delivery id seen again — idempotent replay (status: duplicate).
202Accepted — work queued; agent runs in the background.

Advanced: Python

The gateway builds the adapter from YAML. Programmatic use matches the constructor:

from agentix.gateway.adapters.webhook import WebhookAdapter
from agentix.gateway.adapters._webhook.config import parse_webhook_routes, parse_webhook_agents

routes = parse_webhook_routes({...}) # same shape as YAML `routes`
named = parse_webhook_agents({...}) # same shape as YAML `agents`
gateway.add_channel(WebhookAdapter(routes=routes, named_agents=named))

There is no route= / extract_message= shortcut on WebhookAdapter — prompts are built from prompt and {payload} substitution only.