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.status → FAILED
  • InboundEvent.error_message → Error description
  • Event is acknowledged (not retried automatically)

Execution-Level Errors ​

If a specific listener fails:

  • EventExecution.status → FAILED
  • EventExecution.error_message → Error description
  • Other listeners continue processing
  • Final InboundEvent.status → FAILED 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 ​