LLM単体では不可能な「利害調整」を実装する:Pythonで作るAIエージェント自動交渉システムの設計思想
近年、ビジネスの現場におけるAI活用は急速に進化し、RAGによる社内文書検索やFunction CallingによるAPI実行が実用化されています。しかし、システム受託開発やITコンサルティングの現場では、多くのプロジェクトが共通の「壁」に直面する傾向にあります。
それは、「利害が対立する状況下での意思決定」です。
例えば日程調整において、単一エージェントが空き時間を提示するのは容易です。しかし、相手の都合や優先順位、譲れない条件(重要な商談の可能性や移動時間など)といった複雑な事情をすり合わせるプロセスこそが、ビジネスにおける「調整」や「交渉」の本質です。
単一のLLMに「安く仕入れて」と指示しても、相手の提示価格をそのまま受け入れるか、ルールベースで拒否するかの二択になりがちです。これではビジネスで求められる「落とし所を見つける」高度な振る舞いは実現できません。
ビジネスモデル構築の観点から、「タスクの実行(Execution)」と「合意の形成(Consensus)」には全く異なるアプローチが必要です。既存のAIエージェントは前者に長けていますが、後者はまだ黎明期にあります。本記事では、技術的な実現可能性とビジネス上の成果を両立させる視点から、自動交渉システムの設計思想を解説します。
単一エージェントの限界とマルチエージェントの利点
「LLMに一人二役をさせればよい」と思うかもしれません。プロンプトで買い手と売り手の両方を演じさせれば(Self-Play)、それらしい会話ログは生成されます。
しかし、モデルが同一のコンテキストを共有するため、情報の非対称性を維持できないという構造的な課題があります。
交渉で最も重要なのは、予算上限や原価下限といった秘匿情報(Private State)です。一人二役では相手の手札が完全に見えており、緊張感のある駆け引きや相手の出方を探るプロセスは生まれません。最新LLMの推論能力が高くても、この限界は存在します。
マルチエージェントシステム(MAS)で各エージェントを独立したインスタンスとして設計し、異なる「目標」と「秘密」を持たせることで初めて、現実世界に近いシミュレーションや、実務に耐えうる信頼性の高い代行が可能になります。
「合意形成」がビジネスプロセス自動化の鍵になる理由
社内の会議室予約システムが、単なる「早い者勝ち」ではなくなった状況を想像してください。
- Agent A: 「この時間帯、どうしても重要顧客との面談で使いたいんです。譲ってくれませんか?」
- Agent B: 「こちらも定例会議なんですが...わかりました。では、来週の優先予約権を譲ってくれるなら、今回は時間をずらしましょう」
金銭だけでなく「条件」や「権利」を交換し、組織全体の最適解を導くプロセスこそが次世代の自動化です。実現には、エージェント同士が対話し妥協点を探る「自動交渉」の仕組みが不可欠です。
本記事で作成する「最小構成プラットフォーム」の全体像
本記事では、AutoGenやCrewAIといったフレームワークをあえて使いません。内部ロジックがブラックボックス化され、「なぜ交渉が成立・決裂したのか」というデータに基づいた客観的な分析が難しくなるためです。
今回はPythonとLLMのAPIのみを用い、「Buyer(購入者)」と「Seller(販売者)」が1対1で価格交渉を行い、合意に至るまでの最小構成をフルスクラッチで実装します。読者が自身の業務にすぐ取り入れられるよう、再現性を重視した構成としています。
ここで重要なのがモデルの選定です。OpenAIの公式情報(2026年2月時点)によると、GPT-4oやGPT-4.1、OpenAI o4-miniといったレガシーモデルは2026年2月13日をもって廃止されました。既存チャットは新モデルへ自動移行され、APIの世代交代が進んでいます。
そのため本実装では、最新の業務標準モデルGPT-5.2を想定して構築します。GPT-5.2は100万トークン級のコンテキストウィンドウを持ち、Thinking(思考プロセス)とInstant(即時応答)の自動ルーティングが向上しているため、高度な推論を要する交渉エージェントに最適です。開発支援にはコーディング特化のGPT-5.3-Codexも有効です。レガシーモデルに依存したコードやプロンプトは、GPT-5.2環境で再テストし移行することを推奨します。
「車輪の再発明」に思えるかもしれませんが、交渉の深層構造を理解することは、将来複雑なシステムを構築する際の強固な土台となります。
設計編:交渉を成立させる3つの技術要素
コードを書く前にアーキテクチャを設計します。エージェント同士をチャットさせるだけでは交渉になりません。システムとして成立させるには、以下の3要素を厳密に定義する必要があります。
1. エージェントの「役割(Persona)」と「目標(Goal)」の定義
各エージェントは、以下の情報を持つ独立したオブジェクトとして設計します。
- Public Profile(公開情報): 名前、肩書き、初期提案価格など。相手に知られても良い情報です。
- Private Goal(秘匿情報):
- Target Price(目標価格): 理想的な着地点。
- Reservation Price(留保価格/許容限界価格): これを超えたら交渉を決裂させるというデッドライン。
- Strategy(戦略): 譲歩のスタンス(強気、協調的、急いでいるなど)。
最も重要なのがReservation Price(留保価格)です。交渉学のBATNA(交渉決裂時の最善の代替案)とも関連しますが、システム上は「これ以上は絶対に譲れないライン」として設定します。これがないと、LLMは際限なく譲歩したり全く譲らなかったりと、不安定な挙動を示します。
2. 対話プロトコル:ターン制と終了条件の設計
人間同士の会話には割り込みや沈黙がありますが、システム上の交渉には明確な構造(プロトコル)が必要です。
- Turn-taking(ターン制): 必ず交互に発言する(Buyer -> Seller -> Buyer...)。状態管理をシンプルにするためです。
- Action Space(行動空間): エージェントが取れる行動を制限します。今回は以下の4つに限定します。
- Offer: 新しい価格を提案する。
- Accept: 相手の提案を受け入れる(合意形成)。
- Reject: 相手の提案を拒否する(現状維持)。
- Quit: 交渉を終了する(決裂)。
- Max Rounds(最大ラウンド数): 無限ループを防ぐため、例えば「10往復しても決まらなければ決裂」という強制終了ルールを設けます。
3. 共有メモリ:コンテキストをどう同期させるか
ここが実装の肝です。各エージェントは独自の「脳(LLMのコンテキスト)」を持ちますが、交渉の履歴(History)は共有される必要があります。
「環境(Environment)」または「仲介者(Mediator)」クラスを用意し、会話履歴を一元管理します。エージェント同士が直接通信せず、常に「環境」を介してメッセージを受け渡す設計にします。
- Buyerが「環境」にメッセージを投げる。
- 「環境」が履歴を更新し、Sellerにターンを渡す。
- Sellerは「環境」から直前のメッセージを受け取り、思考する。
このアーキテクチャにより、デバッグやログ監視が容易になり、プロジェクト進行における円滑なコミュニケーションの基盤となります。
実装Step 1:交渉エージェントのプロンプトエンジニアリング
具体的な実装に入ります。まずはエージェントの思考を司るプロンプト設計です。思考の過程(Chain of Thought)と、システムが解釈可能な構造化データ(JSON)を分離して出力させることが重要です。
自然言語と構造化データの分離
LLMの出力を自然言語だけに頼ると、後続プログラムで価格数値(8000など)を抽出する際に正規表現などの複雑な処理が必要になり、バグの温床となります。
最初からJSON形式で思考させます。PythonのPydantic等も使えますが、ここでは原理理解のためシンプルなプロンプトで制御します。
以下は、Seller(売り手)エージェントのシステムプロンプト例です。
SELLER_SYSTEM_PROMPT = """
あなたは中古PCの販売者です。以下の条件に従って交渉を行ってください。
# あなたの条件
- 目標販売価格: 15,000円
- 最低販売価格(これ以下なら売らない): 12,000円
# 戦略
- 最初は目標価格に近い金額を提示し、徐々に譲歩してください。
- 相手の提案が最低販売価格を下回る場合は、理由を述べて拒否し、対案を出してください。
- 相手の提案が最低販売価格以上であれば、利益を最大化しつつ合意(Accept)を検討してください。
# 出力フォーマット
必ず以下のJSON形式のみを出力してください。余計な文章は不要です。
{
"thought": "相手の提案に対するあなたの思考プロセス(なぜその行動をとるのか)",
"action": "Offer" | "Accept" | "Reject" | "Quit",
"price": 数値 (Offerの場合のみ提案価格、それ以外は0またはnull),
"message": "相手へのメッセージ(交渉の言葉)"
}
"""
Buyerエージェント:予算制約と購買意欲のバランス
同様に、Buyer(買い手)のプロンプトも作成し、「安く買いたい」というインセンティブを持たせます。
BUYER_SYSTEM_PROMPT = """
あなたは中古PCの購入希望者です。
# あなたの条件
- 予算上限: 13,000円
- 目標購入価格: 10,000円
# 戦略
- 予算オーバーの提案は絶対に受け入れないでください。
- 粘り強く交渉し、可能な限り安く購入することを目指してください。
# 出力フォーマット
(Sellerと同じJSON形式)
"""
thought(思考)とmessage(発話)を分けることで、エージェントは「本音」と「建前」を使い分けることができ、人間らしい交渉が可能になります。
実装Step 2:合意形成プラットフォーム(環境)の構築
次に、2体のエージェントが活動する「場(プラットフォーム)」を構築します。Pythonのクラスを使い、メッセージのルーティングと状態管理を行います。
Mediator(仲介役)の実装とメッセージルーティング
エージェント同士を直接通信させず、必ず「環境(Environment)」を介してやり取りさせる設計にします。これにより、会話ログ管理、不正アクション監視、終了条件判定を一元管理できます。
NegotiationEnvironmentクラスを作成し、以下の機能を持たせます。
- 履歴管理: 交渉の全プロセスを時系列データとして保持。
- ターン制御: 発言権(ターン)の管理。
- 終了判定:
Accept(合意)やQuit(決裂)のアクション、または最大ターン数を監視。
import json
from typing import List, Dict, Optional
class NegotiationEnvironment:
def __init__(self, max_rounds=10):
self.history: List[Dict] = []
self.max_rounds = max_rounds
self.current_round = 0
self.status = "ongoing" # ongoing, agreed, failed, failed_timeout
def add_event(self, agent_name: str, action_data: Dict):
"""
エージェントのアクションを履歴に追加し、交渉の状態を更新する
"""
event = {
"round": self.current_round,
"agent": agent_name,
"action": action_data.get("action"),
"price": action_data.get("price"),
"message": action_data.get("message"),
"thought": action_data.get("thought") # デバッグ用に思考プロセス(CoT)も保存
}
self.history.append(event)
# 終了判定ロジック
action = action_data.get("action")
if action == "Accept":
self.status = "agreed"
elif action == "Quit":
self.status = "failed"
elif self.current_round >= self.max_rounds:
self.status = "failed_timeout"
def get_last_message(self) -> Optional[Dict]:
"""直前のメッセージを取得"""
if not self.history:
return None
return self.history[-1]
このクラスはシンプルですが、マルチエージェントシステムの核となる「状態管理(State Management)」の役割を果たします。エージェントはこのインスタンスを通じてのみ世界を認識するため、将来的なエージェント数の増加や複雑なルール(外部市場価格の変動など)導入時の拡張性が担保されます。
交渉ループの実行
最後に、これらを動かすメインループを作成します。
ここで重要なのが、LLMを呼び出すcall_llm関数の実装です。OpenAIやAnthropicなどの主要プロバイダーはモデルの推論能力やAPI仕様を頻繁に更新しており、最新モデルは複雑な文脈理解や構造化データの出力精度が向上しているため交渉タスクに最適です。
実装時は特定のモデルバージョンにハードコードせず、設定ファイル等で柔軟に切り替えられるようにすることを推奨します。
def run_negotiation():
env = NegotiationEnvironment()
# 初回はBuyerからスタート(設定により変更可能)
next_agent = "Buyer"
while env.status == "ongoing":
env.current_round += 1
print(f"--- Round {env.current_round} ---")
# 直前の相手のメッセージを取得し、コンテキストを形成
last_msg = env.get_last_message()
if last_msg:
context = f"直前の相手のメッセージ: {last_msg['message']} (提示価格: {last_msg['price']})"
else:
context = "交渉を開始してください。希望価格を提示し、その根拠を述べてください。"
# LLMを呼び出してアクションを決定
# ※ call_llmは、各社の最新SDKを用いて実装してください(OpenAI, Anthropic等)
if next_agent == "Buyer":
# Buyerのシステムプロンプトとコンテキストを渡す
response = call_llm(BUYER_SYSTEM_PROMPT, context)
env.add_event("Buyer", response)
next_agent = "Seller"
else:
# Sellerのシステムプロンプトとコンテキストを渡す
response = call_llm(SELLER_SYSTEM_PROMPT, context)
env.add_event("Seller", response)
next_agent = "Buyer"
# 結果の表示(ストリーミング出力のように逐次確認)
print(f"{response.get('agent', next_agent)}: {response.get('message')} "
f"(Action: {response.get('action')}, Price: {response.get('price')})")
print(f"\n交渉終了: 結果 = {env.status}")
return env.history
このコードを実行すると、コンソール上で2体のAIが「15,000円はどうですか?」「予算オーバーです、10,000円なら即決します」「では間をとって12,500円で...」といった人間さながらの駆け引きを繰り広げます。
最新LLMを使用すれば、価格の往復だけでなく論理的な説得や戦略的な発言も観察できます。ログのthought(思考プロセス)を確認し、AIの発言意図を分析することも可能です。
検証とチューニング:交渉を収束させるコツ
実際にシステムを動かすと、「話が噛み合わない」「決まらない」「すぐに諦める」などの問題に直面します。これらを解決する実践的なチューニング手法を紹介します。
Temperature設定と創造性のバランス
交渉において、Temperature(生成のランダム性)の設定は重要です。
- 高すぎる(0.7以上): 創造的な提案ができる一方で、JSONのフォーマットが崩れたり、突拍子もない価格(いきなり0円など)を提示するリスクが増えます。
- 低すぎる(0.2以下): 安定しますが、頑固になりがちです。「1円もまけられない」という同じセリフを繰り返し、デッドロックに陥ることがあります。
一般的なチャットモデルを使用した交渉エージェントには0.3〜0.5程度の設定が適しています。
ただし、最新の推論強化モデル(思考プロセスを内包するモデル等)を使用する場合は注意が必要です。Temperatureを1.0(デフォルト)に固定することが推奨されるケースがあるため、公式ドキュメントで仕様を確認してください。
また、フォーマット崩れを防ぐため、OpenAI等のAPIで提供されるStructured Outputs(構造化出力)や「Function Calling(Tool Use)」を活用し、出力を厳格なJSONスキーマに準拠させることが不可欠です。
よくある失敗:譲歩しないエージェントへの対処
最も多い失敗は、双方が譲らず並行線をたどることです。これを防ぐには、プロンプトに「時間経過による譲歩(Time-dependent Strategy)」を組み込むのが効果的です。
例えば、システムプロンプトに以下の指示を追加します。
現在のラウンド数が進むにつれて、合意を優先するために譲歩の幅を広げてください。ラウンド8を超えたら、利益が少なくても決裂よりは合意を選んでください。
また、プログラム側で現在のラウンド数をプロンプトに注入(Inject)し、エージェントに「焦り」を感じさせることも可能です。
「戦略的譲歩」を促すプロンプトの改善テクニック
人間味のある交渉には、ZOPA(Zone of Possible Agreement:合意可能領域)を意識させることが重要です。
- Buyerの上限: 13,000円
- Sellerの下限: 12,000円
この場合、12,000円〜13,000円がZOPAです。思考プロセス(thought)内で「相手の提示額から下限を推測する」よう指示を与えると、収束スピードが格段に上がります。
なお、AIモデルの進化は速く、旧世代モデルは順次廃止(Deprecation)やアクセス方法の変更が行われます。システム設計時は特定バージョンに依存せず、環境変数等で柔軟に切り替えられるようにすることを強く推奨します。目的に応じた最新モデルの選択が交渉の質を向上させます。
次のステップ:2者間交渉から多地点マーケットプレイスへ
今回構築した1対1の交渉システムは最小単位のモデルですが、この基本設計はより大規模なシステムへ拡張可能です。
1対N、N対Nへのスケーリング課題
例えば、1人のBuyerに複数Sellerが入札する「オークション形式」や「マッチングプラットフォーム」への拡張です。この場合、Mediator(環境)の役割がより重要になり、メッセージのブロードキャストや密室交渉など、情報の流路設計がカギとなります。
人間が承認プロセスに介入するHuman-in-the-loop
完全自動化を避ける場合、最終的な合意(Accept)のみ人間が承認するフローに変更できます。エージェントが「条件のすり合わせ」を行い、最後に人間に通知を送る仕組みです。これにより、AI倫理の観点からAIの暴走リスクを抑えつつ、社会的な責任を果たしながら調整業務の大部分を自動化できます。
次に学ぶべきフレームワーク
基礎を理解した今なら、AutoGenやCrewAI、LangGraphといった高度なフレームワークも深く理解できるはずです。これらは「会話の順番制御」や「履歴管理」を抽象化し、複雑なチーム構成(交渉役、リサーチャー、監査役の連携など)を容易に実装可能にします。
まずは今回紹介したシンプルなコードを動かし、AI同士が「意志」を持ってぶつかり合う様子を体験してください。単なるチャットボットとは違う、自律的な知性の萌芽が感じられるはずです。
コメント