에이전트 실행하기
에이전트 실행하기 (Running agents)
에이전트를 정의하는 것은 설정 단계일 뿐이에요. 런타임 질문은 단일 실행이 무엇을 하는지, 다음 턴이 어떻게 계속되는지, 승인이나 도구 작업으로 일시 중지될 때 워크플로우가 어떻게 동작하는지예요.
출처: 문서
본문
에이전트를 정의하는 것은 설정 단계일 뿐이에요. 런타임 질문은 단일 실행이 무엇을 하는지, 다음 턴이 어떻게 계속되는지, 승인이나 도구 작업으로 일시 중지될 때 워크플로우가 어떻게 동작하는지예요.
에이전트 루프 (The agent loop)
하나의 SDK 실행은 하나의 애플리케이션 수준 턴이에요. 러너는 실제 중지 지점에 도달할 때까지 계속 루프해요:
- 준비된 입력으로 현재 에이전트의 모델을 호출해요.
- 모델 출력을 검사해요.
- 모델이 도구 호출을 만들었다면 실행하고 계속해요.
- 모델이 다른 전문가에게 핸드오프했다면 에이전트를 전환하고 계속해요.
- 모델이 더 이상의 도구 작업 없이 최종 답변을 만들었다면 결과를 반환해요.
그 루프가 SDK의 핵심 개념이에요. 도구, 핸드오프, 승인, 스트리밍은 모두 그것을 대체하는 것이 아니라 그 위에 구축돼요.
하나의 대화 전략 선택하기
다음 턴으로 상태를 이어가는 네 가지 일반적인 방법이 있어요:
| 전략 | 상태가 사는 곳 | 가장 적합한 경우 | 다음 턴에 전달할 것 |
|---|---|---|---|
TypeScript의 result.history 또는 Python의 result.to_input_list() |
애플리케이션 | 작은 채팅 루프와 최대 제어 | 재생 가능한 히스토리 |
session |
여러분의 저장소 + SDK | 지속적인 채팅 상태, 재개 가능한 실행, 여러분이 제어하는 저장소 | 동일한 세션 |
conversationId |
OpenAI Conversations API | 워커나 서비스 간에 공유되는 서버 관리 상태 | 동일한 대화 ID와 새로운 턴만 |
TypeScript의 previousResponseId 또는 Python의 previous_response_id |
OpenAI Responses API | 응답에서 응답으로 이어지는 가장 가벼운 서버 관리 연속 | 마지막 응답 ID와 새로운 턴만 |
대부분의 애플리케이션에서는 대화마다 하나의 전략을 선택하세요. 두 계층 모두를 의도적으로 조정하지 않는 한, 로컬 재생과 서버 관리 상태를 혼합하면 컨텍스트가 중복될 수 있어요.
세션으로 다중 턴 상태 유지하기
import { Agent, MemorySession, run } from "@openai/agents";
const agent = new Agent({
name: "Tour guide",
instructions: "Answer with compact travel facts.",
});
const session = new MemorySession();
const firstTurn = await run(agent, "What city is the Golden Gate Bridge in?", {
session,
});
console.log(firstTurn.finalOutput);
const secondTurn = await run(agent, "What state is it in?", { session });
console.log(secondTurn.finalOutput);
import asyncio
from agents import Agent, Runner, SQLiteSession
agent = Agent(
name="Tour guide",
instructions="Answer with compact travel facts.",
)
session = SQLiteSession("conversation_123")
async def main() -> None:
first_turn = await Runner.run(
agent,
"What city is the Golden Gate Bridge in?",
session=session,
)
print(first_turn.final_output)
second_turn = await Runner.run(
agent,
"What state is it in?",
session=session,
)
print(second_turn.final_output)
if __name__ == "__main__":
asyncio.run(main())
세션은 지속적인 메모리, 재개 가능한 승인 흐름, 또는 애플리케이션이 제어하는 저장소를 원할 때 가장 좋은 기본값이에요.
서버 관리 상태로 계속하기
import { Agent, run } from "@openai/agents";
import OpenAI from "openai";
const agent = new Agent({
name: "Assistant",
instructions: "Reply very concisely.",
});
const client = new OpenAI();
const { id: conversationId } = await client.conversations.create({});
const first = await run(agent, "What city is the Golden Gate Bridge in?", {
conversationId,
});
console.log(first.finalOutput);
const second = await run(agent, "What state is it in?", {
conversationId,
});
console.log(second.finalOutput);
import asyncio
from agents import Agent, Runner
agent = Agent(
name="Assistant",
instructions="Reply very concisely.",
)
async def main() -> None:
first = await Runner.run(
agent,
"What city is the Golden Gate Bridge in?",
)
print(first.final_output)
second = await Runner.run(
agent,
"What state is it in?",
previous_response_id=first.last_response_id,
)
print(second.final_output)
if __name__ == "__main__":
asyncio.run(main())
여러 시스템이 하나의 이름 있는 대화를 공유해야 할 때 conversationId를 사용하세요. 가장 저렴한 응답 대 응답 연속 옵션을 원할 때 TypeScript의 previousResponseId 또는 Python의 previous_response_id를 사용하세요.
실행을 점진적으로 스트리밍하기
스트리밍은 동일한 에이전트 루프와 동일한 상태 전략을 사용해요. 유일한 차이는 실행이 여전히 진행되는 동안 이벤트를 소비한다는 점이에요.
텍스트가 도착하는 대로 실행 스트리밍하기
import { Agent, run } from "@openai/agents";
const agent = new Agent({
name: "Planet guide",
instructions: "Answer with short facts.",
});
const stream = await run(agent, "Give me three short facts about Saturn.", {
stream: true,
});
for await (const event of stream) {
if (
event.type === "raw_model_stream_event" &&
event.data.type === "output_text_delta"
) {
process.stdout.write(event.data.delta);
}
}
await stream.completed;
console.log("\nFinal:", stream.finalOutput);
import asyncio
from openai.types.responses import ResponseTextDeltaEvent
from agents import Agent, Runner
agent = Agent(
name="Planet guide",
instructions="Answer with short facts.",
)
async def main() -> None:
stream = Runner.run_streamed(
agent,
"Give me three short facts about Saturn.",
)
async for event in stream.stream_events():
if event.type == "raw_response_event" and isinstance(
event.data, ResponseTextDeltaEvent
):
print(event.data.delta, end="", flush=True)
print(f"\nFinal: {stream.final_output}")
if __name__ == "__main__":
asyncio.run(main())
세 가지 실용적인 규칙이 중요해요:
- 실행이 완결된 것으로 취급하기 전에 스트림이 끝날 때까지 기다리세요.
- 실행이 승인으로 일시 중지되면 새 사용자 턴을 시작하는 대신
interruptions를 해결하고state에서 재개하세요. - 턴 중간에 스트림을 취소하면, 같은 턴을 나중에 계속하고 싶다면
state에서 미완료 턴을 재개하세요.
일시 중지와 실패를 의도적으로 처리하기
비정상 경로 결과의 두 가지 광범위한 클래스가 중요해요:
- 런타임 또는 검증 실패 — 최대 턴 한도, 가드레일 예외, 도구 오류 같은 것들.
- 예상되는 일시 중지 — 인간 승인 요청 같은 것들로, 실행이 의도적으로 중단되고 나중에 동일한 상태에서 재개되어야 해요.
승인은 새 턴이 아니라 일시 중지된 실행으로 취급하세요. 그 구분을 유지하면 턴 수, 히스토리, 서버 관리 연속 ID가 일관되게 유지돼요.
다음 단계
런타임 루프가 명확해지면, 설계해야 할 다음 워크플로우 경계와 일치하는 가이드로 이동하세요.
[Results and state
Learn which result surfaces your application should carry into the next
turn.](https://developers.openai.com/api/docs/guides/agents/results)
[Orchestration and handoffs
Decide how multiple specialists behave inside the same runtime loop.](https://developers.openai.com/api/docs/guides/agents/orchestration)
[Guardrails and human review
Add validation and approval pauses without breaking turn continuity.](https://developers.openai.com/api/docs/guides/agents/guardrails-approvals)
더 알아보기 (Learn more)
관련 문서: 결과와 상태와 오케스트레이션 및 핸드오프를 참고하세요.