onTrigger handler receives a typed event object with the payload.
In TypeScript, terse generate writes a single Triggers object in src/terse.generated.ts. Import it and call the nested helper for your event (for example Triggers.github.onPROpened(...)). Each integration and system trigger has its own section below.
Integration triggers
GitHub
| Trigger | Event type | Description |
|---|---|---|
Triggers.github.onPush() | GithubPushTrigger | Code is pushed to a branch |
Triggers.github.onPROpened() | GithubPROpenedTrigger | A pull request is opened |
Triggers.github.onPRMerged() | GithubPRMergedTrigger | A pull request is merged |
Triggers.github.onPRClosed() | GithubPRClosedTrigger | A pull request is closed |
Triggers.github.onPRSynchronized() | GithubPRSynchronizedTrigger | New commits are pushed to a PR |
Triggers.github.onPR() | GithubPRTrigger | Any pull request event |
Triggers.github.onIssueComment() | GithubIssueCommentCreatedTrigger | A comment is created on an issue or pull request |
Triggers.github.trigger() | GithubTrigger | Any GitHub event you select with eventTypes |
repo parameter.
Slack
| Trigger | Event type | Description |
|---|---|---|
Triggers.slack.onMessage() | SlackMessageTrigger | A message is posted in a channel |
Triggers.slack.onDm() | SlackMessageTrigger | A direct message is received |
Triggers.slack.onAppMention() | SlackAppMentionTrigger | The Slack app is mentioned in a channel |
Triggers.slack.onReactionAdded() | SlackReactionAddedTrigger | An emoji reaction is added to a message |
Triggers.slack.trigger() | SlackTrigger (union) | Any Slack event you select with eventTypes |
Linear
| Trigger | Event type | Description |
|---|---|---|
Triggers.linear.onIssueCreated() | LinearIssueCreatedTrigger | An issue is created |
Triggers.linear.onIssueUpdated() | LinearIssueUpdatedTrigger | An issue is updated |
Triggers.linear.onComment() | LinearCommentCreatedTrigger | A comment is added to an issue |
Triggers.linear.trigger() | LinearTrigger (union) | Any Linear event you select with eventTypes |
LinearTeam / LinearProject constants (same pattern as SlackChannel for Slack).
Attio
Connect Attio under Integrations, configure which Attio events start each workflow in the Terse app, then runterse generate. When Attio input triggers are enabled for your workspace, Triggers.attio appears in src/terse.generated.ts.
| Trigger | Event type | Description |
|---|---|---|
Triggers.attio.onRecordCreated() | AttioRecordCreatedTrigger | A record is created |
Triggers.attio.onRecordUpdated() | AttioRecordUpdatedTrigger | A record is updated |
Triggers.attio.onRecordMerged() | AttioRecordMergedTrigger | Two records are merged |
Triggers.attio.onRecordDeleted() | AttioRecordDeletedTrigger | A record is deleted |
Triggers.attio.onObjectAttributeCreated() | AttioObjectAttributeCreatedTrigger | An object attribute is created |
Triggers.attio.onObjectAttributeUpdated() | AttioObjectAttributeUpdatedTrigger | An object attribute is updated |
Triggers.attio.onListCreated() | AttioListCreatedTrigger | A list is created |
Triggers.attio.onListUpdated() | AttioListUpdatedTrigger | A list is updated |
Triggers.attio.onListDeleted() | AttioListDeletedTrigger | A list is deleted |
Triggers.attio.onListAttributeCreated() | AttioListAttributeCreatedTrigger | A list attribute is created |
Triggers.attio.onListAttributeUpdated() | AttioListAttributeUpdatedTrigger | A list attribute is updated |
Triggers.attio.onListEntryCreated() | AttioListEntryCreatedTrigger | A list entry is created |
Triggers.attio.onListEntryUpdated() | AttioListEntryUpdatedTrigger | A list entry is updated |
Triggers.attio.onListEntryDeleted() | AttioListEntryDeletedTrigger | A list entry is deleted |
Triggers.attio.onNoteCreated() | AttioNoteCreatedTrigger | A note is created |
Triggers.attio.onNoteContentUpdated() | AttioNoteContentUpdatedTrigger | A note’s content is updated |
Triggers.attio.onNoteUpdated() | AttioNoteUpdatedTrigger | A note is updated |
Triggers.attio.onNoteDeleted() | AttioNoteDeletedTrigger | A note is deleted |
Triggers.attio.onCommentCreated() | AttioCommentCreatedTrigger | A comment is created |
Triggers.attio.onCommentResolved() | AttioCommentResolvedTrigger | A comment is resolved |
Triggers.attio.onCommentUnresolved() | AttioCommentUnresolvedTrigger | A resolved comment is reopened |
Triggers.attio.onCommentDeleted() | AttioCommentDeletedTrigger | A comment is deleted |
Triggers.attio.onTaskCreated() | AttioTaskCreatedTrigger | A task is created |
Triggers.attio.onTaskUpdated() | AttioTaskUpdatedTrigger | A task is updated |
Triggers.attio.onTaskDeleted() | AttioTaskDeletedTrigger | A task is deleted |
Triggers.attio.onWorkspaceMemberCreated() | AttioWorkspaceMemberCreatedTrigger | A workspace member is added |
Triggers.attio.onCallRecordingCreated() | AttioCallRecordingCreatedTrigger | A call recording is created |
Triggers.attio.trigger() | AttioTrigger (union) | Any Attio events you select with eventTypes |
object: AttioObject.YourObject on the record helpers (onRecordCreated, onRecordUpdated, onRecordMerged, onRecordDeleted) to scope deliveries to a single CRM object. Omit object when you want the union of every generated object’s attribute shape.
Gmail
| Trigger | Event type | Description |
|---|---|---|
Triggers.gmail.onEmail() | GmailTrigger | A new email is received |
Triggers.gmail.trigger() | GmailTrigger (union) | Any Gmail event you select with eventTypes |
HeyReach
HeyReach fires when LinkedIn outreach events occur (messages, connection requests, campaign milestones, and more). Connect HeyReach under Integrations in the Terse app, then runterse generate so Triggers.heyReach and typed HeyReachCampaign constants appear in src/terse.generated.ts.
Each helper maps to one HeyReachEventType value (also exported from terse-sdk). Use Triggers.heyReach.trigger({ eventType: HeyReachEventType.MESSAGE_REPLY_RECEIVED }) when you want to pick the event type dynamically.
| Trigger | Event type |
|---|---|
Triggers.heyReach.onConnectionRequestSent() | HeyReachConnectionRequestSentTrigger |
Triggers.heyReach.onConnectionRequestAccepted() | HeyReachConnectionRequestAcceptedTrigger |
Triggers.heyReach.onMessageSent() | HeyReachMessageSentTrigger |
Triggers.heyReach.onMessageReplyReceived() | HeyReachMessageReplyReceivedTrigger |
Triggers.heyReach.onInmailSent() | HeyReachInmailSentTrigger |
Triggers.heyReach.onInmailReplyReceived() | HeyReachInmailReplyReceivedTrigger |
Triggers.heyReach.onFollowSent() | HeyReachFollowSentTrigger |
Triggers.heyReach.onLikedPost() | HeyReachLikedPostTrigger |
Triggers.heyReach.onViewedProfile() | HeyReachViewedProfileTrigger |
Triggers.heyReach.onCampaignCompleted() | HeyReachCampaignCompletedTrigger |
Triggers.heyReach.onLeadTagUpdated() | HeyReachLeadTagUpdatedTrigger |
campaigns with generated HeyReachCampaign instances to handle only those campaigns; omit it to receive events from all campaigns.
WorkOS
| Trigger | Event type | Description |
|---|---|---|
Triggers.workOS.onUserCreated() | WorkOSUserCreatedTrigger | A user is created |
Triggers.workOS.onUserUpdated() | WorkOSUserUpdatedTrigger | A user is updated |
Triggers.workOS.onUserDeleted() | WorkOSUserDeletedTrigger | A user is deleted |
Triggers.workOS.onMembershipCreated() | WorkOSOrganizationMembershipCreatedTrigger | An organization membership is created |
Triggers.workOS.onMembershipUpdated() | WorkOSOrganizationMembershipUpdatedTrigger | An organization membership is updated |
Triggers.workOS.onMembershipDeleted() | WorkOSOrganizationMembershipDeletedTrigger | An organization membership is deleted |
Triggers.workOS.onMembershipChanged() | WorkOSMembershipTrigger | Any membership change |
Triggers.workOS.onInvitationCreated() | WorkOSInvitationCreatedTrigger | An invitation is created |
Triggers.workOS.onInvitationResent() | WorkOSInvitationResentTrigger | An invitation is resent |
Triggers.workOS.onInvitationSent() | WorkOSInvitationTrigger | An invitation is created or resent |
Triggers.workOS.onInvitationAccepted() | WorkOSInvitationAcceptedTrigger | An invitation is accepted |
Triggers.workOS.onInvitationRevoked() | WorkOSInvitationRevokedTrigger | An invitation is revoked |
Triggers.workOS.onOrganizationCreated() | WorkOSOrganizationTrigger | An organization is created |
Triggers.workOS.trigger() | WorkOSTrigger (union) | Any WorkOS event you select with eventTypes |
eventTypes to trigger() for multiple.
Web Monitor
Track web changes continuously and get notified when there are updates. You can add multipleTriggers.webMonitor.onEvent(...) triggers to the same workflow. Terse runs each monitor independently and calls the same onTrigger handler for every matching event.
| Trigger | Event type | Description |
|---|---|---|
Triggers.webMonitor.onEvent() | WebMonitorTrigger | Fires when scheduled web monitoring detects relevant changes |
WebMonitorTriggerFor from terse-sdk and bind it to your Zod schema:
Writing effective queries
The monitor matches by intent, not keywords. Write your query as a natural sentence describing what you care about — not a search string. Do:- Write in plain language:
"What are a16z's latest investments?" - Track narratives and social buzz:
"What are people saying on Twitter about Cloud agents?" - Be specific about subject and signal:
"FDA approval decisions for GLP-1 drugs" - Combine related signals:
"OpenAI or Anthropic model releases and benchmark results"
- Use Boolean operators (
AND,OR,NOT) — this is not a search engine - Include specific dates — monitors track new developments going forward, not history
- Write keyword dumps:
"acme corp acme funding raise series B"
| Frequency | Best for |
|---|---|
1h | Breaking news, social signals, fast-moving markets |
1d | Press releases, blog posts, job postings, pricing page changes |
1w | Regulatory filings, quarterly reports, slow competitive signals |
System triggers
Schedule
| Trigger | Event type | Description |
|---|---|---|
Triggers.schedule.cron() | CronTrigger | Fires on a cron schedule |
Webhook
| Trigger | Event type | Description |
|---|---|---|
Triggers.webhook.onRequest() | WebhookTrigger | Fires when an HTTP request hits the generated webhook URL |
terse deploy, the CLI prints that URL for each affected workflow so you can copy it straight into your caller or load test.
Pass a type argument to Triggers.webhook.onRequest<YourPayload>() so onTrigger and filter see your JSON body shape on event.body (defaults to unknown when omitted).
Common event interface
All triggers resolve to the shared canonicalTrigger payload shape. Your handler receives the concrete subtype for the trigger you selected.
