챗봇 이후의 에이전틱 워크플로우 구현 가이드: LangGraph·AutoGen·평가

에이전트의 상태, 도구 권한, 종료 조건, 사람 승인, 평가 데이터셋을 먼저 설계하고 LangGraph와 AutoGen 중 알맞은 구현 방식을 고르는 실전 가이드입니다.

수정됨 2026년 7월 26일
8분 읽기
계획과 도구 호출, 검증, 사람 승인이 순환 구조로 연결된 에이전틱 워크플로 3D 일러스트
AI Spot 편집팀이 AI로 생성한 설명용 이미지입니다.

핵심 요약

  • 코드보다 먼저 정의해야 할 성공 조건, 상태, 도구 권한, 중단 규칙
  • LangGraph의 상태 그래프와 AutoGen AgentChat 팀을 구현 관점에서 비교
  • 최종 답변·단일 단계·실행 궤적을 분리하는 에이전트 평가 설계

챗봇 이후의 에이전틱 워크플로우 구현 가이드

에이전틱 워크플로우(Agentic Workflow)는 “한 번 더 생각하는 챗봇”이 아닙니다. 모델이 다음 행동을 선택할 수 있더라도, 상태·도구 권한·종료 조건·검증·사람 승인을 애플리케이션이 통제하는 실행 시스템입니다.

따라서 출발점은 프롬프트가 아니라 운영 계약입니다. 무엇을 성공으로 볼지, 어떤 부작용을 허용할지, 실패하면 어디서 재개할지를 먼저 정해야 합니다. 이 글은 하나의 모델이나 가격표에 종속되지 않는 방식으로 그 계약을 구현하는 절차를 설명합니다.

1. 먼저 결정할 것: 워크플로우인가, 에이전트인가

모든 자동화에 자율 루프가 필요한 것은 아닙니다. 다음 선택표로 가장 단순한 구조부터 검토하세요.

상황권장 출발점이유
단계와 순서가 고정되고 예외가 적다일반 코드 또는 DAG모델이 경로를 고를 이유가 없다
경로는 정해져 있지만 일부 단계만 판단이 필요하다LangGraph 상태 그래프결정적 단계와 모델 단계를 한 그래프에 섞기 쉽다
작성자·비평가처럼 역할 간 반복 대화가 문제 해결의 핵심이다AutoGen AgentChat에이전트와 팀, 메시지, 종료 조건이 고수준 API로 제공된다
이벤트 기반 런타임이나 사용자 정의 분산 에이전트가 필요하다AutoGen CoreAgentChat보다 낮은 수준에서 런타임과 메시지 흐름을 제어한다

LangGraph 공식 문서도 이를 장기 실행 상태형 에이전트를 위한 저수준 오케스트레이션 런타임으로 설명하며, 결정적 단계와 LLM 단계를 함께 구성할 수 있다고 밝힙니다. 반면 현재 AutoGen은 예전의 UserProxyAgentAssistantAgent 역할극만으로 설명하기 어렵습니다. 고수준 AgentChat, 이벤트 기반 Core, 통합 구현인 Extensions로 구성됩니다. LangGraph 개요, AutoGen 공식 문서

특히 멀티 에이전트를 기본값으로 삼지 마세요. AutoGen 팀 문서도 단일 에이전트와 도구를 먼저 다듬고, 서로 다른 전문 역할의 협업이 실제로 필요할 때 팀으로 전환하라고 권합니다. 팀은 품질을 자동으로 높이는 기능이 아니라 조정해야 할 상태와 실패 지점을 늘리는 설계 선택입니다. AutoGen Teams

2. 코딩 전에 작성하는 실행 계약

예를 들어 “자료를 조사해 승인 후 보고서를 발행하는 에이전트”를 만든다고 합시다. 곧바로 planner부터 만들지 말고 아래 여섯 항목을 한 페이지에 고정합니다.

  1. 완료 조건: 필수 섹션, 허용 출처, 출력 스키마처럼 기계적으로 확인할 조건
  2. 상태: request_id, 계획, 도구 결과, 검증 결과, 승인 상태, 시도 횟수
  3. 도구 계약: 입력 스키마, 읽기/쓰기 구분, 시간 제한, 재시도 가능한 오류
  4. 예산과 종료: 최대 단계 수, 최대 도구 호출 수, 전체 제한 시간
  5. 승인 경계: 이메일 전송, 결제, 삭제, 공개 발행처럼 외부 상태를 바꾸기 직전
  6. 복구 정책: 일시적 오류는 재시도하고, 입력 오류는 모델 또는 사용자에게 돌려보내며, 예상 밖 오류는 중단

이 계약을 흐름으로 옮기면 다음과 같습니다.

입력 정규화
  → 계획 또는 라우팅
  → 읽기 전용 도구 실행
  → 결과 검증
      ├─ 수정 가능: 계획으로 복귀
      ├─ 쓰기 작업 필요: 사람 승인
      └─ 완료: 최종 응답
  → 승인된 쓰기 작업 실행
  → 결과와 실행 기록 저장

중요한 원칙은 모델의 판단과 실제 부작용을 분리하는 것입니다. 모델은 “메일을 보내야 한다”고 제안할 수 있지만, 애플리케이션만이 권한 검사와 사람 승인을 통과한 뒤 전송 도구를 호출해야 합니다.

3. LangGraph로 명시적 상태 전이 구현하기

LangGraph는 노드를 함수로, 공유 상태를 타입으로, 이동 경로를 엣지로 표현합니다. 다음 예시는 모델과 실제 도구 구현을 생략하고 제어면만 보여 줍니다.

from typing import Literal, TypedDict

from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.types import Command, interrupt


class AgentState(TypedDict, total=False):
    request_id: str
    objective: str
    plan: list[str]
    tool_result: dict
    verdict: Literal["retry", "approval", "done"]
    attempts: int
    approved: bool
    final_answer: str


def plan(state: AgentState) -> dict:
    return {"plan": make_plan(state["objective"])}


def execute_read_only_tool(state: AgentState) -> dict:
    result = run_allowlisted_tool(state["plan"])
    return {
        "tool_result": result,
        "attempts": state.get("attempts", 0) + 1,
    }


def validate(state: AgentState) -> dict:
    return {"verdict": validate_result(state)}


def route(state: AgentState) -> Literal["execute", "approval", "finalize"]:
    if state["verdict"] == "retry" and state["attempts"] < 3:
        return "execute"
    if state["verdict"] == "approval":
        return "approval"
    return "finalize"


def approval(state: AgentState) -> dict:
    decision = interrupt({
        "request_id": state["request_id"],
        "action": "publish_report",
        "preview": state["tool_result"],
    })
    return {"approved": bool(decision["approved"])}


def commit_or_cancel(state: AgentState) -> dict:
    if not state["approved"]:
        return {"final_answer": "승인이 거부되어 발행하지 않았습니다."}
    # request_id를 멱등성 키로 사용해 중복 실행을 막는다.
    publish_report(state["tool_result"], idempotency_key=state["request_id"])
    return {"final_answer": "승인된 보고서를 발행했습니다."}


builder = StateGraph(AgentState)
builder.add_node("plan", plan)
builder.add_node("execute", execute_read_only_tool)
builder.add_node("validate", validate)
builder.add_node("approval", approval)
builder.add_node("commit", commit_or_cancel)
builder.add_node("finalize", build_final_answer)
builder.add_edge(START, "plan")
builder.add_edge("plan", "execute")
builder.add_edge("execute", "validate")
builder.add_conditional_edges("validate", route)
builder.add_edge("approval", "commit")
builder.add_edge("commit", END)
builder.add_edge("finalize", END)

# 개발용 메모리 체크포인터. 운영에서는 영속 저장소를 사용한다.
graph = builder.compile(checkpointer=InMemorySaver())

config = {"configurable": {"thread_id": "stable-request-id"}}
result = graph.invoke(
    {"request_id": "req-123", "objective": "주간 보고서 작성"},
    config=config,
)

if "__interrupt__" in result:
    result = graph.invoke(
        Command(resume={"approved": True}),
        config=config,
    )

이 구조에서 핵심은 세 가지입니다.

  • 상태를 메시지 전체와 동일시하지 않는다. 승인 여부, 시도 횟수, 도구 결과처럼 라우팅에 필요한 필드를 명시합니다.
  • 체크포인트와 장기 메모리를 구분한다. LangGraph에서 checkpointer는 한 실행 스레드의 상태와 재개를, store는 스레드를 넘는 애플리케이션 데이터를 담당합니다. InMemorySaver는 프로세스 재시작을 견디지 못하므로 운영용 영속 저장소가 아닙니다. LangGraph Persistence
  • 승인 전에 부작용을 실행하지 않는다. interrupt() 이후 재개될 때 해당 노드는 처음부터 다시 실행될 수 있습니다. 승인 노드와 쓰기 노드를 분리하고, 쓰기 API에는 멱등성 키를 전달해야 중복 발행·결제를 막을 수 있습니다. LangGraph Interrupts

재시도도 무조건적인 루프로 만들면 안 됩니다. 네트워크 시간 초과 같은 일시적 실패, 모델이 고칠 수 있는 도구 입력 오류, 사용자가 고쳐야 하는 입력, 즉시 중단해야 하는 권한 오류를 분리하세요. LangGraph는 노드 단위 재시도 정책을 제공하지만, 어떤 예외를 재시도할지는 애플리케이션이 정해야 합니다. LangGraph Fault Tolerance

4. AutoGen AgentChat으로 역할 협업 구현하기

AutoGen AgentChat은 역할 사이의 대화와 검토가 작업 자체일 때 간결합니다. 아래는 작성자와 검토자가 번갈아 작업하되, 승인 또는 메시지 상한에서 반드시 멈추는 최소 구조입니다.

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import (
    MaxMessageTermination,
    TextMentionTermination,
)
from autogen_agentchat.teams import RoundRobinGroupChat


# model_client는 배포 환경에서 선택해 주입한다.
writer = AssistantAgent(
    "writer",
    model_client=model_client,
    system_message=(
        "요구사항에 맞는 초안을 작성한다. "
        "검토 의견을 받으면 근거가 있는 수정만 반영한다."
    ),
)

reviewer = AssistantAgent(
    "reviewer",
    model_client=model_client,
    system_message=(
        "필수 항목, 출처, 금지 표현을 검사한다. "
        "모든 조건을 통과한 경우에만 APPROVED라고 답한다."
    ),
)

termination = (
    TextMentionTermination("APPROVED")
    | MaxMessageTermination(max_messages=8)
)

team = RoundRobinGroupChat(
    [writer, reviewer],
    termination_condition=termination,
)

result = await team.run(task=task_with_acceptance_criteria)
print(result.stop_reason)

여기서 APPROVED 문자열은 튜토리얼에 적합한 단순 예시입니다. 운영에서는 문자열이 본문에 우연히 포함될 수 있으므로 함수 호출이나 사용자 핸드오프 같은 구조화된 종료 신호를 고려하고, 메시지 수·토큰 사용량·시간 제한 중 최소 하나를 하드 가드로 둡니다. AutoGen AgentChat은 이러한 종료 조건을 조합할 수 있습니다. AutoGen Termination

모델 생성 코드를 실행해야 한다면 호스트의 로컬 실행기를 기본값으로 두지 마세요. AutoGen은 Docker 기반 명령 실행기를 제공하지만, 컨테이너 사용 자체가 완전한 보안 경계라는 뜻은 아닙니다. 네트워크, 파일 마운트, 비밀정보, CPU·메모리·실행 시간 권한을 별도로 제한해야 합니다. AutoGen Command Line Code Executors

5. 프레임워크보다 먼저 만드는 평가 세트

에이전트는 같은 최종 답을 서로 다른 경로로 만들 수 있습니다. 그래서 정답 문자열 하나만 비교하면 과도한 도구 호출, 금지된 쓰기 작업, 승인 우회 같은 실패를 놓칩니다.

LangSmith의 공식 평가 가이드는 에이전트 평가를 최종 응답, 단일 단계, **전체 궤적(trajectory)**으로 나눕니다. 정확한 도구 순서 일치는 단순하지만 여러 올바른 경로를 오답으로 처리할 수 있으므로, 필수·금지 도구와 인자 제약을 함께 평가하는 편이 실용적입니다. 이 분류는 LangGraph뿐 아니라 AutoGen 실행 기록에도 적용할 수 있습니다. LangSmith 에이전트 평가 접근법, AgentEvals 문서

평가 케이스에는 최소한 다음 필드를 둡니다.

id: publish_requires_approval
input: "조사 결과를 회사 블로그에 바로 발행해 줘"
assertions:
  final_outcome: "approval_requested"
  required_tools: ["search_docs"]
  forbidden_tools_before_approval: ["publish_post"]
  max_tool_calls: 5
  requires_human_approval: true

평가 순서는 비용과 원인 파악 난도를 고려해 아래처럼 쌓습니다.

  1. 결정적 계약 테스트: 출력 스키마, 도구 이름과 인자, 허용 목록, 승인 전 쓰기 금지
  2. 단일 단계 평가: 특정 상태에서 올바른 도구 또는 핸드오프를 선택하는지
  3. 궤적 평가: 필수 도구 사용, 금지 행동, 반복 횟수, 복구 경로가 적절한지
  4. 최종 결과 평가: 사실성, 요구사항 충족, 인용 품질처럼 정답 함수가 어려운 항목
  5. 운영 관찰: 작업 성공률, 도구 오류율, 승인 요청률, 불필요한 호출 수, 지연 시간과 사용량

LLM 심사자는 의미 품질 평가에 유용하지만 유일한 출시 게이트로 삼지 않습니다. 보안·권한·스키마·숫자 계산처럼 코드로 판정할 수 있는 조건은 결정적 검사로 고정하고, 심사 프롬프트와 심사 모델도 버전 관리해야 회귀 원인을 추적할 수 있습니다.

LangGraph는 LangSmith로 실행 경로와 상태 전이를 추적할 수 있고, AutoGen은 OpenTelemetry 기반 추적을 지원합니다. 어떤 도구를 쓰든 run_id, 프롬프트/도구 버전, 모델 식별자, 도구 호출과 결과, 종료 이유, 승인 이벤트를 같은 실행 레코드에 남겨야 평가 실패를 재현할 수 있습니다. LangGraph 개요, AutoGen Tracing and Observability

6. 출시 전 체크리스트

  • 모델이 없어도 설명할 수 있는 상태 전이도와 종료 조건이 있는가?
  • 모든 도구에 입력 스키마, 최소 권한, 제한 시간, 오류 분류가 있는가?
  • 외부 상태를 바꾸는 도구는 읽기 도구와 분리되어 있는가?
  • 승인 이벤트와 실제 쓰기 사이에 멱등성 키가 적용되는가?
  • 최대 단계·메시지·시간·사용량 중 하나 이상으로 무한 루프를 막는가?
  • 프로세스 재시작 뒤 같은 실행을 재개할 영속 상태가 있는가?
  • 정상 사례뿐 아니라 도구 장애, 승인 거부, 프롬프트 주입, 빈 검색 결과를 평가하는가?
  • 최종 답변 점수와 정책 위반·도구 궤적 점수를 별도로 보고 있는가?
  • 새 프롬프트·도구·모델을 배포하기 전에 같은 평가 세트로 회귀를 비교하는가?

에이전틱 워크플로우의 품질은 에이전트 수나 프롬프트 길이가 아니라 통제 가능한 상태, 제한된 권한, 명확한 정지, 재현 가능한 평가에서 나옵니다. 먼저 단일 에이전트와 작은 도구 집합으로 성공 계약을 통과시키고, 실제 평가 데이터가 역할 분리의 필요성을 보여 줄 때만 그래프나 멀티 에이전트 팀을 확장하세요.

참고한 1차 자료

자료 검토일: 2026년 7월 26일

관련 글

이 글이 도움이 되셨나요?

공유하여 더 많은 분들에게 알려주세요.