에이전트 실행하기

에이전트 실행하기 (Running agents)

에이전트를 정의하는 것은 설정 단계일 뿐이에요. 런타임 질문은 단일 실행이 무엇을 하는지, 다음 턴이 어떻게 계속되는지, 승인이나 도구 작업으로 일시 중지될 때 워크플로우가 어떻게 동작하는지예요.

출처: 문서

본문

에이전트를 정의하는 것은 설정 단계일 뿐이에요. 런타임 질문은 단일 실행이 무엇을 하는지, 다음 턴이 어떻게 계속되는지, 승인이나 도구 작업으로 일시 중지될 때 워크플로우가 어떻게 동작하는지예요.

에이전트 루프 (The agent loop)

하나의 SDK 실행은 하나의 애플리케이션 수준 턴이에요. 러너는 실제 중지 지점에 도달할 때까지 계속 루프해요:

  1. 준비된 입력으로 현재 에이전트의 모델을 호출해요.
  2. 모델 출력을 검사해요.
  3. 모델이 도구 호출을 만들었다면 실행하고 계속해요.
  4. 모델이 다른 전문가에게 핸드오프했다면 에이전트를 전환하고 계속해요.
  5. 모델이 더 이상의 도구 작업 없이 최종 답변을 만들었다면 결과를 반환해요.

그 루프가 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)

관련 문서: 결과와 상태와 오케스트레이션 및 핸드오프를 참고하세요.