MongoDB は、 OpenAI Agents SDK で構築するエージェントのバッキングデータベースとして使用できます。エージェント SDK は、少数のプリミティブ セットからエージェント アプリケーションを構築するためのPythonフレームワークです。
エージェントは、指示とツールが設定された大規模言語モデル(LLM)です。
ハンドオフ。あるエージェントがタスクを別のエージェントに委任することを可能にするもの。
ガードレール。エージェントの入力と出力を検証します。
セッション。エージェントの実行全体で会話履歴を保存します。
SDK は 2 つのデザイン原則に従っています。実際のアプリケーションをビルドするのに十分な機能が含まれていますが、短時間で学ぶのに十分なほど少ないプリミティブです。そのデフォルト設定でも良い結果が得られます。また、エージェントの実行する各ステップをカスタマイズできます。
Agents SDK で MongoDB を使用する理由とは?
エージェント SDK は、MongoDB に会話履歴を持続化するセッション実装である MongoDBSession を提供します。MongoDB にその履歴を保存することで、エージェントは以下の利点を得られます。
水平スケーラブルなマルチプロセスセッションストレージ。セッション状態は単一プロセスのメモリではなく、クラスター内に保存されます。そのため、同じクラスターに接続するワーカー、コンテナ、またはサーバーレス関数は会話を続行できます。各メッセージには単調増加の
seqカウンターが含まれており、これによって複数の同時書き込みでのメッセージの順序が維持されます。1 つのデータベースで会話データとアプリケーションデータを取り扱います。アプリケーションで既に MongoDB を使用している場合、エージェントは同じ接続と同じドライバーを介して操作データを読み取り、セッション履歴を書き込みます。このため、メモリサービスの配置することとセキュリティのための別個のサービスは不要です。
エージェントの状態向けの柔軟なドキュメント。document model は、会話のターン、ツールの呼び出し、構造化された出力を、それらが進化するにつれてまとめて保存します。これにより、スキーマ移行を行わずにレコードする内容を拡張することができます。
クエリ可能なエージェント履歴。セッション履歴は通常のコレクションに保存されます。そのため、エージェントの動作を監査したり、分析をビルドするために、クエリ、集計、インデックスを行うことができます。
検索するパス。エージェントはすでにMongoDBに接続されているため、同じクラスターにMongoDB ベクトル検索 を追加して、データのセマンティック検索を提供できます。詳細については、「 エージェント RG 」を参照してください。
Tutorial
このチュートリアルでは、マルチエージェントの旅行アシスタントをビルドする。トリアージ エージェントは、2 人の専門エージェントをツールとして呼び出し、質問に答えます。そして、両方の専門エージェントは、会話セッションを保存する同じクラスターから参照データを読み取ります。
前提条件
Atlas の サンプル データ セット からの映画データを含むコレクションを使用します。
Python 3.10 以降。
次のいずれかのMongoDBクラスター タイプ
MongoDBバージョン6.0.11 、7.0.2 、またはそれ以降を実行中Atlas クラスター。 IPアドレスが Atlas プロジェクトのアクセス リストに含まれていることを確認します。
PythonとDockerを使用して作成されたローカル Atlas 配置。プログラムでローカル配置を作成および管理するには、
atlas-local-lib-py(pip install atlas-local-lib-py)をインストールします。詳細については、 atlas-local-lib-pyリポジトリを参照してください。Search とベクトル検索がインストールされたMongoDB Community クラスター。
OpenAI APIキー。 APIリクエストに使用できるクレジットを持つ OpenAI アカウントが必要です。 OpenAI アカウントの登録の詳細については、 OpenAI APIウェブサイト を参照してください。
環境を設定する
環境変数を設定します。
アプリケーションは Atlas 接続文字列を ATLAS_URI から読み取ります。また、エージェント SDK は OPENAI_API_KEY からキーを読み取ります。
export ATLAS_URI="<connection-string>" export OPENAI_API_KEY="<api-key>"
<connection-string>プレースホルダー値をクラスターの SRV接続文字列に置き換えます。
接続stringには、次の形式を使用する必要があります。
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net
エージェントをビルドする
アプリケーションファイルを作成します。
multi_agent_app.py というファイルを作成し、次のコードを貼り付けます。インライン コメントには、アプリケーションの各パートがどのように MongoDB を使用しているかが説明されています。
"""Multi-agent travel assistant backed by MongoDB Atlas. A triage agent answers travel questions by calling two specialist agents as tools. Both specialists read reference data from the same Atlas cluster that stores the conversation session, so every agent in the application shares one database. """ import asyncio import os from agents import Agent, Runner, function_tool from agents.extensions.memory import MongoDBSession from pymongo import AsyncMongoClient # The script reads your credentials from the environment so that you # don't commit them to source control. REQUIRED_ENV_VARS = ("ATLAS_URI", "OPENAI_API_KEY") DATABASE_NAME = "travel_assistant" # One client serves both the agent tools and the session store. Because # you create the client yourself, your application owns its lifecycle. # main() assigns both of these after it validates the environment. client: AsyncMongoClient | None = None database = None async def lookup_destination(city: str) -> str: """Look up travel guidance for a destination city.""" # Sub-agent tools query the shared database directly, so the agents # answer from your data instead of from model training data. document = await database.destinations.find_one({"city": city}) if document is None: return f"No destination guide found for {city}." return ( f"{document['city']}: best months are {document['best_months']}. " f"{document['summary']}" ) async def lookup_policy(topic: str) -> str: """Look up the company travel policy for a topic.""" document = await database.policies.find_one({"topic": topic}) if document is None: return f"No policy found for {topic}." return f"{document['topic']}: {document['rule']}" # Each specialist is a full agent with its own instructions and tools. destination_agent = Agent( name="Destination expert", instructions=( "You advise travelers on destinations. Always call " "lookup_destination and answer only from what it returns." ), tools=[lookup_destination], ) policy_agent = Agent( name="Policy expert", instructions=( "You answer questions about the company travel policy. Always " "call lookup_policy and answer only from what it returns." ), tools=[lookup_policy], ) # The as_tool() pattern turns each specialist into a tool that the # triage agent can call. Unlike a handoff, control returns to the # triage agent after each call, so it can combine both answers in one # reply. triage_agent = Agent( name="Travel assistant", instructions=( "You are a travel assistant. Use the destination and policy " "tools to gather facts before you answer, and call both when " "the question needs both. Remember details the traveler shared " "earlier in the conversation." ), tools=[ destination_agent.as_tool( tool_name="ask_destination_expert", tool_description="Get travel guidance about a city.", ), policy_agent.as_tool( tool_name="ask_policy_expert", tool_description="Get the company travel policy for a topic.", ), ], ) async def seed_reference_data() -> None: """Load the sample data that the specialist agents read.""" await database.destinations.delete_many({}) await database.policies.delete_many({}) await database.destinations.insert_many( [ { "city": "Lisbon", "best_months": "March through May", "summary": "Mild spring weather and low hotel rates.", }, { "city": "Reykjavik", "best_months": "June through August", "summary": "Long daylight hours and open highland roads.", }, ] ) await database.policies.insert_many( [ {"topic": "flights", "rule": "Book economy for flights under six hours."}, {"topic": "hotels", "rule": "Nightly rates must stay under 250 USD."}, ] ) async def main() -> None: global client, database # Fail fast with a clear message instead of surfacing a connection # error or an authentication error later in the run. missing = [name for name in REQUIRED_ENV_VARS if not os.environ.get(name)] if missing: raise SystemExit( "Set these environment variables before you run this script: " + ", ".join(missing) ) client = AsyncMongoClient(os.environ["ATLAS_URI"]) database = client[DATABASE_NAME] await seed_reference_data() # The session stores conversation history in Atlas. Pass the # existing client so the session and the agent tools share one # connection pool. session = MongoDBSession( session_id="traveler-123", client=client, database=DATABASE_NAME, ) # Confirm connectivity before the first run. await session.ping() # The Runner loads prior turns from the session and writes the new # turn back, so the second question resolves "there" without you # passing the history yourself. first = await Runner.run( triage_agent, "I'm planning a trip to Lisbon. When should I go?", session=session, ) print(first.final_output) second = await Runner.run( triage_agent, "What's our hotel budget for that trip?", session=session, ) print(second.final_output) # session.close() is a no-op when you supply the client, so close # the client yourself. await client.close() if __name__ == "__main__": asyncio.run(main())
アプリケーションを実行します。
python multi_agent_app.py
エージェントは、destinations コレクションからの最初の質問と policies コレクションからの 2 番目の質問に答えます。セッションは最初のターンをMongoDBに保存するため、アシスタントは履歴を自分で渡す必要なく、2回目の質問で "その旅" を解決します。
For Lisbon, the best time to go is **March through May**. That's the sweet spot for **mild weather**, comfortable sightseeing, **fewer crowds**, and generally **better hotel rates** than peak summer. If you want the best single month, I'd pick **May** for warmer days while still avoiding the biggest summer crowds. I still don't see a company policy entry for a **Lisbon hotel budget/nightly cap**. Best next step: check the company booking tool or ask your travel/admin team to confirm the approved lodging allowance for Lisbon.
アプリケーションで MongoDB を使用する方法
アプリケーションは 1 つの AsyncMongoClient を作成し、それをエージェントとセッション間で共有します。
専門エージェントは、ツール機能から
destinationsとpoliciesのコレクションをクエリします。そのため、ユーザーのデータから答えます。MongoDBSession各会話のターンを、同じデータベース内のagent_sessionsコレクションとagent_messagesコレクションに書き込みます。両方のコレクション名は設定可能です。また、セッションは初回使用時に必要なインデックスを作成します。
アプリケーションがクライアント自体を構築するため、クライアントのライフサイクルはアプリケーションに属し、session.close() は何も行いません。セッションにクライアントを所有させるには、MongoDBSession.from_uri() を使用して作成します。
次のステップ
Agents SDK を使用した複数のエージェントの連携について学ぶには、OpenAI ドキュメントの以下のページを参照してください。