
Sim 触发器开发规范从目录结构到 Registry 注册的完整指南【免费下载链接】simSim is the collaborative workspace to build, deploy, and monitor AI agents and workflows. Used by 100,000 builders.项目地址: https://gitcode.com/GitHub_Trending/sim16/sim导读本文基于 apps/sim/triggers/AGENTS.md 中的 Triggers Scope 规范结合 Sim 开源仓库中 70 个服务、500 个触发器定义的源码实现系统讲解 Sim 触发器的架构约定与开发方法论。读完本文你将掌握如何为一个新集成服务规划触发器目录与文件拆分、如何利用共享 helper 复用配置代码、如何设计对下游 blocks 友好且明确的输出结构以及如何在TRIGGER_REGISTRY中注册触发器并遵循 ID 命名规范。一、触发器在 Sim 中的定位Sim 是用于构建、部署和监控 AI Agent 与工作流的协作平台。触发器Trigger是工作流执行的入口它监听外部服务GitHub、Slack、Linear、Jira、Stripe 等或内部系统Sim 工作区事件、表格新行产生的事件将事件数据转换为结构化输出交给下游 blocks 处理。从源码结构看触发器体系由四个核心文件构成apps/sim/triggers/types.ts —— 定义TriggerConfig、TriggerOutput、TriggerRegistry类型契约apps/sim/triggers/registry.ts —— 集中注册全部触发器实例是触发器的唯一事实来源apps/sim/triggers/index.ts —— 提供getTrigger、getAllTriggers、buildTriggerSubBlocks等查询与构建工具apps/sim/triggers/constants.ts —— 定义系统级 subblock ID、轮询 provider 集合、内部触发器 provider 集合等常量。TRIGGER_REGISTRY中注册了 500 个触发器覆盖 Airtable、Attio、Bitbucket、ClickUp、Confluence、Grain、HubSpot、Intercom、Jira、Notion、PagerDuty、QuickBooks、Salesforce、ServiceNow、Zendesk、Zoom 等大量 SaaS 服务以及generic_webhook通用 Webhook、table_new_row表格新行、sim_workspace_eventSim 工作区事件等平台内置触发器。二、目录结构与文件组织规范AGENTS.md 明确规定每个服务独立一个目录使用 barrel exports事件按文件拆分。apps/sim/triggers/ ├── github/ # 服务目录 │ ├── index.ts # barrel export统一导出该服务的所有触发器 │ ├── webhook.ts # 该服务的通用 webhook 触发器 │ ├── issue_opened.ts # 事件特定文件 │ ├── issue_closed.ts │ ├── pr_opened.ts │ ├── push.ts │ ├── ... │ └── utils.ts # 服务内共享工具 ├── linear/ │ ├── index.ts │ ├── webhook.ts │ ├── issue_created.ts │ ├── issue_updated.ts │ └── utils.ts ├── slack/ │ ├── index.ts │ ├── webhook.ts │ ├── oauth.ts # 基于 OAuth 凭据路由的触发器 │ ├── shared.ts │ └── capabilities.ts ├── registry.ts # 全局注册表 ├── types.ts # 类型契约 └── index.ts # 触发器查询/构建工具以 apps/sim/triggers/github/index.ts 为例它只是将事件特定文件逐一 re-exportexport { githubIssueClosedTrigger } from ./issue_closed export { githubIssueOpenedTrigger } from ./issue_opened export { githubPRMergedTrigger } from ./pr_merged export { githubPushTrigger } from ./push export { githubWebhookTrigger } from ./webhook // ...这样做的收益在于单文件职责单一每个事件触发器如issue_opened.ts只描述一个事件便于 review 和测试导入路径稳定外部只依赖/triggers/github这个 barrel新增事件不需要改动调用方按需加载友好Tree-shaking 时只打包被引用的触发器。三、TriggerConfig一个触发器的完整契约在 apps/sim/triggers/types.ts 中每个触发器是一个TriggerConfig对象字段如下字段类型说明idstring触发器唯一 ID遵循{provider}_{event}命名见第六节namestring展示名称如 GitHub Issue Openedproviderstring所属集成服务标识如github、slack用于身份校验与路由descriptionstring一句话功能描述versionstring触发器定义版本如1.0.0iconReact.ComponentType展示图标组件subBlocksSubBlockConfig[]配置面板中的字段定义下拉、输入框、说明文本等outputsRecordstring, TriggerOutput触发器输出给下游 blocks 的数据结构webhook{ method, headers }Webhook 请求方法POST/GET/PUT/DELETE与期望请求头pollingboolean为true时表示基于轮询cron 驱动而非推送deprecatedboolean为true时保留注册以兼容存量工作流但从生成的文档中排除其中deprecated字段的语义很关键它专用于被更新版本取代但旧工作流仍在引用的触发器例如 Grain 的 view-scoped 触发器在 v1 API 下线后仍保持注册只是不再进入文档。3.1 一个真实触发器剖析以 apps/sim/triggers/github/issue_opened.ts 为例export const githubIssueOpenedTrigger: TriggerConfig { id: github_issue_opened, name: GitHub Issue Opened, provider: github, description: Trigger workflow when a new issue is opened in a GitHub repository, version: 1.0.0, icon: GithubIcon, subBlocks: [ /* ... */ ], outputs: { /* ... */ }, webhook: { method: POST, headers: { Content-Type: application/json, X-GitHub-Event: issues, X-Hub-Signature-256: sha256..., }, }, }webhook.headers中声明的X-GitHub-Event、X-GitHub-Delivery、X-Hub-Signature-256是 GitHub 投递事件时的真实请求头——AGENTS.md 要求实现触发器前先研究服务的 webhook 模型这正是研究结果在配置层面的落地请求头声明既是文档也是校验依据。四、subBlocks配置面板与多触发器类型切换subBlocks描述触发器在画布/配置面板上的字段。AGENTS.md 特别要求当集成模式需要时主触发器必须支持在触发器类型之间切换。4.1 selectedTriggerId 下拉切换机制Sim 允许把同一服务的多个触发器合并进一个块通过selectedTriggerId下拉在事件类型间切换。github_issue_opened.ts的subBlocks首字段就是这样的下拉列出了该服务全部 11 个可选事件{ id: selectedTriggerId, title: Trigger Type, type: dropdown, mode: trigger, options: [ { label: Issue Opened, id: github_issue_opened }, { label: Issue Closed, id: github_issue_closed }, { label: PR Merged, id: github_pr_merged }, { label: Code Push, id: github_push }, // ... ], value: () github_issue_opened, required: true, }其余所有字段都通过condition: { field: selectedTriggerId, value: github_issue_opened }与当前选中的事件绑定只有选中对应事件时才显示该字段。从源码结构可以推断这种一个块内嵌多个触发器定义的合并模式是 Sim 保持画布简洁、同时支持丰富事件类型的关键设计。4.2 命名空间机制避免多触发器合并时的字段冲突apps/sim/triggers/index.ts 的namespaceSubBlockId函数解决了合并冲突问题当多个触发器被合并进同一块时只对 display-only 的 subBlocktext类型或readOnly为true且条件绑定selectedTriggerId的字段进行 ID 命名空间化追加_${triggerId}后缀而用户输入字段保持共享——这样切换触发器类型时用户填写过的值如 Webhook Secret不会丢失if (subBlock.type text || subBlock.readOnly true) { // display-only若 condition 绑定 selectedTriggerId 则命名空间化 return { ...subBlock, id: ${subBlock.id}_${triggerId} } } // 用户输入字段不命名空间化值在切换时保留同时SHARED_SUBBLOCK_IDS当前含selectedTriggerId被排除在命名空间化之外因为它是切换的控制字段本身就该共享。4.3 系统级 subBlock 约定apps/sim/triggers/constants.ts 定义了六类系统 subblock ID它们提供 UI/UX 能力但不属于用户配置数据不会被聚合进triggerConfig或作为用户字段校验ID用途triggerCredentialsOAuth 凭据 subblocktriggerInstructions分步配置说明文本webhookUrlDisplayWebhook URL 展示与复制samplePayload示例 payload 展示setupScript设置脚本代码如 Apps ScriptscheduleInfo轮询触发器调度状态下次/上次运行时间此外还有一组运行时元数据subblock IDwebhookId、triggerPath、triggerConfig、triggerId它们保留在工作流状态中但 diff 操作不得修改或清除——edit_workflow会拒绝写入这些 ID防止 Copilot 或外部写入复活旧的配置结构。五、共享 helper减少同一服务内的重复配置AGENTS.md 第三条要求当同一服务的多个触发器需要 setup instructions、extra fields 或 output definitions 时使用共享 helper。5.1 buildTriggerSubBlocksindex.ts 中的buildTriggerSubBlocks提供了标准化的 subBlock 组装流水线export function buildTriggerSubBlocks(options: BuildTriggerSubBlocksOptions): SubBlockConfig[] { const { triggerId, triggerOptions, includeDropdown false, setupInstructions, extraFields [], fieldsBeforeWebhookUrl [], providerWebhookUrl, webhookPlaceholder Webhook URL will be generated, } options // 1. 可选selectedTriggerId 下拉 // 2. fieldsBeforeWebhookUrl放在 URL 之前的字段 // 3. webhookUrlDisplay只读、带复制按钮、condition 绑定 triggerId // 4. extraFields事件专属字段 // 5. triggerInstructions分步配置说明 }固定顺序为Trigger Type 下拉 → 前置字段 → Webhook URL只读 复制按钮→ 事件专属字段 → Setup Instructions。这保证了同一服务内所有触发器的配置面板体验一致。5.2 服务级共享文件从目录结构可以观察到一个明显模式多事件服务普遍带有webhook.ts、utils.ts、shared.ts这类共享文件。例如apps/sim/triggers/github/webhook.ts 提供通用的github_webhook捕获任意 GitHub 事件github/utils.ts承载公共的 outputs 定义与字段构造apps/sim/triggers/linear/webhook.ts 与linear/utils.ts同理且 Linear 服务同时存在_v2后缀触发器对应新版 webhook API老版本通过deprecated标记退役apps/sim/triggers/slack/ 目录下的capabilities.ts、oauth.ts、shared.ts分别处理 Slack 能力探测、OAuth 凭据路由与共享逻辑。5.3 自动注入 samplePayloadgetTrigger在返回触发器配置时会为 webhook/轮询类触发器自动注入一个只读的samplePayloadsubblock调用generateMockPayloadFromOutputsDefinition(trigger.outputs)根据 outputs 定义生成 mock payload并格式化为 JSON 展示index.ts。这正是 AGENTS.md 要求outputs 定义明确的直接收益——outputs 写得好示例 payload 自动生成无需人工维护。六、Registry 注册与 ID 命名规范AGENTS.md 最后一条要求在triggers/registry.ts中注册触发器ID 与集成命名方案保持一致。6.1 注册方式apps/sim/triggers/registry.ts 顶部从各服务 barrel 导入触发器然后在TRIGGER_REGISTRY对象中按 ID 挂载import { githubIssueOpenedTrigger, githubPushTrigger, /* ... */ } from /triggers/github // ... export const TRIGGER_REGISTRY: TriggerRegistry { github_issue_opened: githubIssueOpenedTrigger, github_push: githubPushTrigger, // ...500 条 }该文件共 1008 行注册了 500 触发器。TriggerRegistry类型为Recordstring, TriggerConfigisTriggerValid(triggerId)index.ts直接以triggerId in TRIGGER_REGISTRY判断合法性因此漏注册 触发器不可用。6.2 ID 命名方案从 registry 可以归纳出明确的 snake_case 命名模式{provider}_{event}动词位于事件名之前或之后均可但必须与集成命名方案一致事件型github_issue_opened、linear_issue_created、notion_page_deleted、jira_sprint_started对象型salesforce_record_created、quickbooks_invoice_events平台型generic_webhook、table_new_row、sim_workspace_event、credential_group_event轮询型gmail_poller、google_calendar_poller、hubspot_poller、imap_poller、rss_pollerregistry 中google_calendar_poller等 ID 即来自polling: true的触发器凭据路由型slack_oauth按凭据路由而非按工作流 URL版本后缀linear_webhook_v2、grain_recording_added_v2新 API 版本。注意gmail_poller这类轮询触发器在 registry 中的 ID 后缀为poller而非webhook与常量文件中的轮询 provider 集合gmail、google-calendar、google-drive、google-sheets、hubspot、imap、outlook、rss一一对应。七、触发器的三类运行模型AGENTS.md 第一条要求研究服务 webhook 模型是因为 Sim 触发器按事件送达方式分为三类实现前必须先判断服务属于哪一类7.1 Webhook 推送型绝大多数服务向 Sim 的公开端点POST /api/webhooks/trigger/{path}推送事件。webhook-url.ts中的buildWebhookTriggerUrl负责拼接该 URL${getBaseUrl()}/api/webhooks/trigger/${path}。配置面板中的webhookUrlDisplaysubblock 会展示这个可复制的 URL配合triggerInstructions引导用户在服务控制台完成配置。7.2 轮询型cron 驱动Gmail、Google Calendar、Google Drive、Google Sheets、HubSpot、IMAP、Outlook、RSS 等服务不支持或不适合webhook 推送采用定时轮询。constants.ts中的POLLING_PROVIDERS集合与isPollingWebhookProvider判断用于路由执行方式轮询 provider 走完整任务队列Trigger.dev非轮询 provider 内联执行export const POLLING_PROVIDERS new Set([ gmail, google-calendar, google-drive, google-sheets, hubspot, imap, outlook, rss, ])这类触发器的 subBlocks 通常包含scheduleInfo下次运行/上次运行时间等调度展示字段。7.3 内部触发型credential-group、sim、table三个 provider 的触发器由 Sim 内部事件驱动表格行事件、工作区事件不经过外部 HTTP webhook。constants.ts中的INTERNAL_TRIGGER_PROVIDERS集合用于安全防护它们的 webhook 行仍会注册路径但公开触发路由必须拒绝投递——否则任何知道 block ID 的人都能伪造事件export const INTERNAL_TRIGGER_PROVIDERS new Set([credential-group, sim, table])八、Outputs对下游 blocks 明确且有用AGENTS.md 第四条要求保持触发器输出对下游 blocks 明确且有用Keep trigger outputs explicit and useful for downstream blocks。outputs定义是触发器与下游 blocks 之间的数据结构契约TriggerOutput支持嵌套结构、type声明与description描述还可通过conditionOutputCondition按触发器配置限制该输出在标签下拉中的可见性types.ts以github_issue_opened为例其 outputs 完整描述了event_type、action、issue含id/number/title/body/state/labels/assignees等、repository含full_name/stargazers_count/default_branch等、sender五大部分每个字段都有类型与语义说明下游 blocks 通过 outputs 的字段路径引用事件数据同时如前所述outputs 还驱动samplePayload的自动生成。从getTrigger的实现可以进一步确认只有定义了outputs的 webhook/轮询触发器才会自动注入示例 payload这强化了outputs 必须明确的规范动机。九、触发器身份解析与路由apps/sim/triggers/webhook-url.ts 中的resolveBlockTriggerId是触发器身份的唯一解析入口它按优先级判定一个 block 实际部署为哪个触发器专用触发器 blockblockConfig.category triggers且类型合法则 block 类型即触发器 ID工具 block 翻转模式triggerMode为真时读取selectedTriggerId子字段存量兼容读取存储的triggerId子字段兜底取配置声明的第一个可用触发器。注释明确说明为何要单源化webhook 部署路径与任何推理 block 投递方式的层必须对同一问题给出相同答案否则一个 block 可能按触发器 A 部署、却被另一层分类为触发器 B。resolveBlockTriggerProvider则返回事件的投递身份provider注释强调入站请求就是按这个身份做校验的——由slack路径服务的请求会校验 Slack 签名并解析 Slack 事件结构因此两个不同 provider 的触发器无论如何相似都不可能共享同一个 URL。这也解释了为什么注册 ID 的 provider 前缀必须准确。十、开发一个新触发器的完整步骤清单综合 AGENTS.md 的六条规则与仓库实现为一个新服务添加触发器可按以下流程执行研究服务 webhook 模型确认是推送型 webhook、轮询型还是内部事件型确认事件结构、请求头、签名校验方式对应规则 1创建服务目录triggers/{service}/目录内拆分webhook.ts或poller定义、各事件特定文件、utils.ts并提供index.tsbarrel export对应规则 2提取共享 helper将 setup instructions、extra fields、outputs 定义放入共享文件或使用buildTriggerSubBlocks组装避免同服务内重复对应规则 3实现触发器类型切换若服务有多个事件设置selectedTriggerId下拉并让各字段通过condition绑定使用户可在类型间切换对应规则 4精确定义 outputs逐字段声明类型与描述供下游 blocks 引用并自动生成示例 payload对应规则 5注册并保持命名一致在registry.ts的TRIGGER_REGISTRY中挂载触发器ID 遵循{provider}_{event}命名轮询型用{provider}_poller对应规则 6。总结apps/sim/triggers/目录是 Sim 工作流生态的入口层其开发规范AGENTS.md虽然只有六条但每条背后都有源码级的强约束registry.ts的集中注册与 ID 命名、types.ts的TriggerConfig契约、index.ts的 subBlock 组装与命名空间机制、constants.ts的轮询/内部 provider 分类与运行元数据保护。理解这套规范不仅能让你快速为 Sim 添加新的服务集成也能理解为什么 Sim 能支撑 500 触发器定义而保持一致的画布体验与可靠的路由校验——这正是规范先行、共享复用、输出明确三原则的工程价值所在。【免费下载链接】simSim is the collaborative workspace to build, deploy, and monitor AI agents and workflows. Used by 100,000 builders.项目地址: https://gitcode.com/GitHub_Trending/sim16/sim创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考