Triggers

Copy page

Create webhook endpoints that allow external services to invoke your agents

Triggers create webhook endpoints that allow external services (like GitHub, Slack, Stripe, or custom applications) to invoke your agents. When a webhook is received, the payload is validated, transformed, and used to start a new conversation with the agent.

Overview

Triggers are useful for:

  • Event-driven workflows - Respond to events from external services (GitHub issues, Stripe payments, etc.)
  • Third-party integrations - Connect services that can send webhooks to your agents
  • Automated tasks - Trigger agent actions based on external events
  • Custom applications - Allow your own services to invoke agents via HTTP

Creating Triggers

Basic Trigger

import { agent, trigger, subAgent } from "@inkeep/agents-sdk";

const slackTrigger = trigger({
  name: "Slack Messages",
  description: "Handle incoming Slack messages",
  messageTemplate: "New message from {{user.name}}: {{text}}",
  authentication: { type: "none" },
});

export default agent({
  id: "support-agent",
  name: "Support Agent",
  defaultSubAgent: subAgent({
    id: "support",
    name: "Support Assistant",
    prompt: "You help answer support questions.",
  }),
  triggers: () => [slackTrigger],
});

Trigger with Input Validation

Use JSON Schema or Zod to validate incoming webhook payloads:

import { z } from "zod";

const githubWebhookTrigger = trigger({
  name: "GitHub Events",
  description: "Handle GitHub webhook events",
  inputSchema: z.object({
    action: z.string(),
    repository: z.object({
      full_name: z.string(),
    }),
    sender: z.object({
      login: z.string(),
    }),
  }),
  messageTemplate:
    "GitHub event: {{action}} on {{repository.full_name}} by {{sender.login}}",
  authentication: { type: "none" },
  signingSecret: process.env.GITHUB_WEBHOOK_SECRET,
});

Trigger with Authentication

Triggers support multiple authentication methods:

Configuration Options

OptionTypeRequiredDescription
namestringYesHuman-readable name for the trigger
descriptionstringNoDescription of what the trigger does
enabledbooleanNoWhether the trigger is active (default: true)
inputSchemaobject | ZodObjectNoJSON Schema or Zod schema for payload validation
messageTemplatestringYesTemplate for the message sent to the agent
authenticationobjectNoAuthentication configuration
signingSecretstringNoHMAC-SHA256 secret for signature verification
outputTransformobjectNoPayload transformation configuration

Message Templates

Message templates use {{placeholder}} syntax to interpolate values from the webhook payload:

const trigger = trigger({
  name: "Order Webhook",
  messageTemplate: `
New order received:
- Order ID: {{order.id}}
- Customer: {{customer.name}} ({{customer.email}})
- Total: ${{order.total}}
- Items: {{order.items.length}} items

Please process this order and send a confirmation.
  `.trim(),
  authentication: { type: "none" },
});

Nested properties are accessed with dot notation ({{customer.email}}). Array length can be accessed with .length.

Payload Transformation

Transform incoming payloads before they reach the message template:

const transformingTrigger = trigger({
  name: "Transformed Webhook",
  messageTemplate: "Event: {{eventType}} - {{summary}}",
  outputTransform: {
    // JMESPath expression for complex transformations
    jmespath: "{ eventType: type, summary: data.description }",
  },
  authentication: { type: "none" },
});

// Or use simple object mapping
const mappingTrigger = trigger({
  name: "Mapped Webhook",
  messageTemplate: "User {{userName}} performed {{actionName}}",
  outputTransform: {
    objectTransformation: {
      userName: "payload.user.display_name",
      actionName: "payload.action.type",
    },
  },
  authentication: { type: "none" },
});

Signature Verification

For services that sign webhooks (like GitHub, Stripe, Slack), use signingSecret:

const githubTrigger = trigger({
  name: "GitHub Webhook",
  messageTemplate: "GitHub: {{action}} on {{repository.full_name}}",
  authentication: { type: "none" },
  signingSecret: process.env.GITHUB_WEBHOOK_SECRET,
});

The framework automatically verifies HMAC-SHA256 signatures in the X-Hub-Signature-256 header.

Webhook URL

After pushing your agent configuration, each trigger gets a unique webhook URL:

POST /tenants/{tenantId}/projects/{projectId}/agents/{agentId}/triggers/{triggerId}

You can find the full webhook URL in the Inkeep dashboard or via the API response when creating/listing triggers.

Invocation Tracking

Every webhook invocation is tracked with:

  • Invocation ID - Unique identifier for the invocation
  • Status - pending, success, or failed
  • Request Payload - Original webhook payload
  • Transformed Payload - Payload after transformation
  • Conversation ID - ID of the conversation created
  • Error Message - Error details if the invocation failed

Query invocation history via the API:

# List invocations for a trigger
curl "https://api.inkeep.com/v1/tenants/{tenantId}/projects/{projectId}/agents/{agentId}/triggers/{triggerId}/invocations"

# Filter by status or date range
curl "https://api.inkeep.com/v1/.../invocations?status=failed&from=2024-01-01T00:00:00Z"

Complete Example

Here's a complete example with a GitHub webhook trigger that handles issue events:

import { z } from "zod";
import { agent, trigger, subAgent } from "@inkeep/agents-sdk";

// Define the expected GitHub webhook payload
const githubIssueSchema = z.object({
  action: z.enum(["opened", "closed", "reopened", "edited"]),
  issue: z.object({
    number: z.number(),
    title: z.string(),
    body: z.string().nullable(),
    user: z.object({
      login: z.string(),
    }),
    labels: z.array(
      z.object({
        name: z.string(),
      })
    ),
  }),
  repository: z.object({
    full_name: z.string(),
  }),
});

const githubIssueTrigger = trigger({
  name: "GitHub Issues",
  description: "Responds to GitHub issue events",
  enabled: true,
  inputSchema: githubIssueSchema,
  messageTemplate: `
GitHub Issue {{action}}:
- Repository: {{repository.full_name}}
- Issue #{{issue.number}}: {{issue.title}}
- Author: {{issue.user.login}}
- Body: {{issue.body}}

Please analyze this issue and provide a helpful response.
  `.trim(),
  authentication: { type: "none" },
  signingSecret: process.env.GITHUB_WEBHOOK_SECRET,
});

const issueResponder = subAgent({
  id: "issue-responder",
  name: "Issue Responder",
  prompt: `You are a helpful assistant that responds to GitHub issues.
When an issue is opened, analyze the content and provide:
1. A summary of the issue
2. Suggested labels if appropriate
3. Initial guidance or questions for the issue author`,
});

export default agent({
  id: "github-bot",
  name: "GitHub Bot",
  defaultSubAgent: issueResponder,
  triggers: () => [githubIssueTrigger],
});

Best Practices

  1. Always validate input - Use inputSchema to ensure payloads match expected format
  2. Use signing secrets - Verify webhook authenticity when the source supports it
  3. Write clear templates - Make message templates readable and include relevant context
  4. Handle errors gracefully - Check invocation status and logs for failed webhooks
  5. Use descriptive names - Name triggers clearly to identify their purpose in dashboards