Movatterモバイル変換


[0]ホーム

URL:


콘텐츠로 이동

도구

도구는 에이전트가 행동을 취할 수 있게 합니다. 예를 들어 데이터 가져오기, 코드 실행, 외부 API 호출, 심지어 컴퓨터 사용까지 가능합니다. SDK 는 다섯 가지 카테고리를 지원합니다:

  • OpenAI 호스트하는 도구: OpenAI 서버에서 모델과 함께 실행됩니다
  • 로컬 런타임 도구: 사용자 환경에서 실행됩니다(컴퓨터 사용, 셸, 패치 적용)
  • 함수 호출: 어떤 Python 함수든 도구로 감쌉니다
  • Agents as tools: 완전한 핸드오프 없이 에이전트를 호출 가능한 도구로 노출합니다
  • 실험적: Codex 도구: 도구 호출로 워크스페이스 범위의 Codex 작업을 실행합니다

호스티드 툴

OpenAI 는OpenAIResponsesModel 사용 시 몇 가지 내장 도구를 제공합니다:

  • WebSearchTool 은 에이전트가 웹을 검색할 수 있게 합니다
  • FileSearchTool 은 OpenAI 벡터 스토어에서 정보를 검색할 수 있게 합니다
  • CodeInterpreterTool 은 LLM 이 샌드박스 환경에서 코드를 실행할 수 있게 합니다
  • HostedMCPTool 은 원격 MCP 서버의 도구를 모델에 노출합니다
  • ImageGenerationTool 은 프롬프트로부터 이미지를 생성합니다
fromagentsimportAgent,FileSearchTool,Runner,WebSearchToolagent=Agent(name="Assistant",tools=[WebSearchTool(),FileSearchTool(max_num_results=3,vector_store_ids=["VECTOR_STORE_ID"],),],)asyncdefmain():result=awaitRunner.run(agent,"Which coffee shop should I go to, taking into account my preferences and the weather today in SF?")print(result.final_output)

로컬 런타임 도구

로컬 런타임 도구는 사용자 환경에서 실행되며, 사용자가 구현을 제공해야 합니다:

fromagentsimportAgent,ApplyPatchTool,ShellToolfromagents.computerimportAsyncComputerfromagents.editorimportApplyPatchResult,ApplyPatchOperation,ApplyPatchEditorclassNoopComputer(AsyncComputer):environment="browser"dimensions=(1024,768)asyncdefscreenshot(self):return""asyncdefclick(self,x,y,button):...asyncdefdouble_click(self,x,y):...asyncdefscroll(self,x,y,scroll_x,scroll_y):...asyncdeftype(self,text):...asyncdefwait(self):...asyncdefmove(self,x,y):...asyncdefkeypress(self,keys):...asyncdefdrag(self,path):...classNoopEditor(ApplyPatchEditor):asyncdefcreate_file(self,op:ApplyPatchOperation):returnApplyPatchResult(status="completed")asyncdefupdate_file(self,op:ApplyPatchOperation):returnApplyPatchResult(status="completed")asyncdefdelete_file(self,op:ApplyPatchOperation):returnApplyPatchResult(status="completed")asyncdefrun_shell(request):return"shell output"agent=Agent(name="Local tools agent",tools=[ShellTool(executor=run_shell),ApplyPatchTool(editor=NoopEditor()),# ComputerTool expects a Computer/AsyncComputer implementation; omitted here for brevity.],)

함수 도구

어떤 Python 함수든 도구로 사용할 수 있습니다. Agents SDK 가 도구를 자동으로 설정합니다:

  • 도구 이름은 Python 함수 이름이 됩니다(또는 이름을 제공할 수 있습니다)
  • 도구 설명은 함수의 docstring 에서 가져옵니다(또는 설명을 제공할 수 있습니다)
  • 함수 입력의 스키마는 함수 인자에서 자동으로 생성됩니다
  • 각 입력에 대한 설명은 비활성화하지 않는 한 함수의 docstring 에서 가져옵니다

Python 의inspect 모듈을 사용해 함수 시그니처를 추출하고,griffe 로 docstring 을 파싱하며,pydantic 으로 스키마를 생성합니다.

importjsonfromtyping_extensionsimportTypedDict,AnyfromagentsimportAgent,FunctionTool,RunContextWrapper,function_toolclassLocation(TypedDict):lat:floatlong:float@function_tool# (1)!asyncdeffetch_weather(location:Location)->str:# (2)!"""Fetch the weather for a given location.    Args:        location: The location to fetch the weather for.    """# In real life, we'd fetch the weather from a weather APIreturn"sunny"@function_tool(name_override="fetch_data")# (3)!defread_file(ctx:RunContextWrapper[Any],path:str,directory:str|None=None)->str:"""Read the contents of a file.    Args:        path: The path to the file to read.        directory: The directory to read the file from.    """# In real life, we'd read the file from the file systemreturn"<file contents>"agent=Agent(name="Assistant",tools=[fetch_weather,read_file],# (4)!)fortoolinagent.tools:ifisinstance(tool,FunctionTool):print(tool.name)print(tool.description)print(json.dumps(tool.params_json_schema,indent=2))print()
  1. 함수 인자로 어떤 Python 타입이든 사용할 수 있으며, 함수는 동기 또는 비동기일 수 있습니다
  2. docstring 이 있으면, 설명과 인자 설명을 캡처하는 데 사용됩니다
  3. 함수는 선택적으로context 를 받을 수 있습니다(첫 번째 인자여야 함). 또한 도구 이름, 설명, 사용할 docstring 스타일 등 오버라이드도 설정할 수 있습니다
  4. 데코레이트된 함수를 tools 리스트에 전달할 수 있습니다
출력 보기 위해 펼치기
fetch_weatherFetch the weather for a given location.{"$defs": {  "Location": {    "properties": {      "lat": {        "title": "Lat",        "type": "number"      },      "long": {        "title": "Long",        "type": "number"      }    },    "required": [      "lat",      "long"    ],    "title": "Location",    "type": "object"  }},"properties": {  "location": {    "$ref": "#/$defs/Location",    "description": "The location to fetch the weather for."  }},"required": [  "location"],"title": "fetch_weather_args","type": "object"}fetch_dataRead the contents of a file.{"properties": {  "path": {    "description": "The path to the file to read.",    "title": "Path",    "type": "string"  },  "directory": {    "anyOf": [      {        "type": "string"      },      {        "type": "null"      }    ],    "default": null,    "description": "The directory to read the file from.",    "title": "Directory"  }},"required": [  "path"],"title": "fetch_data_args","type": "object"}

함수 도구에서 이미지 또는 파일 반환

텍스트 출력뿐 아니라, 함수 도구의 출력으로 하나 또는 여러 개의 이미지나 파일을 반환할 수 있습니다. 이를 위해 다음 중 아무 것이나 반환할 수 있습니다:

커스텀 함수 도구

때로는 Python 함수를 도구로 사용하고 싶지 않을 수 있습니다. 원한다면FunctionTool 을 직접 만들 수 있습니다. 다음을 제공해야 합니다:

  • name
  • description
  • params_json_schema: 인자에 대한 JSON 스키마
  • on_invoke_tool:ToolContext 와 인자를 JSON 문자열로 받아, 도구 출력을 문자열로 반환해야 하는 비동기 함수
fromtypingimportAnyfrompydanticimportBaseModelfromagentsimportRunContextWrapper,FunctionTooldefdo_some_work(data:str)->str:return"done"classFunctionArgs(BaseModel):username:strage:intasyncdefrun_function(ctx:RunContextWrapper[Any],args:str)->str:parsed=FunctionArgs.model_validate_json(args)returndo_some_work(data=f"{parsed.username} is{parsed.age} years old")tool=FunctionTool(name="process_user",description="Processes extracted user data",params_json_schema=FunctionArgs.model_json_schema(),on_invoke_tool=run_function,)

인자 및 docstring 자동 파싱

앞서 언급했듯이, 도구의 스키마를 추출하기 위해 함수 시그니처를 자동으로 파싱하고, 도구 및 개별 인자에 대한 설명을 추출하기 위해 docstring 을 파싱합니다. 이에 대한 참고 사항은 다음과 같습니다:

  1. 시그니처 파싱은inspect 모듈로 수행됩니다. 인자 타입을 이해하기 위해 타입 어노테이션을 사용하고, 전체 스키마를 나타내는 Pydantic 모델을 동적으로 구성합니다. Python 기본 타입, Pydantic 모델, TypedDict 등 대부분의 타입을 지원합니다
  2. docstring 파싱에는griffe 를 사용합니다. 지원되는 docstring 형식은google,sphinx,numpy 입니다. docstring 형식을 자동으로 감지하려고 시도하지만 최선의 노력(best-effort)이며,function_tool 호출 시 명시적으로 설정할 수 있습니다. 또한use_docstring_infoFalse 로 설정해 docstring 파싱을 비활성화할 수 있습니다

스키마 추출 코드는agents.function_schema 에 있습니다.

Agents as tools

일부 워크플로에서는 제어권을 핸드오프하기보다, 중앙 에이전트가 전문화된 에이전트 네트워크를 멀티 에이전트 오케스트레이션하도록 만들고 싶을 수 있습니다. 이를 위해 에이전트를 도구로 모델링할 수 있습니다.

fromagentsimportAgent,Runnerimportasynciospanish_agent=Agent(name="Spanish agent",instructions="You translate the user's message to Spanish",)french_agent=Agent(name="French agent",instructions="You translate the user's message to French",)orchestrator_agent=Agent(name="orchestrator_agent",instructions=("You are a translation agent. You use the tools given to you to translate.""If asked for multiple translations, you call the relevant tools."),tools=[spanish_agent.as_tool(tool_name="translate_to_spanish",tool_description="Translate the user's message to Spanish",),french_agent.as_tool(tool_name="translate_to_french",tool_description="Translate the user's message to French",),],)asyncdefmain():result=awaitRunner.run(orchestrator_agent,input="Say 'Hello, how are you?' in Spanish.")print(result.final_output)

도구-에이전트 커스터마이징

agent.as_tool 함수는 에이전트를 도구로 쉽게 바꾸기 위한 편의 메서드입니다.max_turns,run_config,hooks,previous_response_id,conversation_id,session,needs_approval 같은 일반적인 런타임 옵션을 지원합니다. 또한parameters,input_builder,include_input_schema 로 구조화된 입력도 지원합니다. 고급 오케스트레이션(예: 조건부 재시도, 폴백 동작, 여러 에이전트 호출 체이닝)의 경우, 도구 구현에서Runner.run 을 직접 사용하세요:

@function_toolasyncdefrun_my_agent()->str:"""A tool that runs the agent with custom configs"""agent=Agent(name="My agent",instructions="...")result=awaitRunner.run(agent,input="...",max_turns=5,run_config=...)returnstr(result.final_output)

도구-에이전트를 위한 구조화된 입력

기본적으로Agent.as_tool() 은 단일 문자열 입력({"input": "..."})을 기대하지만,parameters(Pydantic 모델 또는 dataclass 타입)를 전달해 구조화된 스키마를 노출할 수 있습니다.

추가 옵션:

  • include_input_schema=True 는 생성된 중첩 입력에 전체 JSON Schema 를 포함합니다
  • input_builder=... 는 구조화된 도구 인자가 중첩된 에이전트 입력이 되는 방식을 완전히 커스터마이징할 수 있게 합니다
  • RunContextWrapper.tool_input 에는 중첩 run 컨텍스트 내부에서 파싱된 구조화 페이로드가 들어 있습니다
frompydanticimportBaseModel,FieldclassTranslationInput(BaseModel):text:str=Field(description="Text to translate.")source:str=Field(description="Source language.")target:str=Field(description="Target language.")translator_tool=translator_agent.as_tool(tool_name="translate_text",tool_description="Translate text between languages.",parameters=TranslationInput,include_input_schema=True,)

완전히 실행 가능한 예시는examples/agent_patterns/agents_as_tools_structured.py 를 참고하세요.

도구-에이전트를 위한 승인 게이트

Agent.as_tool(..., needs_approval=...)function_tool 과 동일한 승인 플로우를 사용합니다. 승인이 필요하면 run 이 일시정지되고 보류 항목이result.interruptions 에 나타납니다. 이후result.to_state() 를 사용하고,state.approve(...) 또는state.reject(...) 호출 후 재개하세요. 전체 일시정지/재개 패턴은Human-in-the-loop guide 를 참고하세요.

커스텀 출력 추출

일부 경우에는 도구-에이전트의 출력을 중앙 에이전트에 반환하기 전에 수정하고 싶을 수 있습니다. 이는 다음과 같은 경우에 유용할 수 있습니다:

  • 하위 에이전트의 채팅 히스토리에서 특정 정보(예: JSON 페이로드)를 추출
  • 에이전트의 최종 답변을 변환 또는 재포맷(예: Markdown 을 일반 텍스트 또는 CSV 로 변환)
  • 출력 유효성 검증 또는 응답이 누락되었거나 형식이 잘못된 경우 폴백 값 제공

이를 위해as_tool 메서드에custom_output_extractor 인자를 제공할 수 있습니다:

asyncdefextract_json_payload(run_result:RunResult)->str:# Scan the agent’s outputs in reverse order until we find a JSON-like message from a tool call.foriteminreversed(run_result.new_items):ifisinstance(item,ToolCallOutputItem)anditem.output.strip().startswith("{"):returnitem.output.strip()# Fallback to an empty JSON object if nothing was foundreturn"{}"json_tool=data_agent.as_tool(tool_name="get_data_json",tool_description="Run the data agent and return only its JSON payload",custom_output_extractor=extract_json_payload,)

중첩 에이전트 run 스트리밍

as_toolon_stream 콜백을 전달하면, 스트림이 완료된 뒤 최종 출력을 반환하면서도 중첩 에이전트가 내보내는 스트리밍 이벤트를 수신할 수 있습니다.

fromagentsimportAgentToolStreamEventasyncdefhandle_stream(event:AgentToolStreamEvent)->None:# Inspect the underlying StreamEvent along with agent metadata.print(f"[stream]{event['agent'].name} ::{event['event'].type}")billing_agent_tool=billing_agent.as_tool(tool_name="billing_helper",tool_description="Answer billing questions.",on_stream=handle_stream,# Can be sync or async.)

예상 동작:

  • 이벤트 타입은StreamEvent["type"] 를 미러링합니다:raw_response_event,run_item_stream_event,agent_updated_stream_event
  • on_stream 을 제공하면 중첩 에이전트가 자동으로 스트리밍 모드로 실행되며, 최종 출력을 반환하기 전에 스트림을 모두 소비합니다
  • 핸들러는 동기 또는 비동기일 수 있으며, 각 이벤트는 도착하는 순서대로 전달됩니다
  • 도구가 모델 도구 호출을 통해 호출되면tool_call 이 존재하며, 직접 호출은None 으로 남을 수 있습니다
  • 완전히 실행 가능한 샘플은examples/agent_patterns/agents_as_tools_streaming.py 를 참고하세요

조건부 도구 활성화

is_enabled 매개변수를 사용해 런타임에 에이전트 도구를 조건부로 활성화 또는 비활성화할 수 있습니다. 이를 통해 컨텍스트, 사용자 선호, 또는 런타임 조건에 따라 LLM 에 사용 가능한 도구를 동적으로 필터링할 수 있습니다.

importasynciofromagentsimportAgent,AgentBase,Runner,RunContextWrapperfrompydanticimportBaseModelclassLanguageContext(BaseModel):language_preference:str="french_spanish"deffrench_enabled(ctx:RunContextWrapper[LanguageContext],agent:AgentBase)->bool:"""Enable French for French+Spanish preference."""returnctx.context.language_preference=="french_spanish"# Create specialized agentsspanish_agent=Agent(name="spanish_agent",instructions="You respond in Spanish. Always reply to the user's question in Spanish.",)french_agent=Agent(name="french_agent",instructions="You respond in French. Always reply to the user's question in French.",)# Create orchestrator with conditional toolsorchestrator=Agent(name="orchestrator",instructions=("You are a multilingual assistant. You use the tools given to you to respond to users. ""You must call ALL available tools to provide responses in different languages. ""You never respond in languages yourself, you always use the provided tools."),tools=[spanish_agent.as_tool(tool_name="respond_spanish",tool_description="Respond to the user's question in Spanish",is_enabled=True,# Always enabled),french_agent.as_tool(tool_name="respond_french",tool_description="Respond to the user's question in French",is_enabled=french_enabled,),],)asyncdefmain():context=RunContextWrapper(LanguageContext(language_preference="french_spanish"))result=awaitRunner.run(orchestrator,"How are you?",context=context.context)print(result.final_output)asyncio.run(main())

is_enabled 매개변수는 다음을 받을 수 있습니다:

  • 불리언 값:True (항상 활성) 또는False (항상 비활성)
  • 호출 가능한 함수:(context, agent) 를 받아 불리언을 반환하는 함수
  • 비동기 함수: 복잡한 조건 로직을 위한 비동기 함수

비활성화된 도구는 런타임에서 LLM 에 완전히 숨겨지므로, 다음에 유용합니다:

  • 사용자 권한에 따른 기능 게이팅
  • 환경별 도구 가용성(dev vs prod)
  • 서로 다른 도구 구성에 대한 A/B 테스트
  • 런타임 상태에 따른 동적 도구 필터링

실험적: Codex 도구

codex_tool 은 Codex CLI 를 래핑하여, 에이전트가 도구 호출 중에 워크스페이스 범위 작업(셸, 파일 편집, MCP 도구)을 실행할 수 있게 합니다.이 인터페이스는 실험적이며 변경될 수 있습니다.기본적으로 도구 이름은codex 입니다. 커스텀 이름을 설정한다면codex 이거나codex_ 로 시작해야 합니다.에이전트에 여러 Codex 도구가 포함될 때는, 각각이 고유한 이름을 사용해야 합니다(Codex 도구끼리뿐 아니라 비 Codex 도구와도 포함하여).

fromagentsimportAgentfromagents.extensions.experimental.codeximportThreadOptions,TurnOptions,codex_toolagent=Agent(name="Codex Agent",instructions="Use the codex tool to inspect the workspace and answer the question.",tools=[codex_tool(sandbox_mode="workspace-write",working_directory="/path/to/repo",default_thread_options=ThreadOptions(model="gpt-5.2-codex",model_reasoning_effort="low",network_access_enabled=True,web_search_mode="disabled",approval_policy="never",),default_turn_options=TurnOptions(idle_timeout_seconds=60,),persist_session=True,)],)

알아둘 점:

  • 인증:CODEX_API_KEY(권장) 또는OPENAI_API_KEY 를 설정하거나,codex_options={"api_key": "..."} 를 전달하세요
  • 런타임:codex_options.base_url 이 CLI base URL 을 오버라이드합니다
  • 바이너리 해석: CLI 경로를 고정하려면codex_options.codex_path_override(또는CODEX_PATH)를 설정하세요. 그렇지 않으면 SDK 가PATH 에서codex 를 찾고, 이후 번들된 vendor 바이너리로 폴백합니다
  • 환경:codex_options.env 가 서브프로세스 환경을 완전히 제어합니다. 이것이 제공되면 서브프로세스는os.environ 을 상속하지 않습니다
  • 스트림 제한:codex_options.codex_subprocess_stream_limit_bytes(또는OPENAI_AGENTS_CODEX_SUBPROCESS_STREAM_LIMIT_BYTES)가 stdout/stderr 리더 제한을 제어합니다. 유효 범위는65536 ~67108864 이며 기본값은8388608 입니다
  • 입력: 도구 호출에는inputs{ "type": "text", "text": ... } 또는{ "type": "local_image", "path": ... } 항목이 최소 1개 포함되어야 합니다
  • 스레드 기본값:model_reasoning_effort,web_search_mode(레거시web_search_enabled 보다 권장),approval_policy,additional_directories 를 위해default_thread_options 를 구성하세요
  • 턴 기본값:idle_timeout_seconds 와 취소signal 을 위해default_turn_options 를 구성하세요
  • 안전:sandbox_modeworking_directory 와 함께 사용하고, Git 저장소 밖에서는skip_git_repo_check=True 를 설정하세요
  • run 컨텍스트 스레드 지속성:use_run_context_thread_id=True 는 동일한 컨텍스트를 공유하는 run 들에 걸쳐 run 컨텍스트에thread_id 를 저장하고 재사용합니다. 이를 위해서는 변경 가능한 run 컨텍스트(예:dict 또는 쓰기 가능한 객체 필드)가 필요합니다
  • run 컨텍스트 키 기본값: 저장 키는name="codex" 일 때 기본적으로codex_thread_id,name="codex_<suffix>" 일 때는codex_thread_id_<suffix> 입니다. 오버라이드하려면run_context_thread_id_key 를 설정하세요
  • Thread ID 우선순위: 호출별thread_id 입력이 최우선이며, 그 다음은(활성화된 경우) run 컨텍스트thread_id, 그 다음은 구성된thread_id 옵션입니다
  • 스트리밍:on_stream 은 스레드/턴 라이프사이클 이벤트와 아이템 이벤트(reasoning,command_execution,mcp_tool_call,file_change,web_search,todo_list,error 아이템 업데이트)를 받습니다
  • 출력: 결과에는response,usage,thread_id 가 포함되며, usage 는RunContextWrapper.usage 에 추가됩니다
  • 구조:output_schema 는 타입 있는 출력이 필요할 때 구조화된 Codex 응답을 강제합니다
  • 완전히 실행 가능한 샘플은examples/tools/codex.pyexamples/tools/codex_same_thread.py 를 참고하세요

함수 도구에서 오류 처리

@function_tool 로 함수 도구를 만들 때failure_error_function 을 전달할 수 있습니다. 이는 도구 호출이 크래시했을 때 LLM 에 제공할 오류 응답을 만들어주는 함수입니다.

  • 기본값(아무것도 전달하지 않으면)으로는default_tool_error_function 이 실행되며, LLM 에 오류가 발생했다고 알립니다
  • 사용자 정의 오류 함수를 전달하면, 대신 그 함수가 실행되어 응답이 LLM 으로 전송됩니다
  • None 을 명시적으로 전달하면, 도구 호출 오류가 다시 raise 되어 사용자가 처리해야 합니다. 이는 모델이 유효하지 않은 JSON 을 생성한 경우의ModelBehaviorError 일 수도 있고, 코드가 크래시한 경우의UserError 일 수도 있습니다
fromagentsimportfunction_tool,RunContextWrapperfromtypingimportAnydefmy_custom_error_function(context:RunContextWrapper[Any],error:Exception)->str:"""A custom function to provide a user-friendly error message."""print(f"A tool call failed with the following error:{error}")return"An internal server error occurred. Please try again later."@function_tool(failure_error_function=my_custom_error_function)defget_user_profile(user_id:str)->str:"""Fetches a user profile from a mock API.     This function demonstrates a 'flaky' or failing API call.    """ifuser_id=="user_123":return"User profile for user_123 successfully retrieved."else:raiseValueError(f"Could not retrieve profile for user_id:{user_id}. API returned an error.")

FunctionTool 객체를 수동으로 생성하는 경우에는on_invoke_tool 함수 내부에서 오류를 처리해야 합니다.


[8]ページ先頭

©2009-2026 Movatter.jp