defineLogicFunction
ロジック関数とそのトリガーを定義
defineLogicFunction
ロジック関数とそのトリガーを定義
各関数ファイルは、ハンドラーと任意のトリガーを含む設定を 利用可能なトリガーの種類:
ハンドラー内では、転送されたヘッダーに次のようにアクセスします:セキュリティ上の理由から、レスポンスヘッダーは許可リストに限定されています。 リストに含まれていないヘッダー(例: エンドポイントには次の URL でアクセスできます:識別子は、マニフェストに記載されている resolver の Resolver の契約。SDK の
リクエスト署名については、ほとんどのプロバイダーが HMAC-SHA256 で署名します。異なるのはヘッダー名、ダイジェストのエンコーディング、および署名対象となるペイロード文字列です。 いくつかの例を示します。
上記の resolver の例では、すでに GitHub の HMAC-SHA256 フローを示しています。連携するプロバイダーに合わせて、ヘッダー名、ダイジェストのエンコーディング、および署名対象となるペイロード文字列を調整してください。ペイロードには次のものが含まれます:
ソフトデリートの場合、レコードの 作成イベントの例:更新イベントの例:メール更新時のみトリガーする例:削除イベントの例:主なポイント:パラメーターを一度だけ宣言して両方のサーフェスで利用できるようにするには、単一の JSON Schema(
defineLogicFunction() でエクスポートします。src/logic-functions/createPostCard.logic-function.ts
- httpRoute:
/s/エンドポイント配下で、HTTP のパスとメソッドで関数を公開します:
例:path: '/post-card/create'はhttps://your-twenty-server.com/s/post-card/createで呼び出せます
(ヘッドレスの)フロントコンポーネントからルートトリガー型ロジック関数を呼び出す方法については、ロジック関数を呼び出すを参照してください。
- cron: CRON 式を使用してスケジュールで関数を実行します。
- databaseEvent: ワークスペースのオブジェクトのライフサイクルイベントで実行されます。 イベント操作が
updatedの場合、監視する特定のフィールドをupdatedFields配列で指定できます。 未定義または空のままにすると、任意の更新でも関数がトリガーされます。
例:person.updated、*.created、company.*
- serverRoute: 1 つの登録スコープの HTTP ルートを公開します。 resolver 関数(
serverRouteTriggerSettingsで宣言)は、オーナーワークスペースで実行され、ディスパッチ先のターゲットワークスペースとターゲットロジック関数の両方を返します。その後、プラットフォームはその target 関数を実行し、そのレスポンスを返します。 サーバールートトリガー を参照してください。
CLI を使用して、関数を手動で実行することもできます:ログは次のコマンドで監視できます:
ルートトリガーのペイロード
ルートトリガーがロジック関数を呼び出すと、 AWS HTTP API v2 形式 に従うRoutePayload オブジェクトを受け取ります。
RoutePayload 型を twenty-sdk/logic-function からインポートします:RoutePayload 型は次の構造になっています:| プロパティ | タイプ | 説明 | 例 |
|---|---|---|---|
headers | Record\<string, string | undefined> | HTTP ヘッダー (forwardedRequestHeaders に列挙されたもののみ) | 下記のセクションを参照 |
queryStringParameters | Record\<string, string | undefined> | クエリ文字列パラメーター (複数の値はカンマで連結) | /users?ids=1&ids=2&ids=3&name=Alice -> { ids: '1,2,3', name: 'Alice' } |
pathParameters | Record\<string, string | undefined> | ルートパターンから抽出されたパスパラメーター | /users/:id, /users/123 -> { id: '123' } |
body | object | null | 解析済みのリクエストボディ (JSON) | { id: 1 } -> { id: 1 } |
rawBody | string | undefined | JSON 解析前の元の UTF-8 リクエストボディ。 HMAC 方式の Webhook 署名を検証する際に役立ちます(例: GitHub の X-Hub-Signature-256、Stripe)。 ランタイムがそれを保持しなかった場合は undefined です。 | |
isBase64Encoded | boolean | body が base64 エンコードされているかどうか | |
requestContext.http.method | string | HTTP メソッド (GET, POST, PUT, PATCH, DELETE) | |
requestContext.http.path | string | 生のリクエストパス |
forwardedRequestHeaders
デフォルトでは、セキュリティ上の理由から、受信リクエストの HTTP ヘッダーはロジック関数に渡されません。 特定のヘッダーにアクセスするには、forwardedRequestHeaders 配列に明示的に列挙してください:ヘッダー名は小文字に正規化されます。 小文字のキーを使用してアクセスしてください(例:
event.headers['content-type'])。カスタム HTTP レスポンス
デフォルトでは、ハンドラーからプレーンな値を返すと、それが200 レスポンスとして送信されます(オブジェクトの場合は JSON、文字列の場合は text/plain)。 ステータスコードとレスポンスヘッダーを制御するには、twenty-sdk/logic-function から Response を返します。Set-Cookie、Access-Control-Allow-Origin などの CORS ヘッダー、カスタム X-* ヘッダー)は、レスポンスが送信される前に暗黙的に削除されます。 許可されているレスポンスヘッダーは次のとおりです。content-typecontent-languagecontent-dispositioncache-controlretry-after
ステータスコードは、有効な HTTP ステータスコード(100 から 599 の間)でなければなりません。 レスポンスヘッダー名は、大文字と小文字を区別せずに照合されます。
サーバールートトリガー
httpRouteTriggerSettings は /s/ 配下に関数を公開し、リクエストホストからワークスペースを特定します。これは、各ワークスペースが独自ドメインを持つ場合に機能します。 しかし、サードパーティプロバイダーは、すべてのテナントのイベントを 1 つの URL に配信します。 その場合は、serverRouteTriggerSettings を使用します。トリガーには 2 つの構成要素があります:- resolver ロジック関数 —
serverRouteTriggerSettingsで宣言される — は、オーナーワークスペース(アプリケーション登録を所有するワークスペース)で実行されます。 受信リクエストを検査し、{ workspaceId, targetLogicFunctionUniversalIdentifier, payload? }を返し、ターゲットのワークスペースと関数の 両方 を選択します。 resolver は単一の認可ポイントであり、URL には resolver の識別子のみが含まれます。 ここがリクエスト署名を検証するための推奨箇所です。resolver は副作用が発生する前に実行され、元のrawBodyと転送されたヘッダーにアクセスでき、ターゲットに一切触れずにリクエストを拒否できます。 - target ロジック関数 — 通常のワークスペース単位のロジック関数 — は、その後、resolver によって解決されたワークスペースで、resolver が返したペイロード(resolver が変換しなかった場合は元のリクエストペイロード)を使って実行されます。 その戻り値が HTTP レスポンスになります。
src/logic-functions/resolve-server-route.logic-function.ts
src/logic-functions/handle-invoice-paid.logic-function.ts
universalIdentifier です。 その URL をプロバイダーに登録します。アプリケーションは所有者ワークスペースでクレームされ、インストールされている必要があります。 リゾルバーは 所有者ワークスペース(アプリケーション登録を所有しているワークスペース)上で実行されるため、サーバールートトリガーが動作するのは、アプリケーションがクレームされている、つまり所有者ワークスペースを持っていること かつ そのアプリケーションが 所有者ワークスペースにインストールされている 場合のみです。 この2つの条件がどちらも満たされるまでは、リゾルバーを実行する場所が存在しないため、ルートをディスパッチできません。 したがって、
serverRouteTriggerSettings ロジック関数を公開するアプリケーションは、所有者ワークスペースでクレームされインストールされるまで、マーケットプレイスに掲載することはできません。LogicFunctionConfig 型は、コンパイル時にこれを強制します。serverRouteTriggerSettings を設定するとすぐに、ハンドラーは { workspaceId: string; targetLogicFunctionUniversalIdentifier: string; payload?: object }(またはその Promise)を返すように制約されます。 workspaceId は、ターゲット関数がインストールされているワークスペースである必要があります。そうでない場合、リクエストは 404 で拒否されます。| フィールド | タイプ | ノート |
|---|---|---|
workspaceId | string | ターゲットが実行されるワークスペースの UUID。 |
targetLogicFunctionUniversalIdentifier | string | そのワークスペースで呼び出すロジック関数の universalIdentifier。 |
payload | object(オプション) | 設定された場合、ターゲットに送信されるリクエストボディを置き換えます。 |
| プロバイダー | 転送するヘッダー | 署名対象文字列 | ダイジェスト |
|---|---|---|---|
| Svix (Recall, Resend, Clerk) | webhook-id, webhook-timestamp, webhook-signature | {id}.{timestamp}.{rawBody} | base64(シークレットは whsec_ を取り除いた後の文字列を base64 として扱います) |
| Stripe | stripe-signature | {timestamp}.{rawBody} | hex |
| GitHub | x-hub-signature-256 | {rawBody} | hex(先頭に sha256= が付与されます) |
| Shopify | x-shopify-hmac-sha256 | {rawBody} | base64 |
| Slack | x-slack-signature, x-slack-request-timestamp | v0:{timestamp}:{rawBody} | hex(先頭に v0= が付与されます) |
target は同期的に実行され、その戻り値が HTTP レスポンスになるため、呼び出し元はあなたのステータスコードを確認し、2xx 以外の場合にリトライできます。 両方のハンドラーを高速に保ってください。Slack など一部のプロバイダーは数秒でタイムアウトします。 resolver はパブリックエンドポイントとして到達可能であるため、エッジでレート制限をかけて保護してください。
データベースイベントトリガーのペイロード
データベースイベントトリガーがロジック関数を呼び出すと、変更されたレコードごとに 1 つのDatabaseEventPayload を受け取ります。 このペイロードは、ソースワークスペースとオブジェクトに関するメタデータを、レコードレベルのイベントと組み合わせたものです。| プロパティ | 説明 |
|---|---|
name | person.updated などのイベント名。 |
workspaceId | イベントが発生したワークスペース。 |
objectMetadata | 変更されたオブジェクトのメタデータ。 |
recordId | 変更されたレコードの ID。 |
userId, userWorkspaceId, workspaceMemberId | イベントがワークスペースユーザーによって引き起こされた場合のアクターに関するフィールド。 |
properties | イベントのレコードデータ。操作に応じて before、after、diff、updatedFields が含まれます。 |
| イベント | レコードデータ |
|---|---|
person.created | event.properties.after |
person.updated | event.properties.before, event.properties.after, event.properties.diff, event.properties.updatedFields |
person.destroyed | event.properties.before |
deletedAt フィールドが変化するため、.deleted はアップデート時と同じ形式になります。
完全な削除の場合は .destroyed を使用します。databaseEventTriggerSettings.updatedFields は、どの更新イベントで関数をトリガーするかをフィルタリングします。
event.properties.updatedFields は、現在のイベントで実際にどのフィールドが変更されたかを示します。関数を AI ツールまたはワークフロー アクションとして公開する
ロジック関数は 2 つのサーフェス上で公開でき、それぞれに固有のトリガーがあります:toolTriggerSettings— Twenty の AI 機能(チャット、MCP、関数呼び出し)からその関数を見つけられるようにします。 標準的な JSON Schema を使用します。これは LLM がネイティブに理解する形式です。workflowActionTriggerSettings— ビジュアル ワークフロー ビルダー内のステップとして関数を表示します。 ビルダーが適切なフィールドエディタ、変数ピッカー、ラベルをレンダリングできるよう、Twenty の充実したInputSchemaを使用します。
cronTriggerSettings、databaseEventTriggerSettings、httpRouteTriggerSettings と並列に存在します — 同じパターン、同じ形です。src/logic-functions/enrich-company.logic-function.ts
- 関数はサーフェスを混在させることができます —
toolTriggerSettingsとworkflowActionTriggerSettingsの両方を宣言して、チャットおよびワークフロー ビルダーの両方に公開します。 toolTriggerSettings.inputSchemaとworkflowActionTriggerSettings.inputSchemaはいずれも任意です。 省略された場合、マニフェストビルダーはハンドラーのソースコードからそれらを推論します(AI ツールには JSON Schema、ワークフロー アクションには Twenty のInputSchema)。 より豊富な型付けが必要な場合は、明示的に指定してください — たとえば、ワークフロー ビルダー向けにCURRENCYやRELATIONといったFieldMetadataTypeに対応したフィールド、または AI エージェントが読み取れるdescriptionフィールドを使用する場合など:
InputJsonSchema)を定義し、twenty-sdk/logic-function の jsonSchemaToInputSchema を使ってワークフローアクション用に変換します。 toolTriggerSettings.inputSchema は JSON Schema を直接受け取りますが、workflowActionTriggerSettings.inputSchema には Twenty の InputSchema が必要です。良い
description を記述してください。 AI エージェントは、ツールをいつ使用するかを判断するために関数の description フィールドに依存します。 ツールが何を行い、いつ呼び出すべきかを具体的に記述してください。ランタイムヘルパー。
twenty-sdk/utils は、小さなランタイムヘルパーを再エクスポートすることで、ハンドラーが直接 twenty-shared からインポートする必要がないようにします。 たとえば、isDefined(value) は null と undefined の両方に対して false を返します。これを使うと、オプショナルなハンドラー入力を安全に絞り込めます。こうした入力は、型としては T | undefined であっても、実行時には null として渡される場合があります。インストールフック — pre-install と post-install のハンドラー — はこのランタイムを共有しますが、それぞれ独自の define 関数で宣言され、トリガー設定は受け取りません。
definePreInstallLogicFunction と definePostInstallLogicFunction については、インストールフック を参照してください。型付き API クライアント(twenty-client-sdk)
twenty-client-sdk パッケージは、ロジック関数やフロントコンポーネントから Twenty API とやり取りするための、型付き GraphQL クライアントを 2 つ提供します。
| クライアント | インポート | エンドポイント | 自動生成? |
|---|---|---|---|
CoreApiClient | twenty-client-sdk/core | /graphql — ワークスペースデータ(レコード、オブジェクト) | はい、開発/ビルド時 |
MetadataApiClient | twenty-client-sdk/metadata | /metadata — ワークスペース設定、ファイルアップロード | いいえ、あらかじめビルド済みで提供 |
CoreApiClient
ワークスペースデータ(レコード、オブジェクト)をクエリおよび変更
CoreApiClient
ワークスペースデータ(レコード、オブジェクト)をクエリおよび変更
CoreApiClient は、ワークスペースデータのクエリと変更のための主要なクライアントです。 yarn twenty dev または yarn twenty dev:build の実行時にワークスペースのスキーマから生成されるため、オブジェクトやフィールドに一致する完全な型付けが行われます。true を渡し、引数には __args を使い、リレーションにはオブジェクトをネストします。 ワークスペースのスキーマに基づく完全な補完と型チェックが得られます。CoreApiClient は開発/ビルド時に生成されます。 先に
yarn twenty dev または yarn twenty dev:build を実行せずに使用すると、エラーが発生します。 生成は自動で行われます—CLI がワークスペースの GraphQL スキーマをイントロスペクトし、@genql/cli を使用して型付きクライアントを生成します。CoreSchema を型注釈に使用する
CoreSchema は、ワークスペースのオブジェクトに対応する TypeScript の型を提供し、コンポーネントの状態や関数パラメーターの型付けに役立ちます:MetadataApiClient
ワークスペースの設定、アプリケーション、ファイルアップロード
MetadataApiClient
ワークスペースの設定、アプリケーション、ファイルアップロード
MetadataApiClient は SDK に同梱されており、あらかじめビルド済みです(生成は不要)。 ワークスペースの設定、アプリケーション、ファイルアップロードのために /metadata エンドポイントに対してクエリを実行します。ファイルのアップロード
MetadataApiClient には、ファイル型フィールドにファイルを添付するための uploadFile メソッドが含まれています:| パラメーター | タイプ | 説明 |
|---|---|---|
fileBuffer | Buffer | ファイルの生データ |
filename | string | 保存および表示に使用されるファイル名 |
contentType | string | MIME タイプ(省略時は application/octet-stream がデフォルト) |
fieldMetadataUniversalIdentifier | string | オブジェクト上のファイルタイプのフィールドの universalIdentifier |
- フィールドの
universalIdentifier(ワークスペース固有の ID ではありません)を使用するため、アップロードコードはアプリがインストールされている任意のワークスペースで動作します。 - 返される
urlは、アップロード済みファイルにアクセスするために使用できる署名付き URL です。
コードが Twenty 上で実行される際(ロジック関数やフロントコンポーネント)、プラットフォームは認証情報を環境変数として注入します:
TWENTY_API_URL— Twenty API のベース URLTWENTY_APP_ACCESS_TOKEN— アプリケーションのデフォルト関数ロールにスコープされた短命のキー
process.env から読み取ります。 API キーの権限は、defineApplicationRole() で宣言されたロール(または application-config.ts の defaultRoleUniversalIdentifier で参照されるロール)によって決まります。