Triggers
Triggers enable agents to execute in response to external events via webhooks. When something happens in another system, it can automatically invoke your agent.
Integration Event Registry
Deeployd maintains a registry of events from connected integrations. When you connect an integration (HubSpot, Slack, GitHub, etc.), you gain access to its events.
Available Integration Events
| Integration | Events |
|---|---|
| HubSpot | Contact Created, Deal Created, Deal Stage Changed, Deal Won/Lost, Ticket Created, Form Submitted, Meeting Booked |
| Slack | Message Posted, Bot Mentioned, Reaction Added, Channel Created, User Joined, File Shared |
| GitHub | Code Pushed, PR Opened/Merged/Closed, Review Requested, Issue Opened/Closed, Release Published, Workflow Completed/Failed |
| Stripe | Payment Succeeded/Failed, Invoice Paid, Subscription Created/Updated/Canceled, Customer Created, Dispute Created |
Event Categories
Events are organized by category for easier discovery:
- CRM: Contact, deal, and company events
- Communication: Messages, mentions, notifications
- Development: Code, PRs, issues, deployments
- Payment: Transactions, subscriptions, invoices
- Support: Tickets, cases, escalations
- Calendar: Meetings, scheduling
- HR: User provisioning, onboarding
- Task: Work items, assignments
Trigger Types
| Type | Description |
|---|---|
| Webhook | External system sends event to Deeployd |
| Polling | Deeployd periodically checks for changes |
| WebSocket | Real-time bidirectional connection |
| Triggers from email events | |
| Manual | User-initiated triggers |
Why Triggers?
Connect your agents to the outside world:
- Form submissions: Process new leads instantly
- Payment events: Handle Stripe webhooks
- CI/CD: Run agents on deployment events
- Custom integrations: Any system that can send HTTP requests
How Triggers Work
External System ──HTTP POST──▶ Trigger Webhook ──▶ Agent Execution
- External system sends HTTP request to trigger URL
- Trigger receives and validates the request
- Trigger extracts and maps input data
- Agent executes with the mapped input
- Response returned to external system
Creating Triggers
Basic Trigger
const trigger = await client.triggers.create({
name: 'New Lead Processor',
description: 'Process new leads from website form',
targetType: 'agent',
targetId: 'lead-agent-123'
});
console.log(trigger.webhookUrl);
// https://api.deeployd.com/triggers/abc123
With Signature Verification
Secure your trigger with HMAC signature verification:
const trigger = await client.triggers.create({
name: 'Stripe Webhook',
targetType: 'agent',
targetId: 'payment-agent',
requireSignature: true
});
console.log(trigger.webhookUrl); // Public URL
console.log(trigger.webhookSecret); // Use this to verify signatures
With Input Mapping
Transform incoming webhook data before passing to agent:
const trigger = await client.triggers.create({
name: 'GitHub PR Handler',
targetType: 'agent',
targetId: 'code-review-agent',
inputMapping: {
// Extract specific fields using JSONPath
template: {
prNumber: '$.pull_request.number',
prTitle: '$.pull_request.title',
author: '$.pull_request.user.login',
repo: '$.repository.full_name'
},
// Add static fields
staticFields: {
source: 'github',
reviewType: 'automated'
},
// Include specific headers
includeHeaders: ['x-github-event']
}
});
Trigger for Workflow
Triggers can also start workflows:
const trigger = await client.triggers.create({
name: 'Order Processing Workflow',
targetType: 'workflow',
targetId: 'order-workflow-123',
inputMapping: {
template: {
orderId: '$.order.id',
customerId: '$.order.customer_id',
items: '$.order.line_items'
}
}
});
Webhook URL
Each trigger gets a unique webhook URL:
https://api.deeployd.com/triggers/{slug}
This URL accepts POST requests with JSON payloads.
Calling the Webhook
curl -X POST https://api.deeployd.com/triggers/abc123 \
-H "Content-Type: application/json" \
-d '{
"event": "new_lead",
"lead": {
"name": "John Doe",
"email": "john@example.com"
}
}'
Response
{
"success": true,
"executionId": "exec-789",
"message": "Trigger executed successfully"
}
Signature Verification
When requireSignature: true, incoming requests must include a valid HMAC signature.
How It Works
- Sender computes HMAC-SHA256 of request body using webhook secret
- Sender includes signature in
X-Signature-256header - Deeployd verifies signature before processing
Example: Sending Signed Requests
import crypto from 'crypto';
const webhookSecret = 'your-webhook-secret';
const payload = JSON.stringify({ event: 'test' });
const signature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
await fetch('https://api.deeployd.com/triggers/abc123', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Signature-256': `sha256=${signature}`
},
body: payload
});
Rotate Webhook Secret
If your secret is compromised:
const newSecret = await client.triggers.rotateSecret('trigger-123');
console.log(newSecret.webhookSecret); // New secret
Input Mapping
Control how webhook data is transformed for your agent.
JSONPath Extraction
Extract nested values from webhook payload:
inputMapping: {
template: {
// $.path.to.field syntax
userId: '$.user.id',
userName: '$.user.profile.name',
firstItem: '$.items[0].name',
allTags: '$.metadata.tags'
}
}
Static Fields
Add constant values:
inputMapping: {
staticFields: {
source: 'webhook',
environment: 'production',
priority: 'high'
}
}
Include Headers
Pass specific headers as input:
inputMapping: {
includeHeaders: [
'x-request-id',
'x-correlation-id',
'user-agent'
]
}
Combined Example
inputMapping: {
template: {
orderId: '$.order.id',
customerEmail: '$.customer.email'
},
staticFields: {
notifyTeam: true,
processor: 'order-handler'
},
includeHeaders: ['x-shopify-shop-domain']
}
Managing Triggers
List Triggers
const triggers = await client.triggers.list({
status: 'active',
limit: 50
});
Get Trigger
const trigger = await client.triggers.get('trigger-123');
// Note: webhookSecret is masked in response
Update Trigger
await client.triggers.update('trigger-123', {
name: 'Updated Name',
status: 'paused',
inputMapping: {
template: { newField: '$.new.path' }
}
});
Delete Trigger
await client.triggers.delete('trigger-123');
Trigger Status
| Status | Description |
|---|---|
active | Accepting and processing requests |
paused | Accepting but not processing (queued) |
disabled | Rejecting all requests |
Pause Trigger
await client.triggers.update('trigger-123', {
status: 'paused'
});
Execution History
Track all trigger executions:
const executions = await client.triggers.listExecutions('trigger-123', {
limit: 100,
status: 'failed' // Optional filter
});
for (const exec of executions.data) {
console.log({
id: exec.id,
method: exec.method,
path: exec.path,
status: exec.status,
duration: exec.durationMs,
requestBody: exec.requestBody,
responseBody: exec.responseBody,
error: exec.error
});
}
Integration Examples
Stripe Webhooks
const trigger = await client.triggers.create({
name: 'Stripe Payment Handler',
targetType: 'agent',
targetId: 'payment-agent',
requireSignature: true,
inputMapping: {
template: {
eventType: '$.type',
paymentId: '$.data.object.id',
amount: '$.data.object.amount',
currency: '$.data.object.currency',
customerId: '$.data.object.customer'
}
}
});
GitHub Webhooks
const trigger = await client.triggers.create({
name: 'GitHub PR Review',
targetType: 'agent',
targetId: 'code-review-agent',
requireSignature: true,
inputMapping: {
template: {
action: '$.action',
prNumber: '$.number',
prTitle: '$.pull_request.title',
prBody: '$.pull_request.body',
author: '$.pull_request.user.login',
repo: '$.repository.full_name',
baseBranch: '$.pull_request.base.ref',
headBranch: '$.pull_request.head.ref'
},
includeHeaders: ['x-github-event']
}
});
Slack Events
const trigger = await client.triggers.create({
name: 'Slack Message Handler',
targetType: 'agent',
targetId: 'slack-bot-agent',
inputMapping: {
template: {
eventType: '$.event.type',
userId: '$.event.user',
channelId: '$.event.channel',
text: '$.event.text',
timestamp: '$.event.ts'
}
}
});
Custom CRM Integration
const trigger = await client.triggers.create({
name: 'New Customer Handler',
targetType: 'workflow',
targetId: 'onboarding-workflow',
inputMapping: {
template: {
customerId: '$.customer.id',
email: '$.customer.email',
name: '$.customer.name',
plan: '$.subscription.plan',
source: '$.attribution.source'
},
staticFields: {
workflow: 'customer-onboarding',
notifyTeam: true
}
}
});
Best Practices
1. Always Use Signature Verification
// ✅ Good - verify webhook authenticity
requireSignature: true
// ❌ Bad - anyone can call your trigger
requireSignature: false
2. Extract Only Needed Data
// ✅ Good - specific fields
template: {
orderId: '$.order.id',
status: '$.order.status'
}
// ❌ Bad - passing entire payload
// (can contain sensitive data, bloats input)
3. Add Source Identification
staticFields: {
source: 'stripe',
environment: 'production'
}
4. Monitor Execution History
Check failed executions regularly and set up alerts:
const failures = await client.triggers.listExecutions('trigger-123', {
status: 'failed',
limit: 10
});
if (failures.data.length > 0) {
// Alert or investigate
}
5. Use Descriptive Names
// ✅ Good
name: 'Stripe Payment Success Handler'
name: 'GitHub PR Opened - Code Review'
// ❌ Bad
name: 'Webhook 1'
name: 'Handler'
Next: Learn about Workflows for orchestrating multi-step processes.