Skip to main content
ロジック関数は、Twenty プラットフォーム上で実行されるサーバーサイドの TypeScript 関数です。 HTTPリクエスト、cronスケジュール、またはデータベースイベントでトリガーでき、AIエージェント向けのツールとして公開することもできます。
各関数ファイルは、ハンドラーと任意のトリガーを含む設定を defineLogicFunction() でエクスポートします。
src/logic-functions/createPostCard.logic-function.ts
利用可能なトリガーの種類:
  • httpRoute:HTTP のパスとメソッドで関数を公開します。 アプリのコードでは、RestApiClient を使用する際、ルートパスの先頭に /s/ を付けてください。デプロイ後の URL では、TWENTY_FUNCTIONS_URL で注入されたベース URL が使用され、未設定の場合は \<server-url>/s が使用されます。
(ヘッドレスの)フロントコンポーネントからルートトリガー型ロジック関数を呼び出す方法については、ロジック関数を呼び出すを参照してください。
  • cron: CRON 式を使用してスケジュールで関数を実行します。
  • databaseEvent: ワークスペースのオブジェクトのライフサイクルイベントで実行されます。 イベント操作が updated の場合、監視する特定のフィールドを updatedFields 配列で指定できます。 未定義または空のままにすると、任意の更新でも関数がトリガーされます。
例:person.updated*.createdcompany.*
  • serverRoute: 1 つの登録スコープの HTTP ルートを公開します。 resolver 関数(serverRouteTriggerSettings で宣言)は、オーナーワークスペースで実行され、同期的な Response を返すか、ターゲットワークスペースとエンキューする対象のロジック関数を返します。エンキュールートでは、プラットフォームは 202 で ACK し、その target をワーカーキュー上で実行します。 サーバールートトリガー を参照してください。
CLI を使用して、関数を手動で実行することもできます:
ログは次のコマンドで監視できます:

ルートトリガーのペイロード

ルートトリガーがロジック関数を呼び出すと、 AWS HTTP API v2 形式 に従う RoutePayload オブジェクトを受け取ります。 RoutePayload 型を twenty-sdk/logic-function からインポートします:
RoutePayload 型は次の構造になっています:

forwardedRequestHeaders

デフォルトでは、セキュリティ上の理由から、受信リクエストの HTTP ヘッダーはロジック関数に渡されません。 特定のヘッダーにアクセスするには、forwardedRequestHeaders 配列に明示的に列挙してください:
ハンドラー内では、転送されたヘッダーに次のようにアクセスします:
ヘッダー名は小文字に正規化されます。 小文字のキーを使用してアクセスしてください(例:event.headers['content-type'])。

カスタム HTTP レスポンス

デフォルトでは、ハンドラーからプレーンな値を返すと、それが 200 レスポンスとして送信されます(オブジェクトの場合は JSON、文字列の場合は text/plain)。 ステータスコードとレスポンスヘッダーを制御するには、twenty-sdk/logic-function から Response を返します。
セキュリティ上の理由から、レスポンスヘッダーは許可リストに限定されています。 リストに含まれていないヘッダー(例: Set-CookieAccess-Control-Allow-Origin などの CORS ヘッダー、カスタム X-* ヘッダー)は、レスポンスが送信される前に暗黙的に削除されます。 許可されているレスポンスヘッダーは次のとおりです。
  • content-type
  • content-language
  • content-disposition
  • cache-control
  • retry-after
ステータスコードは、有効な HTTP ステータスコード(100 から 599 の間)でなければなりません。 レスポンスヘッダー名は、大文字と小文字を区別せずに照合されます。

プラットフォームのエラー応答

ハンドラー自身のレスポンス以外に、いくつかの状況ではプラットフォームがルート呼び出しに直接応答します。ルートまたは関数が存在しない場合は 404、アプリケーションが停止している場合は 403、実行レート制限に達した場合は 429、アプリケーションの本番用 dependencies が大きすぎてインストールできない場合は 422 が返されます。詳しくは dependencies size limits を参照してください。

サーバールートトリガー

httpRouteTriggerSettings/s/ 配下に関数を公開し、リクエストホストからワークスペースを特定します。これは、各ワークスペースが独自ドメインを持つ場合に機能します。 しかし、サードパーティプロバイダーは、すべてのテナントのイベントを 1 つの URL に配信します。 その場合は、serverRouteTriggerSettings を使用します。トリガーには 2 つの構成要素があります:
  1. resolver ロジック関数 — serverRouteTriggerSettings で宣言される — は、オーナーワークスペース(アプリケーション登録を所有するワークスペース)で実行されます。 この関数は受信リクエストを検査し、次のいずれかを返します。
    • { workspaceId, targetLogicFunctionUniversalIdentifier, payload? } — プラットフォームは解決済みワークスペースでその target をキューに入れ、202 { queued: true } で ACK します、または
    • twenty-sdk/logic-function からの Response — プラットフォームはその HTTP レスポンスを同期的にエコーし、ターゲットをキューに入れることはありません(Slack の url_verification のようなチャレンジハンドシェイクに使用します)。
    resolver は単一の認可ポイントであり、URL には resolver の識別子のみが含まれます。 ここがリクエスト署名を検証するための推奨箇所です。resolver は副作用が発生する前に実行され、元の rawBody と転送されたヘッダーにアクセスでき、ターゲットに一切触れずにリクエストを拒否できます。
  2. target ロジック関数 — 通常のワークスペース単位のロジック関数 — は、その後、resolver によって解決されたワークスペースで、resolver が返したペイロード(resolver が変換しなかった場合は元のリクエストペイロード)を使って実行されます。 resolver が enqueue パスを選択した場合、その戻り値は HTTP 呼び出し元からは観測されません
src/logic-functions/resolve-server-route.logic-function.ts
src/logic-functions/handle-invoice-paid.logic-function.ts
エンドポイントには次の URL でアクセスできます:
識別子は、マニフェストに記載されている resolver の universalIdentifier です。 その URL をプロバイダーに登録します。
アプリケーションは所有者ワークスペースでクレームされ、インストールされている必要があります。 リゾルバーは 所有者ワークスペース(アプリケーション登録を所有しているワークスペース)上で実行されるため、サーバールートトリガーが動作するのは、アプリケーションがクレームされている、つまり所有者ワークスペースを持っていること かつ そのアプリケーションが 所有者ワークスペースにインストールされている 場合のみです。 この2つの条件がどちらも満たされるまでは、リゾルバーを実行する場所が存在しないため、ルートをディスパッチできません。 したがって、serverRouteTriggerSettings ロジック関数を公開するアプリケーションは、所有者ワークスペースでクレームされインストールされるまで、マーケットプレイスに掲載することはできません。
Resolver の契約。 SDK の LogicFunctionConfig 型はコンパイル時にこれを強制します。serverRouteTriggerSettings を設定するとすぐに、ハンドラーは Response か、{ workspaceId: string; targetLogicFunctionUniversalIdentifier: string; payload?: object }(またはそのいずれかの Promise)を返すように制約されます。 dispatch パスでは、workspaceId は target 関数がインストールされているワークスペースである必要があります。そうでない場合、リクエストは 404 で拒否されます。 どちらの形にも一致しない結果(識別子が UUID でないものを含む)は、502 で拒否されます。
署名の検証はあなたの責任です — resolver 内で検証してください。 プラットフォームはリクエスト署名を検証しません。 resolver はそれを行う推奨箇所です。最初に実行され、event.rawBody と、forwardedRequestHeaders に指定したヘッダーにアクセスできます。また、エラーをスローする(または一致しない workspaceId を返す)ことで、ターゲットが呼び出される前にディスパッチを停止できます。 代わりに検証処理を target 側に押し下げる場合、target は rawBody とヘッダーを失わないよう注意する必要があります。つまり、resolver は payload を返してはいけません。 副作用を伴う処理の前に必ず検証を行い、コンスタントタイム比較を使用してください。
リクエスト署名については、ほとんどのプロバイダーが HMAC-SHA256 で署名します。異なるのはヘッダー名、ダイジェストのエンコーディング、および署名対象となるペイロード文字列です。 いくつかの例を示します。上記の resolver の例では、すでに GitHub の HMAC-SHA256 フローを示しています。連携するプロバイダーに合わせて、ヘッダー名、ダイジェストのエンコーディング、および署名対象となるペイロード文字列を調整してください。
resolver が dispatch オブジェクトを返すと、ルートは 202 { queued: true } を返し、target はワーカーキュー上で実行されます。呼び出し元は target のレイテンシ、結果、失敗を一切観測しません(それらは実行ログに記録されます)。 これにより、送信側の再配信によって処理の遅延が増幅されるのを防げます。これは、Webhook 取り込みにおいて望ましい動作です。呼び出し元が同じリクエストでレスポンスボディを読み取る必要がある場合(チャレンジハンドシェイク、対話的な受領確認など)、代わりに resolver から Response を返してください。 プラットフォームはそれを同期的にエコーし、キューをスキップします。そのヘッダーは HTTP ルートレスポンスと同じ許可リストを通過します。 resolver は高速に保ってください。Slack など一部のプロバイダーは数秒でタイムアウトします。 resolver はパブリックエンドポイントとして到達可能であるため、エッジでレート制限をかけて保護してください。

データベースイベントトリガーのペイロード

データベースイベントトリガーがロジック関数を呼び出すと、変更されたレコードごとに 1 つの DatabaseEventPayload を受け取ります。 このペイロードは、ソースワークスペースとオブジェクトに関するメタデータを、レコードレベルのイベントと組み合わせたものです。
ペイロードには次のものが含まれます:ソフトデリートの場合、レコードの deletedAt フィールドが変化するため、.deleted はアップデート時と同じ形式になります。 完全な削除の場合は .destroyed を使用します。
databaseEventTriggerSettings.updatedFields は、どの更新イベントで関数をトリガーするかをフィルタリングします。 event.properties.updatedFields は、現在のイベントで実際にどのフィールドが変更されたかを示します。
作成イベントの例:
更新イベントの例:
メール更新時のみトリガーする例:
削除イベントの例:

関数を AI ツールまたはワークフロー アクションとして公開する

ロジック関数は 2 つのサーフェス上で公開でき、それぞれに固有のトリガーがあります:
  • toolTriggerSettings — Twenty の AI 機能(チャット、MCP、関数呼び出し)からその関数を見つけられるようにします。 標準的な JSON Schema を使用します。これは LLM がネイティブに理解する形式です。
  • workflowActionTriggerSettings — ビジュアル ワークフロー ビルダー内のステップとして関数を表示します。 ビルダーが適切なフィールドエディタ、変数ピッカー、ラベルをレンダリングできるよう、Twenty の充実した InputSchema を使用します。
関数は一方、もう一方、またはその両方を選択できます。 これらは cronTriggerSettingsdatabaseEventTriggerSettingshttpRouteTriggerSettings と並列に存在します — 同じパターン、同じ形です。
ワークフローの Code アクションとの関係。 ワークフロービルダーに組み込まれている Code アクション自体もロジック関数です。Twenty は Code ステップごとに 1 つ作成し、そのエディタをインラインで表示します。 workflowActionTriggerSettings を使うことで、その使い捨てのインラインコードを再利用可能なアクションに変換できます。アプリ内でその関数を 1 度定義すれば、各 Code ステップにコードをコピーペーストする代わりに、任意のワークフローで選択できるようになります。 エンドユーザー側の表示については、ユーザーガイドの Code action を参照してください。
src/logic-functions/enrich-company.logic-function.ts
主なポイント:
  • 関数はサーフェスを混在させることができます — toolTriggerSettingsworkflowActionTriggerSettings の両方を宣言して、チャットおよびワークフロー ビルダーの両方に公開します。
  • toolTriggerSettings.inputSchemaworkflowActionTriggerSettings.inputSchema はいずれも任意です。 省略された場合、マニフェストビルダーはハンドラーのソースコードからそれらを推論します(AI ツールには JSON Schema、ワークフロー アクションには Twenty の InputSchema)。 より豊富な型付けが必要な場合は、明示的に指定してください — たとえば、ワークフロー ビルダー向けに CURRENCYRELATION といった FieldMetadataType に対応したフィールド、または AI エージェントが読み取れる description フィールドを使用する場合など:
パラメーターを一度だけ宣言して両方のサーフェスで利用できるようにするには、単一の JSON Schema(InputJsonSchema)を定義し、twenty-sdk/logic-functionjsonSchemaToInputSchema を使ってワークフローアクション用に変換します。 toolTriggerSettings.inputSchema は JSON Schema を直接受け取りますが、workflowActionTriggerSettings.inputSchema には Twenty の InputSchema が必要です。
ワークフローアクションの完全な例
workflowActionTriggerSettings は 4 つのフィールドを受け取ります:これらを組み合わせると、ワークフローアクションとして公開される関数になり、taskId を後続ステップから参照できるように出力を宣言できます。
src/logic-functions/enrich-company.logic-function.ts
アプリがインストールされると、ワークフロービルダーのアクションピッカーに Enrich Company が表示されます。 ビルダーは companyNamedomain を入力フィールドとしてレンダリングします(それぞれが前のステップから値を取得可能)、さらに下流のステップでは、そのステップの taskIdenriched の出力を参照できます。
良い description を記述してください。 AI エージェントは、ツールをいつ使用するかを判断するために関数の description フィールドに依存します。 ツールが何を行い、いつ呼び出すべきかを具体的に記述してください。
ランタイムヘルパー。 twenty-sdk/utils は、小さなランタイムヘルパーを再エクスポートすることで、ハンドラーが直接 twenty-shared からインポートする必要がないようにします。 たとえば、isDefined(value)nullundefined の両方に対して false を返します。これを使うと、オプショナルなハンドラー入力を安全に絞り込めます。こうした入力は、型としては T | undefined であっても、実行時には null として渡される場合があります。
インストールフック — pre-install、post-install、uninstall の各ハンドラー — はこのランタイムを共有しますが、それぞれ独自の define 関数で宣言され、トリガー設定は受け取りません。 definePreInstallLogicFunctiondefinePostInstallLogicFunctiondefineUninstallLogicFunction については、インストールフック を参照してください。

型付き API クライアント(twenty-client-sdk

twenty-client-sdk パッケージは、ロジック関数やフロントコンポーネントから Twenty API とやり取りするための、型付き GraphQL クライアントを 2 つ提供します。
CoreApiClient は、ワークスペースデータのクエリと変更のための主要なクライアントです。 yarn twenty dev または yarn twenty dev:build の実行時にワークスペースのスキーマから生成されるため、オブジェクトやフィールドに一致する完全な型付けが行われます。
このクライアントは selection-set 構文を使用します。フィールドを含めるには true を渡し、引数には __args を使い、リレーションにはオブジェクトをネストします。 ワークスペースのスキーマに基づく完全な補完と型チェックが得られます。
CoreApiClient は開発/ビルド時に生成されます。 先に yarn twenty dev または yarn twenty dev:build を実行せずに使用すると、エラーが発生します。 生成は自動で行われます—CLI がワークスペースの GraphQL スキーマをイントロスペクトし、@genql/cli を使用して型付きクライアントを生成します。

CoreSchema を型注釈に使用する

CoreSchema は、ワークスペースのオブジェクトに対応する TypeScript の型を提供し、コンポーネントの状態や関数パラメーターの型付けに役立ちます:
MetadataApiClient は SDK に同梱されており、あらかじめビルド済みです(生成は不要)。 ワークスペースの設定、アプリケーション、ファイルアップロードのために /metadata エンドポイントに対してクエリを実行します。

ファイルのアップロード

MetadataApiClient には、ファイル型フィールドにファイルを添付するための uploadFile メソッドが含まれています:
主なポイント:
  • フィールドの universalIdentifier(ワークスペース固有の ID ではありません)を使用するため、アップロードコードはアプリがインストールされている任意のワークスペースで動作します。
  • 返される url は、アップロード済みファイルにアクセスするために使用できる署名付き URL です。
コードが Twenty 上で実行される際(ロジック関数やフロントコンポーネント)、プラットフォームは認証情報を環境変数として注入します:
  • TWENTY_API_URL — Twenty API のベース URL
  • TWENTY_APP_ACCESS_TOKEN — アプリケーションのデフォルト関数ロールにスコープされた短命のキー
これらをクライアントに渡す必要はありません — 自動的に process.env から読み取ります。 API キーの権限は、defineApplicationRole() で宣言されたロール(または application-config.tsdefaultRoleUniversalIdentifier で参照されるロール)によって決まります。