Agent webhooks are designed to allow you to launch an agent in response to a message from a platform like email, slack, etc.

Not to be confused with webhooks, which allows you to receive a notification when an approval or human contact is completed, Agent webhooks are specifically designed for kicking off new tasks and workflows. They use the same webhook console in the HumanLayer dashboard, with an event type of v1beta2.agent_email.received.

Agent webhooks are currently in beta. If you’d like to help us test and improve the feature, please reach out to us at contact@humanlayer.dev

Breaking Change 01/2025: Agent webhooks are transitioning to a new format. Please use the v1beta2.agent_email.received event type to configure where email webhooks are sent. The email address configuration functionality remains unchanged.

Use cases

Agent webhooks are useful for:

  • Forwarding an email to an agent to handle
  • Launching an agent workflow in response to a message in Slack

You can see examples of using agent webhooks in:

  • Mailcrew - an open source agent that uses HumanLayer to receive and respond to inbound emails
  • FastAPI Email Example - a complete example of handling inbound emails with FastAPI

Overview

To get started with agent webhooks, you’ll need to:

  1. Implement an AI Agent in your language and/or framework of choice, and create an API endpoint that can launch the agent
  2. Create a publicly reachable URL that can receive webhooks from HumanLayer (we recommend ngrok to catch webhooks while you’re developing locally)
  3. Create a new agent webhook in the HumanLayer dashboard
  4. Configure your webhook endpoint to receive events with the v1beta2.agent_email.received event type in the Response Webhooks section of the HumanLayer dashboard
  5. Test the webhook by sending an email to the webhook email address

Email Payload

The webhook payload models are defined in models_agent_webhook.py.

For email webhooks, the payload will have the following structure:

webhook_payload
object

a JSON example might look like

{
  "event": {
    "body": "Hello,\n\nJust a reminder about our important meeting scheduled for tomorrow at 2 PM. Please come prepared with your quarterly reports.\n\nBest regards,\nSender",
    "from_address": "sender@example.com",
    "message_id": "<20230615123456.ABC123@example.com>",
    "previous_thread": [
      {
        "bcc_address": [],
        "cc_address": [
          "manager@example.com"
        ],
        "content": "Thank you for the update. I'll review the documents and get back to you soon.",
        "datetime": "2023-06-14T15:30:00Z",
        "from_address": "recipient@example.com",
        "subject": "Re: Project Update",
        "to_address": [
          "sender@example.com"
        ]
      },
      {
        "bcc_address": [
          "archive@example.com"
        ],
        "cc_address": [
          "manager@example.com"
        ],
        "content": "Hi,\n\nI've attached the latest project documents for your review. Let me know if you have any questions.",
        "datetime": "2023-06-14T14:00:00Z",
        "from_address": "sender@example.com",
        "subject": "Project Update",
        "to_address": [
          "recipient@example.com"
        ]
      }
    ],
    "raw_email": "From: sender@example.com\nTo: recipient@example.com\nSubject: Important Meeting Tomorrow\nDate: Thu, 15 Jun 2023 12:34:56 +0000\nMessage-ID: <20230615123456.ABC123@example.com>\n\nHello,\n\nJust a reminder about our important meeting scheduled for tomorrow at 2 PM. Please come prepared with your quarterly reports.\n\nBest regards,\nSender",
    "subject": "Important Meeting Tomorrow",
    "to_address": "recipient@example.com"
  },
  "is_test": true,
  "type": "agent_email.received"
}

State Preservation

When making function calls or human contacts, you can include a state object that will be preserved and returned in webhooks. This allows your application to be stateless while maintaining context across the request lifecycle.

Example:

# Store the current state when requesting approval
function_call = FunctionCall(
    run_id="run_123",
    call_id="call_456",
    spec=FunctionCallSpec(
        fn="send_email",
        kwargs={"to": "user@example.com"},
        state={
            "conversation_history": previous_messages,
            "user_preferences": preferences,
        }
    )
)


### Using Ngrok for local development

1. Start your local API server and note the port it's running on
2. Install ngrok and run `ngrok http <port>`
3. Copy the ngrok URL and use it as the callback URL in the HumanLayer dashboard