Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

AIエージェントのための段階的セマンティックレイヤの育て方

SansanのData Direction Groupの中村崚です。

前回、齊藤が「AgenticとWorkflowを"いい感じに"併用する」という設計論を書きました。探索寄りの依頼にはAgenticが強く、定型出力寄りの依頼にはWorkflowが強い、という話でした。

Data Direction Groupブログリレー4回目の本記事では、Workflowを支える「セマンティックレイヤ」の構築方法を、データエンジニアリングの観点から解説します。

私たちは現在、営業支援AIエージェントを開発しています。ユーザーが自然言語で依頼を投げると、エージェントが蓄積された営業活動に関するデータを探索し、必要な情報をまとめて返す構成です。その過程で「生データをそのままエージェントに渡しても使い物にならない」という壁にぶつかり、セマンティックレイヤを段階的に育てるアプローチに辿り着きました。

以下、この開発を通じて得られたプラクティスを、具体的な事例とともに紹介します。


最初の壁:Text-to-SQLの限界と生データの課題

まず、私たちがぶつかった壁について説明します。開発初期、以下のシンプルな構成で検証しました。

  • データ:Sansanが保有するCRM/SFAのデータや企業・ニュースなどのマスタデータを未加工状態でBigQueryに格納
  • MCP Toolbox for Databases経由のクエリ:MCP Toolbox for Databasesを介して、エージェントが自由にSQLを発行
  • AIエージェント:ユーザーの自然言語による依頼を受け、SQLを生成・実行し結果を返す

結果として、意図しないテーブルの参照や条件の抜け落ち、存在しないカラムの指定など、エージェントは誤ったクエリを発行してしまいました。業務で使えるレベルには程遠い状態でした。

原因は、生データにビジネスコンテキストが欠如していることです。具体例を挙げます。

  • 「架電」の記録があっても「留守電」の場合がある。単純なカウントでは実際に会話できた件数と異なる
  • 「失注日」の管理方法が曖昧。失注日カラムが入っているレコードもあれば、ステータス変更で判断すべきケースもある
  • 「グループ企業」や「キーマン」の定義がない。「A社グループの売上」と言われても、どこまでをグループと見なすかが不明確
  • 「ARR」の算出方法が不明。「今月のMRR × 12」なのか、別の定義があるのか

これらはドメイン知識がなければ正しく解釈できません。エージェントに自由なSQL生成を任せても、こうしたニュアンスを汲み取ることは期待できません。


解決策:セマンティックレイヤの段階的構築

この課題に対して、私たちはセマンティックレイヤを段階的に構築するアプローチを採用しました。以下、具体的なステップを紹介します。

Step 1: ユースケースの選定

「営業活動を支援する」といっても、ロールによって求めるものは異なります。マーケティング担当者であればメール配信ターゲットの抽出効率化を求めますし、カスタマーサクセス担当者であれば既存顧客のフォローアップに注力したいでしょう。
最初から全領域をカバーしようとすると、データの集約・整備・プロンプト設計も複雑になりすぎます。そこで、まずは想定されるユーザーとユースケースを列挙し、優先順位を定めました。具体的には「商談準備のための公開企業情報レポート」や「現在進行中の商談サマリ作成」など、価値の高い10程度のユースケースに絞って対応することにしました。
中根の記事でも触れられていた「屋台骨に最短で辿り着く」という考え方と同じです。

Step 2: データモデリングによる探索範囲の限定

ユースケースが決まったら、次はデータモデリングです。以下の3層でデータを整理しています。

  • prep:ノイズ除去、正規化。不要カラムの削除や表記ゆれの統一(エージェントは参照しないレイヤ)
  • dim/fact:ディメンショナルモデリング。企業マスタ、案件ファクト、活動ファクトなどへの整理
  • agg:主要な集計済みマート。月次売上サマリ、営業活動KPIなど利用頻度の高い事前集計

ポイントは、エージェントが参照すべきデータを「構造化」かつ「限定的」にすることです。

生データをそのまま見せるのではなく、分析に適した形に整えることで、ハルシネーションのリスクを低減できます。探索すべき領域が絞られ、クエリ生成の複雑さも下がります。

Step 3: MCP Toolboxをセマンティックレイヤとして機能させる

モデリングしたdim/fact/aggだけでは不十分です。「このテーブルをどう使えば、どんな問いに答えられるか」という意味づけが必要になります。

前述の通り、MCP Toolbox for Databasesは開発初期から使用していました。当初は自由にSQLを発行できる構成でしたが、ここではPreset Query Toolsを定義し、セマンティックレイヤとして機能させるよう進化させました。

具体的には、get_company_summary(company_id)get_pipeline_by_stage(stage, period) のようなToolを定義しています。各Tool内部ではTemplate化されたSQLが実行されるため、確定的な挙動になります。

この設計の狙いは、エージェントの役割を「SQLの組み立て」から「Toolの選択」にシフトさせることです。エージェントはユーザーの依頼と各Toolの説明を見比べて最適なToolを選び、Tool内部では決まったSQLが実行されます。エージェントは返ってきた結果をユーザー向けに整形することに集中します。

前回の齊藤の記事で言う「Workflow型」の実装がこれに当たります。参照範囲・クエリ・出力形式が固定されているため、再現性が高く、「揃う」アウトプットが出せます。

Step 4: 自由クエリを探索用のfallbackとして残す

すべてをWorkflow型で固めてしまうと、新しいユースケースの発掘が難しくなります。

そこで、自由にSQLを発行できるMCP Toolも並行して用意しています。既知のユースケースはPreset Query Tools(Workflow型)で対応し、未知の探索的な依頼はFree SQL Tool(Agentic型)で対応する使い分けです。そのため、dim/fact/aggにおいては、テーブルやカラムのdescription(説明)も整備することでAgentic型でのハルシネーションを抑制しています。

それでもなお、Agentic型ではハルシネーションやパフォーマンスの課題が付きまといます。そのため、頻出するパターンやユーザーフィードバックからWorkflow型に落とし込めるユースケースが見つかったら、それを起点にリモデリングとセマンティックレイヤ構築を進めています。

探索(Agentic)で発掘し、定型化(Workflow)で固める。このサイクルを回し続けることで、セマンティックレイヤを段階的に成長させていきます。

現時点での構成図

現在地:このアプローチは機能しているか

現在は、当初想定していたユースケースを実装し、実際の営業メンバーにも触ってもらっています。感触としても非常に良く、段階的に育てるアプローチが機能していることを実感しています。

機能拡張要望もいただいており、追加のユースケースへの対応のためのデータ追加やセマンティックレイヤ構築を進めています。まさに「探索→定型化」のサイクルが回り始めているところです。


まとめ

営業支援AIエージェントの開発を通じて、私たちは以下のプラクティスを得ました。

生データをそのまま渡さない。AIエージェントに生データを渡しても、業務で使えるレベルにはなりません。モデリング層で整理し、セマンティックレイヤで「意味」を付与して、初めてエージェントが正しくデータを扱えるようになります。

最初から完璧を目指さない。重厚な基盤を最初から作るのではなく、必要に応じて育てていくアプローチが有効です。私たちもMCP Toolboxで自由クエリから始め、課題が見えてからPreset Query Toolsへと進化させました。

探索と定型化のサイクルを回す。探索(Agentic)で新しいユースケースを発掘し、定型化(Workflow)で固める。このサイクルを回し続けることが、変化の速いAI領域でセマンティックレイヤを育てていく鍵です。

現場に積極的に入り込む。ユースケースの発掘はデータを眺めているだけでは進みません。私たちの場合は営業メンバーでしたが、実際にエージェントを使うユーザーに話を聞きに行き、現場の課題を拾い上げることが、セマンティックレイヤを実際に使われるものへと育てる近道です。

AIエージェント開発においてデータ整備に悩んでいる方の参考になれば幸いです。

さいごに

AIが驚異的に進化する今。ビジネス課題の発掘とそれらを解決するための適切なデータ整備やAIエージェント開発の検証サイクルを高速に回し、価値を生み出す。これらを一気通貫して実現できる環境はなかなか無いと思います。本記事を読み興味が湧いた方、是非お話しましょう!

© Sansan, Inc.