OpenAI Agents SDK로 빌드 에이전트의 백업 데이터베이스 로 MongoDB 사용할 수 있습니다. Agents SDK는 다음과 같은 작은 기본 설정하다 로 에이전트 애플리케이션을 빌드하기 위한 Python 프레임워크 입니다.
에이전트, 즉 명령과 도구로 구성된 대규모 언어 모델(LLM)
핸드오프, 한 에이전트가 다른 에이전트에게 작업을 위임할 수 있도록 하는 기능입니다.
가드레일, 에이전트의 입력과 출력을 검증합니다.
세션: 에이전트 실행 전체에 걸쳐 대화 기록을 저장합니다.
SDK는 두 가지 디자인 원칙을 따릅니다. 실제 애플리케이션을 빌드할 수 있는 충분한 기능이 포함되어 있지만, 짧은 시간 내에 학습할 수 있을 만큼 기본 요소가 적습니다. 에이전트의 기본값은 또한 좋은 결과를 생성하며, 에이전트 실행의 모든 단계를 사용자 지정할 수 있습니다.
에이전트 SDK와 함께 MongoDB를 사용하는 이유
에이전트 SDK는 MongoDB에서 대화 기록을 유지하는 세션 구현인 MongoDBSession을 제공합니다. MongoDB에 해당 기록을 저장하면 에이전트에게 다음과 같은 장점을 제공합니다.
수평적으로 확장 가능한 다중 프로세스 세션 저장. 세션 상태는 단일 프로세스의 메모리에 있지 않고 클러스터에 저장됩니다. 그러므로 동일한 클러스터에 연결하는 모든 워커, 컨테이너 또는 서버리스 함수는 대화를 계속할 수 있습니다. 각 메시지는 단조 증가하는
seq카운터를 포함하고 있으며, 이는 동시 작성자 간에서 메시지 순서를 유지합니다.대화와 애플리케이션 데이터를 위한 단일 데이터베이스. 애플리케이션이 이미 MongoDB를 사용하고 있다면, 에이전트는 배포하고 보안할 필요가 없는 별도의 메모리 서비스 없이 동일한 연결과 동일한 드라이버를 통해 운영 데이터를 읽고 세션 기록을 쓰기 (write) 됩니다.
에이전트 상태를 위한 유연한 문서. document model은 대화 턴, 도구 호출 및 구조화된 출력을 진화하면서 함께 저장합니다. 따라서 스키마 마이그레이션 없이 기록하는 내용을 확장할 수 있습니다.
쿼리 가능한 에이전트 내역. 세션 기록은 일반 컬렉션에 저장되므로 쿼리, 집계 및 인덱싱하여 에이전트 동작을 감사하거나 분석을 빌드할 수 있습니다.
A path to retrieval. Because your agents already connect to MongoDB, you can add MongoDB Vector Search to the same cluster to give them semantic retrieval over your data. To learn more, see Agentic RAG.
튜토리얼
이 튜토리얼에서 다중 에이전트 기반 여행 도우미를 빌드합니다. 트리아지 에이전트는 도구로 두 명의 전문 에이전트를 호출하여 질문에 답변합니다. 두 전문가 모두 대화 세션을 저장하는 동일한 클러스터에서 참조 데이터를 읽습니다.
전제 조건
이 튜토리얼을 완료하려면 다음 조건을 충족해야 합니다.
Python 3.10 이상.
다음 MongoDB cluster 유형 중 하나입니다.
MongoDB 버전 6.0.11을 실행하는 Atlas 클러스터, 7.0.2 이상. 당신의 IP 주소가 Atlas 프로젝트의 액세스 목록에 포함되어 있는지 확인하세요.
Python과 Docker를 사용하여 만든 로컬 Atlas 배포서버입니다.
atlas-local-lib-py(pip install atlas-local-lib-py)를 설치하여 로컬 배포서버를 프로그래밍으로 만들고 관리할 수 있습니다. 자세한 내용은 atlas-local-lib-py 리포지토리를 참조하십시오.A MongoDB Community cluster with Search and Vector Search installed.
OpenAI API 키입니다. API 요청에 사용할 수 있는 크레딧이 있는 OpenAI 계정이 있어야 합니다. OpenAI 계정 등록에 대해 자세히 학습하려면 OpenAI API 웹사이트를 참조하세요.
환경 설정
환경 변수를 설정합니다.
애플리케이션은 ATLAS_URI에서 사용자의 Atlas 연결 문자열을 읽습니다. 그리고 에이전트 SDK는 OPENAI_API_KEY에서 사용자의 키를 읽습니다:
export ATLAS_URI="<connection-string>" export OPENAI_API_KEY="<api-key>"
<connection-string> 자리 표시자 값을 클러스터의 SRV 연결 문자열 로 바꿉니다.
연결 문자열은 다음 형식을 사용해야 합니다.
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())
애플리케이션의 MongoDB 사용 방법
애플리케이션은 하나의 AsyncMongoClient을(를) 생성하고 에이전트와 세션 간에 공유합니다.
전문 에이전트는 자신의 도구 기능에서
destinations및policies컬렉션을 쿼리하여 사용자의 데이터에서 답변합니다.MongoDBSession각 대화 턴을 동일한 데이터베이스의agent_sessions및agent_messages컬렉션에 쓰기 (write)합니다. 두 컬렉션 이름 모두 설정 가능합니다. 그리고 세션은 첫 사용 시 필요한 인덱스를 생성합니다.
애플리케이션이 클라이언트를 직접 생성하므로 클라이언트 수명 주기는 애플리케이션에 속하며 session.close()은(는) 아무것도 하지 않습니다. 대신 세션이 클라이언트를 소유하도록 하려면 MongoDBSession.from_uri()로 만들어야 합니다.
다음 단계
Agents SDK를 사용하여 여러 에이전트를 조정하는 방법에 대해 자세히 알아보려면 OpenAI 설명서의 다음 페이지를 참조하세요.
코드를 통한 오케스트레이션과 LLM을 통한 오케스트레이션 간의 균형을 위해여러 에이전트를 오케스트레이션합니다.
대화를 도구로 호출하는 대신 다른 에이전트 에게 대화를위임하기 위한 핸드오프입니다.