콘텐츠로 이동

핸드오프

핸드오프를 사용하면 에이전트가 대화의 일부를 다른 에이전트에 위임할 수 있습니다. 이는 서로 다른 에이전트가 특정 영역에 특화되어 있을 때 유용합니다. 예를 들어 고객 지원 앱에서는 예약, 환불 또는 FAQ를 처리하는 에이전트를 둘 수 있습니다.

핸드오프는 LLM에 도구로 표현됩니다. Refund Agent라는 에이전트로 핸드오프하면 도구 이름은 transfer_to_refund_agent가 됩니다.

전문 에이전트가 대화를 이어받아야 한다는 점을 알고 있다면 에이전트를 읽은 뒤 이 페이지를 읽으세요. 전문 에이전트가 원래 에이전트 뒤에 남아 있어야 한다면 대신 agents as tools를 사용하세요.

모든 에이전트는 handoffs 옵션을 받습니다. 이 옵션에는 다른 Agent 인스턴스나 handoff() 헬퍼가 반환하는 Handoff 객체를 포함할 수 있습니다.

일반 Agent 인스턴스를 전달하면 해당 인스턴스의 handoffDescription(제공된 경우)이 기본 도구 설명에 추가됩니다. 모델이 해당 핸드오프를 언제 선택해야 하는지 명확히 설명하는 데 사용하세요.

기본 핸드오프
import { Agent, handoff } from '@openai/agents';
const billingAgent = new Agent({ name: 'Billing agent' });
const refundAgent = new Agent({ name: 'Refund agent' });
// Use Agent.create method to ensure the finalOutput type considers handoffs
const triageAgent = Agent.create({
name: 'Triage agent',
handoffs: [billingAgent, handoff(refundAgent)],
});

handoff()를 통한 핸드오프 사용자 지정

섹션 제목: “handoff()를 통한 핸드오프 사용자 지정”

handoff() 함수를 사용하면 생성되는 도구를 조정할 수 있습니다.

  • agent – 핸드오프할 에이전트
  • toolNameOverride – 기본 transfer_to_<agent_name> 도구 이름 재정의
  • toolDescriptionOverride – 기본 도구 설명 재정의
  • onHandoff – 핸드오프가 발생할 때의 콜백입니다. RunContext를 받고, inputType이 구성된 경우 파싱된 핸드오프 페이로드를 받습니다.
  • inputType – 핸드오프 도구 호출 인수의 스키마
  • inputFilter – 다음 에이전트에 전달되는 기록 필터링
  • isEnabled – 일치하는 실행에만 핸드오프를 노출하는 불리언 또는 조건자

handoff() 헬퍼는 항상 전달한 특정 agent로 제어를 넘깁니다. 가능한 목적지가 여러 개라면 목적지마다 하나의 핸드오프를 등록하고 모델이 그중에서 선택하게 하세요. 자체 핸드오프 코드가 호출 시점에 어떤 에이전트를 반환할지 결정해야 하는 경우에는 사용자 지정 Handoff를 사용하세요.

사용자 지정 핸드오프
import { z } from 'zod';
import { Agent, handoff, RunContext } from '@openai/agents';
const FooSchema = z.object({ foo: z.string() });
function onHandoff(ctx: RunContext, input?: { foo: string }) {
console.log('Handoff called with:', input?.foo);
}
const agent = new Agent({ name: 'My agent' });
const handoffObj = handoff(agent, {
onHandoff,
inputType: FooSchema,
toolNameOverride: 'custom_handoff_tool',
toolDescriptionOverride: 'Custom description',
});

때로는 모델이 핸드오프를 선택할 때 작은 구조화된 페이로드를 함께 첨부하기를 원할 수 있습니다. 이 경우 inputTypeonHandoff를 함께 정의하세요.

핸드오프 입력
import { z } from 'zod';
import { Agent, handoff, RunContext } from '@openai/agents';
const EscalationData = z.object({ reason: z.string() });
type EscalationData = z.infer<typeof EscalationData>;
async function onHandoff(
ctx: RunContext<EscalationData>,
input: EscalationData | undefined,
) {
console.log(`Escalation agent called with reason: ${input?.reason}`);
}
const agent = new Agent<EscalationData>({ name: 'Escalation agent' });
const handoffObj = handoff(agent, {
onHandoff,
inputType: EscalationData,
});

inputType은 핸드오프 도구 호출 자체의 인수를 설명합니다. SDK는 이 스키마를 핸드오프 도구의 parameters로 모델에 노출하고, 반환된 인수를 로컬에서 파싱한 다음 파싱된 값을 onHandoff에 전달합니다.

이는 다음 에이전트의 기본 입력을 대체하지 않으며, 다른 목적지를 선택하지도 않습니다. handoff() 헬퍼는 여전히 감싼 특정 에이전트로 전달하고, 수신 에이전트는 inputFilter로 변경하지 않는 한 대화 기록을 그대로 봅니다.

inputTypeRunContext와도 별개입니다. 로컬에 이미 있는 애플리케이션 상태나 의존성이 아니라, 핸드오프 시점에 모델이 결정하는 메타데이터에 사용하세요.

핸드오프에 reason, language, priority, summary와 같은 모델 생성 라우팅 메타데이터의 작은 조각이 필요할 때 inputType을 사용하세요. 예를 들어 분류 에이전트는 { reason: 'duplicate_charge', priority: 'high' }와 함께 환불 에이전트로 핸드오프할 수 있으며, onHandoff는 환불 에이전트가 이어받기 전에 해당 메타데이터를 기록하거나 저장할 수 있습니다.

목표가 다른 경우에는 다른 메커니즘을 선택하세요.

  • 기존 애플리케이션 상태는 RunContext에 넣으세요.
  • 수신 에이전트가 보는 기록을 변경하려면 inputFilter를 사용하세요.
  • 가능한 전문 에이전트가 여러 개라면 목적지마다 하나의 핸드오프를 등록하세요. inputType은 선택된 핸드오프에 메타데이터를 추가할 수 있지만, 목적지 간 디스패치하지는 않습니다.
  • onHandoff가 실행되기 전에 SDK가 파싱된 페이로드를 검증하기를 원한다면 Zod 스키마를 선호하세요. 원문 JSON Schema는 모델에 전송되는 도구 계약만 정의합니다.

기본적으로 핸드오프는 전체 대화 기록을 받습니다. 다음 에이전트에 전달되는 내용을 수정하려면 inputFilter를 제공하세요. 공통 헬퍼는 @openai/agents-core/extensions에 있습니다.

입력 필터
import { Agent, handoff } from '@openai/agents';
import { removeAllTools } from '@openai/agents-core/extensions';
const agent = new Agent({ name: 'FAQ agent' });
const handoffObj = handoff(agent, {
inputFilter: removeAllTools,
});

inputFilterHandoffInputData 객체를 받고 반환합니다.

  • inputHistory – 실행이 시작되기 전의 입력 기록
  • preHandoffItems – 핸드오프가 발생한 턴 이전에 생성된 항목
  • newItems – 현재 턴 중에 생성된 항목으로, 핸드오프 호출/출력 항목을 포함합니다.
  • runContext – 활성 실행 컨텍스트

RunnerhandoffInputFilter도 구성한 경우, 해당 특정 핸드오프에는 핸드오프별 inputFilter가 우선합니다.

LLM은 프롬프트에 핸드오프가 언급되어 있을 때 더 안정적으로 응답합니다. SDK는 RECOMMENDED_PROMPT_PREFIX를 통해 권장 접두사를 노출합니다.

권장 프롬프트
import { Agent } from '@openai/agents';
import { RECOMMENDED_PROMPT_PREFIX } from '@openai/agents-core/extensions';
const billingAgent = new Agent({
name: 'Billing agent',
instructions: `${RECOMMENDED_PROMPT_PREFIX}
Fill in the rest of your prompt here.`,
});
  • 관리자와 핸드오프 중 선택하는 방법은 에이전트를 참고하세요.
  • 더 넓은 워크플로 트레이드오프는 에이전트 오케스트레이션을 참고하세요.
  • agent.asTool()을 사용하는 관리자 스타일의 대안은 도구를 참고하세요.
  • 실행 시 핸드오프가 어떻게 동작하는지는 에이전트 실행을 참고하세요.
  • 핸드오프 그래프 전반의 타입이 지정된 finalOutput실행 결과를 참고하세요.