Section 1오케스트레이터 루프
에이전트가 어떻게 선택되고 조율되든, 모든 오케스트레이션 패턴은 동일한 근본 오케스트레이터 루프를 따른다.
# The core pattern that powers all orchestration while not termination.is_met(): next_agent = select_next_agent() # 패턴 고유 로직 context = prepare_context_for_agent() # 패턴 고유 로직 result = await next_agent.run(context) update_shared_state(result) check_termination(result)
다섯 단계 — 다음 에이전트 선택, 컨텍스트 준비, 실행, 공유 상태 갱신, 종료 점검. 이 루프는 모든 패턴에 일관성을 부여하고, 컴포지션 가능성을 열며, 확장성을 보장하고, 포괄적 관측 가능성을 제공한다.
BaseOrchestrator는 모든 패턴이 따를 계약을 정의한다 — 에이전트·종료 조건·공유 상태를 초기화하고, 조율 충돌을 막기 위해 에이전트 이름이 고유한지 검증한다. max_iterations는 폭주 실행을 막는 안전 장치다. 패턴마다 다른 것은 단 두 메서드 — select_next_agent()와 prepare_context_for_agent().
Section 2종료 조건 — 폭주를 막는 장치
BaseTermination 인터페이스는 언제 멈출지를 결정한다. 종료 조건은 컴포지션 가능하다 — | 연산자로 결합한다.
orchestrator = RoundRobinOrchestrator( agents=[researcher, writer], termination=( MaxMessageTermination(6) | TextMentionTermination("TERMINATE") ))
메시지 한도에 도달하거나 작가가 완료 신호를 보낼 때 — 둘 중 어느 쪽이든 충족되는 순간 협업이 멈춘다. 흔히 쓰이는 패턴 — MaxMessageTermination, TextMentionTermination, 그리고 연습 문제로 제시되는 TokenBudgetTermination(예산 초과 시 중단), FunctionTermination(외부 함수가 판단).
Section 3라운드 로빈 오케스트레이션
가장 단순한 패턴 — 에이전트들이 정해진 순서를 반복하며 차례를 이어간다. RoundRobinOrchestrator는 차례 교대 루프를 관리하고, 공유 대화 컨텍스트를 유지하며, 종료 조건을 점검한다.
🚀 Starting solar energy research collaboration... 👤 [USER]: Write a brief article about solar energy benefits 🔬 [RESEARCHER]: **The Benefits of Solar Energy** ... ✍️ [WRITER]: **Summary: The Benefits of Solar Energy** ... TERMINATE ✅ Collaboration complete! Generated 3 messages 📊 Stop reason: Text mention found: 'TERMINATE' ⏱️ Duration: 17,427ms
오케스트레이터는 어느 에이전트가 말하는지 추적하고, 대화 흐름을 유지하며, 어떤 이유로 끝났는지 명확한 피드백을 제공한다.
Section 4AI 주도 오케스트레이션
라운드 로빈은 예측 가능한 턴 교대에 좋지만, 더 지능적인 조율이 필요하다면? AI 주도 오케스트레이션은 LLM이 대화를 분석해 다음 발화자를 결정한다. 핵심 통찰 — 라운드 로빈 인프라를 그대로 재사용하고 select_next_agent()만 교체한다.
async def select_next_agent() -> BaseAgent: capabilities = get_agent_capabilities_summary() context = format_conversation_for_selection() prompt = f"""You are coordinating AI agents. Available agents: {capabilities} Recent conversation: {context} Choose which agent should respond next.""" result = await llm_client.create( messages=[UserMessage(content=prompt)], output_format=AgentSelection) return find_agent_by_name(result.structured_output.selected_agent)
대화가 자연스럽게 적응한다 — 작가가 더 많은 정보를 필요로 하면 LLM은 고정 순서를 강제하는 대신 다시 리서처를 선택한다.
이 패턴은 매번 에이전트를 선택할 때마다 LLM 비용이 추가된다 — 모든 조율 요청에 대화 이력과 에이전트 역량 정보가 포함되기 때문이다.
Section 5계획 기반 오케스트레이션
라운드 로빈과 AI 주도는 다음 에이전트를 그때그때 결정한다. 계획 기반은 다르다 — 명시적인 실행 계획을 먼저 수립한 뒤, 진행을 모니터링하며 각 단계를 체계적으로 수행한다.
구조화된 출력이 이 패턴을 가능케 한다
class PlanStep(BaseModel): task: str # 명확하고 실행 가능한 과업 설명 agent_name: str # 이 단계를 맡을 에이전트 reasoning: str # 이 에이전트를 선택한 이유 class ExecutionPlan(BaseModel): steps: List[PlanStep] # 순서가 있는 단계 목록 class StepProgressEvaluation(BaseModel): step_completed: bool # 단계가 성공했는가 failure_reason: str # 실패 시 설명 confidence_score: float # 0.0 ~ 1.0 suggested_improvements: List[str] # 재시도 제안
output_format=ExecutionPlan 파라미터가 예측 불가능한 LLM 텍스트를 신뢰할 수 있는 데이터 구조로 탈바꿈시킨다. "재생 에너지 가이드를 조사·작성하라"는 과업이 구조화된 계획이 된다 — Step 1(리서처: 사실 수집), Step 2(작가: 콘텐츠 작성), Step 3(검토자: 정확성 검증).
지능적인 재시도 로직
단계 평가가 실패를 가리키면, 오케스트레이터는 그냥 넘어가거나 멈추지 않는다 — 실패 분석을 토대로 한층 풍부해진 컨텍스트로 해당 단계를 재시도한다. 핵심 통찰 — 재시도 지시문이 다음 시도에서 에이전트 컨텍스트의 일부가 된다. "이전 시도는 X 때문에 실패했습니다. Y와 Z를 개선해 보세요."
명확한 순차 단계의 다단계 파이프라인(research→write→review), 자동 검증이 실패를 잡아내야 하는 품질 중요 작업, 피드백 동반 재시도가 성공률을 크게 올리는 회복 가능한 실패. 비용 고려 — 단계마다 두 번 이상의 LLM 호출(계획 + 평가 + 실행). 단순 턴 교대라면 라운드 로빈을, 명시적 계획이 필요 없는 동적 조율이라면 AI 주도를 쓰라.