はじめに — なぜ freee × Agentforce なのか
freee会計を使っている企業にとって、請求書まわりの確認作業は日々の"小さなストレス"の積み重ねです。
- 「A社への請求書、もう出した?」と営業から経理に都度チャットで確認
- 月次締めのタイミングで入金消込の漏れに気づき、慌てて対応
- freeeにログインして請求書を検索し、ステータスを一つひとつ確認
こうした作業は1件あたり数分で済むものの、月間で積み上げると無視できない工数になります。さらに、確認の抜け漏れが発生すると、キャッシュフローへの影響や取引先との信頼関係の毀損にもつながりかねません。
本記事では、Salesforce Agentforce を活用して、freee for Salesforceの請求書データに自然言語で問い合わせできる「請求書アシスタント」を構築する方法をステップバイステップで解説します。完成すると、Agentforceのチャット欄に「未入金の請求書は?」と入力するだけで、freeeの最新データをもとに即座に回答が返ってくるようになります。
| 項目 | 内容 |
|---|---|
| 対象読者 | Salesforce管理者、freee利用企業の経理担当者 |
| 前提知識 | Salesforceの基本操作、freee for Salesforceパッケージ導入済み |
| 構築方法 | Apex 1クラス + Agent Builder設定(ノーコード中心) |
| 所要時間 | 約2〜3時間(Apex開発含む) |
| 環境 | Salesforce Enterprise Edition以上 + Agentforceライセンス |
完成形のイメージ
まず、完成したエージェントがどのように動作するかを見てみましょう。
デモ 1 — 未入金の請求書を一括確認
ユーザー
未入金の請求書を教えてください
エージェント
未入金の請求書は以下の 5件 です。
| 請求書番号 | 取引先 | 合計金額 | 請求日 | 入金 | 送信 |
|---|---|---|---|---|---|
| INV-0000000003 | ひだまりネクスト株式会社 | ¥1,100,000 | 2026-03-16 | 未入金 | 未送信 |
| INV-0000000008 | ひだまりネクスト株式会社 | ¥13,200,000 | 2026-03-11 | 未入金 | 未送信 |
| INV-0000000006 | ひだまりネクスト株式会社 | ¥0 | 2026-03-11 | 未入金 | 未送信 |
| INV-0000000007 | ひだまりネクスト株式会社 | ¥13,200,000 | 2026-03-11 | 未入金 | 未送信 |
| INV-0000000009 | ひだまりネクスト株式会社 | ¥13,200,000 | 2026-03-11 | 未入金 | 未送信 |
合計金額 ¥40,700,000 未入金件数 5件

デモ 2 — 取引先名で請求書を検索
ユーザー
ひだまりネクスト株式会社の請求書の状況を教えて
エージェント
ひだまりネクスト株式会社の請求書状況は以下の通りです。
| 請求書番号 | 合計金額 | 請求日 | 入金 | 送信 |
|---|---|---|---|---|
| INV-0000000003 | ¥1,100,000 | 2026-03-16 | 未入金 | 未送信 |
| INV-0000000008 | ¥13,200,000 | 2026-03-11 | 未入金 | 未送信 |
| INV-0000000006 | ¥0 | 2026-03-11 | 未入金 | 未送信 |
| INV-0000000007 | ¥13,200,000 | 2026-03-11 | 未入金 | 未送信 |
| INV-0000000009 | ¥13,200,000 | 2026-03-11 | 未入金 | 未送信 |
合計金額 ¥40,700,000 未入金件数 5件 未送信件数 5件

事前準備
構築を始める前に、以下の環境が整っていることを確認してください。
必要なライセンス・エディション
| 項目 | 要件 |
|---|---|
| Salesforce Edition | Enterprise Edition 以上 |
| Agentforce ライセンス | Agentforce for Service または Agentforce for Sales |
| freee for Salesforce | AppExchangeからインストール済み |
freee for Salesforce パッケージの確認
freee for Salesforceパッケージが正しくインストールされていると、以下のカスタムオブジェクトが利用可能になります。
| オブジェクトAPI名 | 用途 |
|---|---|
| freee__IV_Invoice__c | freeeの請求書データ |
| freee__Partner__c | freeeの取引先データ |
確認方法は、設定 > オブジェクトマネージャー で「freee」と検索し、上記オブジェクトが存在することを確認します。
Agentforce の有効化
Agentforceが有効化されていない場合は、設定 > Einstein > Agentforce から有効化してください。Agentforce Studioに既存のエージェントが一覧表示されていれば準備完了です。

1 Invocable Apex の作成
最初のステップは、freee for Salesforceの請求書データを検索する Invocable Apex クラスの作成です。このクラスがAgentforceのActionとして機能し、エージェントが請求書データにアクセスする窓口となります。
FreeeInvoiceSearchAction の機能
| 機能 | 説明 |
|---|---|
| 取引先名フィルタ | 部分一致で取引先名を検索 |
| 入金ステータスフィルタ | unsettled(未入金)/ settled(入金済み)で絞り込み |
| 送信ステータスフィルタ | unsent(未送信)/ sent(送信済み)で絞り込み |
| 請求日フィルタ | 開始日〜終了日の範囲指定 |
| サマリー生成 | 合計金額・未入金件数・未送信件数を自動集計 |
Apex コード全文
以下のApexクラスを開発者コンソールまたはVS Codeから作成してください。
/**
* FreeeInvoiceSearchAction
* freee請求書データをSalesforceから検索するAgentforceアクション
*/
public with sharing class FreeeInvoiceSearchAction {
public class SearchRequest {
@InvocableVariable(required=false
label='取引先名'
description='検索したい取引先名(部分一致)')
public String partnerName;
@InvocableVariable(required=false
label='入金ステータス'
description='unsettled=未入金, settled=入金済み')
public String paymentStatus;
@InvocableVariable(required=false
label='送信ステータス'
description='unsent=未送信, sent=送信済み')
public String sendingStatus;
@InvocableVariable(required=false
label='請求日From'
description='請求日の開始日(YYYY-MM-DD形式)')
public String billingDateFrom;
@InvocableVariable(required=false
label='請求日To'
description='請求日の終了日(YYYY-MM-DD形式)')
public String billingDateTo;
}
public class SearchResponse {
@InvocableVariable(label='検索結果')
public String result;
@InvocableVariable(label='件数')
public Integer totalCount;
@InvocableVariable(label='成功フラグ')
public Boolean success;
}
@InvocableMethod(
label='freee請求書検索'
description='freee for Salesforceの請求書データを検索します'
category='freee連携'
)
public static List<SearchResponse> searchInvoices(
List<SearchRequest> requests) {
List<SearchResponse> responses = new List<SearchResponse>();
SearchRequest req = requests[0];
try {
String query = 'SELECT Name, freee__InvoiceNumber__c, '
+ 'freee__TotalAmount__c, freee__PaymentStatus__c, '
+ 'freee__DealStatus__c, freee__BillingDate__c, '
+ 'freee__DueDate__c, freee__SendingStatus__c, '
+ 'freee__TotalVat__c, freee__Partner__r.Name '
+ 'FROM freee__IV_Invoice__c';
List<String> conditions = new List<String>();
if (String.isNotBlank(req.partnerName)) {
conditions.add(
'freee__Partner__r.Name LIKE ''%'
+ String.escapeSingleQuotes(req.partnerName)
+ '%''');
}
if (String.isNotBlank(req.paymentStatus)) {
conditions.add(
'freee__PaymentStatus__c = '''
+ String.escapeSingleQuotes(req.paymentStatus)
+ '''');
}
if (String.isNotBlank(req.sendingStatus)) {
conditions.add(
'freee__SendingStatus__c = '''
+ String.escapeSingleQuotes(req.sendingStatus)
+ '''');
}
if (String.isNotBlank(req.billingDateFrom)) {
conditions.add(
'freee__BillingDate__c >= '
+ req.billingDateFrom);
}
if (String.isNotBlank(req.billingDateTo)) {
conditions.add(
'freee__BillingDate__c <= '
+ req.billingDateTo);
}
if (!conditions.isEmpty()) {
query += ' WHERE '
+ String.join(conditions, ' AND ');
}
query += ' ORDER BY freee__BillingDate__c DESC LIMIT 50';
List<freee__IV_Invoice__c> invoices =
Database.query(query);
SearchResponse res = new SearchResponse();
res.totalCount = invoices.size();
res.success = true;
if (invoices.isEmpty()) {
res.result = '該当する請求書は見つかりませんでした。';
} else {
List<String> lines = new List<String>();
lines.add('【freee請求書検索結果 '
+ invoices.size() + '件】n');
for (freee__IV_Invoice__c inv : invoices) {
String partnerNameStr =
inv.freee__Partner__r != null
? inv.freee__Partner__r.Name
: '(取引先未設定)';
lines.add('請求書番号 '
+ (inv.freee__InvoiceNumber__c != null
? inv.freee__InvoiceNumber__c : 'N/A'));
lines.add('取引先 ' + partnerNameStr);
lines.add('合計金額 ¥'
+ (inv.freee__TotalAmount__c != null
? String.valueOf(
inv.freee__TotalAmount__c.intValue())
: '0'));
lines.add('請求日 '
+ (inv.freee__BillingDate__c != null
? String.valueOf(inv.freee__BillingDate__c)
: '未設定'));
lines.add('');
}
Decimal totalAmount = 0;
Integer unsettledCount = 0;
Integer unsentCount = 0;
for (freee__IV_Invoice__c inv : invoices) {
if (inv.freee__TotalAmount__c != null)
totalAmount += inv.freee__TotalAmount__c;
if (inv.freee__PaymentStatus__c == 'unsettled')
unsettledCount++;
if (inv.freee__SendingStatus__c == 'unsent')
unsentCount++;
}
lines.add('合計金額 ¥'
+ String.valueOf(totalAmount.intValue()));
lines.add('未入金 ' + unsettledCount + '件');
lines.add('未送信 ' + unsentCount + '件');
res.result = String.join(lines, 'n');
}
responses.add(res);
} catch (Exception e) {
SearchResponse errRes = new SearchResponse();
errRes.success = false;
errRes.totalCount = 0;
errRes.result = 'エラーが発生しました '
+ e.getMessage();
responses.add(errRes);
}
return responses;
}
private static String getPaymentStatusLabel(String status) {
if (status == 'unsettled') return '未入金';
if (status == 'settled') return '入金済み';
return status != null ? status : '不明';
}
private static String getSendingStatusLabel(String status) {
if (status == 'unsent') return '未送信';
if (status == 'sent') return '送信済み';
return status != null ? status : '不明';
}
}コードのポイント
設計上の重要ポイント
Apexクラスの設計上、特に押さえておきたいポイントを以下に整理します。
- @InvocableMethod アノテーション — ApexクラスがAgentforceのActionとして認識されます。labelとdescriptionはAgent Builder上での表示名と説明文になります。
- @InvocableVariable アノテーション — 各パラメータにlabelとdescriptionを設定することで、エージェントがユーザーの自然言語入力からパラメータを自動マッピングします。
- with sharing — 実行ユーザーの共有ルールに従ったデータアクセスを保証します。
- 動的SOQL — ユーザーの問い合わせ内容に応じて、必要なフィルタ条件のみを動的に組み立てます。
デプロイ方法
開発者コンソールからデプロイする場合の手順です。
- Salesforceの右上の歯車アイコンから 開発者コンソール を開く
- File > New > Apex Class を選択
- クラス名に FreeeInvoiceSearchAction と入力
- 上記コードを貼り付けて Save(Ctrl+S)

2 Agent Builder で Topic を追加
Apexクラスのデプロイが完了したら、Agent Builderでエージェントに新しいTopicを追加します。
Agent Builder を開く
- 設定 > Agentforce エージェント(または Agentforce Studio)に移動
- エージェント一覧から「請求トラブル応答用エージェント」をクリック
- 画面上部の New Draft をクリックして新しいドラフトを作成

Topic「請求書ステータス確認」の作成
左サイドバーの Topics セクションで + ボタンをクリックし、新しいTopicを作成します。

| 設定項目 | 設定値 |
|---|---|
| Topic Label | 請求書ステータス確認 |
| Topic API Name | InvoiceStatusCheck |
Classification Description の設定
Classification Descriptionは、エージェントがユーザーの質問をこのTopicに振り分けるかどうかを判断するための説明文です。以下の内容を入力してください。
Classification Description の入力内容
このTopicは、ユーザーが特定の取引先やプロジェクトに関する請求書の発行状況・送付状態・入金状態を確認したい場合に使用します。
該当する質問の例
- 「A社の請求書の状況は?」
- 「今月発行した請求書の一覧を見せて」
- 「まだ送付していない請求書はある?」
- 「B社向けの3月分の請求書は発行済み?」
- 「未入金の請求書を教えて」
該当しない質問の例
- 入金の消込確認
- freee会計の仕訳・取引データの検索
- 請求書の新規作成依頼
ポイント
Classification Descriptionには、該当する質問例だけでなく「該当しない質問例」も記述することで、Topicの振り分け精度が大幅に向上します。

Scope の設定
Scopeは、このTopicでエージェントが「できること」と「できないこと」を定義します。
エージェントが実行できる操作
- freee請求書データの検索・取得
- Salesforce上の取引先情報との名寄せ(取引先名での照合)
- 請求書のステータス(下書き・送付済み・入金済み等)の確認と報告
- 複数請求書の一覧表示とフィルタリング(期間・取引先・ステータス別)
エージェントが実行できない操作
- 請求書の新規作成・編集・削除
- 入金の消込処理
- freee会計の仕訳データへのアクセス

Instructions の設定
Instructionsは、エージェントがこのTopic内でどのように振る舞うかを制御する指示です。
Instructions の入力内容
- 取引先名を指定した場合 — Action「freee請求書検索」を呼び出し、取引先名をパラメータとして検索。件数、ステータス、金額、発行日を一覧形式で回答する。
- ステータスで絞り込んだ場合 — 該当するステータスコードにマッピングし(unsettled=未入金, settled=入金済み等)、フィルタ結果を件数とともに回答する。
- 期間を指定した場合 — 指定された期間を日付範囲に変換し(例 「今月」→ 2026-03-01〜2026-03-31)、検索を実行する。
- データが見つからない場合 — 「該当する請求書が見つかりませんでした」と回答し、取引先名の表記揺れの可能性を示唆する。
回答フォーマット
- 必ず件数を最初に伝える(例 「A社の請求書は3件見つかりました」)
- 各請求書は「請求書番号 / 金額 / 発行日 / ステータス」の形式で表示
- 金額は3桁カンマ区切りで表示(例 ¥1,500,000)

3 Action を Topic に紐づける
Topicの設定が完了したら、Step 1で作成したInvocable ApexクラスをActionとして登録します。
Action の登録手順
- Agent Builderの左サイドバーで、作成した InvoiceStatusCheck Topicを展開
- Topic設定画面内の Actions セクションで + New Action をクリック
- 以下の内容を設定して Save をクリック
| 設定項目 | 設定値 |
|---|---|
| Action Type | Apex Invocable Action |
| Action | freee請求書検索(FreeeInvoiceSearchAction) |
| Action Label | freee請求書検索 |

Action のパラメータ確認
登録後、Actionの詳細画面でパラメータが正しく認識されていることを確認します。
| パラメータ名 | 型 | 必須 | 説明 |
|---|---|---|---|
| partnerName | String | No | 検索したい取引先名(部分一致) |
| paymentStatus | String | No | 入金ステータスでフィルタ |
| sendingStatus | String | No | 送信ステータスでフィルタ |
| billingDateFrom | String | No | 請求日の開始日 |
| billingDateTo | String | No | 請求日の終了日 |

ポイント
すべてのパラメータが required=false であるため、ユーザーが条件を省略しても全件検索として動作します。「未入金の請求書は?」のような質問では、エージェントが自動的に paymentStatus=unsettled を設定します。
4 テスト実行
設定が完了したら、Agent Builderのプレビュー機能を使ってエージェントの動作を確認します。
テスト環境の確認
Agent Builder画面の右側に表示されているチャットパネルでテストを実行できます。テスト前に、freee for Salesforceの請求書データがサンドボックス内に存在することを確認してください。
本サンドボックスには以下のテストデータが登録されています。
| 請求書番号 | 取引先 | 合計金額 | 入金 | 送信 |
|---|---|---|---|---|
| INV-0000000003 | ひだまりネクスト株式会社 | ¥1,100,000 | 未入金 | 未送信 |
| INV-0000000008 | ひだまりネクスト株式会社 | ¥13,200,000 | 未入金 | 未送信 |
| INV-0000000006 | ひだまりネクスト株式会社 | ¥0 | 未入金 | 未送信 |
| INV-0000000007 | ひだまりネクスト株式会社 | ¥13,200,000 | 未入金 | 未送信 |
| INV-0000000009 | ひだまりネクスト株式会社 | ¥13,200,000 | 未入金 | 未送信 |
テスト会話パターン
以下の5パターンでテストを実行し、期待通りの回答が得られることを確認します。
パターン 1 全件検索
ユーザー 「現在の請求書の状況を教えて」 期待結果 5件の請求書一覧が表示される

パターン 2 ステータスフィルタ
ユーザー 「未入金の請求書はある?」 期待結果 paymentStatus=unsettledで検索され、5件が表示される

パターン 3 取引先名検索
ユーザー 「青空コーポレーションの請求書を見せて」 期待結果 partnerNameで検索され、該当件が表示される
パターン 4 該当なし
ユーザー 「株式会社テストXYZの請求書はある?」 期待結果 「該当する請求書が見つかりませんでした」と表示される
パターン 5 複合条件
ユーザー 「青空コーポレーションの未入金の請求書を確認して」 期待結果 partnerName + paymentStatus=unsettled で検索される
Reasoning Log の確認
テスト実行後、Agent BuilderのReasoning Logを確認して、エージェントが正しくTopicを選択し、適切なパラメータでActionを呼び出しているかを検証します。
| 確認項目 | 期待値 |
|---|---|
| Topic Selection | InvoiceStatusCheck が選択されている |
| Action Selection | freee請求書検索 が呼び出されている |
| Parameter Mapping | ユーザーの入力から適切なパラメータが設定されている |
| Response Quality | 件数・金額・ステータスが正確に表示されている |
5 freee MCP との連携(応用編)
ここまでの構成では、freee for Salesforceパッケージで同期されたSalesforce内のデータを検索しています。さらに一歩進めて、freee MCP(Model Context Protocol)を活用することで、freeeのAPIにリアルタイムでアクセスし、より幅広いデータを取得できるようになります。
freee MCP とは
freee MCPは、freee公式がOSSとして公開しているMCPサーバーです。freee Public APIをMCPツールとして網羅的に公開しており、Claude DesktopやClaude CodeなどのMCPクライアントから、自然言語でfreeeのデータにアクセスできます。
| 項目 | 内容 |
|---|---|
| 認証方式 | OAuth 2.0 + PKCE(トークン自動更新対応) |
| 対応サービス | 会計・人事労務・請求書・工数管理・販売(5サービス) |
Agentforce と freee MCP の連携フロー
AgentforceのネイティブMCPクライアント機能を使うことで、Agent Builderから直接freee MCPサーバーに接続できます。
- ユーザー
- Agentforce
- freee MCP
- freee API
注意事項
2026年3月時点では、AgentforceのネイティブMCPクライアント機能はPilot段階です。GA版のリリース時期はSalesforce公式発表をご確認ください。Pilot未参加の環境では、Step 1で紹介したApex Invocable Action方式でfreee for Salesforceのデータを活用してください。
応用ユースケース
本記事で構築したエージェントをベースに、さらに発展させることができるユースケースを紹介します。
1. 入金期限超過アラートの自動送信
スケジュールフロー(毎朝9時実行)で未入金かつ入金期限超過の請求書を検出し、Slack通知やメール送信を自動化します。
- 毎朝9時 自動実行
- 未入金請求書を検索
- 期限超過をフィルタ
- Slack / メール通知
2. Salesforce 商談金額との自動照合
商談のCloseDate到来時に、freeeの入金データと自動照合し、消込漏れをリアルタイムに検知します。金額の一致・不一致・振込手数料差異を自動判定できます。
3. 税理士事務所での顧問先請求管理
顧問先ごとにfreeeアカウントを切り替えて請求書ステータスを一元管理する構成です。AgentforceのマルチテナントTopicとして構築することで、1つのエージェントで複数のfreee事業所のデータを横断検索できます。
4. 月次決算前の請求書ステータス一括チェック
月末の経理業務として、全取引先の請求書ステータスを一括で確認するレポートを自動生成します。Agentforceに「今月の請求書ステータスサマリーを出して」と依頼するだけで、送信済み/未送信/入金済み/未入金の内訳を取引先別に集計してくれます。
まとめと本番運用に向けて
本記事で構築したもの
| コンポーネント | 内容 |
|---|---|
| Apex クラス | FreeeInvoiceSearchAction(freee請求書データの検索) |
| Topic | 請求書ステータス確認(InvoiceStatusCheck) |
| Action | freee請求書検索(Apex Invocable Action) |
| 対応する問い合わせ | 取引先名検索、ステータスフィルタ、期間指定、複合条件 |
構築にかかった時間
| 作業 | 所要時間 |
|---|---|
| Apexクラスの開発・テスト | 約1時間 |
| Agent BuilderでのTopic・Action設定 | 約30分 |
| テスト・チューニング | 約1時間 |
| 合計 | 約2.5時間 |
導入効果の見積もり
| 指標 | Before | After |
|---|---|---|
| 請求書ステータス確認の時間 | 5分/件(freeeにログイン→検索→確認) | 10秒/件(Agentforceに質問するだけ) |
| 月間の確認作業工数(50件/月) | 約4時間 | 約8分 |
| 確認漏れのリスク | 月次締めまで検知不可 | リアルタイムで検知可能 |
本番運用時の拡張ポイント
さらなる発展
本記事の構成をベースに、以下のような発展形が考えられます。
- Topic の追加 — 「入金消込チェック」「freee取引データ参照」Topicを追加することで、より包括的な請求管理エージェントに拡張できます。
- freee MCP 連携 — Agentforce MCPクライアントのGA後、freee MCPとの直接連携に切り替えることで、リアルタイムデータにもアクセス可能になります。
- Knowledge 記事との連携 — 「請求書が届いていないと言われた場合の対応手順」などのFAQ記事を登録することで、実務的なガイダンスも提供できるようになります。