はじめに
「Agentforceの標準UIを使わず、自前の画面で生成AIを動かせないか」と聞かれる場面は、Salesforce開発の現場で増えてきています。
私自身もLWCにAI生成機能を組み込もうとして、最初の一歩でしばらく手が止まりました。
そこで使えるのがAgentforce Models APIです。ApexとLWCという普段の開発スキルのまま、Anthropic・Google・OpenAIなど複数プロバイダーのLLMを呼び出せます。
Flowからも@InvocableMethod経由で利用できるため、ノーコード/ローコードの構成にも組み込めます。
この記事では、Models APIの基本構造から、Apex・LWC・Flowそれぞれでの呼び出し方、Einstein Trust Layerが裏で行っている処理、そして実装時にハマりやすいポイントまで一通り整理します。
Models APIとは何か
Models APIは、Salesforceが提供するLLM呼び出し用のAPIです。
Anthropic・Google・OpenAIなど複数のプロバイダーのモデルを、Apexから統一されたインターフェースで呼び出せる設計になっています。
名前空間は aiplatform、中心クラスは ModelsAPI クラスです。開発者は、このクラスが持つ4つのメソッドを呼び出すだけで生成AI機能をアプリに組み込めます。
| メソッド名 | 機能 |
|---|---|
createGenerations() |
テキスト生成(プロンプトに対して回答を生成) |
createChatGenerations() |
チャット生成(メッセージ履歴を元に回答を生成) |
createEmbeddings() |
埋め込みベクトルの生成 |
submitFeedback() |
生成テキストへのフィードバック送信 |
submitFeedback()以外のメソッドは、呼び出す際にモデルのAPI名を指定します。
たとえば
GPT-4o Miniを使う場合は
sfdc_ai__DefaultOpenAIGPT4OmniMini、
Claude Sonnet 4.6なら
sfdc_ai__DefaultBedrockAnthropicClaude46Sonnet
を指定します。
つまり「どのLLMを使うか」をコード側で動的に切り替えられる、ということです。
GPT系からClaude系への切り替えも、API名を変えるだけで済みます。
利用可能なエディション: Enterprise Edition、Performance Edition、Unlimited Edition、Developer Edition(Lightning Experience)
Einstein Trust Layerを経由するとはどういうことか
Models APIへのすべての呼び出しは、Einstein Trust Layerを経由します。これは開発者が意識的に設定する必要はなく、Models APIを使う時点で自動的に適用されます。
Einstein Trust Layerが提供する主な保護機能は以下の通りです。
- 機密データのマスキング:プロンプトに含まれる個人情報などをLLMに渡す前にマスクする
- ゼロリテンション:LLMプロバイダー側にデータが保持されない
- 有害性検出:生成されたテキストの有害コンテンツをチェック
- 監査証跡:すべてのやり取りを記録
正直なところ、最初は「Trust Layerを経由すると遅くなるのでは」と思っていました。
ただ実際に触れてみると、体感の遅延はあまり気にならない水準で、特にセキュリティ要件が厳しい本番環境では安心感があります。
注意点として、データマスキングがONの状態ではコンテキストウィンドウが65,536トークンに制限されます。非常に長いテキストを処理する場合は、この上限を意識した設計が必要です。
ApexからModels APIを呼び出す
テキスト生成(createGenerations)
ModelsAPI.createGenerations()は、与えたプロンプトに対してLLMがテキストを生成する機能です。
呼び出しの基本パターンはこうです。
// リクエストオブジェクトを作成
aiplatform.ModelsAPI.createGenerations_Request request = new aiplatform.ModelsAPI.createGenerations_Request();
// モデルを指定
request.modelName = 'sfdc_ai__DefaultGPT4Omni';
// ボディを作成してプロンプトをセット
aiplatform.ModelsAPI_GenerationRequest requestBody = new aiplatform.ModelsAPI_GenerationRequest();
requestBody.prompt = 'Salesforceの特徴を3つ教えてください。';
request.body = requestBody;
try {
// 実行
aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
aiplatform.ModelsAPI.createGenerations_Response result = modelsAPI.createGenerations(request);
// 生成されたテキストを取得
String generatedText = result.Code200.generation.generatedText;
System.debug(generatedText);
} catch(aiplatform.ModelsAPI.createGenerations_ResponseException e) {
System.debug('Response code: ' + e.responseCode);
System.debug('The following exception occurred: ' + e);
}
リクエストが成功した場合は Code200.generation.generatedText にテキストが格納されます。
エラー時は ModelsAPI.createGenerations_ResponseException がスローされるため、try-catchで適切にハンドリングする必要があります。
チャット生成(createChatGenerations)
チャット形式の場合は createChatGenerations() を使います。
過去のメッセージ履歴を渡すことで、文脈を踏まえた応答が得られます。
// チャットメッセージのリストを組み立てる
List<aiplatform.ModelsAPI_ChatMessageRequest> messages = new List<aiplatform.ModelsAPI_ChatMessageRequest>();
// システムプロンプト(エージェントの振る舞いを定義)
aiplatform.ModelsAPI_ChatMessageRequest systemMsg = new aiplatform.ModelsAPI_ChatMessageRequest();
systemMsg.role = 'system';
systemMsg.content = 'あなたはSalesforceの専門家です。簡潔に回答してください。';
messages.add(systemMsg);
// ユーザーのメッセージ
aiplatform.ModelsAPI_ChatMessageRequest userMsg = new aiplatform.ModelsAPI_ChatMessageRequest();
userMsg.role = 'user';
userMsg.content = 'Agentforceとは何ですか?';
messages.add(userMsg);
// リクエスト作成
aiplatform.ModelsAPI.createChatGenerations_Request request = new aiplatform.ModelsAPI.createChatGenerations_Request();
request.modelName = 'sfdc_ai__DefaultBedrockAnthropicClaude46Sonnet';
// ボディを作成してメッセージをセット
aiplatform.ModelsAPI_ChatGenerationsRequest body = new aiplatform.ModelsAPI_ChatGenerationsRequest();
body.messages = messages;
request.body = body;
try {
// 呼び出し
aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
aiplatform.ModelsAPI.createChatGenerations_Response result = modelsAPI.createChatGenerations(request);
System.debug('Models API response: ' + result.Code200.generationDetails.generations);
} catch(aiplatform.ModelsAPI.createChatGenerations_ResponseException e) {
System.debug('Response code: ' + e.responseCode);
System.debug('The following exception occurred: ' + e);
}
チャット形式は、ユーザーとの連続した会話や、システムプロンプトでAIの振る舞いを細かく制御したい場面に向いています。
LWCからModels APIを呼び出す構成
LWCからModels APIを直接呼ぶことはできません。LWC → Apex → Models API という3層構成がパターンです。
この構成のポイントは、LWC側がUIとプロンプト組み立てを担当し、Apex側がModels APIとの通信を担当するという役割分担です。
Apexクラスの作成
まず、LWCから呼び出せるApexメソッドを作ります。@AuraEnabledアノテーションをつけることでLWCから呼び出せるようになります。
public with sharing class ModelsApiController {
@AuraEnabled
public static String getGeneratedText(String prompt, String modelName) {
try {
// リクエスト作成
aiplatform.ModelsAPI.createGenerations_Request request =
new aiplatform.ModelsAPI.createGenerations_Request();
request.modelName = modelName;
// ボディにプロンプトをセット
aiplatform.ModelsAPI_GenerationRequest requestBody =
new aiplatform.ModelsAPI_GenerationRequest();
requestBody.prompt = prompt;
request.body = requestBody;
// 呼び出し
aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
aiplatform.ModelsAPI.createGenerations_Response result =
modelsAPI.createGenerations(request);
return result.Code200.generation.generatedText;
} catch (aiplatform.ModelsAPI.createGenerations_ResponseException e) {
throw new AuraHandledException('生成エラー: ' + e.getMessage());
}
}
}
LWCのJavaScript側
Apexメソッドをimperative(命令型)で呼び出します。
import { LightningElement } from 'lwc';
import getGeneratedText from '@salesforce/apex/ModelsApiController.getGeneratedText';
export default class ModelsApiDemo extends LightningElement {
prompt = '';
generatedText = '';
isLoading = false;
handlePromptChange(event) {
this.prompt = event.target.value;
}
async handleGenerate() {
this.isLoading = true;
try {
this.generatedText = await getGeneratedText({
prompt: this.prompt,
modelName: 'sfdc_ai__DefaultGPT4Omni'
});
} catch (error) {
console.error('エラー:', error);
} finally {
this.isLoading = false;
}
}
}
LWCのHTML側
<template>
<lightning-card title="AI文章生成">
<div class="slds-p-around_medium">
<lightning-textarea
label="プロンプト"
value={prompt}
onchange={handlePromptChange}
></lightning-textarea>
<lightning-button
label="生成する"
onclick={handleGenerate}
disabled={isLoading}
></lightning-button>
<template if:true={generatedText}>
<p class="slds-m-top_medium">{generatedText}</p>
</template>
</div>
</lightning-card>
</template>
SalesforceのレコードIDやオブジェクトデータをプロンプトに組み込む場合は、@wireデコレータでレコードデータを取得してJavaScript側でプロンプト文字列に埋め込みます。
つまり「CRMのデータを使ってAIに文章を書かせる」という構成が、既存の開発スキルで実現できるということです。
出典:LWC と Models API で、高度にカスタマイズしたAIアプリを作る | Salesforce Developers Blog(日本語)
FlowからModels APIを呼び出す
Flowから呼び出す場合は、@InvocableMethodアノテーションを使います。このアノテーションを付けることで、ApexクラスのメソッドがFlow Builderのアクションとして利用できるようになります。
public with sharing class ModelsApiFlowAction {
public class ActionInput {
@InvocableVariable(label='プロンプト' required=true)
public String prompt;
@InvocableVariable(label='モデルAPI名')
public String modelName;
}
public class ActionOutput {
@InvocableVariable(label='生成テキスト')
public String generatedText;
}
@InvocableMethod(label='Models APIでテキスト生成'
description='指定したプロンプトでLLMからテキストを生成します')
public static List<ActionOutput> generateText(List<ActionInput> inputs) {
List<ActionOutput> outputs = new List<ActionOutput>();
for (ActionInput input : inputs) {
ActionOutput output = new ActionOutput();
try {
String targetModel = String.isNotBlank(input.modelName)
? input.modelName
: 'sfdc_ai__DefaultOpenAIGPT4OmniMini';
// リクエスト作成
aiplatform.ModelsAPI.createGenerations_Request request =
new aiplatform.ModelsAPI.createGenerations_Request();
request.modelName = targetModel;
// ボディにプロンプトをセット
aiplatform.ModelsAPI_GenerationRequest requestBody =
new aiplatform.ModelsAPI_GenerationRequest();
requestBody.prompt = input.prompt;
request.body = requestBody;
// 呼び出し
aiplatform.ModelsAPI modelsAPI = new aiplatform.ModelsAPI();
aiplatform.ModelsAPI.createGenerations_Response result =
modelsAPI.createGenerations(request);
output.generatedText = result.Code200.generation.generatedText;
} catch (Exception e) {
output.generatedText = 'エラーが発生しました: ' + e.getMessage();
}
outputs.add(output);
}
return outputs;
}
}
Flow Builder上では「Apex アクション」として登録されたこのクラスを選択し、プロンプトにFlow変数をバインドするだけで使えます。
AgentforceのエージェントアクションとしてこのApexを登録する場合も同様の仕組みです。

アクションでApexを呼び出すことができる

フローデバッグ画面
つまずきポイント・注意事項
① Apexのコールアウト制限に注意
Models APIの呼び出しは、内部的にはApexのコールアウトとして扱われます。1トランザクション内でのコールアウト上限(デフォルト100回)と、タイムアウト制限(最大120秒)の両方が適用されます。
複雑な処理とModels API呼び出しを組み合わせる場合は、この制限を意識した設計が必要です。
② レート制限:本番と開発環境でまったく異なる
環境によってレート制限が大きく異なるため、開発段階でうまく動いていても本番でハマることがあります。
| 環境 | 制限 |
|---|---|
| 本番環境 | 500 RPM(モデルによって変動) |
| サンドボックス(Apex経由) | 200 req/時 |
| デモ・トライアル | 150 req/時 |
サンドボックスの制限は特に厳しく、連続テストを繰り返していると上限に当たることがあります。429エラーが返ってきたときはレート制限を疑うのが先決です。
③ 呼び出しはすべてEinstein Requestsとして課金対象
Models APIの呼び出しはすべてEinstein Requestsの消費となります。開発・テスト段階からFlexクレジットを消費するため、特にサンドボックスでの反復テストでは使用量の管理が必要です。
Digital Walletで定期的に消費量を確認する習慣をつけておくと安心です。
④ 非同期コンテキストからの呼び出しに注意
@futureアノテーションの非同期Apexからコールアウトするには callout=true の指定が必要です。
バッチApexからのModels API呼び出しは制限があるため、同期的なコンテキスト(LWCからのimperative call、Flowのアクション)で使うのが基本的に安全です。
まとめ
- Models APIは
aiplatform名前空間のApexクラスで提供。Apex・LWC・Flowから呼び出せる - 主要メソッドは
createGenerations()(テキスト)、createChatGenerations()(チャット)、createEmbeddings()(埋め込み)の3種類 - LWCからは「LWC → Apex → Models API」の3層構成が基本パターン
- Flowからは
@InvocableMethodでApexをアクション化して呼び出す - すべての呼び出しがEinstein Trust Layerを経由し、データマスキング・ゼロリテンションが自動適用される
- 本番環境と開発環境でレート制限が大きく異なるため、早めに確認しておく
「既存のLWC開発スキルでここまでできるのか」と感じている方は、まずDeveloper Edition環境で試してみることをおすすめします。思ったより入り口は低いという印象を持っています。
AI×資格学習・Salesforce業務活用の情報をnoteでも発信しています。


