Recipes

AutoGen AgentChat 기반으로 구축된 멀티 에이전트 리서치 및 리포트 파이프라인

README 링크에서 발견 · 2 days ago

Research & KnowledgeSoftware & DevOps

주제를 리서치하고, 초안을 비평하고, 결과물을 배포하는 AutoGen 에이전트 팀

What they did

그들은 대화 창을 계속 들여다보지 않고도 거친 질문을 세련된 서면 브리프로 바꾸는 반복 가능한 방법을 원했다. AutoGen 퀵스타트에서 시작해 autogen-agentchat과 OpenAI 확장을 설치하고, GPT-4.1 모델 클라이언트를 기반으로 하는 AssistantAgent를 생성한 뒤 hello-world 루프가 처음부터 끝까지 실행되는 것을 확인했다. 거기서부터 그들은 작은 팀으로 확장했다. 질문을 하위 질문으로 분해하는 플래너 에이전트, 각 하위 질문에 답하는 리서처 에이전트, 초안을 조립하는 라이터 에이전트, 그리고 원래 질문에 비추어 초안을 검토하고 구체적인 수정 사항을 반환하는 크리틱 에이전트였다. 그들은 AutoGen의 팀 추상화를 사용해 라운드 로빈 방식의 대화로 에이전트들을 실행했으며, 종료 조건은 크리틱이 초안을 수용 가능하다고 선언하거나 최대 턴 수에 도달하는 것이었다. 또한 코드로 확정하기 전에 AutoGen Studio로 같은 흐름을 노코드 GUI에서 스케치해 보았고, 이는 비엔지니어에게 설계를 설명하는 데 도움이 되었다. 프롬프트와 에이전트 설명은 작은 config 모듈에 두어 오케스트레이션 코드를 건드리지 않고도 반복할 수 있었다. 출력은 reports 디렉터리의 마크다운 파일에 기록되었고, 감사 가능성을 위해 전체 메시지 트랜스크립트도 함께 저장되었다.

How it went

파이프라인은 범위가 잘 정의된 질문에서 사용 가능한 초안을 만들어냈고, critic 루프는 몇 차례의 시험 실행에서 모호하거나 주제를 벗어난 섹션을 측정 가능할 정도로 줄였다. 설정은 빨랐다. quickstart는 몇 분 만에 실행됐고 멀티 에이전트 버전은 반나절이 걸렸다. 완성도 수준은 프로토타입급이었다. 내부 브리핑에는 충분했지만, 사람의 검토 없이 고객에게 보여줄 수 있는 수준은 아니었다. 가장 큰 마찰은 critic이 무한 루프에 빠지거나 너무 일찍 승인하지 않도록 종료 조건을 튜닝하는 일이었다.

Worth knowing

AutoGen은 아카이브되어 Microsoft에서 더 이상 유지 관리하지 않으므로 버그나 보안 수정이 없으며 문서에서도 프로덕션 사용을 권장하지 않습니다. 새로운 작업은 Microsoft Agent Framework를 대상으로 해야 하며, 기존 코드는 마이그레이션 가이드를 따라야 합니다. 샘플은 환경에 export된 OpenAI API 키를 가정하며, 비용은 모든 에이전트 턴마다 누적되므로 긴 critic 루프는 비용이 많이 듭니다. 에이전트 품질은 프롬프트 문구에 크게 좌우되며, 연구가 내부 데이터를 다루는 경우 transcript 파일에 민감한 자료가 포함될 수 있습니다.

Wiring

Python 3.10+에서 `pip install -U "autogen-agentchat" "autogen-ext[openai]"`로 설치하고 `OPENAI_API_KEY`를 export합니다. 선택한 모델에 대한 `OpenAIChatCompletionClient`를 생성한 뒤, planner, researcher, writer, critic 각각에 대해 서로 다른 system message를 가진 `AssistantAgent` 객체를 인스턴스화합니다. 이들을 팀(round-robin 또는 selector 방식)으로 구성하고, 최대 메시지 제한과 critic이 승인을 표시할 때의 텍스트 멘션 또는 handoff 중단을 결합한 종료 조건을 설정합니다. `asyncio.run`으로 팀을 비동기 실행하고, 반환된 task result를 캡처하여 최종 메시지와 전체 메시지 목록을 모두 디스크에 저장합니다. 실행 종료 시 모델 클라이언트를 닫아 연결을 해제합니다. 선택적으로 autogenstudio를 설치하여 동일한 그래프를 코드로 이식하기 전에 GUI에서 프로토타이핑할 수 있습니다.

Try it yourself

# AutoGen AgentChat 파이프라인 설정

## 1. 의존성 설치

```bash
pip install "autogen-agentchat" "autogen-ext[openai]"
```

## 2. `config.py` — 에이전트 프롬프트

```python
"""Agent prompts and pipeline configuration."""

MODEL = "gpt-4o-mini"
MAX_TURNS = 12
REPORTS_DIR = "reports"

PLANNER_PROMPT = """You are the Planner. Break the user's request into a short,
ordered list of research questions and a proposed outline. Be concise. Do not
write the final draft yourself."""

RESEARCHER_PROMPT = """You are the Researcher. For each question from the Planner,
provide factual notes, key points, and any caveats. If you are unsure, say so
explicitly rather than inventing details."""

WRITER_PROMPT = """You are the Writer. Using the Planner's outline and the
Researcher's notes, produce a clear, well-structured draft. Do not add facts
that were not provided by the Researcher."""

CRITIC_PROMPT = """You are the Critic. Review the Writer's draft for accuracy,
clarity, and completeness. If it is acceptable, reply with a message that
starts with the exact token APPROVED and then a one-line summary. Otherwise,
list concrete, actionable revisions and do not use the APPROVED token."""
```

## 3. `pipeline.py` — 팀 구성 및 실행

```python
"""AutoGen AgentChat pipeline: planner -> researcher -> writer -> critic."""

import asyncio
import json
import os
from datetime import datetime

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_ext.models.openai import OpenAIChatCompletionClient

import config


def build_team() -> RoundRobinGroupChat:
    model_client = OpenAIChatCompletionClient(model=config.MODEL)

    planner = AssistantAgent(
        name="planner",
        model_client=model_client,
        system_message=config.PLANNER_PROMPT,
    )
    researcher = AssistantAgent(
        name="researcher",
        model_client=model_client,
        system_message=config.RESEARCHER_PROMPT,
    )
    writer = AssistantAgent(
        name="writer",
        model_client=model_client,
        system_message=config.WRITER_PROMPT,
    )
    critic = AssistantAgent(
        name="critic",
        model_client=model_client,
        system_message=config.CRITIC_PROMPT,
    )

    termination = TextMentionTermination("APPROVED") | MaxMessageTermination(
        config.MAX_TURNS
    )

    return RoundRobinGroupChat(
        [planner, researcher, writer, critic],
        termination_condition=termination,
    )


def _extract_final_draft(messages) -> str:
    """Return the last message authored by the writer agent."""
    for msg in reversed(messages):
        if getattr(msg, "source", None) == "writer":
            return msg.content
    return ""


def _serialize_transcript(messages) -> list[dict]:
    out = []
    for msg in messages:
        out.append(
            {
                "source": getattr(msg, "source", None),
                "type": type(msg).__name__,
                "content": getattr(msg, "content", None),
            }
        )
    return out


async def run(task: str) -> None:
    team = build_team()
    result = await team.run(task=task)

    os.makedirs(config.REPORTS_DIR, exist_ok=True)
    stamp = datetime.now().strftime("%Y%m%d-%H%M%S")

    draft_path = os.path.join(config.REPORTS_DIR, f"draft-{stamp}.md")
    transcript_path = os.path.join(config.REPORTS_DIR, f"transcript-{stamp}.json")

    with open(draft_path, "w", encoding="utf-8") as f:
        f.write(_extract_final_draft(result.messages))

    with open(transcript_path, "w", encoding="utf-8") as f:
        json.dump(_serialize_transcript(result.messages), f, indent=2, ensure_ascii=False)

    print(f"Wrote {draft_path}")
    print(f"Wrote {transcript_path}")


if __name__ == "__main__":
    import sys

    task = " ".join(sys.argv[1:]) or "Write a short briefing on the state of MCP adoption."
    asyncio.run(run(task))
```

## 4. `README.md` 노트 추가

```markdown
## AutoGen pipeline

This repo includes a small AutoGen AgentChat pipeline (`pipeline.py`) with a
planner, researcher, writer, and critic agent. It runs as a round-robin team
and stops when the critic emits `APPROVED` or after `MAX_TURNS` messages.

> **Note:** AutoGen is archived. Microsoft Agent Framework is the successor
> project. This pipeline is kept for reference and may be migrated in the
> future.
```

## 5. 실행

```bash
export OPENAI_API_KEY=...
python pipeline.py "Write a short briefing on the state of MCP adoption."
```

`reports/`에 `draft-<timestamp>.md`와 `transcript-<timestamp>.json`이 생성됩니다.

Source

English

Tools in this stack