|
| 1 | +--- |
| 2 | +search: |
| 3 | + exclude: true |
| 4 | +--- |
| 5 | +# 에이전트 |
| 6 | + |
| 7 | +에이전트는 앱의 핵심 빌딩 블록입니다. 에이전트는 instructions 와 tools 로 구성된 대규모 언어 모델(LLM)입니다. |
| 8 | + |
| 9 | +## 기본 구성 |
| 10 | + |
| 11 | +에이전트를 구성할 때 가장 일반적으로 설정하는 속성은 다음과 같습니다: |
| 12 | + |
| 13 | +- `name`: 에이전트를 식별하는 필수 문자열 |
| 14 | +- `instructions`: 개발자 메시지 또는 system prompt 로도 알려져 있음 |
| 15 | +- `model`: 사용할 LLM 및 temperature, top_p 등 모델 튜닝 매개변수를 설정하는 선택적 `model_settings` |
| 16 | +- `tools`: 에이전트가 작업을 수행하는 데 사용할 수 있는 도구 |
| 17 | + |
| 18 | +```python |
| 19 | +from agents import Agent, ModelSettings, function_tool |
| 20 | + |
| 21 | +@function_tool |
| 22 | +def get_weather(city: str) -> str: |
| 23 | + """returns weather info for the specified city.""" |
| 24 | + return f"The weather in {city} is sunny" |
| 25 | + |
| 26 | +agent = Agent( |
| 27 | + name="Haiku agent", |
| 28 | + instructions="Always respond in haiku form", |
| 29 | + model="o3-mini", |
| 30 | + tools=[get_weather], |
| 31 | +) |
| 32 | +``` |
| 33 | + |
| 34 | +## 컨텍스트 |
| 35 | + |
| 36 | +에이전트는 `context` 타입에 대해 제네릭합니다. 컨텍스트는 의존성 주입 도구로, 여러분이 생성하여 `Runner.run()` 에 전달하는 객체이며, 모든 에이전트, 도구, 핸드오프 등에 전달되고 에이전트 실행을 위한 의존성과 상태를 담는 용도로 사용됩니다. 컨텍스트로는 임의의 Python 객체를 제공할 수 있습니다. |
| 37 | + |
| 38 | +```python |
| 39 | +@dataclass |
| 40 | +class UserContext: |
| 41 | + name: str |
| 42 | + uid: str |
| 43 | + is_pro_user: bool |
| 44 | + |
| 45 | + async def fetch_purchases() -> list[Purchase]: |
| 46 | + return ... |
| 47 | + |
| 48 | +agent = Agent[UserContext]( |
| 49 | + ..., |
| 50 | +) |
| 51 | +``` |
| 52 | + |
| 53 | +## 출력 타입 |
| 54 | + |
| 55 | +기본적으로 에이전트는 일반 텍스트(즉, `str`) 출력을 생성합니다. 에이전트가 특정 타입의 출력을 생성하도록 하려면 `output_type` 매개변수를 사용할 수 있습니다. 일반적인 선택은 [Pydantic](https://docs.pydantic.dev/) 객체를 사용하는 것이지만, Pydantic [TypeAdapter](https://docs.pydantic.dev/latest/api/type_adapter/) 로 래핑할 수 있는 모든 타입(데이터클래스, 리스트, TypedDict 등)을 지원합니다. |
| 56 | + |
| 57 | +```python |
| 58 | +from pydantic import BaseModel |
| 59 | +from agents import Agent |
| 60 | + |
| 61 | + |
| 62 | +class CalendarEvent(BaseModel): |
| 63 | + name: str |
| 64 | + date: str |
| 65 | + participants: list[str] |
| 66 | + |
| 67 | +agent = Agent( |
| 68 | + name="Calendar extractor", |
| 69 | + instructions="Extract calendar events from text", |
| 70 | + output_type=CalendarEvent, |
| 71 | +) |
| 72 | +``` |
| 73 | + |
| 74 | +!!! note |
| 75 | + |
| 76 | + `output_type` 을 전달하면, 모델은 일반 텍스트 응답 대신 [structured outputs](https://platform.openai.com/docs/guides/structured-outputs) 를 사용하도록 지시받습니다. |
| 77 | + |
| 78 | +## 핸드오프 |
| 79 | + |
| 80 | +핸드오프는 에이전트가 위임할 수 있는 하위 에이전트입니다. 핸드오프 목록을 제공하면, 에이전트는 관련성이 있을 경우 그들에게 위임할 수 있습니다. 이는 단일 작업에 특화된 모듈식 에이전트를 멀티 에이전트 오케스트레이션 하는 강력한 패턴입니다. 자세한 내용은 [핸드오프](handoffs.md) 문서를 참조하세요. |
| 81 | + |
| 82 | +```python |
| 83 | +from agents import Agent |
| 84 | + |
| 85 | +booking_agent = Agent(...) |
| 86 | +refund_agent = Agent(...) |
| 87 | + |
| 88 | +triage_agent = Agent( |
| 89 | + name="Triage agent", |
| 90 | + instructions=( |
| 91 | + "Help the user with their questions." |
| 92 | + "If they ask about booking, handoff to the booking agent." |
| 93 | + "If they ask about refunds, handoff to the refund agent." |
| 94 | + ), |
| 95 | + handoffs=[booking_agent, refund_agent], |
| 96 | +) |
| 97 | +``` |
| 98 | + |
| 99 | +## 동적 instructions |
| 100 | + |
| 101 | +대부분의 경우 에이전트를 생성할 때 instructions 를 제공할 수 있습니다. 그러나 함수로 동적 instructions 를 제공할 수도 있습니다. 이 함수는 에이전트와 컨텍스트를 입력으로 받아 프롬프트를 반환해야 합니다. 일반 함수와 `async` 함수 모두 허용됩니다. |
| 102 | + |
| 103 | +```python |
| 104 | +def dynamic_instructions( |
| 105 | + context: RunContextWrapper[UserContext], agent: Agent[UserContext] |
| 106 | +) -> str: |
| 107 | + return f"The user's name is {context.context.name}. Help them with their questions." |
| 108 | + |
| 109 | + |
| 110 | +agent = Agent[UserContext]( |
| 111 | + name="Triage agent", |
| 112 | + instructions=dynamic_instructions, |
| 113 | +) |
| 114 | +``` |
| 115 | + |
| 116 | +## 라이프사이클 이벤트(hooks) |
| 117 | + |
| 118 | +때로는 에이전트의 라이프사이클을 관찰하고 싶을 수 있습니다. 예를 들어 이벤트를 로깅하거나 특정 이벤트가 발생할 때 데이터를 미리 가져오고 싶을 수 있습니다. `hooks` 속성으로 에이전트 라이프사이클에 훅을 걸 수 있습니다. [`AgentHooks`][agents.lifecycle.AgentHooks] 클래스를 상속하고, 관심 있는 메서드를 오버라이드하세요. |
| 119 | + |
| 120 | +## 가드레일 |
| 121 | + |
| 122 | +가드레일을 사용하면 에이전트가 실행되는 동안 사용자 입력에 대한 검사/검증을 병렬로 수행하고, 에이전트 출력이 생성된 후에도 검사할 수 있습니다. 예를 들어 사용자 입력과 에이전트 출력을 관련성 기준으로 스크리닝할 수 있습니다. 자세한 내용은 [가드레일](guardrails.md) 문서를 참조하세요. |
| 123 | + |
| 124 | +## 에이전트 복제/복사 |
| 125 | + |
| 126 | +에이전트의 `clone()` 메서드를 사용하면 에이전트를 복제하고, 원하는 속성을 선택적으로 변경할 수 있습니다. |
| 127 | + |
| 128 | +```python |
| 129 | +pirate_agent = Agent( |
| 130 | + name="Pirate", |
| 131 | + instructions="Write like a pirate", |
| 132 | + model="o3-mini", |
| 133 | +) |
| 134 | + |
| 135 | +robot_agent = pirate_agent.clone( |
| 136 | + name="Robot", |
| 137 | + instructions="Write like a robot", |
| 138 | +) |
| 139 | +``` |
| 140 | + |
| 141 | +## 도구 사용 강제 |
| 142 | + |
| 143 | +도구 목록을 제공한다고 해서 LLM 이 항상 도구를 사용하는 것은 아닙니다. [`ModelSettings.tool_choice`][agents.model_settings.ModelSettings.tool_choice] 를 설정하여 도구 사용을 강제할 수 있습니다. 유효한 값은 다음과 같습니다: |
| 144 | + |
| 145 | +1. `auto`: LLM 이 도구 사용 여부를 결정 |
| 146 | +2. `required`: LLM 이 반드시 도구를 사용하도록 함(어떤 도구를 사용할지는 지능적으로 결정) |
| 147 | +3. `none`: LLM 이 도구를 사용하지 않도록 요구 |
| 148 | +4. 특정 문자열 설정 예: `my_tool` — 해당 특정 도구 사용을 강제 |
| 149 | + |
| 150 | +```python |
| 151 | +from agents import Agent, Runner, function_tool, ModelSettings |
| 152 | + |
| 153 | +@function_tool |
| 154 | +def get_weather(city: str) -> str: |
| 155 | + """Returns weather info for the specified city.""" |
| 156 | + return f"The weather in {city} is sunny" |
| 157 | + |
| 158 | +agent = Agent( |
| 159 | + name="Weather Agent", |
| 160 | + instructions="Retrieve weather details.", |
| 161 | + tools=[get_weather], |
| 162 | + model_settings=ModelSettings(tool_choice="get_weather") |
| 163 | +) |
| 164 | +``` |
| 165 | + |
| 166 | +## 도구 사용 동작 |
| 167 | + |
| 168 | +`Agent` 구성의 `tool_use_behavior` 매개변수는 도구 출력 처리 방식을 제어합니다: |
| 169 | +- `"run_llm_again"`: 기본값. 도구를 실행한 뒤, LLM 이 결과를 처리하여 최종 응답을 생성 |
| 170 | +- `"stop_on_first_tool"`: 첫 번째 도구 호출의 출력을 추가 LLM 처리 없이 최종 응답으로 사용 |
| 171 | + |
| 172 | +```python |
| 173 | +from agents import Agent, Runner, function_tool, ModelSettings |
| 174 | + |
| 175 | +@function_tool |
| 176 | +def get_weather(city: str) -> str: |
| 177 | + """Returns weather info for the specified city.""" |
| 178 | + return f"The weather in {city} is sunny" |
| 179 | + |
| 180 | +agent = Agent( |
| 181 | + name="Weather Agent", |
| 182 | + instructions="Retrieve weather details.", |
| 183 | + tools=[get_weather], |
| 184 | + tool_use_behavior="stop_on_first_tool" |
| 185 | +) |
| 186 | +``` |
| 187 | + |
| 188 | +- `StopAtTools(stop_at_tool_names=[...])`: 지정된 도구 중 하나가 호출되면 중지하고 그 출력을 최종 응답으로 사용 |
| 189 | +```python |
| 190 | +from agents import Agent, Runner, function_tool |
| 191 | +from agents.agent import StopAtTools |
| 192 | + |
| 193 | +@function_tool |
| 194 | +def get_weather(city: str) -> str: |
| 195 | + """Returns weather info for the specified city.""" |
| 196 | + return f"The weather in {city} is sunny" |
| 197 | + |
| 198 | +@function_tool |
| 199 | +def sum_numbers(a: int, b: int) -> int: |
| 200 | + """Adds two numbers.""" |
| 201 | + return a + b |
| 202 | + |
| 203 | +agent = Agent( |
| 204 | + name="Stop At Stock Agent", |
| 205 | + instructions="Get weather or sum numbers.", |
| 206 | + tools=[get_weather, sum_numbers], |
| 207 | + tool_use_behavior=StopAtTools(stop_at_tool_names=["get_weather"]) |
| 208 | +) |
| 209 | +``` |
| 210 | +- `ToolsToFinalOutputFunction`: 도구 결과를 처리하고 중지할지 LLM 으로 계속할지 결정하는 커스텀 함수 |
| 211 | + |
| 212 | +```python |
| 213 | +from agents import Agent, Runner, function_tool, FunctionToolResult, RunContextWrapper |
| 214 | +from agents.agent import ToolsToFinalOutputResult |
| 215 | +from typing import List, Any |
| 216 | + |
| 217 | +@function_tool |
| 218 | +def get_weather(city: str) -> str: |
| 219 | + """Returns weather info for the specified city.""" |
| 220 | + return f"The weather in {city} is sunny" |
| 221 | + |
| 222 | +def custom_tool_handler( |
| 223 | + context: RunContextWrapper[Any], |
| 224 | + tool_results: List[FunctionToolResult] |
| 225 | +) -> ToolsToFinalOutputResult: |
| 226 | + """Processes tool results to decide final output.""" |
| 227 | + for result in tool_results: |
| 228 | + if result.output and "sunny" in result.output: |
| 229 | + return ToolsToFinalOutputResult( |
| 230 | + is_final_output=True, |
| 231 | + final_output=f"Final weather: {result.output}" |
| 232 | + ) |
| 233 | + return ToolsToFinalOutputResult( |
| 234 | + is_final_output=False, |
| 235 | + final_output=None |
| 236 | + ) |
| 237 | + |
| 238 | +agent = Agent( |
| 239 | + name="Weather Agent", |
| 240 | + instructions="Retrieve weather details.", |
| 241 | + tools=[get_weather], |
| 242 | + tool_use_behavior=custom_tool_handler |
| 243 | +) |
| 244 | +``` |
| 245 | + |
| 246 | +!!! note |
| 247 | + |
| 248 | + 무한 루프를 방지하기 위해, 프레임워크는 도구 호출 후 `tool_choice` 를 자동으로 "auto" 로 재설정합니다. 이 동작은 [`agent.reset_tool_choice`][agents.agent.Agent.reset_tool_choice] 로 구성할 수 있습니다. 무한 루프는 도구 결과가 LLM 에게 전달되고, `tool_choice` 때문에 LLM 이 또 다른 도구 호출을 생성하는 상황이 반복되며 발생합니다. |
0 commit comments