Agentforce Agent Script 入門 — Agent Builder との違いとカスタマーサポート標準化への活用

約18分で読めます

Agentforce Agent Script 入門 — Agent Builder との違いとカスタマーサポート標準化への活用

はじめに

社内の IT 勉強会で Agentforce を触り始めてしばらく経つ中、「Agent Script」という機能の存在を知りました。Agent Builder とは設計思想がかなり異なると聞き、まずはカスタマーサポート対応の標準化を題材に試してみました。

この記事では、

  • Agent Builder と Agent Script がそれぞれどういう仕組みか
  • 2 つのアプローチを比較したときにどんな違いがあるか
  • 実際に Agent Script を使ってカスタマーサポートフローを組んでみた経緯と結果
  • 使ってみてわかったメリット・デメリットと使い分けの考え方

をまとめています。Salesforce を触り始めて間もない方や、Agent Builder は知っているけど Agent Script はまだという方に、少しでも参考になれば幸いです。

alt text


1. Agent Builder おさらい

まず、従来の Agent Builder の仕組みをざっくりおさらいします。

Agent Builder は、Agentforce の中心的な設定画面です。「このエージェントは何をする存在か」をトピック(Topic)として定義し、そのトピックに対して実行できるアクション(Action)を紐づけることで AI エージェントの振る舞いを設計します。

alt text

会話の流れはあらかじめ細かく決めず、ユーザーの発言内容を AI(Einstein)がリアルタイムに判断して、適切なアクションを選んで応答します。

つまり Agent Builder における会話制御の主役は AI であり、開発者はあくまで「何ができるか」を定義するだけで、「どの順番でどう進めるか」は AI に委ねる設計です。

この柔軟さは大きな強みで、想定外の質問にも対応しやすく、幅広い問い合わせを一つのエージェントで受け付けることができます。


2. Agent Script とは何か

Agent Script は、会話の流れを「ステップ」として明示的に定義できる機能です。日本では 2026 年 2 月からベータ提供が開始されました。

Agent Builder と根本的に異なるのは、会話の構造が可視化されている点です。各ステップで「何を確認するか」「次にどこへ進むか」をあらかじめ定義することで、エージェントの動きを開発者がコントロールできます。

alt text

重要なのは、Agent Script はフローを「固定する」ためだけの機能ではない点です。各ステップの中で AI にどこまで裁量を持たせるかは設計次第で、全ステップを AI に任せる形でも書けます。「構造は開発者が決め、その中で AI が動く」というイメージで、Agent Builder でできることはすべて Agent Script でも実現できます。

また、ステップが明示されていることでテストがしやすくなっています。「このステップでこう入力したらどう動くか」をパターンごとに確認しやすく、動作確認の効率が Agent Builder よりも上がります。


3. Agent Builder vs Agent Script 比較

2 つの違いを表にまとめます。

観点Agent BuilderAgent Script
会話構造の可視化なし(AI が内部で判断)あり(ステップとして明示)
AI への裁量の渡し方全体を AI に委ねるステップごとに調整できる
テスト・デバッグのしやすさ動作が追いにくいステップ単位で確認しやすい
設定の学習コスト比較的低いステップ設計の理解が必要
リリース状況GA(正式リリース)ベータ版(日本は 2026 年 2 月〜)

「AI の制御度」ではなく「構造の透明性」と「テスタビリティ」が主な違いです。Agent Script は Agent Builder の代替ではなく、同じことをより見通しよく設計できる手段として捉えるとわかりやすいです。この点は後半の 7. Agent Script は新規開発の第一選択になるか でも触れます。


4. 実装:カスタマーサポート対応の標準化に挑戦

解決したかった課題

今回 Agent Script を試そうと思ったきっかけは、カスタマーサポートの問い合わせ対応にあるばらつきでした。

担当者によって確認する情報の順番が異なったり、必要な情報を聞き忘れたまま対応を進めてしまうことがあり、「最低限このフローを守ってほしい」という業務要件がありました。Agent Builder だけでは AI の判断に依存する部分が多く、フローの統一が難しかったのです。

Agent Script のセットアップ

Agent Script は、Salesforce の設定画面からアクセスできます。

新規スクリプトを作成する際は、まずスクリプト全体の目的を定義し、続いて個々のステップを追加していきます。各ステップには以下のような要素を設定できます。

  • ステップのタイトル(何を確認するステップか)
  • AI がユーザーに伝えるメッセージや確認事項
  • 次のステップへの遷移条件(条件分岐)
  • ステップ内で呼び出すアクション

組んだフローの概要

今回作成したカスタマーサポート対応のスクリプトは、大まかに以下の流れです。

  1. 問い合わせ内容のカテゴリ確認(注文・返品・その他)
  2. カテゴリに応じた情報収集(注文番号・購入日・症状など)
  3. 収集した情報をもとにした対応案の提示
  4. 対応完了の確認・クローズ

押さえておきたい注意点

Agent Script は YAML や JSON ではなく、Salesforce 独自の DSL(ドメイン固有言語)です。ファイルは .agent 拡張子で記述し、ブロック構造はインデントで表現します。コメントは # を使います。

実装を通じてハマりやすかったポイントを 4 つ取り上げます。

1. ブロックの順序と system の必須項目

トップレベルブロックには決まった順序があります(config → system → language → variables → start_agent / topic)。また system ブロックには instructions だけでなく、messages.welcomemessages.error の 2 つが必須です。どちらが欠けても起動時にエラーになります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
config:
  developer_name: "Customer_Support_Agent"
  agent_label:    "Customer Support Agent"

system:
  instructions: |
    あなたはカスタマーサポートエージェントです。
  messages:
    welcome: "カスタマーサポートへようこそ。どのようなご用件でしょうか?"  # 必須
    error:   "申し訳ありません。システムエラーが発生しました。"           # 必須

variables:
  inquiry_category: mutable string = ""
  order_id:         mutable string = ""

2. @utils.setVariablesreasoning.actions 内でアクション名に直接参照する

変数を LLM にセットさせるには @utils.setVariables を使いますが、Flow や Apex と異なり topic.actions には定義できません。reasoning.actions 内でアクション名の右に @utils.setVariables を直接指定し、値は with で渡します。set @variables.xxx = @outputs.xxx のような記述は不要です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# ✅ 正しい書き方 — reasoning.actions 内でアクション名に直接参照
reasoning:
  actions:
    set_classify_inquiry: @utils.setVariables
      description: "カテゴリをセット"
      with inquiry_category: ...      # with で変数に直接セットされる

# ❌ 誤り — topic.actions に @utils.setVariables は定義できない
topic order_inquiry:
  actions:
    set_var:
      target: "@utils.setVariables"   # コンパイルエラー

3. 遷移ロジックは after_reasoning:-> に書く

reasoning.instructions-> ブロックは LLM が動く に実行されます。そのため、ここに transition to を書いても変数はまだ空のままで条件が永遠に True にならず、遷移が発火しません。変数への代入は LLM の推論完了後に確定するため、遷移ロジックは after_reasoning:-> に置く必要があります。-> の付け忘れもコンパイルエラーになります。また else ifif のネストはサポートされていないため、sequential な if で記述します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# ❌ 誤り — reasoning.instructions の -> は LLM 実行前なので変数がまだ空
reasoning:
  instructions:->
    if @variables.inquiry_category == "ORDER":
      transition to @topic.order_inquiry    # 変数未設定のため発火しない

# ✅ 正しい書き方 — LLM 推論完了後に実行される after_reasoning:->
after_reasoning:->                          # -> の付け忘れはコンパイルエラー
  if @variables.inquiry_category == "ORDER":
    transition to @topic.order_inquiry      # LLM が変数をセット済みのタイミング
  if @variables.inquiry_category == "RETURN":   # else if は非対応 → sequential な if
    transition to @topic.return_inquiry
  if @variables.inquiry_category == "OTHER":
    transition to @topic.general_support

4. {!@variables.xxx}| のプロンプト内のみ有効

-> コードブロックの with 句など手続き的な箇所では @variables.xxx と直接書きます。{!@variables.xxx} のテンプレート式が使えるのは | で囲まれたプロンプトテキストの中だけです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# ✅ | プロンプトテキスト内 — {!@variables.xxx} が使える
reasoning:
  instructions:->
    if @variables.order_id != "":
      | 注文番号 {!@variables.order_id} の情報を確認しました。

# ✅ -> コードブロック内(with 句など) — @variables.xxx を直接書く
actions:
  get_order: @actions.search_order
    with order_id=@variables.order_id      # テンプレート式ではなく直接参照

# ❌ 誤り — -> ブロック内で {!...} を使うと構文エラー
  get_order: @actions.search_order
    with order_id={!@variables.order_id}   # 構文エラー

サンプルコード全文

上記の注意点を踏まえた、カスタマーサポート対応スクリプトの全体です。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# カスタマーサポート対応 Agent Script
# ファイルパス: force-app/main/aiAuthoringBundles/CustomerSupport/CustomerSupport.agent

config:
  developer_name: "Customer_Support_Agent"
  agent_label: "Customer Support Agent"
  description: "カスタマーサポートの問い合わせを受け付け、クローズまで標準化するエージェント"

system:
  instructions: |
    あなたはカスタマーサポートエージェントです。
    お客様の問い合わせに丁寧かつ正確に対応してください。
  messages:
    welcome: "カスタマーサポートへようこそ。どのようなご用件でしょうか?"
    error: "申し訳ありません。システムエラーが発生しました。しばらくお待ちください。"

variables:
  inquiry_category: mutable string = ""   # ORDER / RETURN / OTHER
  order_id:         mutable string = ""
  order_details:    mutable string = ""
  product_name:     mutable string = ""
  return_reason:    mutable string = ""
  within_period:    mutable boolean = False

start_agent:
  description: "問い合わせ内容を分類し、適切なトピックへ遷移する"

  reasoning:
    instructions:->
      if @variables.inquiry_category == "":
        | ユーザーの問い合わせ内容を確認し、以下のいずれかに分類してください。
        |   ORDER  : 注文・配送に関する問い合わせ
        |   RETURN : 返品・交換に関する問い合わせ
        |   OTHER  : その他
        | 分類が決まったら set_classify_inquiry を使って inquiry_category を設定してください。

    actions:
      set_classify_inquiry: @utils.setVariables
        description: "問い合わせカテゴリを ORDER / RETURN / OTHER のいずれかにセットします"
        with inquiry_category: ...

  after_reasoning:->
    if @variables.inquiry_category == "ORDER":
      transition to @topic.order_inquiry
    if @variables.inquiry_category == "RETURN":
      transition to @topic.return_inquiry
    if @variables.inquiry_category == "OTHER":
      transition to @topic.general_support

topic order_inquiry:
  description: "注文番号を収集し、注文レコードを検索して対応案を提示する"

  actions:
    search_order:
      description: "注文番号でレコードを検索する"
      inputs:
        order_id: string
          description: "検索対象の注文番号"
      outputs:
        order_details: string
          description: "注文の詳細情報"
      target: "flow://Search_Order_Flow"
    close_case:
      description: "ケースをクローズする"
      target: "flow://Close_Case_Flow"

  reasoning:
    instructions:->
      if @variables.order_id == "":
        | 注文番号・注文日・問題の内容(未着 / 破損 / 誤品)をお知らせください。
      if @variables.order_id != "":
        | 注文情報を確認しました。検索結果をもとに適切な解決案をご提案します。

    actions:
      collect_order: @utils.setVariables
        description: "注文番号をユーザーから収集して変数にセットする"
        available when @variables.order_id == ""
        with order_id: ...

      get_order: @actions.search_order
        available when @variables.order_id != ""
        with order_id=@variables.order_id
        set @variables.order_details = @outputs.order_details

  after_reasoning:->
    | 検索結果をもとに、適切な解決案(再配送 / 返金など)を提示してください。
    | 対応完了後、他にお困りの点がないか確認し、問題がなければケースをクローズしてください。

topic return_inquiry:
  description: "返品情報を収集し、ポリシー確認後に対応案を提示する"

  actions:
    check_return_policy:
      description: "返品受付期間内かを確認する"
      inputs:
        product_name: string
          description: "返品対象の商品名"
      outputs:
        within_period: boolean
          description: "返品受付期間内であれば True"
      target: "flow://Check_Return_Policy_Flow"
    close_case:
      description: "ケースをクローズする"
      target: "flow://Close_Case_Flow"

  reasoning:
    instructions:->
      if @variables.product_name == "":
        | 注文番号・返品希望の商品名・返品理由(商品不良 / イメージ違い / 誤注文)をお知らせください。

    actions:
      collect_return: @utils.setVariables
        description: "返品に必要な商品名・返品理由を収集して変数にセットする"
        available when @variables.product_name == ""
        with product_name: ...
        with return_reason: ...

      policy_check: @actions.check_return_policy
        available when @variables.product_name != "" and @variables.return_reason != ""
        with product_name=@variables.product_name
        set @variables.within_period = @outputs.within_period

  after_reasoning:->
    if @variables.within_period == True:
      | 返品受付期間内です。返品手続きの案内をしてください。
    if @variables.within_period == False and @variables.product_name != "":
      | 返品受付期間を超えています。お客様に丁寧にお伝えし、
      | 例外対応の可否を確認するため、上位サポートへのエスカレーションを案内してください。

topic general_support:
  description: "フロー定義外の問い合わせを AI が自律的に対応する"

  actions:
    close_case:
      description: "ケースをクローズする"
      target: "flow://Close_Case_Flow"

  reasoning:
    instructions: |
      お客様の問い合わせ内容に対して、適切な回答をしてください。
      解決できない場合は有人サポートへのエスカレーションを案内してください。
      対応完了後、他にお困りの点がないか確認し、問題がなければケースをクローズしてください。

    actions:
      finish: @actions.close_case
        description: "問題が解決し、お客様の確認が取れたらケースをクローズする"

5. 直面した課題とつまずきポイント

実装を進める中で、いくつかハマった点がありました。同じことを試す方の参考になればと思い、正直に書き残しておきます。

Agent Builder との感覚のギャップ

Agent Builder に慣れていると、最初は「どのステップに何を書けばいいのか」という設計の入り口で迷います。Agent Builder はトピックとアクションを用意すれば AI が会話を組み立ててくれますが、Agent Script はまず会話の骨格を自分で考える必要があります。「AI にどこまで任せて、どこを明示的に制御するか」をステップ設計の段階で意識することが、スムーズな実装への近道です。

ステップの分岐が増えると見通しが悪くなる

条件分岐を重ねると、フロー全体の把握が難しくなります。特に「この条件の場合はどのステップへ飛ぶか」が増えてくると、設定ミスに気づきにくくなりました。事前にフロー図を紙や Miro などで整理してから実装する順序が有効です。

一方で、想定外の質問への対応のように「細かく制御しなくていい領域」は instructions: | だけのトピックとして AI に丸ごと委ねることもできます。どこを決定論的に制御してどこを AI に任せるかの境界を意識して設計することで、不必要に分岐を増やさずに済みます。

alt text

ベータ版特有のエラーはサポートに問い合わせるしかない場面がある

実装中、エラーメッセージが出ても公式ドキュメントにもコミュニティにも情報がなく、Salesforce サポートに直接問い合わせるしか手がない場面がありました。GA 済みの機能であれば Trailhead や Developer フォーラムで解決策が見つかることも多いですが、ベータ版はその蓄積がまだ薄い状態です。「エラーの原因は自分で調べ切れない前提で動く」くらいの心づもりが必要だと感じました。

テスト実行の繰り返しが大切

設定後すぐに本番で動かすのではなく、テストモードでの動作確認が必須です。特に分岐条件の抜け漏れは実際に会話を流してみないと気づきにくいため、パターンを網羅的に試すことをおすすめします。


6. Agent Script のメリット・デメリット

使ってみて感じたことを率直にまとめます。

メリット

対応フローの均一化ができる どのユーザーが利用しても、同じ手順で情報収集と対応が進みます。担当者による対応のばらつきをなくしたい場合に非常に有効です。

業務ルールをそのまま再現できる 「この情報を聞いてから次に進む」「〇〇の場合はこちらへ」といった業務要件を、フロー設計として直接反映できます。AI の解釈に左右されません。

テスト・レビューがしやすい フローが可視化されているため、「このパターンで正しく動くか」を検証しやすいです。チームでのレビューも、フロー図を見ながら議論できます。

AI ツールに構築を手伝ってもらいやすい .agent ファイルはテキストベースの DSL なので、Claude や GitHub Copilot などの AI ツールにスクリプトを貼り付けてレビューや修正を依頼できます。Agent Builder の GUI 設定画面では AI に直接手を動かしてもらうことができませんが、スクリプト形式ならコードと同じ感覚で AI を活用できます。

デメリット

フロー設計のコストがかかる 事前にステップを設計・整理してから実装する必要があります。手順が複雑な業務ほど設計に時間がかかります。

設計が複雑になるとメンテナンスが重くなる 業務フローが変わるたびにスクリプトを更新する必要があります。分岐が多いスクリプトは修正時の影響範囲の確認が大変になります。

現時点ではベータ版でサポート依存になるリスクがある 2026 年 3 月時点ではまだベータ版です。本番運用への採用は GA になってからが安心で、仕様変更や予期しない挙動のリスクは念頭に置いておく必要があります。また、エラーが発生しても公式ドキュメントやコミュニティに情報がなく、Salesforce サポートへの問い合わせが唯一の解決手段になることもあります。GA になるまでは「自己解決できない問題が起きうる」前提で進める覚悟が必要です。

alt text


7. Agent Script は新規開発の第一選択になるか

ここまで触れてきた内容を踏まえると、Agent Script は Agent Builder の「特定用途向け代替」ではなく、新しく作るなら Agent Script を選ぶ方が合理的という結論になります。

理由はシンプルで、Agent Script は Agent Builder でできることをすべてカバーしつつ、会話の構造が可視化されているぶん設計・テスト・レビューがしやすいからです。「手順を固定したい業務だから Agent Script」「自由な対話がしたいから Agent Builder」という振り分けは必要なく、AI の裁量をどこに持たせるかはステップ設計の中で自由に決められます。

alt text

ただし、唯一のブレーキはベータ版であること。既存の本番エージェントをすぐに移行する必要はなく、新規で検証・開発する場合に Agent Script を使いながら慣れていき、GA になったタイミングで本番採用を判断するのが現実的な進め方だと思います。


おわりに

Agent Script を触ってみて一番感じたのは、「Agent Builder でできることが Agent Script でもできる上に、構造が見えているぶん安心して設計できる」という点でした。当初は「手順を固定するための機能」だと思っていましたが、実際には AI の裁量の渡し方を自分でコントロールできる、より表現力の高い設計環境だという理解に変わりました。

個人的な話をすると、コードを書くことに慣れている身としては、GUI でポチポチ設定するよりもテキストでスクリプトを書く方がずっと手に馴染みます。バージョン管理もしやすく、変更の差分がわかりやすい点も気に入っています。「Salesforce の設定がコードで書ける」という体験は、プログラマー寄りの人には素直に楽しいと思います。

今後 GA になれば、新規エージェント開発のデファクトスタンダードになっていく可能性は十分あると思っています。ベータ版のうちに触れておくと、正式リリース後の移行もスムーズになるはずです。同じく試している方がいれば、ぜひ知見を交換しましょう!

TOP