Skip to content

Event-Driven Automation

Learn how to configure event listeners that automatically trigger AI agents and teams in response to external events from your systems.


Overview

The Event Listener System enables external systems to trigger AI agents and teams through a webhook-style API. Events are processed asynchronously via Redis Streams, ensuring high throughput and reliability.

Use Cases:

  • Automatically process orders when order.created events arrive
  • Send notifications when user.signup events occur
  • Trigger data collection workflows from external systems
  • Build event-driven automations between systems

Quick Start

1. Create an Event Listener

bash
curl -X POST "http://localhost:8000/api/v1/event-listeners" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Order Processing Handler",
    "description": "Handles new order events",
    "event_pattern": "order.created",
    "match_type": "exact",
    "target_type": "agent",
    "agent_id": 1,
    "message_template": "New order received: #{{payload.order_id}} from {{payload.customer}} for ${{payload.total}}. Please process this order.",
    "priority": 5,
    "is_active": true
  }'

2. Test Template Rendering

Test your message template without executing the agent:

bash
curl -X POST "http://localhost:8000/api/v1/event-listeners/1/test" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "order.created",
    "payload": {
      "order_id": "12345",
      "customer": "John Doe",
      "total": 99.99
    }
  }'

Response:

json
{
  "listener_id": 1,
  "listener_name": "Order Processing Handler",
  "template": "New order received: #{{payload.order_id}} ...",
  "rendered_message": "New order received: #12345 from John Doe for $99.99. Please process this order.",
  "input": { ... }
}

3. Send an Event

bash
curl -X POST "http://localhost:8000/api/v1/events" \
  -H "X-AUTH-TOKEN: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "order.created",
    "payload": {
      "order_id": "12345",
      "customer": "John Doe",
      "total": 99.99,
      "items": [
        {"name": "Widget", "quantity": 2}
      ]
    },
    "context": {
      "source": "shopify",
      "environment": "production"
    }
  }'

Response:

json
{
  "id": 1,
  "event_type": "order.created",
  "event_id": "auto-generated-uuid",
  "status": "PENDING",
  "listeners_matched": 1,
  "created_at": "2025-01-06T10:30:00Z"
}

4. Monitor Execution

bash
# Check event status
curl "http://localhost:8000/api/v1/events/1" \
  -H "X-AUTH-TOKEN: YOUR_API_KEY"

# View all executions for this event
curl "http://localhost:8000/api/v1/events/1/executions" \
  -H "X-AUTH-TOKEN: YOUR_API_KEY"

Pattern Matching

Event listeners support three match types:

EXACT Match

Matches event type exactly:

json
{
  "event_pattern": "order.created",
  "match_type": "exact"
}
Event TypeMatch?
order.created✅ Yes
order.updated❌ No
order.item.added❌ No

PREFIX Match

Matches events starting with pattern:

json
{
  "event_pattern": "order.",
  "match_type": "prefix"
}
Event TypeMatch?
order.created✅ Yes
order.updated✅ Yes
order.item.added✅ Yes
user.signup❌ No

WILDCARD Match

Uses fnmatch-style wildcards:

json
{
  "event_pattern": "order.*",
  "match_type": "wildcard"
}
PatternEvent TypeMatch?
order.*order.created✅ Yes
order.*order.item.added❌ No (nested)
order.**order.item.added✅ Yes
*.createdorder.created✅ Yes
*.createduser.created✅ Yes

When to use each:

  • EXACT: When you want to handle one specific event type
  • PREFIX: When you want to handle all events in a namespace
  • WILDCARD: When you need complex matching patterns

Message Templates

Message templates use Jinja2 syntax with these available variables:

VariableTypeDescription
{{event_type}}stringThe event type (e.g., "order.created")
{{payload}}dictFull payload object
{{payload.field}}anyAccess specific payload fields
{{context}}dictContext object (may be empty)

Basic Template

text
New {{event_type}} event received!

Order ID: {{payload.order_id}}
Customer: {{payload.customer}}
Total: ${{payload.total}}

Template with Conditionals

text
{% if payload.priority == 'high' %}
URGENT:{% endif %} Order #{{payload.order_id}}

Customer: {{payload.customer.name}} ({{payload.customer.email}})
Total: ${{payload.total}}

{% if payload.items %}
Items:
{% for item in payload.items %}
- {{item.name}} x{{item.quantity}} @ ${{item.price}}
{% endfor %}
{% endif %}

Source: {{context.source | default('unknown')}}

Template Best Practices

  1. Provide context: Include enough information for the agent to act
  2. Use defaults: Handle missing fields gracefully with | default('value')
  3. Format currency: Use consistent formatting for numbers
  4. Add structure: Use clear formatting for readability

Listener Configuration

Target Types

Agent Target:

json
{
  "target_type": "agent",
  "agent_id": 1,
  "team_id": null
}

Triggers a single agent with the rendered message.

Team Target:

json
{
  "target_type": "team",
  "agent_id": null,
  "team_id": 1
}

Triggers all agents in the team (parallel execution).

Priority

Listeners with the same event pattern execute in priority order (1 = highest, 10 = lowest):

json
{
  "priority": 5
}

Use cases:

  • Priority 1: Critical notifications
  • Priority 5: Standard processing (default)
  • Priority 10: Background tasks

Active/Inactive

Disable listeners without deleting them:

json
{
  "is_active": true
}

List only active listeners:

bash
curl "http://localhost:8000/api/v1/event-listeners?active_only=true"

Event Flow


Authentication

Event reception supports JWT tokens or API keys:

bash
# JWT Token
curl -X POST "http://localhost:8000/api/v1/events" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

# API Key
curl -X POST "http://localhost:8000/api/v1/events" \
  -H "X-AUTH-TOKEN: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

Both methods work identically. API keys are recommended for server-to-server integrations.


Idempotency

Prevent duplicate processing by providing an event_id:

json
{
  "event_id": "evt_abc123_unique_id",
  "event_type": "order.created",
  "payload": { ... }
}

If an event with the same event_id already exists for the account, the API returns the existing event instead of creating a duplicate.

Without event_id: A new UUID is auto-generated.


Error Handling

Event-Level Errors

If the event cannot be processed:

  • InboundEvent.statusFAILED
  • InboundEvent.error_message → Error description
  • Event is acknowledged (not retried automatically)

Execution-Level Errors

If a specific listener fails:

  • EventExecution.statusFAILED
  • EventExecution.error_message → Error description
  • Other listeners continue processing
  • Final InboundEvent.statusFAILED if any listener failed

Retry Strategy

Failed executions can be retried via the queue system's retry mechanism. See Background Systems for details.


Monitoring

List All Listeners

bash
curl "http://localhost:8000/api/v1/event-listeners" \
  -H "Authorization: Bearer YOUR_TOKEN"

Get Listener Details

bash
curl "http://localhost:8000/api/v1/event-listeners/1" \
  -H "Authorization: Bearer YOUR_TOKEN"

View Execution History

bash
# All executions for a listener
curl "http://localhost:8000/api/v1/event-listeners/1/executions" \
  -H "Authorization: Bearer YOUR_TOKEN"

# All executions for an event
curl "http://localhost:8000/api/v1/events/1/executions" \
  -H "X-AUTH-TOKEN: YOUR_API_KEY"

Example: E-commerce Order Processing

1. Create Listener

bash
curl -X POST "http://localhost:8000/api/v1/event-listeners" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "name": "Order Processor",
    "event_pattern": "order.created",
    "match_type": "exact",
    "target_type": "agent",
    "agent_id": 5,
    "message_template": "Process order #{{payload.order_id}}\n\nCustomer: {{payload.customer.name}}\nEmail: {{payload.customer.email}}\nTotal: ${{payload.total}}\n\n{% for item in payload.items %}{{loop.index}}. {{item.name}} x{{item.quantity}}\n{% endfor %}\n\nShipping: {{payload.shipping.address}}"
  }'

2. Send Order Event

bash
curl -X POST "http://localhost:8000/api/v1/events" \
  -H "X-AUTH-TOKEN: $API_KEY" \
  -d '{
    "event_type": "order.created",
    "event_id": "order_12345",
    "payload": {
      "order_id": "12345",
      "customer": {
        "name": "Jane Smith",
        "email": "jane@example.com"
      },
      "total": 149.99,
      "items": [
        {"name": "Widget Pro", "quantity": 2, "price": 59.99},
        {"name": "Gadget Plus", "quantity": 1, "price": 29.99}
      ],
      "shipping": {
        "address": "123 Main St, City, ST 12345"
      }
    },
    "context": {
      "source": "shopify",
      "webhook_id": "wh_abc123"
    }
  }'

3. Monitor Results

bash
# Check execution
curl "http://localhost:8000/api/v1/events/1/executions" \
  -H "X-AUTH-TOKEN: $API_KEY"

Cross-References