Skip to main content
Triggers define the event that starts your workflow. Each trigger is tied to an integration and fires when a specific event occurs. Your onTrigger handler receives a typed event object with the payload. In TypeScript, terse generate exports a Triggers object from src/terse.generated.ts, with each integration’s trigger factories and payload types declared in src/terse.generated/<integration>.triggers.ts. Import everything from "./terse.generated" and call the nested helper for your event (for example Triggers.github.onPROpened(...)); the event types in the tables below are importable from the same place. Each integration and system trigger has its own section below. Every event, whatever its trigger, carries triggeredAt: a Date fixed to the moment Terse received the trigger. Use it instead of Date.now() for any date math the run depends on. See trigger time.

Integration triggers

GitHub

Config: Scoped to specific repositories via repo parameter.

Slack

Config: Scoped to specific channels or users.

Linear

Config: Optionally scoped to a team and/or project using generated 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 run terse generate. When Attio input triggers are enabled for your workspace, Triggers.attio appears in src/terse.generated.ts. Config: Pass 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

HeyReach

HeyReach fires when LinkedIn outreach events occur (messages, connection requests, campaign milestones, and more). Connect HeyReach under Integrations in the Terse app, then run terse 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. Config: Pass campaigns with generated HeyReachCampaign instances to handle only those campaigns; omit it to receive events from all campaigns.

WorkOS

Config: Use a typed helper for one event, or pass eventTypes to trigger() for multiple.

Web Monitor

Track web changes continuously and get notified when there are updates. You can add multiple Triggers.webMonitor.onEvent(...) triggers to the same workflow. Terse runs each monitor independently and calls the same onTrigger handler for every matching event.
If you need to annotate monitor events manually, import WebMonitorTriggerFor from ./terse.generated 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"
Don’t:
  • 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"
Choosing frequency:

System triggers

Schedule

Expressions use standard 5-field cron syntax (minute hour day-of-month month day-of-week). The optional timezone is an IANA timezone name — the Timezone union exported by terse-sdk, so your editor autocompletes valid names — and the expression is evaluated as wall-clock time in that zone, adjusting automatically when daylight saving starts or ends. Omit it to evaluate in UTC.

Webhook

Webhook URLs are auto-generated on deploy and remain stable across redeploys. After 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 canonical Trigger payload shape. Your handler receives the concrete subtype for the trigger you selected.
Each trigger subtype adds its own canonical fields, such as Slack message metadata, GitHub PR data, webhook request bodies, or cron trigger context.