Skip to content

Commit 18d64fe

Browse files
authored
add openai agents sdk (#9)
* add openai agents sdk * chore: add English translations for PR #9
1 parent 4f73ca7 commit 18d64fe

File tree

5 files changed

+537
-0
lines changed

5 files changed

+537
-0
lines changed
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
---
2+
layout: post
3+
title: "OpenAI Agent SDK - 간단하게 Agent를 구축하자"
4+
subtitle: "많은 Agent 툴을 사용해보고 느낀점"
5+
feature-img: "assets/img/2025-10-08-openai-agent-sdk/1737661646125-download6.webp"
6+
tags: [LLMOps]
7+
---
8+
9+
10+
11+
2025년이 되면서 뉴스 피드를 보면 하루가 멀다 하고 "Agent"라는 단어가 등장한다. n8n·Make 같은 노코드 워크플로 툴부터, 구글의 ADK, 랭체인의 Agent, 그리고 오늘 이야기할 OpenAI Agent SDK까지 선택지가 급격히 늘어났다. 그 중에서도 OpenAI가 Agent Builder를 공개하며 Agent SDK와의 연동을 시작하고, 해당 SDK는 더욱 주목 받을 수 있을 것 같은 분위기다. Builder에서 만든 플로우를 그대로 코드로 가져와 버전 관리·배포까지 이어갈 수 있기 때문이다.
12+
13+
> Agent Builder 화면에서 **Code** 버튼을 누르면 바로 Agent SDK 코드가 출력된다.
14+
15+
![image-20251009212618233](/assets/img/2025-10-08-openai-agent-sdk/image-20251009212618233.png)
16+
17+
물론 Google ADK나 Microsoft Autogen처럼 다른 접근을 제공하는 툴도 많다. 결국 팀의 요구사항과 사용 중인 인프라에 따라 최적의 선택은 달라질 것이다. 이 글에서는 OpenAI Agent SDK가 어떤 지향점을 갖고 있는지, 어떤 기능이 돋보이는지 정리해 본다.
18+
19+
먼저 눈에 들어온 장점은 다음과 같다.
20+
21+
- 최소한의 추상화로 학습 곡선이 낮고, OpenAI API에 익숙한 사람이라면 바로 감을 잡을 수 있다.
22+
- 멀티 에이전트·핸드오프·가드레일·세션 등 핵심 구성 요소만 깔끔하게 제공한다.
23+
- 기본으로 트레이싱이 켜져 있어 실행 이력을 추적하기 쉽다.
24+
- Agent Builder와 코드를 오가며 실험-배포 사이클을 빠르게 돌릴 수 있다.
25+
26+
27+
28+
### Agent SDK 알아보기
29+
30+
일단, Agent SDK는 과거 베타 단계였던 Swarm에서 출발해 정식 제품군으로 편입된 버전이다. 공식 문서에 명시된 [두 가지 원칙](https://openai.github.io/openai-agents-python)이 특히 인상 깊다.
31+
32+
1. 사용할 가치가 있을 만큼 충분한 기능을 제공하되, 빠르게 배울 수 있도록 기본 구성 요소는 최소화한다.
33+
2. 기본 설정만으로도 훌륭하게 동작하지만, 원하는 대로 커스터마이즈할 수 있게 열린 구조를 유지한다.
34+
35+
결국 "가볍지만 필요한 건 다 있는" 도구가 되겠다는 선언처럼 읽힌다. 실제로 SDK가 다루는 범위는 에이전트, 핸드오프, 가드레일, 세션, 트레이싱 정도로 명확하게 잘라 놓았다. 덕분에 복잡한 설정 없이도 에이전트 시스템의 뼈대를 바로 세울 수 있다.
36+
37+
38+
39+
가장 기본이 되는 코드를 보면 심플함이 더 분명해진다. 에이전트를 선언하는 데 아래의 코드면 충분하다. 오히려 GPT API를 직접 다룰 때보다 선언적이다.
40+
41+
```python
42+
from agents import Agent, Runner
43+
44+
agent = Agent(name="Assistant", instructions="You are a helpful assistant")
45+
46+
result = Runner.run_sync(agent, "Write a haiku about recursion in programming.")
47+
print(result.final_output)
48+
```
49+
50+
51+
52+
53+
54+
### 빠르게 시작하기
55+
56+
Agent SDK를 처음 실험해 볼 때 자주 쓰는 흐름을 정리했다.
57+
58+
설치는 openai-agents 라이브러리를 설치하는 것이 전부이다.
59+
```bash
60+
pip install openai-agents
61+
```
62+
63+
### Handoffs
64+
65+
멀티 에이전트를 엮는 가장 쉬운 방법이 핸드오프다. 각 에이전트를 선언하고 `handoffs` 배열에 넘겨 주면 라우팅을 담당하는 에이전트가 자연스럽게 분기해 준다. 다른 툴에서 오케스트레이션·라우터라고 부르는 개념과 유사하지만, SDK에서는 의도적으로 구성을 단순화했다.
66+
67+
```python
68+
spanish_agent = Agent(
69+
name="Spanish agent",
70+
instructions="You only speak Spanish.",
71+
)
72+
73+
english_agent = Agent(
74+
name="English agent",
75+
instructions="You only speak English",
76+
)
77+
78+
triage_agent = Agent(
79+
name="Triage agent",
80+
instructions="Handoff to the appropriate agent based on the language of the request.",
81+
handoffs=[spanish_agent, english_agent],
82+
)
83+
84+
85+
async def main():
86+
result = await Runner.run(triage_agent, input="Hola, ¿cómo estás?")
87+
print(result.final_output)
88+
```
89+
90+
위 예시는 triage_agent가 입력 언어에 따라 스페인어·영어 에이전트로 작업을 넘겨준다. `Runner.run_sync` 대신 비동기 `Runner.run`을 사용하면 체이닝 도중 외부 API 호출이나 툴 실행을 기다릴 때도 자연스럽게 확장된다. 실제 서비스에서는 핸드오프 체인을 깊게 가져가기보다는, 언어·도메인·권한과 같은 명확한 기준으로만 분기하는 편이 유지보수에 유리했다.
91+
92+
물론 다른 툴들처럼, [멀티에이전트를 툴](https://github.com/openai/openai-agents-python/blob/main/examples/agent_patterns/agents_as_tools.py)들처럼 사용하는 방법도 있으니 참고하면 좋을 듯 하다.
93+
94+
95+
96+
97+
98+
### Tools
99+
100+
Agent SDK가 제공하는 툴 시스템은 함수 한두 개만으로 정의할 수 있을 만큼 단순하다. 기본적인 형식은 아래와 같다.
101+
102+
```python
103+
from agents import Agent, Runner, function_tool
104+
105+
@function_tool
106+
def get_weather(city: str) -> str:
107+
return f"The weather in {city} is sunny."
108+
109+
110+
agent = Agent(
111+
name="Hello world",
112+
instructions="You are a helpful agent.",
113+
tools=[get_weather],
114+
)
115+
```
116+
117+
`@function_tool` 데코레이터로 함수를 감싸면 JSON 스키마가 자동으로 생성되고, `tools` 파라미터에 그대로 넘겨 쓸 수 있다. GPT API와 동일하게, `tool_choice="required"`처럼 호출 정책을 조정해 세밀한 통제가 가능하다.
118+
119+
Agent SDK에서 제공하는 함수형 툴 외에도 MCP 같은 외부 툴 프로토콜을 붙일 수 있다.
120+
121+
```python
122+
async def main():
123+
async with MCPServerStdio(
124+
params={
125+
"command": "uv",
126+
"args": ["run", "-m", "openai_agent_sdk.mcp_server"],
127+
},
128+
) as server:
129+
agent = Agent(
130+
name="test",
131+
instructions="test",
132+
model=settings.OPENAI_MODEL,
133+
mcp_servers=[server],
134+
)
135+
136+
result = await Runner.run(agent, "삼성전자 주가 얼마야?")
137+
print(result)
138+
```
139+
140+
위 예시는 MCP 서버를 stdio 방식으로 붙인 뒤 해당 리소스를 툴로 노출하는 과정이다. 테스트해보면 리소스 조회(`list`·`get`)부터 실행까지 무리 없이 지원해 MCP 생태계와의 궁합이 매우 좋다는 느낌을 받았다.
141+
142+
143+
144+
### Tracing
145+
146+
Agent SDK는 에이전트가 남긴 메시지와 툴 호출, 핸드오프 이력까지 기본값으로 [OpenAI Dashboard - Logs](https://platform.openai.com/logs)에 적재한다. 별도의 옵저버빌리티 스택을 붙이지 않아도 즉시 실행 흐름을 시각화할 수 있다는 점이 강력하다.
147+
148+
다만 모든 트래픽이 OpenAI로 전송되는 만큼 민감한 데이터에 대해서는 사전에 정책을 정해 두는 편이 좋다. 로그 수집을 끄고 싶다면 라이브러리를 import하기 전에 아래와 같이 환경 변수를 지정하면 된다.
149+
150+
```python
151+
os.environ["OPENAI_AGENTS_DISABLE_TRACING"] = "1"
152+
```
153+
154+
155+
156+
다음과 같이 트레이싱이 된다고 보면 된다.
157+
158+
![image-20251009215019250](/assets/img/2025-10-08-openai-agent-sdk/image-20251009215019250.png)
159+
160+
OpenAI 모델이 아니더라도 트레이싱은 유지할 수 있다. LiteLLM 같은 어댑터로 다른 모델을 붙이고, 별도로 발급한 OpenAI API Key를 `set_tracing_export_api_key`에 전달하면 된다. 비용 없이 로그만 수집하는 용도로 사용할 수 있다는 뜻이다.
161+
162+
```python
163+
import os
164+
from agents import set_tracing_export_api_key, Agent, Runner
165+
from agents.extensions.models.litellm_model import LitellmModel
166+
167+
tracing_api_key = os.environ["OPENAI_API_KEY"]
168+
set_tracing_export_api_key(tracing_api_key)
169+
170+
model = LitellmModel(
171+
model="your-model-name",
172+
api_key="your-api-key",
173+
)
174+
175+
agent = Agent(
176+
name="Assistant",
177+
model=model,
178+
)
179+
```
180+
181+
182+
183+
184+
185+
### 가드레일
186+
187+
에이전트가 점점 복잡해질수록 정책을 코드로 강제할 방법이 필요하다. Agent SDK는 가드레일을 장착하는 방식을 명확히 두 가지로 나눈다.
188+
189+
1. 입력 가드레일: 최초 사용자 입력을 검사해 필요 시 실행을 중단한다.
190+
2. 출력 가드레일: 최종 에이전트 응답을 검토해 민감한 내용이 있는지 확인한다.
191+
192+
핵심은 가드레일도 결국 하나의 에이전트 혹은 함수라는 점이다. 입력 가드레일을 예로 들면, 사용자가 입력한 내용을 가드레일 함수에 전달해 차단(tripwire) 여부를 결정한다.
193+
194+
195+
196+
예시 코드는 다음과 같이 소개하고 있다.
197+
198+
```python
199+
from pydantic import BaseModel
200+
from agents import (
201+
Agent,
202+
GuardrailFunctionOutput,
203+
InputGuardrailTripwireTriggered,
204+
RunContextWrapper,
205+
Runner,
206+
TResponseInputItem,
207+
input_guardrail,
208+
)
209+
210+
class MathHomeworkOutput(BaseModel):
211+
is_math_homework: bool
212+
reasoning: str
213+
214+
guardrail_agent = Agent(
215+
name="Guardrail check",
216+
instructions="Check if the user is asking you to do their math homework.",
217+
output_type=MathHomeworkOutput,
218+
)
219+
220+
221+
@input_guardrail
222+
async def math_guardrail(
223+
ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
224+
) -> GuardrailFunctionOutput:
225+
result = await Runner.run(guardrail_agent, input, context=ctx.context)
226+
227+
return GuardrailFunctionOutput(
228+
output_info=result.final_output,
229+
tripwire_triggered=result.final_output.is_math_homework,
230+
)
231+
232+
233+
agent = Agent(
234+
name="Customer support agent",
235+
instructions="You are a customer support agent. You help customers with their questions.",
236+
input_guardrails=[math_guardrail],
237+
)
238+
239+
async def main():
240+
# This should trip the guardrail
241+
try:
242+
await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?")
243+
print("Guardrail didn't trip - this is unexpected")
244+
245+
except InputGuardrailTripwireTriggered:
246+
print("Math homework guardrail tripped")
247+
```
248+
249+
위 코드에서 `math_guardrail` 함수는 별도의 에이전트를 호출해 "수학 숙제를 대신 풀어 달라는 요청인지" 판단하고, 참일 경우 `InputGuardrailTripwireTriggered` 예외를 발생시킨다. Guardrail 로직을 별도 에이전트로 분리하면 정책을 재사용하거나 다른 프로젝트에 쉽게 이식할 수 있다는 장점이 있다. 출력 가드레일 역시 `@output_guardrail` 데코레이터로 동일한 패턴을 구현할 수 있다.
250+
251+
252+
253+
### 세션과 상태 관리
254+
255+
에이전트를 실서비스에 붙이려면 대화 맥락과 사용자별 상태를 꾸준히 보존해야 한다. Agent SDK는 `Session` 개념을 제공해 이런 요구를 깔끔하게 분리한다. 해당 내용은 다루지는 않지만 다른 툴들에서 지원하는 메모리, db등 지원하고 있어서 무리없이 사용할 수 있을 것 같다.
256+
257+
258+
259+
### 단점
260+
261+
사실 다른 툴들과 비교했을 때, 크게 장,단점이 느껴지지 않는 툴이라고 생각한다. 굳이 뽑자면 OpenAI 생태계와의 결합이 강하다. LiteLLM을 통해 다른 모델을 붙일 수 있지만, 결국 트레이싱·권한 관리는 OpenAI 계정에 의존하고, 기본 트레이싱이 OpenAI Dashboard로만 향한다. 사내 모니터링을 이미 쓰고 있다면 별도 파이프라인을 구축해야한다.
262+
263+
264+
265+
### 마치며
266+
267+
Agent SDK는 MS Autogen처럼 심플함을 추구하면서도, OpenAI Builder와의 연동을 통해 실험-배포 루프를 짧게 만들어 줄 수 있을 것 같다는 생각이 든다. 무엇보다 필요한 구성 요소만 남겨 학습 비용을 크게 줄여 준다는 점이 마음에 든다.
268+
269+
270+
271+
추가 예제와 패턴은 [openai-agents-python](https://github.com/openai/openai-agents-python/tree/main/examples/agent_patterns) 저장소에서도 자세히 볼 수 있다. 팀의 요구에 맞는 아키텍처를 직접 실험해 보길 권한다.

0 commit comments

Comments
 (0)