首页
/ Twenty App 逻辑开发参考指南:Logic Functions、Bulk 记录动作与安装/卸载钩子实战

Twenty App 逻辑开发参考指南:Logic Functions、Bulk 记录动作与安装/卸载钩子实战

2026-09-07 23:35:10作者:裴锟轩Denise

本篇指南围绕 Twenty 生态中应用(Twenty App)的逻辑层开发展开,系统讲解逻辑函数(Logic Functions)的文件组织与触发/校验规范、以 records: Array<{id}> 为核心的 Bulk 批量记录动作契约、Skills/Agents 行为约束、第三方连接(Connection Providers)的凭据安全要求,以及 definePostInstallLogicFunctiondefineUninstallLogicFunction 两类安装生命周期钩子的正确用法与幂等约束。阅读后你将掌握为 Twenty 应用编写可维护、可测试、幂等且符合平台约定的逻辑代码与钩子的完整实践方案。

逻辑函数的职责边界:一个文件只做一件事

在 Twenty 应用中,逻辑函数文件(*.logic-function.ts)应当只承载四件事:触发器注册、输入校验、调用外部能力、写回结果。除此之外的一切都应从文件里剥离出来,放到各自相邻的目录中(对应规范详见 app-structure.md):

  • 外部 API 调用 → src/<service>-client/<name>.ts:以 Twenty 后端 *-client 惯例(如 redis-client/sdk-client/)按服务建一个文件夹,作为外部 SDK 或 HTTP 客户端的封装层;
  • 响应解析与映射 → src/utils/<name>.util.ts:纯函数辅助器,保持目录扁平;
  • 响应与 DTO 类型 → src/types/<name>.ts:每个文件只放一个 PascalCase 类型;
  • 跨对象类型共享的结构 → 以对象 kind 为参数实现单一 mapper 工厂,而不是为每个对象写并行函数。

文件命名统一 kebab-case;响应/DTO 类型与解析/映射工具禁止从同一文件同时导出(仅供本工具使用的局部、不导出的类型可以留在 util 文件内),一个文件也禁止出现多个函数导出

其余硬性规则:

  • 在写回或发起远程调用之前先校验必填字段;
  • 记录类动作优先采用 bulk 批量输入;若某逻辑函数可从已选记录触发,其规范输入应为 records: Array<{ id: string; ...fields }>,除非用户明确该函数只服务于单条记录;
  • 使用 records 数组内的 id 承载 Twenty 记录 ID。不要自行添加 recordIdcompanyId 这类对象专属 ID,也不要使用扁平单记录载荷——除非用户明确要求单记录契约;
  • 多记录动作应返回带逐条结果的 bulk 汇总,包含成功、未匹配、失败三类计数;
  • 面向作业(job)与重复调用的行为优先保持幂等
  • 读取密钥必须经由 application-config 辅助器,而不是直接读 process.env
  • 不要用仅 UI 层的动作掩盖会影响客户利益的副作用。

经验阈值:单个 *.logic-function.ts*.post-install.ts 文件超过 200 行,即视为需要重构的信号。

Bulk 记录动作:默认契约与推荐输入输出形态

Bulk 是那些可能从前端组件(front component)选中记录后触发的动作的默认逻辑函数契约。正确流程是:前端组件收集被选中的记录,只调用一次函数;不要在无单记录明确需求时,让前端组件循环遍历选中记录并反复执行同一逻辑函数。

推荐输入形态:

type BulkInput<TRecord extends { id: string }> = {
  records: TRecord[];
};

推荐输出形态(含逐条结果与汇总计数):

type BulkResult = {
  ok: boolean;
  enrichedCount: number;
  noMatchCount: number;
  failedCount: number;
  results: Array<{
    id: string;
    status: 'ENRICHED' | 'NO_MATCH' | 'FAILED';
    pdlId?: string;
    error?: string;
  }>;
};

若要把存量“单记录函数”升级为“选中记录动作”,应把旧的扁平输入替换为 records: Array<{ id: string; ...fields }>,除非用户明确要求保持向后兼容。

每个 Bulk 函数都应该抽出并测试以下纯逻辑片段:

  • 规范 bulk 形状的输入归一化
  • 逐条记录校验
  • 外部 API 载荷映射
  • 逐条结果映射
  • 汇总计数聚合
  • 错误消息归一化

这几点直接对应 app-structure.md 中“单元测试应覆盖 src/utils/ 辅助器与 post-install 钩子幂等性”的约定(完整测试指引见 tests.md):正因为逻辑函数文件本身只保留“注册 + 校验 + 调用 + 写回”,其余映射与聚合逻辑都在 util/type/client 层,才使得这些核心分支可以被无副作用的 *.spec.ts 充分覆盖。

Skills 与 Agents:为 AI 行为设定可判定的边界

在 Twenty 应用中引入 AI 行为时,Skills 与 Agents 应明确描述何时适用、需要哪些上下文、期望产出什么。具体约束如下:

  • 让触发规则(trigger rules)足够具体、可判定;
  • 指令必须锚定在应用内可得的数据与工具之上,不依赖臆想能力;
  • 明确说明 Agent 在何种情况下应向用户询问缺失的 workspace 或记录上下文;
  • 当可读答案足以满足用户时,不要把裸 ID、时间戳或嵌套 API 输出直接抛给终端用户

Connection Providers:第三方连接的凭据纪律

接入第三方连接时需守住三条底线:

  • 密钥绝不能进入源码或公开资源(对应 app-structure.md 中“Read secrets through the application-config helper, not raw process.env”的统一约定);
  • 必需的 OAuth 或 API 开通步骤应写入应用 README 或应用商店 listing 文档;
  • 必须验证“凭据过期/缺失”等失败状态的可观测性与处理路径。

Post-Install 钩子:安装期必需记录的种子来源

凡是应用安装后必须存在的记录——默认工作流、视图(views)、角色(roles)或种子参考数据——都应通过 definePostInstallLogicFunction 在安装期创建,绝不应实现为运行时“首次执行”逻辑。

文件位置与其他逻辑函数相邻(惯例为 src/logic-functions/<name>.post-install.ts),kebab-case 命名、单文件单导出。钩子必须幂等:先按稳定标识查找,存在则更新、绝不去重复创建;单记录查询返回 not-found 一律视为“需要创建”。

注意不要写入 Twenty 会在别处计算出的字段(例如 workflow 的 statuses 由版本状态推导,详见 workflows.md)。

dev sync 会跳过安装钩子,需要在本机手动调用验证:

yarn twenty dev:function:exec

重建(rebuild)后再执行一次,用于验证钩子的幂等性——二次运行不应产生重复记录。

从 SDK 源码看,define-post-install-logic-function.ts 会校验 universalIdentifierhandler(handler 必须是函数),并把结果交给 createValidationResult 汇总;其配置类型 post-install-logic-function-config.ts 在通用配置之上追加了一个 shouldRunSynchronously?: boolean 选项,用于指示钩子是否需要同步执行完成。对应测试见 define-post-install-logic-function.spec.ts

Uninstall 钩子:卸载期的尽力而为清理

当应用被卸载时,应使用 defineUninstallLogicFunction 对外部资源做尽力而为(best-effort)的清理:释放 deprovision API 资源、删除残留机器人、撤销 webhook 等。钩子内失败只会被记录日志,绝不会阻塞卸载流程

文件位置同样与其他逻辑函数相邻(惯例为 src/logic-functions/uninstall.ts),kebab-case、单导出。关键执行时机:卸载钩子在应用元数据、数据与代码被移除之前运行,因此 handler 仍可查询应用自身的对象与记录。handler 接收的载荷为:

type UninstallPayload = {
  version?: string;
};

该类型定义见 uninstall-payload-type.tsdefine-uninstall-logic-function.ts 同样强制校验 universalIdentifier 与函数类型的 handler,校验逻辑与 post-install 完全对齐;测试见 define-uninstall-logic-function.spec.ts

与 SDK 定义的对应关系

逻辑函数、安装/卸载钩子本质上是 Twenty SDK 中的 define 类实体define/index.ts 集中导出了 defineLogicFunctiondefinePostInstallLogicFunctiondefineUninstallLogicFunction。以 define-logic-function.ts 为例,其运行期校验会检查:

  • 必须有 universalIdentifier
  • handler 必须存在且为函数;
  • 若配置了 httpRouteTriggerSettingspathhttpMethod 必填;
  • serverRouteTriggerSettings.httpMethods 仅支持 GETPOST
  • cronTriggerSettings 必须有 pattern
  • databaseEventTriggerSettings 必须有 eventName

handler 的函数签名由 logic-function-config.ts 定义:(payload, context: LogicFunctionExecutionContext) => any | Promise<any>;当存在 serverRouteTriggerSettings 时,handler 被限定为 ServerRouteResolverHandler,可返回 ServerRouteDispatchResult 入队目标工作区执行,或返回 LogicFunctionHttpResponse 同步应答调用方(适用于需要握手回复的 provider webhook URL)。上述触发器形态说明,逻辑函数既可以由记录/前端事件驱动,也可以由 HTTP 路由、cron 或数据库事件驱动——但无论哪种触发入口,文件职责边界、Bulk 契约与密钥读取规范都保持一致。

小结

一份合格的 Twenty 应用逻辑层代码应当同时满足:逻辑函数文件职责单一(≤200 行为佳)、与外部世界交互的代码全部下沉到 *-client/utils/types 分层、记录动作遵循带逐条结果汇总的 Bulk 契约、AI 行为指令可判定且不泄露原始内部数据、第三方凭据始终经由 application-config 读取,以及安装/卸载钩子以幂等、尽力而为的方式承担生命周期职责。配合 yarn twenty dev:function:exec 的本地调用验证与重建后的重复执行检查,即可在 yarn twenty apply 同步前发现绝大多数逻辑与幂等问题。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395