AutoGen

협업을 대화로 본다. 가 직무 기술서라면, 이쪽은 회의록이다. 메시지를 주고받으며 합의에 도달한다는 발상이 시작점이다.


v0.3에서 v0.4로

2024년 말 가 출시되며 메이저 리라이트가 단행됐다. 핵심은 비동기 액터 모델. 모든 가 메일박스를 가진 액터가 되고, 메시지는 큐로 흐른다. 기존 v0.2 동기 호출 모델과는 호환되지 않는다.

v0.4는 v0.2의 후속이 아니라 다시 짠 라이브러리다.

패키지도 갈렸다. 코어는 autogen-core, 멀티 대화 추상은 autogen-agentchat, 외부 어댑터는 autogen-ext로 분리됐다.


액터 모델 한눈에

는 독립 비동기 액터다. 를 받아 처리하고, 다른 액터에 메시지를 보낸다. 호출자가 응답까지 막혀 있지 않는다는 점이 동기 모델과의 결정적 차이다. 이 기본이다.

다이어그램 로딩…

AssistantAgent — LLM 워커

는 LLM 호출 전담 다. name, model_client, tools, system_message가 필수에 가까운 인자다. 은 비동기 함수 리스트로 넘기고, reflect_on_tool_use=True을 켤 수 있다.

from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient

async def web_search(query: str) -> str:
  """가짜 웹 검색."""
  return f"results for {query}"

model_client = OpenAIChatCompletionClient(model="gpt-4o")

researcher = AssistantAgent(
  name="researcher",
  model_client=model_client,
  tools=[web_search],
  system_message="너는 시니어 리서처다. 출처 없는 주장은 하지 않는다.",
  reflect_on_tool_use=True,
)

UserProxyAgent — 사람·실행기 대역

는 두 역할을 동시에 한다. 사람을 대신해 다음 입력을 받거나, 코드 실행기를 끼워 다른 가 생성한 코드를 샌드박스에서 돌린다. 를 붙이면 자동 디버깅 루프가 가능해진다.

from autogen_agentchat.agents import UserProxyAgent
from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor

# 사람 입력을 받는 모드
human = UserProxyAgent(
  name="human",
  input_func=input,  # CLI 입력
)

# 코드 실행기 모드 — 다른 에이전트의 코드 블록을 자동 실행
executor = UserProxyAgent(
  name="executor",
  code_executor=DockerCommandLineCodeExecutor(work_dir="/tmp/run"),
)

GroupChat — 회의 컨테이너

은 여러 를 모은 대화 무대다. v0.4에서는 autogen_agentchat.teams 모듈의 RoundRobinGroupChatSelectorGroupChat이 표준이다. 전자는 발화 순서가 라운드로빈으로 고정, 후자는 매 턴 LLM이 다음 발화자를 고른다. 어느 쪽이든 의 역할을 내장한다.

from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination

# 종료 조건 — 누군가 "APPROVE"를 말하면 끝
termination = TextMentionTermination("APPROVE")

team = RoundRobinGroupChat(
  [researcher, critic],
  termination_condition=termination,
)

result = await team.run(task="A2A 프로토콜에 대해 한 단락 정리해 보자.")
print(result.messages[-1].content)

ChatManager — 발화자 선택

는 GroupChat에서 다음에 누가 말할지 정한다. v0.4의 이 이 역할을 LLM 기반으로 한다.

기본 셀렉터는 “대화 히스토리 + 후보 목록 + 각 후보의 description”을 모델에 보여 주고 다음 발화자 이름을 받는다. 각자에게 또렷한 description을 달아 두는 게 정확도의 1등 변수다.

from autogen_agentchat.teams import SelectorGroupChat

selector_prompt = """다음 대화에서 가장 어울리는 다음 발화자를 골라라.
{roles}
{history}
지금 차례를 가질 한 명의 이름만 출력."""

team = SelectorGroupChat(
  [researcher, writer, critic],
  model_client=model_client,
  selector_prompt=selector_prompt,
  termination_condition=termination,
)

종료 조건

대화는 끝나야 한다. 는 종료 조건을 객체로 다룬다. TextMentionTermination은 특정 문자열, MaxMessageTermination 개수 상한, ExternalTermination은 외부 트리거다. | 연산자로 OR 합성된다. 은 이 조건을 매 발화 직후 평가한다.

from autogen_agentchat.conditions import (
  MaxMessageTermination,
  TextMentionTermination,
  ExternalTermination,
)

stop = (
  TextMentionTermination("APPROVE")
  | MaxMessageTermination(max_messages=12)
)

ext = ExternalTermination()
team = RoundRobinGroupChat([a, b], termination_condition=stop | ext)
# 어디서든 ext.set() 호출하면 즉시 중단

코드 실행 루프

가 파이썬 코드를 작성하면 가 실행, 출력이 다시 어시스턴트로 흘러간다. 이 두 액터의 핑퐁이 의 시그니처 패턴이다. 가 자기 결과를 관찰하면서 답을 정제하는 ReAct의 다른 모습이다.

다이어그램 로딩…

run vs run_stream

team.run(task=...)은 끝까지 기다렸다가 결과를 한 번에 돌려준다. team.run_stream(...) 단위로 이터레이터를 돌려준다. UI에 그대로 붙는다. reset()으로 비우거나, 인자 없이 run()을 다시 불러 직전 대화를 이어 갈 수도 있다.

# 끝까지 한 번에
result = await team.run(task="요약해 줘")

# 메시지 단위 스트림
async for msg in team.run_stream(task="요약해 줘"):
  print(msg.source, ":", msg.content)

# 중단했다가 이어 가기
await team.reset()                # 상태 초기화
await team.run(task="다른 주제")  # 처음부터
# 또는 task 없이 호출 → 직전 대화에 이어 발화

도구·코드 함께 묶기

가장 자주 보이는 구성은 “어시스턴트 + 코드 실행기 + 검수자”의 3액터다. 가 답을 짜고, 가 검증 코드를 돌리고, 검수자가 결과를 채점한다. 에 끼우면 자체 점검 루프가 완성된다.


CrewAI·LangGraph와 비교

같은 멀티 문제를 세 프레임워크가 다르게 본다.

프레임워크일차 추상흐름 결정
그래프·노드·엣지정적/조건부 엣지
역할·태스크sequential / hierarchical
액터·대화가 발화자 선택

자유로운 대화가 본질이면 AutoGen, 명시적 분기가 중요하면 LangGraph, 직무 카드가 가장 깔끔한 도메인이면 CrewAI. 21장에서 더 자세히 비교한다.


다음 장으로

프레임워크 셋을 봤으니, 이번엔 프레임워크 없이 + 메시지 큐로 직접 짜본다. 20장은 같은 시스템을 바닥부터 조립하며, 의 실체를 코드로 확인한다.