snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
---
title: ワークフローによるメール送信
description: ワークフローアクションを使用して、パーソナライズされたメールを自動送信します。
---
CRM で特定のイベントが発生したときにメールを自動送信します—新規連絡先を歓迎し、商談をフォローアップしたり、チームメンバーに通知したりします。
## 前提条件
ワークフローからメールを送信する前に:
1. **設定 → アカウント** でメールアカウントを接続する
2. そのアカウントで送信権限が有効になっていることを確認する
## 基本的なメールワークフロー
### 例:新規連絡先へのウェルカムメール
**目的**: 新しい連絡先が CRM に追加されたときにウェルカムメールを送信する。
**設定**:
1. **ワークフローを作成**: **設定 → ワークフロー** に移動し、**+ New Workflow** をクリック
2. **トリガーを追加**: **Record is Created** → **People** を選択
3. **Send Email アクションを追加**:
* アクションを追加するには **+** をクリック
* **Send Email** を選択
* メールを設定:
| フィールド | 値 |
| ------ | -------------------------------------- |
| **宛先** | `{{trigger.object.email}}` |
| **件名** | `{{Your Company Name}}へようこそ` |
| **本文** | `Hi {{trigger.object.firstName}}, ...` |
4. **テストして有効化**: サンプルレコードでテストし、その後有効化する
## メールで変数を使用する
`{{variable}}` 構文を使用して前のステップのデータを参照します:
```text
Hi {{trigger.object.firstName}},
Thank you for connecting with us!
Your company, {{trigger.object.company.name}}, is now in our system.
Best regards,
The Team
```
### トリガーから利用できる変数
| トリガータイプ | 一般的な変数 |
| -------------- | -------------------------------------- |
| **レコードの作成/更新** | `{{trigger.object.fieldName}}` |
| **手動** | `{{trigger.selectedRecord.fieldName}}` |
| **Webhook** | `{{trigger.body.fieldName}}` |
## 高度: 条件付きメール
### 例:リードのソースに基づいて異なるメール
**目的**: リードの流入元に応じて異なるウェルカムメールを送信する。
**設定**:
1. **トリガー**: レコードが作成される(People)
2. **フィルターアクションを追加**:
* 条件: `{{trigger.object.source}}` が "Website" と等しい
* 真の場合 → ウェブサイトのウェルカムメールに進む
3. **その他のソース用の分岐**:
* ソースごとに並列の分岐を作成する
* 各分岐にそれぞれの Send Email アクションを配置する
## 複数の受信者にメールを送信する
### 例:商談が成立したときにチームへ通知
**目的**: 商談が成約したときに担当営業とそのマネージャーへメールを送る。
**設定**:
1. **トリガー**: レコードが更新(Opportunities、Stage = "Closed Won")
2. **Search Records**: 商談の所有者のマネージャーを見つける
3. **Send Email #1**: 商談の所有者宛て
* 宛先: `{{trigger.object.owner.email}}`
* 件名: `Congratulations on closing {{trigger.object.name}}!`
4. **Send Email #2**: マネージャー宛て
* 宛先: `{{searchRecords.manager.email}}`
* 件名: `Deal Won: {{trigger.object.name}}`
## フォローアップメールのスケジュール送信
### 例:会議の3日後にフォローアップ
**目的**: 会議が記録された3日後にフォローアップメールを送信する。
**設定**:
1. **トリガー**: レコードが作成(Activities、Type = "Meeting")
2. **Delay アクション**: 3日待機
3. **Send Email**:
* 宛先: 会議の参加者
* 件名: 先日の会話のフォロー
* 本文: トリガーから会議の詳細を参照
## メールの添付ファイル
ワークフローから送信されるメールにファイルを添付できます。 添付ファイルは、ワークフローを設定する際にアップロードする静的なファイルです。
### 添付ファイルを追加する方法
1. **メール送信** アクションで、**添付ファイル** ボタンをクリックします
2. クリックしてお使いのコンピューターからファイルをアップロードします
3. このアクションによって送信されるすべてのメールに、そのファイルが添付されます。
### 一般的な使用例
| ユースケース | サンプルファイル |
| ----------------- | --------------- |
| **ウェルカムメール** | 会社案内(PDF) |
| **オンボーディングシーケンス** | 導入ガイド |
| **営業のフォローアップ** | 製品カタログまたは価格表 |
| **イベント確認メール** | イベントの詳細またはアジェンダ |
<Note>
添付ファイルは静的です—すべての受信者に同じファイルが送信されます。 動的ドキュメント(パーソナライズされた見積もりなど)の場合は、[ロジック関数](/l/ja/user-guide/workflows/how-tos/connect-to-other-tools/generate-pdf-from-twenty)を使ってファイルを生成し、添付します。
</Note>
## ベストプラクティス
### メールの内容
* 件名は簡潔かつ関連性の高い内容に保つ
* 受信者名でパーソナライズする
* 明確な行動喚起を含める
* 有効化前にメールをテストする
### 到達性
* 短時間に過度な数のメールを送信しない
* プロフェッショナルなメール署名を使用する
* スパム判定されやすい語句を避ける
* マーケティングメールに配信停止オプションを必ず用意する
### トラブルシューティング
* メールアカウントが接続され有効になっていることを確認する
* 受信者のメールアドレスが有効か確認する
* エラーメッセージがないかワークフローの実行履歴を確認する
* まず自分のメールアドレスでテストする
## 関連
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,88 @@
---
title: ワークフローでブランチを使用する
description: ブランチの仕組みと、どのパスが実行されるかの制御方法を理解します。
---
## ブランチの仕組み
ワークフローエディタでは、1 つのノードから分岐する複数のパス(ブランチ)を作成できます。 これにより、異なる結果を持つ複雑な自動化を構築できます。
**重要**: ワークフローが実行されると、**既定ではすべてのブランチが並列に実行されます**。 あるブランチを選択するための組み込みの "if/else" ロジックはありません—すべてのパスが同時に実行されます。
## どのブランチを実行するかの制御
特定の条件に基づいて 1 つのブランチのみを実行するには、**各ブランチの先頭に Filter ノードを追加**します。
### セットアップ例
1. 1 つのノードから複数のブランチを持つワークフローを作成します
2. 各ブランチの最初のステップとして **Filter** ノードを追加します
3. 各 Filter に条件を設定し、そのブランチをいつ続行するかを決めます
4. Filter の条件を満たしたブランチだけが続行します
### Filter の仕組み
* Filter の条件が**満たされた**場合:ブランチは実行を継続します
* Filter の条件が**満たされない**場合:ブランチは Filter ノードで停止します
これにより、データに基づいて該当するブランチだけが実行される条件付きロジックを実質的に作成できます。
## 例:商談金額でルーティング
**シナリオ**: 商談がクローズされたとき、商談金額に応じて異なる通知を送信します。
1. **トリガー**: Opportunity が更新(Stage = Closed Won)
2. **ブランチ 1**: Amount > $10,000 で Filter → #big-deals に Slack メッセージを送信
3. **ブランチ 2**: Amount ≤ $10,000 で Filter → 営業マネージャーにメールを送信
両方のブランチが開始されますが、商談金額に一致する方だけが Filter を通過して続行します。
## ブランチの作成
<Note>
既存のステップから新しいブランチを作成するには、そのステップの **+** ボタンをクリックしてアクションを追加します。 **+** を複数回クリックすると、複数のブランチを追加できます。
</Note>
1. ワークフローエディタで、分岐させたいステップを選択します
2. アクションを追加するには **+** ボタンをクリックします
3. これで 1 つのブランチが作成されます
4. 同じステップで **+** をもう一度クリックして、ブランチを追加作成します
5. 各ブランチは独自のアクションのシーケンスを持てます
## ブランチを再結合する
並列ブランチが処理を完了したら、単一のパスに再結合できます:
1. 分岐したアクションを完了します
2. すべてのブランチの後に実行すべき新しいステップを追加します
3. 各ブランチの最後のステップからこの新しいステップに接続をドラッグします
4. マージされたステップは、接続されたすべてのブランチが完了するまで待機してから実行されます
### 例:処理後に通知
```
Trigger
│
├── Branch A: Update Customer Record
│
└── Branch B: Create Support Ticket
↘ ↙
Merged Step: Send Confirmation Email
```
確認メールは、お客様の更新とチケット作成の両方が完了した後に送信されます。
## ベストプラクティス
* 条件付きで実行したい場合は、ブランチの開始時に常に**Filter ノード**を使用します
* 重複したアクションを避けるために、ブランチの条件は**相互排他的**に保ちます
* さまざまなデータでワークフローをテストし、正しいブランチが実行されることを確認します
* **ブランチのステップ名を変更**して、各パスが何を行うかが明確に分かるようにします
* 並列処理の後に最終アクションが必要な場合は、**ブランチをマージ**します
## 関連
* [ワークフロー FAQ](/l/ja/user-guide/workflows/how-tos/need-more-help/workflows-faq) — 並列実行に関する回答
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions) — ブランチで利用可能なアクション

View File

@@ -0,0 +1,183 @@
---
title: Iterator を使用
description: レコードの配列をループし、各アイテムに対してアクションを実行します。
---
Iterator を使用すると、レコードの配列をループし、各レコードに対してアクションを実行できます。 これは、Search Records で返された複数のレコードや Webhook で受信したレコードを処理する必要があるワークフローに不可欠です。
## Iterator を使用するタイミング
| シナリオ | 例 |
| ------------------ | ------------------ |
| **検索結果を処理** | 見つかった各人物にメールを送信 |
| **Webhook の配列を処理** | 各アイテムごとに順番にレコードを作成 |
| **一括更新** | 計算された値で複数のレコードを更新 |
| **通知** | イベントについて複数人に通知 |
## Iterator の理解
Iterator は入力として**配列**を想定しています。 その後、次を実行します:
1. 配列から最初のアイテムを取り出す
2. そのアイテムを使って Iterator 内のすべてのアクションを実行する
3. 次のアイテムに進む
4. すべてのアイテムが処理されるまで繰り返す
### ループ処理する配列の選択
ほとんどの配列ソース(Search Records、webhook の配列フィールド、Bulk manual trigger)は、変数ピッカーで直接選択できます。
**Code** ステップや **Logic Function** ステップが*トップレベル配列*を返す場合、その出力は変数ピッカー内でインデックス付きエントリ(`0`、`1`、`2`、…)として表示されます。 配列全体をループ処理するには、そのステップの **Whole list** オプションを選択します。Iterator は、そのリストから各アイテムの構造を自動的に推論します。
## 基本的なセットアップ
### 例: 検索結果の全員にメールを送信
**目標**: 特定の会社のすべての連絡先を見つけ、各人にパーソナライズされたメールを送信します。
### ステップ 1: レコードを検索
1. 「**Search Records**」アクションを追加
2. オブジェクト: **People**
3. フィルター: Company が "Acme Inc" に等しい
4. これにより、People の配列が返されます
### ステップ 2: 結果の有無を確認
1. 「**Filter**」アクションを追加
2. 条件: `{{searchRecords.length}}` が 0 より大きい
3. これにより、結果が空の場合の Iterator エラーを防止します
### ステップ 3: Iterator を追加
1. 「**Iterator**」アクションを追加
2. 配列の入力: `{{searchRecords}}` を選択
3. これでループが作成されます
### ステップ 4: Iterator 内にアクションを追加
Iterator の後に配置したアクションは、各アイテムに対して実行されます:
1. Iterator 内に **Send Email** アクションを追加する
2. 宛先: `{{iterator.currentItem.email}}`
3. 件名: こんにちは `{{iterator.currentItem.firstName}}`!
4. 本文: 現在のアイテムのフィールドを使用したパーソナライズメッセージ
### 結果
Search Records が 5 人を返した場合、Iterator は次を実行します:
* 1 人目にメールを送信
* 2 人目にメールを送信
* ... 5 人すべてに対して続行
## 現在のアイテムのデータにアクセスする
Iterator 内では、現在のレコードにアクセスするために `{{iterator.currentItem}}` を使用します:
| 変数 | 説明 |
| --------------------------------------- | ---------------- |
| `{{iterator.currentItem}}` | 現在のレコードオブジェクト全体 |
| `{{iterator.currentItem.id}}` | レコード ID |
| `{{iterator.currentItem.email}}` | メールフィールド |
| `{{iterator.currentItem.company.name}}` | 関連する会社名 |
| `{{iterator.index}}` | 配列内の現在の位置(0 始まり) |
変数ピッカーでは、現在のアイテムの特定のフィールドまでドリルダウンして選択するか、**Use the whole item** を選択して、現在のアイテム全体(`{{iterator.currentItem}}`)を参照できます。 アイテム全体を選択すると、フィールドを 1 つずつ再構築するのではなく、完全なレコードをそのまま後続ステップに渡したい場合に便利です。
## よくあるパターン
### 複数レコードを更新
**目標**: 期限超過のタスクをすべて "Late" としてマークします。
```
1. Search Records (Tasks, Due Date < Today, Status ≠ Completed)
2. Filter (length > 0)
3. Iterator (searchRecords)
└── Update Record
- Object: Tasks
- Record: {{iterator.currentItem.id}}
- Status: Late
```
### 配列からレコードを作成
**目標**: 複数のアイテムを含む注文を Webhook が受信したら、各アイテムのレコードを作成します。
```
1. Webhook Trigger (receives items array)
2. Filter (items.length > 0)
3. Iterator (trigger.body.items)
└── Create Record
- Object: Order Items
- Name: {{iterator.currentItem.name}}
- Quantity: {{iterator.currentItem.qty}}
- Related Order: {{trigger.body.orderId}}
```
### ループ内の条件付き処理
**目標**: 有効なメールアドレスを持つ連絡先にのみメールを送信します。
```
1. Search Records (People)
2. Iterator (searchRecords)
└── Filter (currentItem.email is not empty)
└── Send Email
- To: {{iterator.currentItem.email}}
```
## トラブルシューティング
### "Iterator expects an array"
**原因**: 配列ではなく単一のレコードを渡しました。
**対処**: 単一のレコードではなく、Search Records の結果または配列フィールドを渡していることを確認してください。
```
✅ Correct: {{searchRecords}}
❌ Wrong: {{searchRecords[0]}}
```
### Iterator が実行されない
**原因**: 配列が空です。
**対処**: Iterator の前にフィルターを追加し、配列の長さを確認します:
```
Filter: {{searchRecords.length}} > 0
```
### アクションが過剰に実行される
**原因**: Search Records が想定より多くのレコードを返しました。
**対処**:
* Search Records により具体的なフィルターを追加する
* Search Records に上限を設定する(最大 200)
* 追加条件のために Iterator 内にフィルターを追加する
## パフォーマンス上の考慮事項
* **クレジット使用量**: 各イテレーションでアクション実行分のクレジットを消費します
* **時間**: 大きな配列は処理に時間がかかります
* **制限**: 非常に大きな処理はバッチ化を検討してください
* **レート制限**: 繰り返しが多いと外部 API 呼び出しがレート制限に達する可能性があります
## ベストプラクティス
1. エラーを避けるため、Iterator の前に**配列の長さを必ず確認**
2. **すべてのアイテムを処理する必要がない場合はループ内にフィルターを追加**
3. **何をループしているか分かるように Iterator ステップの名前を変更**
4. **小さな配列でテスト**してから大きなデータセットを処理する
5. **ワークフローの実行を監視**して、イテレーションが想定どおりに完了することを確認する
## 関連
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [ブランチの使い方](/l/ja/user-guide/workflows/capabilities/use-branches-in-workflows)
* [ワークフロー FAQ](/l/ja/user-guide/workflows/how-tos/need-more-help/workflows-faq)

View File

@@ -0,0 +1,332 @@
---
title: ワークフローアクション
description: Twenty のワークフローで利用可能なアクションについて学びましょう。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## アクションについて
アクションはトリガーが起動した後に何が起こるかを定義します。 複数のアクションを連結して、複雑な自動化を構築できます。
<Tip>
* 変数ピッカー(`(x+)` アイコンをクリック)を使用して、前の手順から利用可能なデータを参照します
* 任意の入力フィールドにカーソルを合わせると、変数がどのステップから来ているかがわかります—同じフィールド(例:ID)が複数の前のステップに存在する場合に便利です
* 保守しやすくするため、各アクションにわかりやすい名前を付けてください
</Tip>
## レコードアクション
<img src="/images/user-guide/workflows/workflow_actions.png" style={{width:'100%'}} />
### レコードを作成
選択したオブジェクトに新しいレコードを追加します。
**設定**:
* 対象オブジェクトを選択
* 必要およびオプションのフィールドに入力
* 前の手順のデータを使用するか、手動で値を入力してフィールドに設定します
**出力**:新しく作成されたレコードのデータが後続の手順で使用可能
### レコードを更新
選択したオブジェクト内の既存のレコードを変更します。
<img src="/images/user-guide/workflows/update_record.png" style={{width:'100%'}} />
**設定**:
* 対象オブジェクトを選択
* 更新する具体的なレコードを選択.
* 利用可能なすべてのレコードを表示するドロップダウンメニューから、固定のレコードを選択できます。
* または、`(x+)` を使用して前のステップで見つかったレコードを指定し、レコードを動的に選択できます。 この段階では、異なる条件に基づいてレコードを検索することはできません。 まだレコードを特定していない場合は、この `Update Record` ステップの前に `Search Record` ステップを追加してください。
* 変更するフィールドを選択し、新しい値を入力
**出力**:更新されたレコードのデータが後続の手順で使用可能
### レコードを削除
選択したオブジェクトからレコードを削除します。
**設定**:
* 対象オブジェクトを選択
* 削除する具体的なレコードを選択
**出力**:削除されたレコードのデータは後続の手順で使用可能
### レコードを検索
選択したオブジェクト内のフィルター条件を使用してレコードを探します。
**設定**:
* 検索するオブジェクトを選択
* 結果を絞り込むためのフィルター基準を設定
* 並べ替えや制限を設定
**出力**:一致するレコードを返し、後続の手順で使用可能
<Note>
**制限**:Search Records は最大 **200 件のレコード**を返します。 さらに処理する必要がある場合は、結果を絞り込むフィルターを追加するか、スケジュールされたワークフローを使用してバッチ処理してください。
</Note>
**ベストプラクティス**:Search Records の後に[ブランチ](/l/ja/user-guide/workflows/capabilities/workflow-branches)を使用して、「見つかった」と「見つからない」のシナリオを処理します。
### Upsert Record
一致条件に基づいて、新しいレコードを作成するか、既存のレコードを更新します。 レコードが既に存在するかどうか確信が持てない場合に便利です。
<img src="/images/user-guide/workflows/upsert_double_identifier.png" style={{width:'100%'}} />
**設定**:
* 対象オブジェクトを選択
* どのフィールドがマッチングに使用できるかに注意してください:People には email、Companies には domain、任意のオブジェクトには ID、または Unique としてマークされた任意のフィールド。 以下のうち少なくとも 1 つは入力する必要があります。
* フィールドの値を入力します。 少なくとも 1 つの一意の識別子を必ず入力してください。
<Note>
**通常、一意の識別子を 1 つだけ追加するほうがマッチングはうまく機能します。** 例えば、以下のスクリーンショットでは、ドメインに基づいて会社を照合します。 ID は必ずしも必要ではありません。
</Note>
<img src="/images/user-guide/workflows/upsert_simple_identifier.png" style={{width:'100%'}} />
* 前の手順からのデータを使用してフィールドを埋める
**仕組み**:
1. 指定した条件に一致するレコードを検索します
2. 見つかった場合 → 既存のレコードを更新します
3. 見つからない場合 → 新しいレコードを作成します
**出力**:作成または更新されたレコードのデータは後続の手順で使用できます。
## フローアクション
### イテレータ
**前の手順から返されたレコード配列をループ**し、各レコードに個別にアクションを実行できます。
**設定**:
* 前のステップからレコードの配列を選択します (たとえば、format@@0の結果、format@@1のformat@@2ノードからformat@@3のトリガーを選択します)。 Code または Logic Function ステップがトップレベルの配列を返す場合は、その出力全体をループ処理するために **Whole list** オプションを選択します。
* ループ内の各レコードで実行するアクションを定義.
<Note>
- イテレータ内に複数のアクションを追加できます。
- イテレータ内でブランチを使用する場合は、各ブランチの最後のステップがイテレータに戻ってループを閉じるようにしてください。
</Note>
* `Current Item` フィールドにアクセス:現在処理中のレコードのフィールドを使用するには、**Iterator** ステップをクリックし、**Current item** を選択します。 そのレコードで使用可能なフィールドの一覧が表示され、後続のアクションで使用するために選択できます。 現在のアイテム全体を後続ステップに渡すには、**Use the whole item** を選択することもできます。
<VimeoEmbed videoId="1146577247" title="デモ動画" />
### フィルター
指定された条件に基づいてレコードをフィルタリングし、条件を満たすレコードのみを通過させます。
**設定**:
* フィルター対象のレコードを選択
* フィルタ条件と基準を定義
* 後続の手順に通過するレコードを設定
<Note>
1. **出力**:フィルターノードはデータを返しません—ゲートとして機能します。 条件を満たす場合、ワークフローは継続します。 満たさない場合、その分岐でワークフローは停止します。
2. `IS` 演算子は数値フィールドで使用できます。 これは `EQUAL` と同様に動作します。
</Note>
### 遅延
指定した期間、または特定の日時までワークフローの実行を一時停止します。
**遅延の種類**:
| タイプ | 説明 |
| -------- | --------------------- |
| **期間** | 指定した時間(日、時間、分、秒)待機します |
| **予定日時** | 特定の日時まで待機します |
**期間の設定**:
* 日、時間、分、秒を設定します
* 複数の単位を組み合わせます(例:2日と4時間)
**予定日時の設定**:
* 日付と時刻を選択します
* 前の手順の日付フィールドを参照できます(例:ミーティングの3日後にフォローアップ)
**ユースケース**:
* フォローアップメールを送信する前に24時間待機する
* 商談のクローズ日まで一時停止する
* 営業時間内にアクションを実行するようスケジュールする
<Note>
予定日時は過去に設定できません。 前の手順の日付フィールドを使用し、その日付がすでに過去の場合、ワークフローは失敗します。
</Note>
**制限とクレジット**:
* **最大期間の制限はありません**—分、日、週、さらに長い遅延を設定できます
* 期間に関係なく、Delay ノードの実行時に**1 クレジットを消費**します
* 待機中は**クレジットは消費されません**—5分の遅延も5日の遅延もコストは同じです
## コミュニケーションアクション
### メールを送信
ワークフローからメールを送信します。 テンプレート化されたグループメールに最適です。 メールは、メールボックスから送信するメールと同様の見た目になります。
ニュースレター(より豊かなフォーマットを必要とする)や自動メールシーケンスには適していません。
**前提条件**:設定 → アカウントでメールアカウントを追加
**設定**:
* 送信元のメールアカウントを選択
<Note>
自分の Twenty アカウントと同期されたメールボックスからのみメールを送信できます。 他のチームメンバーのメールボックス(例:アカウント所有者のメール)からの送信はロードマップにあります。
</Note>
以降のすべての手順で、パーソナライズのために前の手順の変数を参照できます。
* 受信者のメールアドレスを入力.
<Note>
現在は受信者は1名のみです。
</Note>
* 件名を設定.
* メッセージ本文を作成. リンクの書式設定、番号付きリストの作成、箇条書きリストの作成、添付ファイルの追加ができます。
<Note>
現在、HTML署名の追加はできません。
</Note>
### フォーム
ワークフロー実行中にフォームをプロンプトしてユーザー入力を収集します。 回答はその後、後続の手順で、入力に基づいてレコード作成、メール送信、その他のアクションの実行に利用できます。
<Warning>
**フォームは手動トリガー専用に設計されています。** 他のトリガーを持つワークフロー(レコード作成、更新など)では、ユーザーが期待する体験とは異なり、フォームにはワークフロー実行インターフェースからのみアクセス可能です。 通知センターは2026年にリリースされ、自動化されたワークフローのフォームを適切にサポートします。
</Warning>
**設定**:
* ユーザーに入力してもらうフィールドを設定します。 各フィールドについて、次を選択します。
* テキスト、数値、日付、特定のレコード、セレクトフィールドのいずれかのタイプ。 すべてのオブジェクトのフィールドは選択可能です。
* ラベル
* `Placeholder` のデフォルト値(任意)
* フォームのタイトルを編集
**出力**:フォームレスポンスが後続の手順で使用可能
**例**: "クイックリード" ワークフローは、すべてのワークスペースでデフォルトで使用できます。コマンドメニューの `Cmd+K` で利用できます。
**フォームの記入方法**:
* コマンドメニュー「Cmd+K」から手動ワークフローをトリガーする
* サイドパネルに表示されるフォームに入力し、`Submit` をクリックします。
<Note>
フィールドを必須にすることはできません。
</Note>
<VimeoEmbed videoId="1147277989" title="デモ動画" />
## 統合アクション
### コード
ワークフロー内でカスタムJavaScriptを実行します。
内部的には、それぞれの Code アクションは独自の **ロジック関数** によって支えられています。これは Twenty プラットフォーム上で実行されるサーバーサイドの TypeScript 関数です。 Code アクションを追加すると、Twenty はそのステップ専用のロジック関数を作成し、そのエディタをインラインで表示します。そのため、記述したコードはワークフローと一体となって存在します。
**設定**:
* 前の手順からの変数にアクセス. 変数の名前を動的に編集できます。
<VimeoEmbed videoId="1147281795" title="デモ動画" />
* エディタでJavaScriptコードを記述
* 後続の手順で使用するための変数を返す
* ステップ内でコードを直接テスト
<Note>
コードで外部のAPIキーを使用する必要がある場合は、関数本体に直接入力する必要があります。 他の場所でAPIキーを設定したり、ロジック関数で参照したりすることはできません。
</Note>
<Tip>
**配列を扱っていますか?** 外部システムや前の手順からの配列は、文字列として渡される場合があります。 配列の扱いの詳細については、[Code アクションで配列を扱う](/l/ja/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)を参照してください。
</Tip>
<Tip>
コードエディタ右上の四角いアイコンをクリックすると全画面表示になります — デフォルトのエディタ幅には制限があるため便利です。
</Tip>
#### ワークフロー間でロジック関数を再利用する
インラインの Code アクションは単発のロジックには最適ですが、その中に保持されるコードはその 1 つのステップ専用のものです。 複数のワークフロー間で同じロジックを共有したい場合や、アプリ内でバージョン管理されたソースとして維持したい場合は、各 Code アクションにコードをコピーペーストするのではなく、**再利用可能なロジック関数** を定義します。
ロジック関数は、アプリ内で一度だけ(SDK の `defineLogicFunction` を使用して)定義され、`workflowActionTriggerSettings` を追加することでワークフロービルダーに公開されます。 アプリがインストールされると、その関数は組み込みアクションと並んで、ワークフロービルダー内で 1 つのアクションとして表示されます。 それを選択すると、宣言した入力スキーマから生成された入力フィールド(他のアクションと同様に変数ピッカー付き)が表示され、共有コードが実行されます。インラインの JavaScript は不要です。
| | コードアクション | 再利用可能なロジック関数 |
| ---------- | --------------------------------- | -------------------------- |
| **コードの所在** | インラインエディタで記述され、1 つのワークフローステップに紐づく | アプリ内で定義され、ソース管理でバージョン管理される |
| **再利用性** | ステップごとにコピー&ペースト | 任意のワークフローでアクションとして追加可能 |
| **入力** | エディタ内で接続された変数 | 宣言した入力スキーマからレンダリングされるフィールド |
| **最適な用途** | 手早く記述できる、ワークフロー固有のロジック | 複数のワークフローで使用される共有ロジック |
両者は同じロジック関数ランタイム上で実行されるため、インラインで試作した Code アクションは、最小限の変更で再利用可能なロジック関数へ昇格させることができます。
<Tip>
ロジック関数を定義し、それらをワークフロービルダーに公開する方法に関する開発者向けリファレンスについては、[Logic Functions](/l/ja/developers/extend/apps/logic/logic-functions) を参照してください。特に **Exposing a function as an AI tool or workflow action** セクションと `workflowActionTriggerSettings` を確認してください。
</Tip>
### HTTPリクエスト
ワークフローの一部として外部APIにリクエストを送信します。
<img src="/images/user-guide/workflows/http_action.png" style={{width:'100%'}} />
**設定**:
* APIエンドポイントURLを入力. 前の手順のパラメーターを使用できます。
* HTTPメソッドを選択(GET, POST, PUT, PATCH, DELETE)
* 必要なヘッダと値を追加
* 構造プレビューのためにサンプルレスポンスを提供
## AI アクション
### AI エージェント - 近日公開
ワークフロー内でAIエージェントを実行し、インテリジェントなタスクを実行します。
**設定**:
* **エージェント**:既存のAIエージェントを選択するか、デフォルトのエージェントを使用します
* **プロンプト**:AIエージェントへの指示を作成します
* プロンプト内で前の手順の変数を参照します
**AI エージェントでできること**:
* データを分析・要約する
* レコードを分類・カテゴリ化する
* テキストコンテンツを生成する
* データに基づいて意思決定する
* ツールを使って CRM データと対話する
**出力**:AIエージェントの応答は後続の手順で使用できます。 エージェントに構造化された出力スキーマがある場合、応答はその形式に従います。
<Note>
AIエージェントのアクションは、使用するAIモデルに応じてワークフロークレジットを消費します。 詳細は[ワークフロークレジット](/l/ja/user-guide/workflows/capabilities/workflow-credits)を参照してください。
</Note>
<Note>
AIエージェントはロールベースの権限に従います。 **設定 → メンバー → ロール** でエージェントに特定のロールを割り当て、アクセスできるデータを制御できます。 詳細は[権限](/l/ja/user-guide/permissions-access/capabilities/permissions)を参照してください。
</Note>

View File

@@ -0,0 +1,66 @@
---
title: ワークフローのブランチ
description: ワークフロー内で並列パスと条件ロジックを作成します。
---
ブランチを使用すると、ワークフローを複数のパスに分割でき、データに基づいて同時に、または条件付きで実行できます。
<img src="/images/user-guide/workflows/branches.png" style={{width:'100%'}} />
## ブランチの仕組み
1つのノードから複数の接続を作成すると、各パスがブランチになります。 既定では、**すべてのブランチは並列に実行**され、互いを待ちません。
## ブランチの作成
### 新しいブランチを追加
1. **ワークフローのメインキャンバスを右クリック**(既存のノード上ではありません)
2. **ノードを追加** をクリック
3. 新しいブランチのノードタイプを選択
4. 前のステップの下部から、この新しいアクションの上部へ矢印をドラッグします
5. 同じノードからさらにブランチを追加するには、これを繰り返します。
<Note>
各ブランチは独立しています。 ブランチを追加しても、そのノードからの他の既存のパスには影響しません。
</Note>
### ビジュアルレイアウト
ブランチはワークフローエディター上で並列のパスとして表示されます。 実行に影響を与えることなく、ノードをドラッグしてビジュアルレイアウトを並べ替えることができます。
## 条件付きブランチ
既定ではすべてのブランチが実行されるため、どのパスを実際に実行するかを制御するには **Filter** ノードを使用します:
| ブランチ | フィルター条件 | アクション |
| ---- | ----------- | ------------- |
| A | ステージ = "受注" | お祝いのメールを送信 |
| B | ステージ = "失注" | フォローアップタスクを作成 |
| C | ステージ = "交渉" | マネージャーに通知 |
1. トリガーまたはアクションからブランチを作成する
2. 各ブランチの最初のステップとして **Filter** ノードを追加する
3. 各 Filter ノードを相互排他的な条件で設定する
4. 各 Filter の後にアクションを追加する
フィルター条件を満たしたブランチだけが実行を継続します。
## ブランチの統合
**ブランチは自動的には統合されません。** 各ブランチは終了するまで独立して実行されます。 この点の取り扱いは柔軟に設計できます:
* **オプション1: ブランチを分離したままにする**
各ブランチがそれぞれのフォローアップアクションを独立して処理します。 ブランチを統合する必要がない場合の最も簡単な方法です。
* **オプション2: ブランチを手動で統合する**
ワークフローを作成する際、複数のブランチを同じ下流のアクションに手動で接続できます。 各ブランチの末端から共通のノードへ矢印をドラッグするだけです。
<Note>
実行を一時停止するために [Delay](/l/ja/user-guide/workflows/capabilities/workflow-actions#delay) ノードを使用できますが、現在は「別のブランチが終了するまで」待機するように設定することはできません。
</Note>
## 関連
* [ワークフローでブランチを使用する方法](/l/ja/user-guide/workflows/capabilities/use-branches-in-workflows) - ステップバイステップのガイド
* [ワークフローアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions) - Filter を含む利用可能なアクション

View File

@@ -0,0 +1,75 @@
---
title: ワークフロークレジット
description: ワークフロークレジットの消費と管理を理解する。
---
ワークフロークレジットは、Twentyでの自動化をサポートします。 その仕組みを理解することで、コストを最適化し、自動化予算を効果的に管理できます。 その仕組みを理解することで、コストを最適化し、自動化予算を効果的に管理できます。
## クレジット配分
ワークフロークレジットは、プランの種類ではなく、請求サイクルに基づいて割り当てられます:
| 請求サイクル | クレジット |
| --------------- | ----------- |
| **月額サブスクリプション** | 月あたり5クレジット |
| **年額サブスクリプション** | 年あたり50クレジット |
<Note>
標準的な自動化には、月間5クレジットで十分に余裕があります。 一般的なワークフローの利用で、この上限を超えるチームはほとんどありません。 追加のクレジットが主に必要になるのは、高度な Code アクションや AI 搭載ワークフローの場合です。
</Note>
## クレジット消費の仕組み
ワークフローは実行時にクレジットを消費し、それを作成する際には消費されません。 各ワークフローアクションはその複雑さに応じてクレジットを消費します。 各ワークフローアクションはその複雑さに応じてクレジットを消費します。 各ワークフローアクションはその複雑さに応じてクレジットを消費します。
### アクションタイプ別クレジット消費
* **基本的な内部操作**: 非常に低いクレジット消費
* レコードを検索
* レコードを作成
* レコードを更新
* レコードを削除
* フォームアクション
* **複雑な操作**: 高いクレジット消費
* コードアクション (JavaScript実行)
* 外部サービスへの HTTP リクエスト
* **AI 機能**: 高いクレジット消費
* AI エージェントのアクションは、使用する AI モデルに応じてクレジットを消費します
* より複雑なプロンプトや長い出力ほど、より多くのクレジットを使用します
* **Delay アクション**: クレジット消費は最小限
* Delay ノードは実行時に**1クレジット**を消費します
* **待機期間中はクレジットは消費されません**
* 5分の遅延も5日の遅延もコストは同じです
### リアルタイム控除
ワークフローが実行されると、クレジットはリアルタイムで控除されます。 つまり: つまり: つまり:
* ドラフトのワークフローはクレジットを消費しません
* アクティブで実行中のワークフローだけがクレジット配分を使用します
* 失敗したワークフローでも、完了したステップに対してはクレジットが消費されます
## クレジットの管理
### クレジット使用の確認
1. **設定 → 請求** へ移動
2. 現在のクレジット消費と残高を確認
3. 消費パターンを監視してワークフローを最適化
### 追加クレジットの購入
プランのクレジット割り当てを超える場合は:
1. **設定 → 請求** へ移動
2. 追加クレジットを購入するオプションをクリックします。 さまざまなサイズのパッケージが用意されています。 さまざまなサイズのパッケージが用意されています。
3. クレジットは現在の残高に追加されます
## ベストプラクティス
* **バッチ処理**: 効率的に一括操作やイテレータアクションを利用して、個々のアクション呼び出しを削減します
* **手動トリガーの最適化**: 手動トリガーでは、単一のワークフロー実行で複数のレコードを処理するために、`Bulk` の可用性を選択してください
* 効率性のためにコードアクションを最適化

View File

@@ -0,0 +1,93 @@
---
title: ワークフロー実行
description: ワークフローの実行を監視および管理します。
---
## 実行について
**実行**は、ワークフロー実行の記録です。 レコードイベント、スケジュール、手動操作、またはWebhookなどでワークフローがトリガーされるたびに、新しい実行が作成されます。
## 実行の表示
### ワークフローエディタから
1. 監視したいワークフローを開きます
2. 右側の**実行**パネルをクリックします
3. 最近の実行とそのステータスの一覧を確認します
### ワークフロー実行ビューから
1. サイドバーの**ワークフロー実行**に移動します
2. すべてのワークフローにわたる実行を表示します
3. ステータス、ワークフロー、日付でフィルタリングします
## 実行ステータス
| ステータス | 説明 |
| ------- | ------------------------------------------ |
| **実行中** | ワークフローが現在実行中です |
| **完了** | ワークフローが正常に完了しました |
| **失敗** | ワークフローでエラーが発生し、停止しました |
| **待機中** | ワークフローが一時停止しています(例:遅延アクションの待機中、フォーム送信の待機中) |
## 実行の詳細
任意の実行をクリックすると、次を確認できます:
* **ステータス**:実行の現在の状態
* **開始時刻**:実行が開始された時刻
* **所要時間**:実行に要した時間
* **トリガーデータ**:ワークフローを開始した入力データ
* **ステップの出力**:各ステップから返されたデータ
* **エラーメッセージ**:実行が失敗した場合に、何が問題だったか
## ステップごとの実行
各実行では、ワークフロー内での進行状況を表示します:
1. どのステップが正常に完了したかを確認します
2. 失敗が発生した箇所を特定します
3. ステップ間で受け渡されたデータを表示します
4. ステップの入力と出力を確認して問題をデバッグします
## エラーハンドリング
実行が失敗したとき:
1. 失敗した実行を開きます
2. 失敗の原因となったステップを特定します
3. エラーメッセージで詳細を確認します
一般的な問題:
* 必須フィールドの欠落
* 無効なデータ形式
* 外部 API エラー
* 権限に関する問題
## ワークフローの再実行
実行が失敗した場合、次のことができます:
* 根本的な問題を修正し、次のトリガーを待つ
* 手動ワークフローの場合、同じデータまたは更新したデータで再度トリガーする
* 今後の失敗を防ぐためにワークフローのロジックを見直す
## パフォーマンスのヒント
### 実行履歴の管理
* 実行は履歴の参照のために保持されます
* 非常に古いランニングは自動的にアーカイブされることがあります
* 記録を保持する必要がある場合は実行データをエクスポートします
### ベストプラクティスの監視
* 新しいワークフローをアクティブにした後に定期的にチェック
* パターンを識別するための実行の確認に失敗しました
## 関連
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [ワークフローのトラブルシューティング](/l/ja/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)

View File

@@ -0,0 +1,136 @@
---
title: ワークフロートリガー
description: ワークフローを開始するさまざまなトリガーについて学びましょう。
---
## トリガーについて
ワークフローは、常に自動化をいつ実行するかを定義する単一のトリガーで開始されます。
<img src="/images/user-guide/workflows/workflow_triggers.png" style={{width:'100%'}} />
<Tip>
**高度なオブジェクトにも対応しています!** 標準の CRM オブジェクト(People、Companies、Opportunities)に加えて、次のオブジェクトでもワークフローをトリガーし、アクションを実行できます:
* ワークスペースメンバー
* カレンダーイベント
* メッセージ(メール)
* タスク、ノート、その他多数のシステムオブジェクト
これにより、カレンダーイベントが作成された際にチームメンバーに通知したり、受信メールを自動処理したりするなど、強力な自動化が可能になります。
</Tip>
## レコードの作成
新しいレコードが選択されたオブジェクト(人物、会社、機会、または任意のカスタムオブジェクト)で作成されるときに、ワークフローを開始します。
**設定**:新しいレコードを監視するオブジェクトタイプを選択します。
<Note>
* このトリガーは、CSV、メールボックス、カレンダー同期、またはAPIによって作成されたレコードに最適です。
* **手動で作成されたレコードには推奨されません**: このトリガーでは、レコードが作成されるとすぐにワークフローが開始します。 Twenty UI はオンザフライで自動保存を提供しています(編集モードがなく、レコードを保存するための検証があります)。 ユーザーがすべての項目を入力する前にワークフローがトリガーされます。
手動で作成されたレコードでこのワークフローをトリガーするには、代わりにトリガー `Record is created or updated` を使用することを推奨します。
</Note>
## レコードの更新
既存のレコードに変更が加えられたときにワークフローを開始します。
**設定**:
* オブジェクトタイプを選択
* 変更を監視するフィールドをオプションで指定
## レコードの更新または作成
選択されたオブジェクトでレコードが作成または更新されたときに、ワークフローを開始します。
**なぜ重要か**:このトリガーが特に役立つのは、さまざまな方法で作成されたレコードが異なる動作をするためです。
* **API/CSV インポート**: レコードはすべてのフィールドが即座に入力されて作成されます。
* **手動作成**: レコードは最初に作成され、その後の更新でフィールドが追加されます。
**設定**:
* 監視するオブジェクトタイプを選択
* 変更を監視するフィールドをオプションで指定
* ワークフローは最初の作成時とその後のすべての更新時にトリガーされます。
## レコードの削除
オブジェクトからレコードが削除されたときにワークフローを開始します。
**設定**:削除を監視するオブジェクトタイプを選択します。
## 手動トリガー
ユーザーのアクションによってトリガーされたときにワークフローを開始します。 このトリガーには、`Cmd+K` メニューから、またはレコードを選択した後にトップナビバーに表示されるカスタムボタン経由でアクセスできます。
<img src="/images/user-guide/workflows/add_to_newsletter_button.png" style={{width:'100%'}} />
**可用性設定**: レコードの選択をワークフローでどのように扱うか選択します。
* **グローバル**: このワークフローをトリガーするためにレコードは必要ありません。 ワークフローは(任意のオブジェクトから)任意のコマンドメニュー`Cmd+K`からトリガーされ、入力として記録を使用しません。
**Single** と **Bulk** の可用性の場合、選択したレコードはワークフローに渡されます。 これは特定のオブジェクトに対して設定されており、ワークフローをトリガーする前に複数のレコードを選択できます。
* **シングル**: ワークフローはレコードが選択されているので、最初から最後まで実行されます。
<Note>
**ソフト上限: 100回/分**。 これを超えると、ワークフローは "Not Started" ステータスのままになり、バックグラウンドジョブによって、または別のワークフローがキューに入ったときに段階的に処理されます。 つまり、単一のトリガーで100件を超えるレコードを選択できますが、実行は遅くなります。
</Note>
* **一括**: ワークフローは一度実行され、レコード全体を入力として提供します。 つまり、このワークフローには [イテレーターアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions#iterator) を含める必要があります。
<Note>
こちらはより高度で、ワークフローの実行回数を最適化したい人に最適です。
</Note>
<img src="/images/user-guide/workflows/manual_trigger.png" style={{width:'100%'}} />
**追加の設定**:
* 対象オブジェクトを選択(シングルと一括の可用性用)
* ワークフロートリガーのコマンドアイコンを選択
* ナビゲーションバープレースメントを設定(固定または未固定)
**アクセス方法**:
* `Cmd+K` メニューで手動ワークフローを見つけて起動
* トップナビゲーションバーのカスタムボタン(設定されている場合)
## 時間ベースのトリガー: スケジュール実行
指定された頻度でワークフローを開始します。
**設定**:
* 時間単位を選択(分、時間、日)
* 高度なスケジュール設定には、値を入力するか、カスタム cron 式を使用します
<Note>
**タイムゾーン**: スケジュールされたワークフローは **UTC** で実行されます。 日次スケジュールの時間を設定する際は、ローカル時間を UTC に変換してください。
</Note>
## 外部トリガー: Webhook
外部サービスからのGETまたはPOSTリクエストを受信するとワークフローを開始します。
<img src="/images/user-guide/workflows/webhook_trigger.png" style={{width:'100%'}} />
**設定**:
* ワークフローは一意の Webhook URL を提供します—これをコピーして、呼び出し先エンドポイントとして外部システムに追加してください。
* POST リクエストの場合、Twenty が想定するデータを認識できるよう、期待されるボディ構造を定義してください。 ここに、ワークフロー内の後続の処理で必要となる、受信するフィールドを追加してください。
* 認証の設定(近日対応)。
## 適切なトリガーの選び方
| ユースケース | 推奨トリガー |
| --------------- | ------------------- |
| 新規リードの処理が必要 | レコードの作成 |
| データ変更の同期が必要 | レコードの更新 |
| インポート/手動でのデータ処理 | レコードの更新または作成 |
| 削除後のクリーンアップ | レコードの削除 |
| ユーザー起点のアクション | 手動で起動 |
| 定期レポート | スケジュールで |
| 外部統合 | Webhook またはスケジュール実行 |

View File

@@ -0,0 +1,84 @@
---
title: ワークフローバージョン
description: ワークフローのバージョンとドラフトを管理します。
---
## バージョンについて
ワークフローを有効化するたびに、新しいバージョンが作成されます。 これにより、経時的な変更を追跡し、必要に応じて以前の設定に戻すことができます。
## バージョンの状態
| ステータス | 説明 |
| ----------- | ------------------- |
| **ドラフト** | 編集中、まだ公開されていない |
| **アクティブ** | トリガーに応答する稼働中のバージョン |
| **無効化済み** | 以前はアクティブだったが手動で停止 |
| **アーカイブ済み** | 履歴のために保存された過去のバージョン |
## ドラフトの操作
アクティブなワークフローを編集すると、変更は**ドラフト**として保存されます。 更新作業中も、アクティブなバージョンは引き続き稼働します。
編集が完了したら、次のいずれかを実行できます。
* **有効化**: ドラフトを新しいアクティブ版として公開します(以前のバージョンはアーカイブされます)
* **破棄**: ドラフトを削除し、現在のアクティブ版を維持します
## バージョン履歴
### 過去のバージョンを表示
1. ワークフローを開く
2. **バージョン** タブをクリック
3. タイムスタンプ付きですべての過去バージョンを確認
### バージョンの復元
1. 復元したいバージョンを見つける
2. 「**ドラフトとして使用**」をクリック
3. そのバージョンが新しいドラフトにコピーされます
4. 必要な更新を行う
5. 準備ができたら有効化する
## ベストプラクティス
### バージョン管理
* 本番運用の準備が整ってからのみ有効化する
* バージョン間の変更は意味のあるものに限定する
* ワークフロー名や説明の大きな変更は記録する
* 有効化する前にドラフトモードでテストする
### 変更のロールバック
* 新しいバージョンで問題が発生した場合は、前のバージョンを復元する
* バージョン履歴を使用して何が変わったかを追跡する
* 復元したバージョンは、有効化前に必ずテストする
## 一般的なワークフロー
### クイック編集
1. アクティブなワークフローに軽微な変更を加える
2. ドラフトモードでテストする
3. 新しいバージョンを有効化する
### 大幅な修正
1. 前のバージョンを出発点として使用する
2. ドラフトで大きな変更を加える
3. あらゆるシナリオを徹底的にテストする
4. 確信が持てたら有効化する
### ロールバック
1. 現在のバージョンの問題を特定する
2. 履歴から最後に正常に動作していたバージョンを見つける
3. 「**ドラフトとして使用**」をクリック
4. 有効化して以前の挙動を復元する
## 関連項目
* [ワークフロー入門](/l/ja/user-guide/workflows/overview)
* [ワークフローの実行](/l/ja/user-guide/workflows/capabilities/workflow-runs)

View File

@@ -0,0 +1,82 @@
---
title: Code アクションで配列を扱う
description: ワークフローの Code アクションで配列入力を適切に扱う方法を学びましょう。
---
Code アクションで配列を扱う際、次の2つの一般的な課題に直面することがあります:
1. **文字列として渡される配列** — 外部システムや前のステップからのデータが、本来の配列ではなく文字列として届く
2. **個々の項目を選べない** — 配列全体しか選択できず、その中の特定フィールドを選べない
どちらも Code ノードで解決できます。
## 文字列から配列をパースする
配列は、ネイティブな配列ではなく、文字列や JSON としてワークフローの各ステップ間で受け渡されることがよくあります。 これは次のような場合に発生します:
* HTTP Request で外部 API からデータを受け取る場合
* Webhook ペイロードを処理する場合
* ワークフローのステップ間でデータを受け渡す場合
**解決策**: Code アクションの先頭に次のパターンを追加します:
```javascript
export const main = async (params: {
users: any;
}): Promise<object> => {
const { users } = params;
// Handle input that may come as a string or an array
const usersFormatted = typeof users === "string" ? JSON.parse(users) : users;
// Now you can safely work with usersFormatted as an array
return {
users: usersFormatted.map((user) => ({
...user,
activityStatus: String(user.activityStatus).toUpperCase(),
})),
};
};
```
重要な行は `typeof users === "string" ? JSON.parse(users) : users` は、入力が文字列かどうかを判定し、必要であればパースし、すでに配列であればそのまま使用します。
## 配列から個別のフィールドを取り出す
Webhook が `answers: [...]` のような配列を返すことがありますが、その後のワークフローのステップでは、**配列全体** — その中の個別の項目は選択できません。
**解決策**: 特定のフィールドを抽出して構造化オブジェクトとして返す Code ノードを追加します:
```javascript
export const main = async (params: {
answers: any;
}): Promise<object> => {
const { answers } = params;
// Handle input that may come as a string or an array
const answersFormatted = typeof answers === "string"
? JSON.parse(answers)
: answers;
// Extract specific fields from the array
const firstname = answersFormatted[0]?.text || "";
const name = answersFormatted[1]?.text || "";
return {
answer: {
firstname,
name
}
};
};
```
この Code ノードは、配列ではなく構造化オブジェクトを返します。 以降のステップでは、変数ピッカーから `answer.firstname` や `answer.name` のような個別フィールドを選択できるようになります。
<Tip>
**配列からフィールドを取り出す代わりに、配列自体をループ処理したいですか?** Code ステップまたは Logic Function ステップがトップレベルの配列を返す場合は、それをそのまま [Iterator](/l/ja/user-guide/workflows/capabilities/use-iterator) に渡せます。Iterator の入力としてそのステップの **Whole list** オプションを選択し、ループ内では `{{iterator.currentItem}}` を使って各要素を参照します。 その場合、配列をオブジェクトに再構成する必要はありません。
</Tip>
<Tip>
コードエディタ右上の四角いアイコンをクリックすると全画面表示になります — デフォルトのエディタ幅には制限があるため便利です。
</Tip>

View File

@@ -0,0 +1,182 @@
---
title: 製品データを Twenty に取り込む
description: データウェアハウスの製品カタログデータをスケジュールに基づいてCRMに同期します。
---
このパターンを使用して、データウェアハウス(例: Snowflake、BigQuery、PostgreSQL)の製品データとTwentyの同期を維持します。
## ワークフローの構成
1. **トリガー**: スケジュール実行
2. **Code**: データウェアハウスをクエリする
3. **Code**(任意):データを配列として整形
4. **Iterator**: 各製品をループ処理する
5. **Upsert Record**: Twentyで作成または更新
<img src="/images/user-guide/workflows/create_users_workflow.png" style={{width:'100%'}} />
## ステップ 1: トリガーをスケジュールする
データの鮮度要件に合わせた頻度でワークフローを実行するよう設定します:
* ほぼリアルタイム同期用に5分ごと
* 重要度の低いデータには1時間ごと
* バッチ更新には毎日
## ステップ 2: データウェアハウスをクエリする
直近のデータを取得するために「**Code**」アクションを追加します:
```javascript
export const main = async () => {
const intervalMinutes = 10; // Match your schedule frequency
const cutoffTime = new Date(Date.now() - intervalMinutes * 60 * 1000).toISOString();
// Replace with your actual data warehouse connection
const response = await fetch("https://your-warehouse-api.com/query", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
query: `
SELECT id, name, sku, price, stock_quantity, updated_at
FROM products
WHERE updated_at >= '${cutoffTime}'
`
})
});
const data = await response.json();
return { products: data.results };
};
```
<Tip>
`updated_at >= last X minutes` でフィルタリングして、最近変更されたレコードのみを取得します。 これにより同期が効率的になります。
</Tip>
## ステップ 3: データを整形(任意)
ウェアハウスが変換を要する形式でデータを返す場合は、別の「**Code**」アクションを追加します。 一般的な変換には、型変換、フィールド名の変更、データのクリーンアップなどがあります。
### 例: 真偽値およびステータスフィールドを含むユーザーデータ
```javascript
export const main = async (params: {
users: any;
}): Promise<object> => {
const { users } = params;
const usersFormatted = typeof users === "string" ? JSON.parse(users) : users;
// Convert string "true"/"false" to actual booleans
const toBool = (v: any) => v === true || v === "true";
return {
users: usersFormatted.map((user) => ({
...user,
activityStatus: String(user.activityStatus).toUpperCase(),
isActiveLast30d: toBool(user.isActiveLast30d),
isActiveLast7d: toBool(user.isActiveLast7d),
isActiveLast24h: toBool(user.isActiveLast24h),
isTwenty: toBool(user.isTwenty),
})),
};
};
```
### 例: 型変換を含む製品データ
```javascript
export const main = async (params: { products: any }) => {
const products = typeof params.products === "string"
? JSON.parse(params.products)
: params.products;
return {
products: products.map(product => ({
externalId: product.id,
name: product.name,
sku: product.sku,
price: parseFloat(product.price), // String → Number
stockQuantity: parseInt(product.stock_quantity),
isActive: product.status === "active" // String → Boolean
}))
};
};
```
### 例: 日付および通貨の整形
```javascript
export const main = async (params: { deals: any }) => {
const deals = typeof params.deals === "string"
? JSON.parse(params.deals)
: params.deals;
return {
deals: deals.map(deal => ({
...deal,
// Convert Unix timestamp to ISO date
closedAt: deal.closed_timestamp
? new Date(deal.closed_timestamp * 1000).toISOString()
: null,
// Ensure amount is a number (remove currency symbols)
amount: parseFloat(String(deal.amount).replace(/[^0-9.-]/g, "")),
// Normalize stage names
stage: deal.stage?.toLowerCase().replace(/_/g, " ")
}))
};
};
```
### 一般的な変換
| ソース形式 | ターゲット形式 | コード |
| -------------------- | ---------------- | ---------------------------------------- |
| `"true"` / `"false"` | `true` / `false` | `v === true \|\| v === "true"` |
| `"123.45"` | `123.45` | `parseFloat(value)` |
| `"active"` | `"ACTIVE"` | `value.toUpperCase()` |
| `1704067200` (Unix) | ISO 日付 | `new Date(v * 1000).toISOString()` |
| `"$1,234.56"` | `1234.56` | `parseFloat(v.replace(/[^0-9.-]/g, ""))` |
| `null` / `undefined` | `""` | `value \|\| ""` |
## ステップ 4: 製品をループ処理する
「**Iterator**」アクションを追加します:
* 入力: `{{code.products}}`
配列内の各製品をループ処理します。
## ステップ 5: 各レコードをアップサートする
Iterator 内で「**Upsert Record**」アクションを追加します:
| 設定 | 値 |
| ---------- | ------------------------- |
| **オブジェクト** | カスタムの Product オブジェクト |
| **一致条件** | 外部IDまたはSKU(一意の識別子) |
| **名前** | `{{iterator.item.name}}` |
| **SKU** | `{{iterator.item.sku}}` |
| **価格** | `{{iterator.item.price}}` |
<Tip>
作成と更新で分岐を作る代わりに、**Upsert**(更新または作成)を使用します。 その方が構築が速く、デバッグも容易です。
</Tip>
## ユースケース例
| ソース | データ |
| ----------------- | ------------------- |
| **ERP システム** | 製品カタログ、価格設定、在庫 |
| **Eコマースプラットフォーム** | 受注、顧客、製品更新 |
| **データウェアハウス** | 集計メトリクス、エンリッチされたデータ |
| **在庫管理システム** | 在庫水準、再発注アラート |
## 関連
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [Code アクションで配列を扱う](/l/ja/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,130 @@
---
title: Typeform の回答を Twenty に取り込む
description: Typeform の webhook ペイロードを処理して、フォームの回答からリードを作成します。
---
標準的な webhook 設定については、[Webhook トリガーを設定](/l/ja/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger)を参照してください。 本記事では、Typeform のカスタムペイロード構造に必要となる特有の処理について説明します。
### ステップ 1: Webhook ワークフローを作成
1. 「**Settings → Workflows**」に移動
2. 「**+ New Workflow**」をクリック
3. トリガーとして「**Webhook**」を選択します
4. webhook URL をコピーします
### ステップ 2: Typeform を設定
1. Typeform でフォームを開く
2. 「**Connect → Webhooks**」に移動
3. Twenty の webhook URL を貼り付けます
4. 保存
### ステップ 3: Typeform のペイロードを理解する
Typeform は入れ子の JSON 構造を送信します。 簡略化した例はこちら:
```json
{
"event_type": "form_response",
"form_response": {
"form_id": "abc123",
"submitted_at": "2025-01-15T10:30:00Z",
"answers": [
{
"text": "Jane",
"type": "text",
"field": { "id": "field1", "type": "short_text", "title": "First Name" }
},
{
"text": "Smith",
"type": "text",
"field": { "id": "field2", "type": "short_text", "title": "Last Name" }
},
{
"text": "Acme Corp",
"type": "text",
"field": { "id": "field3", "type": "short_text", "title": "Company" }
},
{
"email": "jane@acme.com",
"type": "email",
"field": { "id": "field4", "type": "email", "title": "Email" }
},
{
"type": "choice",
"field": { "id": "field5", "type": "dropdown", "title": "Team Size" },
"choice": { "label": "10-50" }
}
]
}
}
```
重要なポイント:
* フォームデータは `form_response` の下に入れ子になっています
* **回答は配列として返され**、名前付きフィールドではありません
* 各回答には参照用にフィールドの種類とタイトルが含まれます
### ステップ 4: answers 配列からフィールドを抽出する
`answers` は配列のため、後続ステップでは配列全体しか選択できず、個別のフィールドは選択できません。 必要なフィールドを抽出するために「**Code**」アクションを追加します:
```javascript
export const main = async (params: {
answers: any;
}): Promise<object> => {
const { answers } = params;
// Handle input that may come as a string or an array
const answersFormatted = typeof answers === "string"
? JSON.parse(answers)
: answers;
// Extract fields by position or by finding the field type
const firstName = answersFormatted[0]?.text || "";
const lastName = answersFormatted[1]?.text || "";
const company = answersFormatted[2]?.text || "";
const email = answersFormatted.find(a => a.type === "email")?.email || "";
const teamSize = answersFormatted.find(a => a.type === "choice")?.choice?.label || "";
return {
contact: {
firstName,
lastName,
company,
email,
teamSize
}
};
};
```
以降のステップでは、変数ピッカーから `contact.firstName` や `contact.email` のような個別フィールドを選択できるようになります。
<Tip>
配列の扱いの詳細については、[Code アクションで配列を扱う](/l/ja/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)を参照してください。
</Tip>
### ステップ 5: レコードを作成
「**Create Record**」アクションを追加します:
| フィールド | 値 |
| ---------- | --------------------------------------- |
| **オブジェクト** | 人物 |
| **名** | `{{code.contact.firstName}}` |
| **姓** | `{{code.contact.lastName}}` |
| **メール** | `{{code.contact.email}}` |
| **会社** | `{{code.contact.company}}` に基づいて検索または作成 |
### ステップ 6: テストして有効化
1. Typeform でテスト回答を送信
2. ワークフローの実行を確認し、データが取り込まれたことを検証
3. ワークフローを有効化します
## 関連
* [Webhook トリガーを設定](/l/ja/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger)
* [Code アクションで配列を扱う](/l/ja/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,263 @@
---
title: Twenty から PDF を生成する
description: PDF(見積書など)を生成してレコードに添付するワークフローを作成します。
---
Twenty で PDF を自動生成または取得し、レコードに添付します。 これは、会社、商談、またはその他のオブジェクトに関連付けられた見積書、請求書、レポートを作成する用途で一般的に使用されます。
## 概要
このワークフローでは **手動トリガー** を使用し、選択した任意のレコードに対してオンデマンドで PDF を生成できるようにします。 次を **ロジック関数** が処理します:
1. URL(PDF 生成サービスから)から PDF をダウンロードする
2. ファイルを Twenty にアップロードする
3. レコードに関連付けられた添付ファイルを作成する
## 前提条件
ワークフローを設定する前に:
1. **API キーを作成**: **Settings → APIs** に移動して新しい API キーを作成します。 ロジック関数にはこのトークンが必要です。
2. **PDF 生成サービスを設定**(任意):PDF を動的に生成したい場合(例: 見積書)は、Carbone、PDFMonkey、DocuSeal のようなサービスを使用して PDF を作成し、ダウンロード URL を取得します。
## ステップバイステップの設定
### ステップ 1: トリガーを設定
1. **Workflows** に移動し、新しいワークフローを作成します
2. **手動トリガー** を選択します
3. PDF を添付したい対象オブジェクト(例: **Company** や **Opportunity**)を選択します
<Tip>
手動トリガー付き ユーザーは、レコードが選択されると右上に表示されるボタンを使用してこのワークフローを実行できます — これは、PDFを生成して添付するためのワークフローを実行します。
</Tip>
### ステップ 2: ロジック関数を追加する
1. **コード** アクション (Logic Function) を追加します
2. 以下のコードで新しい関数を作成します
3. 入力パラメーターを設定します
#### 入力パラメーター
| パラメーター | 値 |
| ----------- | ----------------------- |
| `companyId` | `{{trigger.object.id}}` |
<Note>
別のオブジェクト(Person、Opportunity など)に添付する場合は、適切にパラメーター名を変更(例: `personId`、`opportunityId`)し、ロジック関数を更新します。
</Note>
#### ロジック関数のコード
```typescript
export const main = async (
params: { companyId: string },
) => {
const { companyId } = params;
// Replace with your Twenty GraphQL endpoints (/metadata for metadata and files or /graphql for your records)
// Cloud: https://api.twenty.com/graphql
// Self-hosted: https://your-domain.com/graphql
const metadataGraphqlEndpoint = 'https://api.twenty.com/metadata';
const dataGraphqlEndpoint = 'https://api.twenty.com/graphql';
// Replace with your API key from Settings → APIs
const authToken = 'YOUR_API_KEY';
// Replace with your PDF URL
// This could be from a PDF generation service or a static URL
const pdfUrl = 'https://your-pdf-service.com/generated-quote.pdf';
const filename = 'quote.pdf';
// Step 1: Download the PDF file
const pdfResponse = await fetch(pdfUrl);
if (!pdfResponse.ok) {
throw new Error(`Failed to download PDF: ${pdfResponse.status}`);
}
const pdfBlob = await pdfResponse.blob();
const pdfFile = new File([pdfBlob], filename, { type: 'application/pdf' });
const fieldMetadataIdQuery = `
query FindUploadFileFieldMetadataId {
objects {
edges {
node {
nameSingular
fieldsList {
id
name
}
}
}
}
}
`;
// Step 2: Find a fieldMetadataId of "Attachment file" field in Attachments object with GraphQL API
const response = await fetch(metadataGraphqlEndpoint, {
method: 'POST',
headers: {
Authorization: `Bearer ${authToken}`
},
body: {
query: fieldMetadataIdQuery,
}
});
const result = await response.json();
const uploadFileFieldMetadataId = result.data.objects.edges.find(object => object.node.nameSingular === 'attachment').node.fieldsList.find(field => field.name === 'file').id;
// Step 3: Upload the file via GraphQL multipart upload
const uploadMutation = `
mutation UploadFilesFieldFile($file: Upload!, $fieldMetadataId: String!) {
uploadFilesFieldFile(file: $file, fieldMetadataId: $fieldMetadataId) {
id
}
}
`;
const uploadForm = new FormData();
uploadForm.append('operations', JSON.stringify({
query: uploadMutation,
variables: { file: null, fieldMetadataId: uploadFileFieldMetadataId },
}));
uploadForm.append('map', JSON.stringify({ '0': ['variables.file'] }));
uploadForm.append('0', pdfFile);
const uploadResponse = await fetch(metadataGraphqlEndpoint, {
method: 'POST',
headers: { Authorization: `Bearer ${authToken}` },
body: uploadForm,
});
const uploadResult = await uploadResponse.json();
if (uploadResult.errors?.length) {
throw new Error(`Upload failed: ${uploadResult.errors[0].message}`);
}
const fileId = uploadResult.data?.uploadFilesFieldFile?.id;
if (!fileId) {
throw new Error('No file id returned from upload');
}
// Step 4: Create the attachment linked to the company
const attachmentMutation = `
mutation CreateOneAttachment($data: AttachmentCreateInput!) {
createAttachment(data: $data) {
id
name
}
}
`;
const attachmentResponse = await fetch(dataGraphqlEndpoint, {
method: 'POST',
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: attachmentMutation,
variables: {
data: {
name: filename,
targetCompanyId: companyId,
file: [
{
fileId: fileId,
label: filename
}
]
},
},
}),
});
const attachmentResult = await attachmentResponse.json();
if (attachmentResult.errors?.length) {
throw new Error(`Attachment creation failed: ${attachmentResult.errors[0].message}`);
}
return attachmentResult.data?.createAttachment;
};
```
### ステップ 3: ユースケースに合わせてカスタマイズする
#### 別のオブジェクトに添付する場合
`targetCompanyId` を適切なフィールドに置き換えます:
| オブジェクト | フィールド名 |
| ---------- | -------------------------- |
| 会社 | `targetCompanyId` |
| 人物 | `targetPersonId` |
| 商談 | `targetOpportunityId` |
| カスタムオブジェクト | `targetYourCustomObjectId` |
関数のパラメーターと、添付のミューテーション内の `variables.data` オブジェクトの両方を更新します。
#### 動的な PDF URL を使用する場合
PDF 生成サービスを使用する場合、次のことができます:
1. まず HTTP Request アクションで PDF を生成します
2. 返された PDF URL をパラメーターとしてロジック関数に渡します
```typescript
export const main = async (
params: { companyId: string; pdfUrl: string; filename: string },
) => {
const { companyId, pdfUrl, filename } = params;
// ... rest of the function
};
```
### ステップ 4: テストして有効化
1. ワークフローを保存します
2. Company のレコードに移動します
3. **⋮** メニューをクリックし、ワークフローを選択します
4. レコードの **Attachments** セクションを確認し、PDF が添付されたことを確認します
5. ワークフローを有効化します
## PDF 生成サービスとの連携
動的な見積書や請求書を作成する場合:
### 例: 見積書を生成 → PDF を添付
| 手順 | アクション | 目的 |
| -- | --------------- | ---------------------------- |
| 1 | 手動トリガー(Company) | ユーザーがレコード上で実行を開始 |
| 2 | レコード検索 | Opportunity または明細行の詳細を取得 |
| 3 | HTTPリクエスト | レコードデータを用いて PDF 生成 API を呼び出す |
| 4 | ロジック関数 | 生成された PDF をダウンロードして添付 |
### 一般的な PDF 生成サービス
* **Carbone** - テンプレートベースのドキュメント生成
* **PDFMonkey** - テンプレートからの動的な PDF 作成
* **DocuSeal** - ドキュメント自動化プラットフォーム
* **Documint** - API ファーストのドキュメント生成
各サービスは、PDF URLを返すAPIを提供し、ロジック関数に渡すことができます。
## トラブルシューティング
| 問題 | 解決策 |
| -------------------- | ----------------------------------------- |
| "PDF のダウンロードに失敗しました" | PDF URL にアクセスでき、有効な PDF が返されることを確認します |
| "アップロードに失敗しました" | API キーが有効で、書き込み権限があることを確認します |
| "添付ファイルの作成に失敗しました" | オブジェクト ID のフィールド名が対象オブジェクトに一致していることを確認します |
## 関連
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ロジック関数](/l/ja/user-guide/workflows/capabilities/workflow-actions#code)
* [Twenty から見積書または請求書を生成する](/l/ja/user-guide/workflows/how-tos/connect-to-other-tools/generate-quote-or-invoice-from-twenty)

View File

@@ -0,0 +1,144 @@
---
title: Twenty から見積書または請求書を作成
description: 商談がクローズしたときに、外部ツールで請求書を自動作成します。
---
商談データを請求書発行システム (Stripe、QuickBooks、Xero など) に自動送信します。 商談が受注になったときに。
## ワークフローの構成
1. **トリガー**: レコードが更新 (商談オブジェクト)
2. **フィルター**: ステージ = Closed Won
3. **レコード検索**: 会社の詳細を取得
4. **コード** (任意): ペイロードを整形
5. **HTTP リクエスト**: 請求書発行システムに送信
## ステップ 1: トリガーを設定
1. 新しいワークフローを作成
2. **Record is Updated** トリガーを選択
3. オブジェクトとして **Opportunity** を選択
## ステップ 2: Closed Won でフィルター
商談が受注になったときのみ続行するように、**フィルター** アクションを追加:
| 設定 | 値 |
| --------- | --------------------------- |
| **フィールド** | ステージ |
| **条件** | 等しい |
| **値** | `CLOSED_WON` (またはあなたのステージ名) |
<Tip>
このトリガーは、商談の更新があるたびに発火します。 このフィルターにより、ステージが Closed Won に変わった場合にのみワークフローが続行されます。
</Tip>
## ステップ 3: 会社の詳細を取得
商談レコードには、請求書に必要なすべての会社フィールドが含まれていない可能性があります。 **レコード検索** アクションを追加:
| 設定 | 値 |
| ---------- | ---------------------------------------- |
| **オブジェクト** | 会社 |
| **一致条件** | ID が `{{trigger.object.companyId}}` に等しい |
これにより、請求先住所、税番号などを含む会社の完全なレコードを取得します。
## ステップ 4: ペイロードを整形 (任意)
請求書発行システムが特定のフォーマットを想定している場合は、**コード** アクションを追加:
```javascript
export const main = async (params: {
opportunity: any;
company: any;
}): Promise<object> => {
const { opportunity, company } = params;
return {
invoice: {
// Customer info from Company
customer_name: company.name,
customer_email: company.email || "",
billing_address: {
line1: company.address?.street || "",
city: company.address?.city || "",
postal_code: company.address?.postalCode || "",
country: company.address?.country || ""
},
tax_id: company.taxId || null,
// Invoice details from Opportunity
amount: opportunity.amount,
currency: opportunity.currency || "USD",
description: `Invoice for ${opportunity.name}`,
due_days: 30,
// Reference back to Twenty
metadata: {
opportunity_id: opportunity.id,
company_id: company.id
}
}
};
};
```
## ステップ 5: 請求書発行システムに送信
**HTTP リクエスト** アクションを追加:
| 設定 | 値 |
| -------- | ------------------------------------ |
| **メソッド** | POST |
| **URL** | 請求書発行 API のエンドポイント |
| **ヘッダー** | `Authorization: Bearer YOUR_API_KEY` |
| **本文** | `{{code.invoice}}` またはフィールドを直接マッピング |
### 例: Stripe の請求書
```
POST https://api.stripe.com/v1/invoices
Headers:
Authorization: Bearer sk_live_xxx
Content-Type: application/x-www-form-urlencoded
Body:
customer: {{company.stripeCustomerId}}
collection_method: send_invoice
days_until_due: 30
```
### 例: QuickBooks の請求書
```
POST https://quickbooks.api.intuit.com/v3/company/{realmId}/invoice
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body: {{code.invoice}}
```
## ワークフロー全体の概要
| 手順 | アクション | 目的 |
| -- | -------------------- | ------------------------ |
| 1 | トリガー: Record Updated | 任意の商談が変更されたときに発火 |
| 2 | フィルター | ステージが Closed Won の場合のみ続行 |
| 3 | レコード検索 | 請求用の会社詳細を取得 |
| 4 | コード | 請求書発行 API 向けにデータを整形 |
| 5 | HTTPリクエスト | 外部システムで請求書を作成 |
## ヒント
* **外部 ID を保存**: **Update Record** アクションを使用して、API から返された請求書 ID を商談に保存
* **エラー処理**: HTTP リクエストが失敗した場合に通知を送信する分岐を追加
* **まずテスト**: 本番運用前に、請求書発行システムのサンドボックス/テストモードを使用
## 関連
* [Twenty から PDF を生成する](/l/ja/user-guide/workflows/how-tos/connect-to-other-tools/generate-pdf-from-twenty) — 生成された PDF をレコードに添付する
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [Closed Won の自動化](/l/ja/user-guide/workflows/how-tos/crm-automations/closed-won-automations)

View File

@@ -0,0 +1,170 @@
---
title: Webhook トリガーの設定
description: 外部サービスからデータを受け取り、ワークフローをトリガーします。
---
Webhook トリガーは、一意の URL にデータを送信することで外部サービスがあなたのワークフローを開始できるようにします。 フォーム、サードパーティアプリ、カスタム統合に接続するために使用します。
## Webhook を使用するタイミング
| ユースケース | 例 |
| -------------- | ----------------------- |
| **Web フォーム** | お問い合わせフォームの送信でリードを作成 |
| **サードパーティアプリ** | Stripe の支払い → 顧客レコードを作成 |
| **カスタム統合** | 自社アプリ → Twenty の自動化 |
| **ノーコードツール** | Zapier、Make、n8n との連携 |
## ステップバイステップの設定
### ステップ 1: ワークフローを作成
1. 「**Settings → Workflows**」に移動
2. 「**+ New Workflow**」をクリック
3. 名前を付ける(例: "Website Form Submission")
### ステップ 2: Webhook トリガーを設定
1. トリガーブロックをクリック
2. 「**Webhook**」を選択
3. 次のような一意の Webhook URL が発行されます:
```
https://api.twenty.com/webhooks/workflow/abc123...
```
4. この URL をコピーします—外部サービスで使用します
### ステップ 3: 想定されるデータ構造を定義
**POST** リクエストの場合、想定されるボディ構造を定義します:
1. 「**Define expected body**」をクリック
2. サービスが送信する内容に一致するサンプル JSON を入力します:
```json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"company": "Acme Inc",
"message": "Interested in your product"
}
```
3. 「**Save**」をクリック—これにより、後続のステップで使用できる変数が作成されます
### ステップ 4: アクションを追加
Webhook データを使用するアクションを追加します:
**例: Person レコードを作成**
1. 「**Create Record**」アクションを追加
2. 「**People**」オブジェクトを選択
3. フィールドをマッピング:
| フィールド | 値 |
| ----- | --------------------------------------- |
| 名 | `{{trigger.body.firstName}}` |
| 姓 | `{{trigger.body.lastName}}` |
| メール | `{{trigger.body.email}}` |
| 会社 | `{{trigger.body.company}}` に基づいて検索または作成 |
### ステップ 5: Webhook をテスト
有効化する前に、Webhook をテストします:
**cURL を使用**:
```bash
curl -X POST https://api.twenty.com/webhooks/workflow/abc123... \
-H "Content-Type: application/json" \
-d '{"firstName":"Test","lastName":"User","email":"test@example.com"}'
```
**Postman などを使用**:
1. Webhook URL に対して POST リクエストを作成
2. Content-Type ヘッダーを `application/json` に設定
3. テスト用の JSON ボディを追加
4. 送信してワークフローの実行を確認
### ステップ 6: 有効化
テストが完了したら、ワークフローを稼働させるために「**Activate**」をクリックします。
## さまざまなデータ構造の扱い
### ネストされたデータ
Webhook がネストされたデータを送信する場合:
```json
{
"contact": {
"name": "John Doe",
"email": "john@example.com"
},
"source": "website"
}
```
次のように参照します: `{{trigger.body.contact.email}}`
### 配列
データに配列が含まれる場合:
```json
{
"items": [
{"name": "Product A", "qty": 2},
{"name": "Product B", "qty": 1}
]
}
```
配列の扱い方はユースケースによって異なります:
**項目数が不明 → Iterator を使用**
配列内の各項目を処理する必要がある場合(例: 各項目ごとにレコードを作成)、配列を解析するために **Code** アクションを追加し、その後 **Iterator** を使用します:
```javascript
export const main = async (params: { items: any }) => {
const items = typeof params.items === "string"
? JSON.parse(params.items)
: params.items;
return { items };
};
```
次に Iterator を使用してループ処理します: `{{code.items}}`
**既知/特定のフィールド → 名前付きフィールドとして抽出**
配列に個別にアクセスしたい特定のフィールドが含まれている場合(例: フォーム回答で位置 0 が常に "first name"、位置 1 が常に "last name" のようなケース)、それらを抽出するために **Code** アクションを追加します:
```javascript
export const main = async (params: { items: any }) => {
const items = typeof params.items === "string"
? JSON.parse(params.items)
: params.items;
return {
product: {
name: items[0]?.name || "",
qty: items[0]?.qty || 0
}
};
};
```
これで、後続のステップで `product.name` と `product.qty` を個別に選択できます。
<Tip>
配列の扱いの詳細については、[Code アクションで配列を扱う](/l/ja/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)を参照してください。
</Tip>
## 関連
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,121 @@
---
title: 受信メールへの自動返信
description: AI を使用して受信メールをトリアージし、スレッド返信を自動的に送信するワークフローを構築します。
---
受信メールに数秒で対応 — 数時間ではなく。 このワークフローは、AI Agent を使用してノイズ(ニュースレター、スパム、自動返信)を除去し、実際のメッセージに対するパーソナライズされた応答をドラフトします。 そして、元の会話の中でスレッド返信として送信します。
## メールスレッドの仕組み
すべてのメールには、送信者のメールサーバーによって割り当てられる一意の識別子である非表示の `Message-ID` ヘッダーが含まれています。 メールに返信すると、メールクライアントはフィンガープリントを参照する `In-Reply-To` ヘッダーを設定します。 Gmail、Outlook、その他すべてのクライアントはメッセージをスレッドにまとめています。
Twenty では、そのフィンガープリントは Message オブジェクトに `headerMessageId` として保存されます。 ワークフローはそれをつかみ、返信メール送信アクションのIn-Reply-To 項目に渡します。
## ワークフローの構築
### ステップ 1: 新しいワークフローを作成
**設定->ワークフロー**に進み\*\*+新しいワークフロー\*\*をクリックしてください。
### ステップ2:受信メッセージをトリガーする
**レコードが作成されたら** **メッセージ**を選択します。
メールがTwentyに届くたびに、これは火事になります。
<img src="/images/user-guide/workflows/auto-reply/workflow-overview.png" style={{width:'100%'}} />
### ステップ 3: 送金者を調べてください
**レコードを検索**アクションを追加します。
送信者のアドレスはメッセージ自体にありません — 関連するメッセージ参加者レコードにあります。
| フィールド | 値 |
| ---------- | ----------------------------- |
| **オブジェクト** | メッセージ参加者 |
| **フィルター** | メッセージ **です** `{{trigger.id}}` |
| **フィルター** | ロールは **以下から** |
| **制限** | 1 |
これにより、`handle` で送信者のメールアドレスと、`displayName` で送信者の名前が表示されます。
<img src="/images/user-guide/workflows/auto-reply/find-sender.png" style={{width:'100%'}} />
### ステップ 4: トリアージしてAIとの返信をドラフトする
**AI エージェント** アクションを追加します。 この単一のステップは、2つのことを行います: 電子メールに返信が値するかどうかを決定し、その場合は1つを書き込みます。
次のようなプロンプトを使用します。
```
You are an email triage assistant for a sales team. Read the following
inbound email and decide if it deserves a reply.
Subject: {{trigger.subject}}
Body: {{trigger.text}}
From: {{Find Sender.first.displayName}} ({{Find Sender.first.handle}})
If this email is spam, a newsletter, an automated notification, or
otherwise does not need a human reply, respond with exactly: SKIP
Otherwise, write a short, professional reply (3-4 sentences max) that:
- Acknowledges their specific message
- Lets them know someone from the team will follow up shortly
- Is warm but not overly casual
Respond with only the reply text, no subject line or greeting prefix.
```
AI Agent は、次のステップが参照できるレスポンスを `response` フィールドに出力します。
<img src="/images/user-guide/workflows/auto-reply/ai-triage.png" style={{width:'100%'}} />
### ステップ5:AIの決定に支局
**If/Else**アクションを追加して、AIが返信するかスキップするかを確認します。
| フィールド | 値 |
| ----------- | ------------------------------------ |
| **条件** | AI Agent の`response` **`SKIP`を含まない** |
| **If true** | メール送信を続ける |
| **それ以外** | 何もしない (ワークフロー終了) |
スパム、ニュースレター、自動生成されたメッセージは削除されます。 他のすべてが次のステップに移動します。
<img src="/images/user-guide/workflows/auto-reply/should-reply.png" style={{width:'100%'}} />
### ステップ 6: スレッド返信を送信
"if true" ブランチに **メール送信** アクションを追加します。 **詳細オプション**をクリックし、**返信内に追加**をクリックします。
| フィールド | 値 |
| --------------- | -------------------------------------- |
| **宛先** | `{{Find Sender.first.handle}}` |
| **件名** | `Re: {{trigger.subject}}` |
| **本文** | `{{AI Triage & Draft Reply.response}}` |
| **In-Reply-To** | `{{trigger.headerMessageId}}` |
In-Reply-To フィールドは、新しい会話ではなく返信になります。 受信者は、Gmail、Outlook、または他のクライアントでは、元の電子メールの下でスレッド化されていることを確認します。
<img src="/images/user-guide/workflows/auto-reply/send-email.png" style={{width:'100%'}} />
<Tip>
**In-Reply-To** はトリガーから `message.headerMessageId` を期待します — 受信者のアドレスではなく、メールの固有の指紋です。 空白のままにすると、電子メールは単独のメッセージとして送信されます。
</Tip>
<Warning>
Gmail は件名を使用してメッセージをスレッドにグループ化します。 元のスレッドの中に返信を表示するには、件名が `Re:` (コロンとスペースを含む) で始まる必要があります。 In-Reply-To ヘッダーが正しく設定されている場合でも、返信は別個の会話として表示されます。
</Warning>
### ステップ 7: テストして有効化
**テスト**をクリックし、メールクライアントを確認してください。 返信は元のメッセージの下に入れ子になっているように見えます。
あなたがそれに満足しているときに有効にします。
## 上に構築するアイデア
* **VIPへの返信のみ** — 送信者のドメインを確認するブランチを追加します。
* **意図でルート化** — サポートリクエストとは異なる販売お問い合わせに対応するために、別個の AI Agent プロンプトを使用してください。
* **返信する前にエンリッチする** — 送信者の会社を引っ張ったり、AIプロンプトに履歴を出すために検索レコードのステップを追加し、よりパーソナライズされた返信を求めます。

View File

@@ -0,0 +1,179 @@
---
title: Closed Won の自動化
description: 商談が成約(Closed Won)になったときに、成約後の活動を自動化します。
---
商談がクローズしたら、複数のことを行う必要があります:会社のステータスを更新し、チームメンバーに通知し、オンボーディングタスクを作成します。 これらをひとつのワークフローで自動化します。
## 問題
商談が "Closed Won" に移動したとき:
* 会社タイプを "Prospect" から "Customer" に変更する必要があります
* オンボーディングタスクを作成する必要があります
* カスタマーサクセスチームに通知する必要があります
* 営業担当者への確認が必要です
これを手作業で行うのは時間がかかり、ミスの原因になります。
## 解決策
成約後のすべての作業を自動で処理するワークフローを作成します。
## ワークフローのセットアップを完了
### ステップ 1: ワークフローを作成
1. 「**Settings → Workflows**」に移動
2. 「**+ New Workflow**」をクリック
3. 名前を "Deal Won - Post-Win Automation" にします
### ステップ 2: トリガーを設定
1. 「**Record is Updated**」を選択
2. 「**Opportunities**」を選択
3. "Fields to monitor" で **Stage** を選択
### ステップ 3: ステージフィルターを追加
1. 「**Filter**」アクションを追加
2. 条件: `{{trigger.object.stage}}` が "Closed Won" と等しい
### ステップ 4: 会社タイプを更新
1. 「**Update Record**」アクションを追加
2. 設定:
| フィールド | 値 |
| ------------- | ------------------------------- |
| **オブジェクト** | 会社 |
| **レコード** | `{{trigger.object.company.id}}` |
| **種類** | 顧客 |
| **初回ディール日** | `{{trigger.object.closedAt}}` |
| **アカウントオーナー** | `{{trigger.object.owner.id}}` |
### ステップ 5: オンボーディングタスクを作成
1. 「**Create Record**」アクションを追加
2. 設定:
| フィールド | 値 |
| ---------- | ---------------------------------------------------------------------------------------------------- |
| **オブジェクト** | タスク |
| **タイトル** | `Onboarding: {{trigger.object.name}}` |
| **担当者** | カスタマーサクセスチームのメンバー |
| **期日** | 今から3日後 |
| **優先** | 高 |
| **関連会社** | `{{trigger.object.company.id}}` |
| **関連商談** | `{{trigger.object.id}}` |
| **説明** | `New customer onboarding for {{trigger.object.company.name}}. Deal value: {{trigger.object.amount}}` |
### ステップ 6: カスタマーサクセスに通知
1. 「**Send Email**」アクションを追加
2. 設定:
| フィールド | 値 |
| ------ | -------------------------------------------------- |
| **宛先** | customer-success@yourcompany.com |
| **件名** | `🎉 New Customer: {{trigger.object.company.name}}` |
| **本文** | 下記の例を参照してください |
**メール本文の例**:
```
Hi CS Team,
We have a new customer!
Company: {{trigger.object.company.name}}
Deal: {{trigger.object.name}}
Value: {{trigger.object.amount}}
Sales Rep: {{trigger.object.owner.name}}
Close Date: {{trigger.object.closedAt}}
An onboarding task has been created automatically.
Let's give them a great start!
```
### ステップ 7: 営業担当者に確認を送信
1. さらに「**Send Email**」アクションを追加
2. 設定:
| フィールド | 値 |
| ------ | --------------------------------------------------------------- |
| **宛先** | `{{trigger.object.owner.email}}` |
| **件名** | `✅ Deal Closed: {{trigger.object.name}}` |
| **本文** | おめでとうございます! ディールの処理が完了しました。 カスタマーサクセスチームに通知され、オンボーディングが開始されました。 |
### ステップ 8: テストして有効化
1. テスト用の商談を "Closed Won" に移動してテストします
2. 確認:
* 会社の種別が "Customer" に変更された
* オンボーディングタスクが作成された
* CS チームがメールを受信した
* 営業担当者が確認を受け取った
3. 準備ができたら有効化します
## Closed Lost の処理
失注ディール向けに同様のワークフローを作成します:
### トリガー
* レコードが更新(Opportunities、Stage = "Closed Lost")
### アクション
1. 「**Create Record**」: "Lost Deal Analysis" 用のタスク
2. 「**Update Record**」: 失注理由を会社レコードに追加
3. 「**Send Email**」: 失注の旨をマネージャーに通知
## 高度な設定: 多段階のオンボーディング
複雑なオンボーディングには、複数のタスクを作成します:
```javascript
export const main = async (params) => {
const tasks = [
{ title: "Welcome call", daysFromNow: 1, assignee: "CS" },
{ title: "Send onboarding materials", daysFromNow: 2, assignee: "CS" },
{ title: "Technical setup", daysFromNow: 5, assignee: "Support" },
{ title: "30-day check-in", daysFromNow: 30, assignee: "CS" }
];
return { tasks };
};
```
配列から各タスクを作成するには **Iterator** を使用します。
## カスタマイズのアイデア
### 他のツールも最新状態に保つ
* **HTTP Request** で請求システムに顧客を作成する
### 条件付きアクション
「**Filter**」アクションを使用して次を行います:
* エンタープライズと SMB で異なるオンボーディング
* 地域に基づいて担当者を変える
* 小規模ディールでは通知をスキップ
### 取引の詳細を含める
整形には「**Code**」アクションを使用:
* ディールのサマリードキュメント
* CS チーム向けの引き継ぎメモ
* カスタムのオンボーディングチェックリスト
## 関連
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [ワークフローからメールを送信](/l/ja/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,136 @@
---
title: 停滞した商談を検出
description: 商談が更新されていない場合にマネージャーに自動的に通知します。
---
商談が停滞したときにマネージャーにアラートを送信して、パイプラインの健全性を保ちましょう。 このワークフローは、指定した日数の間更新されていない商談をチェックします。
## 問題
更新されずに放置された商談は次のような事態を招きます:
* 商談が冷え込む
* 予測の信頼性低下
* 収益の損失
## 解決策
停滞した商談を見つけ、マネージャーにメールを送信する定期実行のワークフローを作成します。
## ステップバイステップの設定
### ステップ 1: ワークフローを作成
1. 「**Settings → Workflows**」に移動
2. 「**+ New Workflow**」をクリック
3. 名前を "停滞商談アラート" にします
### ステップ 2: トリガーを設定
1. 「**On a Schedule**」を選択
2. 毎日実行に設定 (例: 毎朝 8 時)
### ステップ 3: 停滞した商談を検索
1. 「**Search Records**」アクションを追加
2. 設定:
| フィールド | 値 |
| ---------- | ----------------------------------------------- |
| **オブジェクト** | 商談 |
| **フィルター** | Updated At が (today - 7 days) より前 |
| **フィルター** | Stage が "Closed Won" ではなく、かつ "Closed Lost" でもない |
| **制限** | 100 |
### ステップ 4: 該当があるか確認
1. 「**Filter**」アクションを追加
2. 条件: `{{searchRecords.length}}` が 0 より大きい
3. 停滞した商談がない場合、ワークフローはここで停止します
### ステップ 5: アラートを整形 (コードアクション)
メールを整形するために「**Code**」アクションを追加します:
```javascript
export const main = async (params) => {
const opportunities = params.opportunities;
// Group opportunities by owner
const byOwner = {};
opportunities.forEach(opp => {
const ownerEmail = opp.owner?.email || 'unassigned';
if (!byOwner[ownerEmail]) {
byOwner[ownerEmail] = [];
}
byOwner[ownerEmail].push({
name: opp.name,
amount: opp.amount,
lastUpdated: opp.updatedAt,
stage: opp.stage
});
});
// Format summary for manager
let summary = "Stale Opportunities Report\n\n";
Object.entries(byOwner).forEach(([owner, opps]) => {
summary += `${owner}: ${opps.length} stale opportunities\n`;
opps.forEach(opp => {
summary += ` - ${opp.name} (${opp.stage})\n`;
});
summary += "\n";
});
return {
summary,
totalCount: opportunities.length
};
};
```
### ステップ 6: アラートメールを送信
「**Send Email**」アクションを追加:
| フィールド | 値 |
| ------ | ------------------------------------ |
| **宛先** | sales-manager@yourcompany.com |
| **件名** | `🚨 要対応の停滞商談が {{code.totalCount}} 件` |
| **本文** | `{{code.summary}}` |
### ステップ 7: テストして有効化
1. ワークフローを実行するには「**Test**」をクリック
2. メールに正しいデータが含まれていることを確認します
3. 準備ができたら有効化します
## カスタマイズオプション
### 停滞のしきい値を変更
「**Search Records**」フィルターを編集し、7 日を希望の期間に変更します:
* 高回転の営業には 3 日
* エンタープライズの商談には 14 日
* 長いセールスサイクルには 30 日
### 個々の担当者にアラート
マネージャー宛ての 1 通のメールではなく、**Iterator** を使用して、各担当者に自分の停滞中の商談についてのパーソナライズされたメールを送信します。
### エスカレーションを追加
深刻度を段階的に上げた複数のワークフローを作成します:
1. 7 日目: 担当者にメール
2. 14 日目: 担当者 + マネージャーにメール
3. 21 日目: マネージャーが介入できるようタスクを作成
### Slack にも通知
メールの代わりに、またはメールに加えて、**HTTP Request** を使用して Slack の Webhook に投稿します。
## 関連
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [ワークフローからメールを送信](/l/ja/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,69 @@
---
title: 受信メール数を表示
description: 各連絡先から受信したメール数を自動的にカウントして表示するワークフローを作成します。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/workflow-number-of-emails-received.png" style={{width:'100%'}} />
## 概要
このワークフローは新しいメールを受信するたびにトリガーされ、その送信者からのメールの合計数で Person レコード上のカスタムフィールドを更新します。
## 前提条件
このワークフローを設定する前に、**People** オブジェクトにカスタムフィールドを作成します:
1. 「**設定 → データモデル → People**」に移動します
2. 新しい **Number** フィールドを追加します
3. 「この人物から受信したメール数」などの名前を付けます
## ステップバイステップの設定
<VimeoEmbed videoId="1148700336" title="デモ動画" />
### ステップ 1: トリガーを設定
1. 「**Workflows**」に移動し、新しいワークフローを作成します
2. トリガーとして **Record is Created** を選択します
3. **Message Participants**(Advanced objects 内にあります)を選択します
<Note>
Message Participant は、メッセージ ID と person ID の組み合わせで、メッセージごとに一意のレコードを作成します。 これは、送信者(または受信者)のメールアドレスを含む `handle` フィールドにアクセスできるため、Messages を直接扱うよりも追跡が容易です。
</Note>
### ステップ 2: Role でフィルター
1. 「**Filter**」アクションを追加します
2. 条件を設定します: **Role** が **FROM** と等しい
これにより、この人物が送信したメッセージのみをカウントし、相手宛てに送られたメッセージは含めないようにします。
### ステップ 3: 同じ Handle を持つすべての Message Participants を検索
1. 「**Search Records**」アクションを追加します
2. オブジェクトとして **Message Participants** を選択します
3. フィルターを追加します: **Handle** がトリガーの handle(送信者のメールアドレス)と等しい、かつ **Role** が **FROM** と等しい
4. **Limit** を 1 から **200**(最大値)に増やします
これにより、このメールアドレスからのすべてのメッセージを見つけ、合計数を取得します。
<Note>
Search Records アクションは、返せるレコードが最大 200 件に制限されています。 ただし、個々のレコードではなく `totalCount` の値のみを使用するため、このステップではこの人物が送信したメールの総数が返されます。
</Note>
### ステップ 4: Create or Update Record アクションで Person レコードを更新
1. 「**Create or Update Record**」アクションを追加します
2. オブジェクトとして **People** を選択します
3. Message Participant の `handle` とメールアドレスを照合して該当の人物を特定します
4. カスタムの「受信メール数」フィールドを `{{searchRecords.totalCount}}` に設定します
Search Records アクションの `totalCount` の値は、この人物から受信したメールの総数を表します。
## 関連
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [カスタムフィールドの作成方法](/l/ja/user-guide/data-model/how-tos/customize-your-data-model)
* [Search Records アクション](/l/ja/user-guide/workflows/capabilities/workflow-actions#search-records)

View File

@@ -0,0 +1,170 @@
---
title: 関連レコードのデータを表示
description: ワークフローを使用して、関連レコードのデータ(例:商談上の会社情報)を表示します。
---
関連レコードのデータを自分のレコード上に直接表示します — たとえば、会社の従業員数をその会社の商談に表示します。 入れ子フィールドがネイティブに利用可能になるまで、このワークフローによる回避策が役立ちます。
## 一般的な使用例
| ソース | コピー先 | コピーするフィールド |
| --- | ---- | -------------- |
| 会社 | 商談 | 業種、会社規模、ARR |
| 人物 | 商談 | メール、電話、役職 |
| 商談 | 会社 | 直近の商談金額、直近の受注日 |
## 基本的なフィールドのコピー
### 例: 連絡先のメールを商談にコピー
**目標**: 商談で連絡担当者を設定したとき、その人物のメールを商談にコピーして簡単に参照できるようにする。
### 前提条件
ワークフローを作成する前に、**設定 → データモデル → 商談** でコピー先フィールドを作成します:
* 連絡先メール(タイプ: Email)
* 連絡先電話(タイプ: Phone)
### セットアップ
1. **トリガー**: レコードが更新(商談、連絡担当者フィールド)
2. **フィルター**: 連絡担当者が空でないことを確認
3. **レコード検索**: リンクされた人物を見つける
* オブジェクト: People
* フィルター: ID が `{{trigger.object.pointOfContact.id}}` に等しい
4. **レコードを更新**:
* オブジェクト: Opportunities
* レコード: `{{trigger.object.id}}`
* 連絡先メール: `{{searchRecords[0].email}}`
* 連絡先電話: `{{searchRecords[0].phone}}`
## 複数フィールドのコピー
### 例: 関連するすべての商談に会社情報を同期
**目標**: 会社の詳細が変更されたら、関連するすべての商談を更新する。
### セットアップ
1. **トリガー**: レコードが更新(会社)
* フィールド: 業種、会社規模、年間売上高
2. **レコード検索**: この会社のすべての商談を見つける
* オブジェクト: Opportunities
* フィルター: 会社 ID が `{{trigger.object.id}}` に等しい
3. **イテレーター**: 各商談をループ処理する
4. **レコードを更新** (イテレーター内):
* オブジェクト: Opportunities
* レコード: `{{iterator.currentItem.id}}`
* 会社の業種: `{{trigger.object.industry}}`
* 会社規模: `{{trigger.object.companySize}}`
* 会社のARR: `{{trigger.object.annualRevenue}}`
## レコード作成時のコピー
### 例: 会社データで商談を事前入力
**目標**: 会社にリンクされた商談を作成するとき、主要な会社情報を自動コピーする。
### 前提条件
**設定 → データモデル → 商談** でコピー先フィールドを作成します:
* 会社の業種(タイプ: Text)
* 会社規模(タイプ: Number)
### セットアップ
1. **トリガー**: レコードが作成(商談)
* フィルター: 会社が空でない
2. **レコード検索**: リンクされた会社の詳細を取得
* オブジェクト: Companies
* フィルター: ID が `{{trigger.object.company.id}}` に等しい
3. **レコードを更新**:
* オブジェクト: Opportunities
* レコード: `{{trigger.object.id}}`
* 会社の業種: `{{searchRecords[0].industry}}`
* 会社規模: `{{searchRecords[0].employees}}`
<Note>
**タスクとノートの制限**: タスクとノートのリレーションは多対多としてハードコードされており、ワークフローのトリガーやアクションではまだ使用できません。 これらのリレーションにアクセスするには、代わりに[API](/l/ja/developers/extend/api)を使用してください。
</Note>
## 双方向同期
### 例: 主担当者を同期した状態に保つ
**目標**: 会社の主担当者が変更されたら、その人物を更新する。 人物が主担当者になったときは、会社を更新する。
### ワークフロー 1: 会社 → 人物
1. **トリガー**: レコードが更新(会社、主担当者フィールド)
2. **レコードを更新**: 人物の "Is Primary Contact" を true に設定
3. **レコード検索**: 以前の主担当者を見つける
4. **レコードを更新**: 以前の連絡先の "Is Primary Contact" を false に設定
### ワークフロー 2: 人物 → 会社
1. **トリガー**: レコードが更新(人物、Is Primary Contact = true)
2. **レコードを更新**: 会社の主担当者をこの人物に設定
<Note>
無限ループを避けるため、双方向同期の取り扱いには注意してください。 更新前に値が実際に変更されたかを確認するフィルターを使用する。
</Note>
## コードによる複雑なマッピング
### 例: コピー時にデータを変換
**目標**: 人物から商談へ電話番号をコピーし、フォーマットする。
```javascript
export const main = async (params) => {
const { phone } = params;
if (!phone) return { formattedPhone: null };
// Remove non-numeric characters
const digits = phone.replace(/\D/g, '');
// Format as (XXX) XXX-XXXX
const formatted = digits.length === 10
? `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`
: phone;
return { formattedPhone: formatted };
};
```
## ベストプラクティス
### ループを回避する
* 互いにトリガーし合って終わらないワークフローを作成しない
* 特定のフィールド条件を使用する
* 値が実際に変更されたかを確認するチェックを追加する
### 欠損データの取り扱い
* コピー前に常にソースレコードの存在を確認する
* 任意フィールドには既定値を用意する
* ソースフィールドが空の場合はフィルターでスキップする
### パフォーマンス
* 多数のレコードにコピーする場合はバッチ更新を使用する
* 大規模な同期処理にはスケジュールされたワークフローを使用する
* 複数レコードの更新にはイテレーターの使用を検討する
## 関連
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)

View File

@@ -0,0 +1,202 @@
---
title: 数式フィールド
description: ネイティブ対応が提供されるまで、ワークフローを使って数式フィールドを作成します。
---
Twenty は現時点でネイティブの数式フィールドをまだサポートしていません(2026 年に提供予定)ですが、ワークフローを使えば同等の結果を実現できます。 この回避策により、単純な連結から複雑なビジネスロジックまで、フィールド値を自動計算して入力できます。
## 一般的な使用例
| ユースケース | 数式例 |
| ------------ | ---------------------------- |
| **氏名** | First Name + " " + Last Name |
| **見込み金額** | Amount × Probability |
| **期日までの日数** | Due Date - Today |
| **ステージ滞在日数** | Today - Stage Entry Date |
| **リードスコア** | 複数の基準に基づくポイント |
<Tip>
パイプラインのステージでの時間を追跡する完全な例については、[商談が各ステージにとどまる時間を追跡](/l/ja/user-guide/views-pipelines/how-tos/track-time-in-stage) を参照してください。
</Tip>
## 基本の式:連結
### 例:氏名を自動入力
**目的**: 名と姓を自動的に結合して氏名フィールドにする。
### セットアップ
1. **トリガー**: レコードが更新または作成される(People)
2. **フィルター**: 名または姓が変更されたかを確認
3. **コードアクション**:
```javascript
export const main = async (params) => {
const { firstName, lastName } = params;
const fullName = [firstName, lastName]
.filter(Boolean)
.join(' ');
return { fullName };
};
```
4. **レコードを更新**: 氏名を `{{code.fullName}}` に設定
## 数値の式:見込み金額
### 例:見込み収益を計算
**目的**: 商談金額に確度を掛けて見込み金額を算出する。
ワークフロー全体については、[パイプラインで見込み金額を表示する方法](/l/ja/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline) を参照してください。
### セットアップ
1. **トリガー**: レコードが更新される(Opportunities、Amount または Probability フィールド)
2. **コードアクション**:
```javascript
export const main = async (params) => {
const { amount, probability } = params;
const expectedAmount = (amount || 0) * (probability || 0) / 100;
return { expectedAmount };
};
```
3. **レコードを更新**: 見込み金額を `{{code.expectedAmount}}` に設定
## 日付の式:日数計算
### 例:タスクの期日までの日数
**目的**: タスクの期日まで残り何日かを計算する。
### セットアップ
1. **トリガー**: レコードが更新または作成される(Tasks、Due Date フィールド)
2. **コードアクション**:
```javascript
export const main = async (params) => {
const { dueDate } = params;
if (!dueDate) {
return { daysUntilDue: null };
}
const due = new Date(dueDate);
const today = new Date();
const diffTime = due - today;
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return { daysUntilDue: diffDays };
};
```
3. **レコードを更新**: 期日までの日数を `{{code.daysUntilDue}}` に設定
<Note>
負の値は期限超過のタスクを示します。 このフィールドを使用して、緊急度でタスクをフィルターまたは並べ替えることができます。
</Note>
## 条件付き式:リードスコア
### 例:条件に基づいてリードスコアを計算
**目的**: 企業規模、業種、エンゲージメントに基づいてリードにスコアを付与する。
### セットアップ
1. **トリガー**: レコードが更新される(People または Companies)
2. **コードアクション**:
```javascript
export const main = async (params) => {
const { companySize, industry, hasEmail, hasPhone, source } = params;
let score = 0;
// Company size scoring
if (companySize === 'Enterprise') score += 30;
else if (companySize === 'Mid-Market') score += 20;
else if (companySize === 'SMB') score += 10;
// Industry scoring
const targetIndustries = ['Technology', 'Finance', 'Healthcare'];
if (targetIndustries.includes(industry)) score += 25;
// Contact info scoring
if (hasEmail) score += 10;
if (hasPhone) score += 15;
// Source scoring
if (source === 'Referral') score += 20;
else if (source === 'Website') score += 10;
return { leadScore: score };
};
```
3. **レコードを更新**: リードスコアを `{{code.leadScore}}` に設定
## テキストの式:ドメイン抽出
### 例:メールからドメインを抽出
**目的**: メールのドメインを自動抽出して保存する。
### セットアップ
1. **トリガー**: レコードが更新される(People、Email フィールド)
2. **コードアクション**:
```javascript
export const main = async (params) => {
const { email } = params;
if (!email) return { domain: null };
const domain = email.split('@')[1]?.toLowerCase();
return { domain };
};
```
3. **レコードを更新**: ドメインフィールドを `{{code.domain}}` に設定
## ベストプラクティス
### パフォーマンス
* 関連するフィールド変更時のみトリガーする
* 計算が不要なレコードをスキップするためにフィルターを使用する
* 大量のワークフローでは複雑な計算を避ける
### エラーハンドリング
* 計算の前に null/undefined の値を確認する
* データが欠落している場合はデフォルト値を使用する
* 計算が失敗したときは明確なエラーメッセージを返す
### テスト
* エッジケース(空のフィールド、ゼロ値)でテストする
* 有効化する前に計算を手動で検証する
* 意図しない結果がないかワークフローの実行を監視する
## 関連
* [パイプラインで見込み金額を表示する方法](/l/ja/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline)
* [ステージ内の時間を追跡する方法](/l/ja/user-guide/views-pipelines/how-tos/track-time-in-stage)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,127 @@
---
title: レビュー対象のノートをチームメンバーに通知
description: ノートのレビュー担当に同僚を割り当てたとき、自動でメール通知を送信します。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<Note>
**ノート内でチームメンバーを直接タグ付けすることはまだサポートされていません。** この機能は 2026 年後半に提供予定です。 当面の間、このワークフローが実用的な回避策となります。
</Note>
## 課題
ノート内で同僚をタグ付けして、レビュー通知が届くようにしたい。 現時点では、Twenty はノートやタスクでの @メンションをサポートしていません。
## 回避策
ノート本文でのタグ付けの代わりに、次のようにします。
1. Notes オブジェクトに **Reviewer** リレーションフィールドを作成する
2. ノートの作成または編集時にレビュアーを割り当てる
3. ワークフローをレビューアに自動的にメールを送信し、ノートへのリンクが付いています。
<Warning>
**制限**: この方法では、フィールドごとに 1 人のレビュアーしか割り当てられません。 複数人に通知する必要がある場合は、リレーションフィールドを追加で作成します(例: Reviewer 1、Reviewer 2)。 一度に多数のコラボレーターをタグ付けする必要がある場合、拡張性は高くありません。
</Warning>
## ステップバイステップの設定
### ステップ 1: Reviewer フィールドを作成
<img src="/images/user-guide/workflows/reviewer-field-for-note.png" style={{width:'100%'}} />
1. 「**設定 → データモデル → Notes**」に移動します
2. **Add Field** をクリック
3. 設定:
| 設定 | 値 |
| ------------- | ----------------------- |
| **Name** | Reviewer |
| **種類** | リレーション |
| **関連オブジェクト** | ワークスペースメンバー |
| **リレーションタイプ** | 複数のノート → 1人のワークスペースメンバー |
4. フィールドを保存
### ステップ 2: ワークフローを作成
<VimeoEmbed videoId="1151897168" title="デモ動画" />
#### ワークフローのトリガーを作成
1. メインビューに移動し、新しいワークフローを作成します
2. トリガーとして **Record Updated** を選択します
3. オブジェクトとして **Note** を選択し、**Reviewer** フィールドを指定します。
4. これにより、ノートのレビュアーが更新されるたびにトリガーされます。
#### レビュアーが割り当てられた直後かを確認するフィルターを追加
レビュアーが割り当てられたときのみ続行するように、**フィルター** アクションを追加します:
| 条件 | 値 |
| ------------ | ----- |
| **Reviewer** | 空ではない |
#### ワークスペースメンバーを検索
1. 「**Search Records**」アクションを追加します
2. 「Advanced Objects」内の **Workspace Member** を選択
3. フィルターを追加:
| 条件 | 値 |
| ------ | ---------------------------- |
| **ID** | が `{{note.reviewerId}}` に等しい |
これにより、メールアドレスや氏名を含むワークスペースメンバーの完全なレコードが取得されます。
#### 通知メールを送信
1. 「**Send Email**」アクションを追加します
2. 設定:
| フィールド | 値 |
| ------ | --------------------------------------------------- |
| **宛先** | Search Record → First Workspace Member → User Email |
| **件名** | ノートのレビューをお願いします |
| **本文** | 下記の例を参照してください |
**メール本文の例:**
```text
Hi {{searchRecord.firstWorkspaceMember.name.firstName}},
You've been assigned to review a note.
View the note here:
https://yourSubDomain.twenty.com/object/note/{{recordIsUpdated.id}}
Best,
Twenty
```
<Note>
`yourSubDomain` を実際の Twenty ワークスペースのサブドメインに置き換えてください。
</Note>
#### テストと有効化
1. ワークフローを手動で実行するには「**Test**」をクリックします
2. ノートを作成または編集し、レビュアーを割り当てます
3. レビュアーの受信トレイに通知メールが届いているか確認します
4. ワークフローを有効化します
## 使用方法
セットアップ後、チームは次の手順でこのワークフローを利用できます。
1. 新しいノートを作成(または既存のノートを編集)
2. **Reviewer** フィールドで同僚を選択
3. 同僚に、ノートへの直接リンク付きメールが自動送信されます
## 関連
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローからメールを送信](/l/ja/user-guide/workflows/capabilities/send-emails-from-workflows)
* [カスタムフィールドの作成方法](/l/ja/user-guide/data-model/how-tos/create-custom-fields)
* [リレーションフィールドの作成方法](/l/ja/user-guide/data-model/how-tos/create-relation-fields)

View File

@@ -0,0 +1,106 @@
---
title: 期限のタスクに関するメールアラートを送信
description: 差し迫ったタスクや期限超過のタスクについてチームメンバーに自動通知します。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/email_tasks_due.png" style={{width:'100%'}} />
本日が期限のタスクについて、各チームメンバーに毎日メールでリマインダーを送信します。
## 概要
このワークフローはスケジュールで実行され、以下を実行します:
1. すべてのワークスペースメンバーを取得
2. 各メンバーを順に処理
3. 各メンバーの本日が期限のタスクを検索
4. 整形し、パーソナライズされたメールを送信
## ステップバイステップの設定
<VimeoEmbed videoId="1147463514" title="デモ動画" />
### ステップ 1: トリガーを設定
1. 「**Settings → Workflows**」に移動し、新しいワークフローを作成します
2. トリガーとして「**On a Schedule**」を選択します
3. 毎日 8:00 の cron 式を使用します: `0 8 * * *`
### ステップ 2: すべてのワークスペースメンバーを検索
1. 「**Search Records**」アクションを追加します
2. 「**Workspace Members**」(advanced objects 内)を選択します
3. フィルターは不要です—すべてのメンバーが取得されます
### ステップ 3: Iterator を追加
1. 「**Iterator**」アクションを追加します
2. 入力配列を前のステップのワークスペースメンバーに設定します
3. Iterator 内のすべてのアクションはメンバーごとに1回実行されます
### ステップ 4: 本日が期限のタスクを検索(Iterator 内)
1. Iterator 内で「**Search Records**」アクションを追加します
2. オブジェクトとして「**Tasks**」を選択します
3. フィルターを追加:
* **Assignee** = 現在のワークスペースメンバー(Iterator から)
* **Due Date** = 今日
### ステップ 5: タスクをメール本文に整形(Iterator 内)
タスクをリンク付きの読みやすいリストに整形するために「**Code**」アクションを追加します:
```javascript
export const main = async (params: {
tasksDue?: Array<{ id: string; title: string }> | null | string;
}) => {
const tasksDue =
typeof params.tasksDue === "string"
? JSON.parse(params.tasksDue)
: params.tasksDue;
if (!Array.isArray(tasksDue) || tasksDue.length === 0) {
return {
formattedTasks: "No tasks due today."
};
}
const formattedTasks = tasksDue
.map(
t =>
`${t.title}\nhttps://yourSubDomain.twenty.com/object/task/${t.id}`
)
.join("\n\n");
return { formattedTasks };
};
```
<Note>
`yourSubDomain` を実際の Twenty ワークスペースのサブドメインに置き換えてください。
</Note>
### ステップ 6: メールを送信(Iterator 内)
1. 「**Send Email**」アクションを追加します(引き続き Iterator 内)
2. 設定:
| フィールド | 値 |
| ------ | --------------------------------------------------------- |
| **宛先** | `{{iterator.currentItem.userEmail}}`(ワークスペースメンバーのメールアドレス) |
| **件名** | 本日が期限のタスク |
| **本文** | `{{code.formattedTasks}}` |
### ステップ 7: テストして有効化
1. ワークフローを手動で実行するには「**Test**」をクリックします
2. 受信トレイでメールを確認します
3. ワークフローを有効化します
## 関連
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [ワークフローからメールを送信](/l/ja/user-guide/workflows/capabilities/send-emails-from-workflows)
* [Code アクションで配列を扱う](/l/ja/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,21 @@
---
title: プロフェッショナルサービス
description: Twenty のチームおよび認定パートナーから、複雑なワークフローや自動化の構築に関する専門的な支援を受けましょう。
---
## いつプロフェッショナルなサポートが必要ですか?
次の用途については、プロフェッショナル サービスの利用をご検討ください:
* 複雑なマルチシステム統合
* 高度なビジネスロジックと自動化ルール
* 大規模データ処理ワークフロー
* カスタムAPIの開発
* チームのトレーニングとワークフローの最適化
* 社内リソースがない場合
## サービスの選択肢
### 実装パートナー
認定パートナーと連携して、高度なカスタマイズを行います。 弊社の[導入パートナー](https://twenty.com/partners)とつながるには、[contact@twenty.com](mailto:contact@twenty.com) までお問い合わせください。

View File

@@ -0,0 +1,170 @@
---
title: ワークフロートラブルシューティング
description: 一般的なワークフローの問題とその解決方法。
---
## 一般的な問題と解決策
### ワークフローがトリガーされない
**症状**: 期待したタイミングでワークフローが実行されない。
**考えられる原因**:
1. **ワークフローが有効化されていない**: ワークフローが "Draft" ではなく "Active" に設定されていることを確認する
2. **トリガー条件が満たされていない**: トリガーが想定するイベントに一致しているか確認する
3. **フィールドが監視対象ではない**: "Record is Updated" トリガーの場合、対象のフィールドが監視されていることを確認する
4. **権限**: ワークフローを実行する権限があるか確認する
**解決策**:
* ワークフロー一覧でワークフローのステータスを確認する
* 想定するアクションで実際にトリガーされるかテストする
* トリガー設定を見直す
* 権限について管理者に連絡する
### ワークフローが早すぎるタイミングでトリガーされる(フィールドが空)
**症状**: UI でレコードを手動作成すると、すべてのフィールドを入力する前にワークフローがトリガーされる。 フィールド値がほぼ空の状態でワークフローが実行されてしまう。
**原因**: Twenty はすべてをリアルタイムで保存します — つまり、"edit" と "read" の別モードはありません。 レコードを作成すると即時に保存され、追加のフィールドを入力する前に "Record is created" イベントがトリガーされます。
**"Record is created" が有効に機能するケース**:
* API 呼び出しで作成されたレコード(1 回のリクエストでフィールドが入力される)
* インポートで作成されたレコード
* 他のワークフローからの自動レコード作成
**解決策**: UI で手動作成したレコードには、トリガーとして **"Record is created or updated"** を使用する。 このようにすることで:
* ユーザーが入力を完了しフィールドを保存した後にワークフローがトリガーされる
* 空の値ではなく完全なデータを取得できる
<Tip>
ワークフローをレコードごとに 1 回だけ実行したい場合は、`createdAt equals updatedAt`(初回保存)などのフィールドを確認するために Filter アクションを追加するか、ワークフローがすでに実行されたかを追跡するカスタムのチェックボックスフィールドを使用する。
</Tip>
### アクションの失敗
**症状**: ワークフローは実行されるが、一部のアクションが失敗する。
**考えられる原因**:
1. **データ不足**: 必須フィールドが空である
2. **無効な参照**: 以前のステップの変数が存在しない
3. **API エラー**: 外部サービスがエラーを返している
4. **権限の問題**: アクションの実行に必要な権限が不足している
**解決策**:
* ワークフローの実行詳細でエラーメッセージを確認する
* すべての必須フィールドに値が入っていることを確認する
* API 接続を個別にテストする
* ロール権限を見直す
### HTTP リクエストのエラー
**症状**: HTTP Request アクションが失敗する、または想定外の結果を返す。
**一般的なエラーコード**:
* **400**: 不正なリクエスト - リクエストボディの形式を確認する
* **401**: 認証エラー - API キーを確認する
* **403**: アクセス拒否 - API の権限を確認する
* **404**: 見つかりません - エンドポイントURLを確認する
* **429**: リクエスト過多 - レート制限を実装する
* **500**: サーバーエラー - 外部サービス側の問題
**解決策**:
* APIエンドポイントURLを確認する
* 認証ヘッダーを確認する
* まず Twenty の外で API 呼び出しをテストする
* Code アクションでエラーハンドリングを追加する
### Code アクションのエラー
**症状**: JavaScript コードが実行に失敗する。
**一般的な問題**:
1. **構文エラー**: タイプミスまたは無効な JavaScript
2. **未定義の変数**: 存在しない変数を参照している
3. **型エラー**: 不適切なデータ型に対する操作
4. **タイムアウト**: コードの実行に時間がかかりすぎている
**解決策**:
* 組み込みのコードエディタの検証機能を使用する
* まず JavaScript コンソールでコードロジックをテストする
* デバッグのために console.log を追加する
* 複雑な処理を簡素化する
### メールが送信されない
**症状**: Send Email アクションでメールが配信されない。
**考えられる原因**:
1. **メールアカウントが未接続**: Settings → Accounts を確認する
2. **無効なメールアドレス**: 受信者のメールアドレスの形式が正しくない
3. **送信制限**: メールプロバイダのレート制限に達している
4. **スパムフィルター**: メールがブロックされている
**解決策**:
* メールアカウントの接続を確認する
* 受信者のメールアドレスを検証する
* メールプロバイダの制限を確認する
* スパム判定される可能性があるメール内容を見直す
## ワークフローのデバッグ
### ワークフロー実行の活用
1. ワークフローエディタに移動する
2. **Runs** パネルを開く
3. 失敗した実行を探す
4. クリックしてステップごとの詳細を表示する
5. エラーメッセージと出力データを確認する
### 個別ステップのテスト
1. Code アクションでは **Test** ボタンを使用する
2. HTTP リクエストでは、エンドポイントを個別にテストする
3. ワークフローをトリガーするテスト用レコードを作成する
4. 制御されたテストには手動トリガーを使用する
### 一般的なデバッグパターン
**ロギングを追加**:
デバッグのために中間値をログ出力する Code アクションを使用する。
**ステップを分離**:
失敗箇所を特定するため、各ステップを個別にテストする。
**データフローを確認**:
各ステップが期待どおりの入力データを受け取っていることを確認する。
## 問題を避けるためのベストプラクティス
### 有効化前
* ドラフトモードで十分にテストする
* すべての API 接続を検証する
* トリガー条件を丁寧に見直す
* 想定される動作を文書化する
### 開発中
* 説明的なステップ名を使用する
* Code アクションにコメントを追加する
* 実データに近いデータでテストする
* エッジケースを想定して計画する
### 有効化後
* 初期の実行を綿密に監視する
* 失敗時のアラートを設定する
* 実行履歴を定期的に見直す
* 可能な限りワークフローをシンプルに保つ

View File

@@ -0,0 +1,236 @@
---
title: ワークフローに関するFAQ
description: Twenty のワークフローに関するよくある質問。
---
<AccordionGroup>
<Accordion title="なぜワークフローを有効化できないのですか?">
これは権限の問題である可能性が高いです。 ワークフローを作成して有効化するには、ワークフローへのアクセス権が必要です。
**解決策**:**Settings → Members → Roles** でワークフローへのアクセス権を付与してもらうよう、ワークスペース管理者に連絡してください。
サイドバーにワークフローセクションがまったく表示されない場合、権限の問題であることが確認できます。
</Accordion>
<Accordion title="上部のナビバーに手動ワークフローのボタンが表示されないのはなぜですか?">
手動ワークフローは、適切に設定されている場合にのみナビバーに表示されます:
1. ワークフローが**アクティブ**(ドラフトモードではない)である必要があります
2. ナビバーの配置は**Pinned**に設定する必要があります
3. Single/Bulk トリガーの場合、正しいオブジェクトのページを表示している必要があります
**確認方法**:ワークフローを開く → トリガーをクリック → "Navbar placement" が "Pinned" に設定されていることを確認します。
ナビバーの設定に関係なく、**Cmd + K**(または **Ctrl + K**)で手動ワークフローに常にアクセスできます。
</Accordion>
<Accordion title="Single、Global、Bulk の手動トリガーの違いは何ですか?">
| タイプ | 必要なレコード | ワークフロー実行 |
| --- | ------- | -------- |
\| **Global** | なし | 1回、レコード入力なし |
\| **Single** | 1件以上を選択 | 選択した各レコードごとに1回 |
\| **Bulk** | 1件以上を選択 | 1回、すべてのレコードを配列として |
* **Global**:ワークフローがレコードのコンテキストを必要としない場合に使用します(例:レポートの生成)
* **Single**:選択した各レコードを個別に処理したい場合に使用します(例:個別メールの送信)
* **Bulk**:レコードをまとめて処理する必要がある場合、またはクレジットの使用を最適化したい場合に使用します(Iterator アクションが必要)
詳細は[ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)を参照してください。
</Accordion>
<Accordion title="If/Else ノードが見つかりません。 どうすればよいですか?">
明示的な If/Else ノードはまだ利用できませんが、ロードマップに含まれています。
**現在の回避策**:ステップから複数のブランチを作成し、それぞれを **Filter** アクションで開始します:
```
Step 1
│
├── Branch A: Filter (condition = true) → Actions...
│
└── Branch B: Filter (condition = false) → Actions...
```
フィルター条件を満たしたブランチのみが、その後のアクションを実行します。
手順については[ブランチの使い方](/l/ja/user-guide/workflows/capabilities/workflow-branches)を参照してください。
</Accordion>
<Accordion title="ワークフローのブランチは並行実行されますか?">
**はい**、ブランチは既定で並行実行されます。
どちらか一方のブランチのみを実行したい場合:
* 各ブランチの先頭に **Filter** アクションを追加します
* 互いに排他的な条件を設定します(例:ブランチA:status = "Open"、ブランチB:status ≠ "Open")
フィルター条件を満たさないブランチは実行を停止し、他のブランチは継続します。
</Accordion>
<Accordion title="ブランチを再び結合できますか?">
**はい**。 並行ブランチの実行が完了した後、両方のブランチが接続するステップを追加できます。
ワークフローエディタで:
1. 分岐したアクションを完了する
2. ブランチの後に新しいステップを追加する
3. 各ブランチの終端からこの新しいステップに接続をドラッグする
すべての接続されたブランチが完了すると、マージされたステップが実行されます。
</Accordion>
<Accordion title="Search Records の結果の上限はどれくらいですか?">
**Search Records は最大 200 件のレコードを返します。**
より多くを処理する必要がある場合:
* 結果を絞り込むために、より具体的なフィルターを追加する
* スケジュールされたワークフローを使用してバッチ処理する
* 一括処理には API の使用を検討する
ほとんどのワークフローでは、200 件のレコードで十分です。 この上限に頻繁に達する場合は、自動化の構成を見直すことを検討してください。
</Accordion>
<Accordion title="ワークフローのメールで CC を追加できますか?">
**まだできません。** Send Email アクションでの CC と BCC フィールドはロードマップにあります。
**現在の回避策**:追加の受信者に送信するために複数の Send Email アクションを追加するか、CC に対応した外部のメールサービス経由で送信するために HTTP Request を使用します。
</Accordion>
<Accordion title="前のステップの出力はどのように使用しますか?">
各アクションは、後続のステップで使用できる出力データを生成します。
**前のステップのデータを参照するには**:
* フィールドを設定する際に変数ピッカーを使用する
* または `{{stepName.fieldName}}` を直接入力する
**例**:
* トリガーデータ:`{{trigger.object.email}}`
* 検索結果:`{{searchRecords[0].name}}`
* コードの出力:`{{code.calculatedValue}}`
アクション設定内の任意のフィールドにカーソルを合わせると、前のステップから利用できる変数が表示されます。
</Accordion>
<Accordion title="Iterator が失敗するのはなぜですか?">
**Iterator は配列入力が必要です。** よくある問題:
1. **入力が配列ではない**:Search Records など配列を返すアクションの結果を渡していることを確認してください
2. **配列が空**:Iterator の前にフィルターを追加し、`{{searchRecords.length}} > 0` を確認してください
3. **誤った変数を選択**:単一レコードではなく、配列そのものを選択していることを確認してください
**正しい設定**:
1. Search Records(配列を返す)
2. Filter:length > 0
3. Iterator:`{{searchRecords}}` を選択
4. Iterator 内のアクションでは `{{iterator.currentItem.fieldName}}` を使用する
</Accordion>
<Accordion title="Code アクションの最大実行時間はどれくらいですか?">
Code アクション(ロジック関数)の**既定のタイムアウトは 5 分**(300 秒)です。
設定可能な最大タイムアウトは**15 分**(900 秒)です。
コードがこの制限を超えると、アクションはタイムアウトエラーで失敗します。
**タイムアウトを回避するためのヒント**:
* 大きな処理は Iterator を使用して小さなチャンクに分割する
* 重い計算は避け、集中的な処理が必要な場合は HTTP Request を介して外部サービスを使用する
* コードを最適化して実行時間を短縮する
* より長時間の処理が必要な場合は、データをバッチ処理するスケジュールされたワークフローの使用を検討する
</Accordion>
<Accordion title="ワークフロー実行履歴はどのように確認しますか?">
ワークフローの実行履歴は、実行の経過を表示し、問題のデバッグに役立ちます。
**アクセス方法**:
* ワークフローエディタ → 右側の **Runs** パネル
* またはサイドバーの **Workflow Runs** に移動
**実行の見方**:
* **ステータス**:Running、Completed、Failed、Waiting
* **ステップ**:どのステップが実行され、どのような出力だったかを確認
* **エラー**:失敗したステップをクリックしてエラーメッセージを確認
* **データ**:各ステップの入力/出力データを表示
詳細は[ワークフローの実行](/l/ja/user-guide/workflows/capabilities/workflow-runs)を参照してください。
</Accordion>
<Accordion title="ワークフローの実行が表示されないのはなぜですか?">
ワークフローの実行が、レート制限により即時に失敗している可能性があります。 Twenty では、ワークスペースあたり 1 時間に 5,000 回の実行というハードリミットが適用されます。
この制限を超えると、ワークフローは即座に失敗としてマークされ、実行リストに表示されなくなります。
**この制限に達しがちな一般的なケース**:
* Single の手動トリガーで 5,000 件を超えるレコードを選択すること
* ワークスペース全体で同時に複数のワークフローが実行されていること
* 高頻度の自動トリガー(例:更新頻度の高いオブジェクトでの Record Updated)
**解決策**:
* 多数のレコードを 1 回の実行で処理するには、Single ではなく**Bulk** トリガーを使用する
* 大規模なバッチ処理の間隔を空ける
* フィルターを使用してトリガーの頻度を下げる
* 負荷の高いワークフローを閑散時間帯にスケジュールする
</Accordion>
<Accordion title="ワークフローのレート制限は何ですか?">
Twenty では、システムの安定性を確保するため 2 種類のレート制限があります:
| 制限 | 値 | 動作 |
| -- | - | -- |
\| **Soft limit** | 1 分あたり 100 実行 | "Not Started" ステータスでキューに入り、徐々に処理される |
\| **Hard limit** | 1 時間あたり 5,000 実行 | 実行は即時に失敗する |
**ソフトリミット(100/分)**:ワークフローは失敗しません。キューで待機し、時間をかけて処理されます。 100 件を超えるレコードをトリガーしても構いませんが、実行は遅くなります。
**ハードリミット(5,000/時)**:これはワークスペース全体に適用されます。 すべてのワークフローの合計が 1 時間に 5,000 回の実行を超えると、追加の実行は即時に失敗します。
**制限内に収めるためのヒント**:
* 大規模バッチには Single トリガーではなく、Iterator と併用した Bulk トリガーを使用する
* 関連する自動化をまとめて、ワークフローの数を減らす
* スケジュールされたワークフローを使用して負荷を時間的に分散する
</Accordion>
<Accordion title="失敗したワークフロー実行を再試行できますか?">
**いいえ、現時点では自動再試行機能はありません。**
ワークフロー実行が失敗した場合は、次を行います:
1. **Settings → Workflows → [Your Workflow] → Runs** でエラーを確認する
2. 問題を修正する(データ、設定、または外部サービス)
3. 影響を受けたレコードに対して、ワークフローを手動で再度トリガーする
**失敗を減らすためのヒント**:
* アクションの前にデータを検証するため、**Filter** ノードを追加する
* **Search Records** を使用して、関連レコードが存在するか確認する
* 一括処理の前に、少数のレコードで十分にテストする
自動再試行機能は、今後のリリースに向けたロードマップに含まれています。
</Accordion>
<Accordion title="CSV インポートの前にワークフローを無効化すべきですか?">
**はい。ワークフローがレコードの作成または更新でトリガーされる場合は無効化してください。**
CSV でデータをインポートすると、作成または更新された各レコードがワークフローをトリガーする可能性があります。 大規模なインポート(数千件のレコード)は次の事態を招く可能性があります:
* 5,000 実行/時の制限に達する
* ワークフロークレジットを大量に消費する
* 想定外のメールや通知を送信する
* 重複するタスクやレコードを作成する
**一括インポートの前に**:
1. **Settings → Workflows** に移動する
2. インポート対象のオブジェクトでトリガーされるワークフローを特定する
3. 一時的に**無効化**する
4. CSV インポートを実行する
5. 完了したらワークフローを**再有効化**する
**代替案**:インポートしたデータでワークフローを実行する必要がある場合は、レート制限内に収めるため小さなバッチでインポートします。
</Accordion>
<Accordion title="ワークフローのレイアウトを整えるにはどうすればよいですか?">
ワークフローのキャンバスでノードが散らばって見づらい場合、自動的に整理できます:
1. ワークフローのキャンバス上の任意の場所を右クリックする
2. **Tidy up workflow** をクリックする
これにより、すべてのノードが自動的に整理され、見やすいレイアウトに再配置されます。
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,81 @@
---
title: ワークフロー
description: Twenty で自動化を構築する方法を学びましょう。
---
## ワークフローが重要な理由
Twentyはユーザーに最大限の柔軟性を提供するために作られました。 Twentyはユーザーに最大限の柔軟性を提供するために作られました。 ビジネスプロセスを堅苦しい既成の機能に適応させるのではなく、ワークフローは自動化を構築して、あなたの独自のビジネスユースケースを最大限にサポートするCRMを作成します。
ワークフローはこれらの自動化を作るためのTwentyのアプリケーション内機能です。 必要な時に必要なものを正確に作成するための構成要素を提供します。 必要な時に必要なものを正確に作成するための構成要素を提供します。 必要な時に必要なものを正確に作成するための構成要素を提供します。
## ワークフローで何ができますか?
主に2つの目的のために自動化を構築することをお勧めします。
1. **チームの日常を効率化する社内自動化**: 手動エントリーやチームの足を引っ張る反復作業を減らします。
2. **データの入出力をTwentyで行う**: APIコールやWebhookを通じてデータベースや他のツールとTwentyを接続します。
## 最初のワークフローの作成
### ステップ 1: 新しいワークフローを作成
1. 他のオブジェクトの下にある **Workflows** に移動します
2. 「**+ New Record**」をクリックします
3. ワークフローに名前を付けます
### ステップ 2: トリガーを追加
すべてのワークフローはトリガーから始まります。 以下から選択します:
* **Record events**: レコードが作成、更新、または削除されたとき
* **Schedule**: 指定した時間に実行(毎日、毎週など)
* **Manual**: ユーザー操作によってトリガーされます
* **Webhook**: Webhook によってトリガーされます
<img src="/images/user-guide/workflows/workflow_triggers.png" style={{width:'100%'}} />
### ステップ 3: アクションを追加
トリガーの後に、1 つ以上のアクションを追加します:
* **Create Record**: 任意のオブジェクトに新しいレコードを追加
* **Update Record**: 既存のレコードデータを変更
* **Delete Record**: オブジェクトからレコードを削除
* **Search Records**: 条件に一致するレコードを見つける
* **Upsert Record**: 一致する条件に基づいて作成または更新する
* **Iterator**: レコードの配列をループ処理する
* **Filter**: 次に進むレコードを制御する
* **Delay**: 続行する前に待機する(期間または指定日時)
* **Send Email**: 接続済みアカウント経由でメールを送信する
* **Code**: カスタム JavaScript を実行する
* **HTTP Request**: 外部 API を呼び出す
* **Form**: 実行時に Twenty の UI でユーザーから入力を取得する
* **AI Agent**(近日公開): インテリジェントな AI タスクを実行する
<img src="/images/user-guide/workflows/workflow_actions.png" style={{width:'100%'}} />
### ステップ 4: テストして有効化
1. **Test** ボタンを使って、サンプルデータでワークフローを実行します
2. 結果を確認し、期待どおりに動作することを確かめます
3. 準備ができたら、ワークフローを **Active** に切り替えます
## ワークフローのベストプラクティス
* **ステップ名を編集する**:各ステップが何をするかを明確に記述するためにワークフローのステップ名を変更します。 これはメンテナンスに役立ち、同僚への引き継ぎが容易になります。 これはメンテナンスに役立ち、同僚への引き継ぎが容易になります。 これはメンテナンスに役立ち、同僚への引き継ぎが容易になります。
* **前のステップのデータを活用する**:ワークフローの前の任意のステップによって返されたレコードのフィールドを使用できます。
* **簡単に始める**:基本的なワークフローから始め、システムに慣れるにつれて複雑さを増していきます。
* **構築する前に計画する**:途中で行き詰まらないように、ワークフローロジックを最初に計画します。
## 次のステップ
* [ワークフローのトリガー](/l/ja/user-guide/workflows/capabilities/workflow-triggers)
* [ワークフローのアクション](/l/ja/user-guide/workflows/capabilities/workflow-actions)
* [CRM の自動化](/l/ja/user-guide/workflows/how-tos/crm-automations/closed-won-automations)
## ヘルプが必要ですか?
<Tip>
ワークフローの自動化についてサポートが必要ですか? [Find a Certified Twenty partner](https://twenty.com/partners/list?categories=SOLUTIONING\&ref=docs-workflows) to design and building your automations end.
</Tip>