πŸ“š Learning Hub
Β· 3 min read
Last updated on

Webhooks for AI Workflows: Background Jobs, Agents, and Reliable Callbacks


A webhook is an HTTP request that one service sends to your application when an event occurs. Instead of repeatedly asking whether a long model response, batch, evaluation, or agent run has finished, your app registers an endpoint and receives a callback.

Webhooks are often called reverse APIs because the provider initiates the request. They are particularly useful when AI work outlives the browser request that started it.

Polling versus a webhook

With polling, your application repeatedly asks for status. That is easy to understand but adds delay, empty requests, and rate-limit pressure. With a webhook, the provider sends one or more event notifications when state changes.

QuestionPollingWebhook
Who initiates?Your appEvent provider
DeliveryOn the next pollPush after an event
Failure modeMissed/slow pollsRetries and duplicates
Best AI fitsimple status screenbackground responses, batches, agent jobs

Neither is universally better. A reliable system often receives a webhook, then fetches the canonical resource state from the provider API.

AI example: a background response completes

OpenAI documents webhook events such as response.completed, response.failed, and response.cancelled for background responses in its webhook event reference.

A production flow looks like this:

  1. Create a job and persist your own job ID plus the provider resource ID.
  2. Return immediately to the user with a pending state.
  3. Receive a signed event at a public HTTPS endpoint.
  4. Verify the signature against the raw body.
  5. Store the event ID transactionally so duplicates become no-ops.
  6. Acknowledge quickly with a 2xx response.
  7. Queue heavier work and fetch current provider state if correctness depends on it.
  8. Update your job and notify the user.

This separates durable job state from delivery. A webhook is a notification, not your database.

Verify with the provider SDK

Do not invent a generic signature scheme when the provider publishes one. The official OpenAI Python SDK can verify and parse the raw payload:

from flask import Flask, request
from openai import OpenAI

app = Flask(__name__)
client = OpenAI()  # reads OPENAI_WEBHOOK_SECRET from the environment

@app.post("/webhooks/openai")
def receive_openai_event():
    event = client.webhooks.unwrap(request.get_data(as_text=True), request.headers)

    enqueue_event(event.id, event.type, event.data)
    return "", 200

Keep the raw body unchanged until verification. Use the exact SDK/header instructions for your provider; Stripe, GitHub, and other services have different formats and replay protections.

Idempotency is mandatory

Providers retry when your endpoint times out or returns a failure. Delivery can be duplicated or reordered. A database uniqueness constraint on provider plus event ID is stronger than an in-memory Set, which disappears on restart and is not shared across instances.

create table webhook_events (
  provider text not null,
  event_id text not null,
  event_type text not null,
  received_at timestamptz not null default now(),
  primary key (provider, event_id)
);

Insert the receipt and enqueue the next step in one durable transaction or use an outbox pattern. If an agent tool may charge money or mutate external data, give that action its own idempotency key as well.

Respond fast, process later

Signature verification, validation, and durable receipt belong in the request path. Model calls, retrieval, document processing, email, and agent continuation belong on a queue or durable workflow.

This avoids timeout-driven retries and lets workers apply independent concurrency, retry, and cost limits. The long-running agent guide explains why an hours-long run should not depend on one HTTP connection.

Security checklist

  • Accept HTTPS only.
  • Verify signatures and enforce a replay window where supported.
  • Keep webhook secrets in a secret manager and rotate them deliberately.
  • Validate event type and schema before dispatch.
  • Allowlist supported events; ignore unknown types safely.
  • Never authorize a destructive agent action solely because text in the payload requested it.
  • Redact sensitive prompts and outputs from logs.
  • Rate-limit endpoints without blocking legitimate provider retries.

Webhook, stream, or WebSocket?

  • Use a webhook for asynchronous service-to-service completion or state changes.
  • Use HTTP streaming/SSE for one-way incremental model output to a client.
  • Use a WebSocket or WebRTC when a realtime session is bidirectional, such as a voice agent.

For broader delivery, retry, and ordering patterns, read webhook architecture patterns. For agent failure policy, use AI agent error handling.

Webhooks make AI workflows reliable when treated as signed, retryable event notifications. The durable job record, idempotent action, and current provider state remain the sources of truth.