Part II · The Shift Chapter 08

멀티 에이전트 평가의 새로운 차원

"단일 에이전트의 성능 합계가 멀티 에이전트의 성능이 아니다. 1+1은 2가 아니라 0.5도, 3도 될 수 있다."

협업, 의사소통, 자원 분배 — 멀티 에이전트 고유의 평가 차원

8.1 왜 단일 → 멀티가 근본적으로 다른가

단일 에이전트 평가에서 멀티 에이전트 평가로 전환하는 것은 "하나의 학생 평가"에서 "팀 프로젝트 평가"로 전환하는 것과 같다. 팀의 성과는 개인 능력의 합이 아니다. 상호작용(interaction)이 핵심 변수가 되며, 이 상호작용은 선형적이지 않다.

단일 vs 멀티: 평가 패러다임의 근본적 차이

속성단일 에이전트멀티 에이전트
평가 대상에이전트의 출력에이전트 간 상호작용 + 출력
성능 모델$P = f(\text{agent})$$P = f(\text{agents}, \text{interactions})$
기준점정답(ground truth) 존재정답 부재 — 프로세스 품질
주요 변수정확도, 지연, 비용IT, RA, CQ, CC, RAE
실패 유형오답, 환각, 태스크 미완정보 누락, 역할 충돌, 집단사고
복잡도$O(M)$ — 행동 수$O(M^N)$ — 조합 폭발
신뢰도$\rho$ (평가자 신뢰도)$\rho^K$ (누적 신뢰도 저하)
디버깅프롬프트/모델 수정협업 구조/역할/프로토콜 수정
멀티 에이전트 성능 (비선형)
$$P_{\text{team}} \neq \sum_{i=1}^{n} P_{\text{agent}_i}$$ $$P_{\text{team}} = f(P_{\text{agent}_1}, \ldots, P_{\text{agent}_n}, C_{12}, C_{13}, \ldots, C_{nn})$$

$C_{ij}$: 에이전트 $i$와 $j$ 간의 협업 품질. 이것이 단일 에이전트 평가에 없는 핵심 차원. $C_{ij}$는 양수(시너지)도 음수(갈등)도 될 수 있다.

8.1.1 창발성(Emergence): 전체는 부분의 합이 아니다

멀티 에이전트 시스템에서 가장 중요한 개념은 창발성(emergence)이다. 개별 에이전트의 행동을 모두 알고 있다고 해서, 시스템 전체의 행동을 예측할 수 없다. 이것은 물리학에서 원자의 행동으로부터 유체의 난류를 예측할 수 없는 것과 같다.

창발성은 두 가지 수준으로 구분된다:

수준정의에이전트 예시평가 함의
약한 창발개별 에이전트 규칙에서 시스템 행동이 시뮬레이션 가능하지만, 분석적으로 예측 불가3개 에이전트의 순차 위임에서 예상치 못한 컨텍스트 누적시뮬레이션 기반 평가 필요
강한 창발시뮬레이션으로도 완전히 예측 불가. 근본적으로 새로운 속성 출현10개+ 에이전트 GroupChat에서 자발적 역할 분담 진화실행 후 사후 평가만 가능
창발적 성능 편차
$$\Delta_{\text{emergence}} = P_{\text{team}} - \sum_{i=1}^{n} P_{\text{agent}_i}$$
$\Delta_{\text{emergence}} > 0$이면 시너지(초선형 성능), $\Delta_{\text{emergence}} < 0$이면 갈등(차선형 성능). 실증 연구에 따르면 3개 에이전트 GroupChat에서 $\Delta \approx -0.15 \sim +0.25$로, 같은 구성이라도 태스크에 따라 시너지와 갈등이 모두 발생한다. 이 편차가 바로 "협업 품질" 평가가 필요한 이유다.

창발성의 실제 예시: 코드 리뷰 시스템

시너지 사례 ($\Delta > 0$): Researcher가 "이 함수의 시간 복잡도가 $O(n^2)$"이라고 보고 → Writer가 이 정보를 활용하여 $O(n \log n)$ 최적화 코드 작성 → Reviewer가 엣지 케이스 검증 추가. 각 에이전트는 개별적으로 이 결과를 낼 수 없었다. $\Delta \approx +0.2$.

갈등 사례 ($\Delta < 0$): Researcher가 "함수 A를 최적화하라"고 보고 → Writer가 함수 A를 최적화하지만 함수 B의 성능이 30% 저하 → Reviewer는 함수 B의 저하를 발견하지 못함. 결과: 전체 시스템 성능이 악화. $\Delta \approx -0.15$. 단일 에이전트가 함수 A만 최적화하는 것보다 나쁜 결과.

창발성이 평가에 미치는 함의

창발성은 "부분 평가의 합 ≠ 전체 평가"를 의미한다. 각 에이전트를 개별적으로 평가하여 모두 "우수"라도, 조합했을 때 "열등"이 될 수 있다. 따라서 멀티 에이전트 평가는 반드시 시스템 수준에서 수행되어야 한다. 개별 에이전트 평가만으로는 창발적 갈등을 탐지할 수 없다.

8.1.2 통신 채널의 조합 폭발

에이전트 수가 증가하면 에이전트 간 통신 채널 수가 조합적으로 폭발한다. 이것은 멀티 에이전트 평가의 복잡성을 근본적으로 결정하는 요인이다.

통신 채널 수
$$\text{Channels}(N) = \binom{N}{2} = \frac{N(N-1)}{2}$$
$N$개 에이전트 사이의 가능한 양방향 통신 채널 수. $N=2$이면 1개, $N=3$이면 3개, $N=5$이면 10개, $N=10$이면 45개, $N=20$이면 190개. 채널이 많을수록 (1) 정보 누락 가능성 증가, (2) 메시지 중복 증가, (3) 평가 복잡도 폭발.
에이전트 수채널 수메시지 증가율평가 복잡도실제 사례
21기준낮음Researcher→Writer
33중간AutoGen 기본 GroupChat
51010×높음CrewAI 크루
104545×매우 높음대규모 시뮬레이션
20190190×사실상 불가이론적 한계

이 폭발은 평가에 직접적 영향을 미친다. 3개 에이전트의 대화를 분석하는 것은 가능하지만, 10개 에이전트의 45개 채널에서 오가는 수백 개의 메시지를 수동 분석하는 것은 현실적으로 불가능하다. 자동화된 협업 분석 도구가 필수적이며, 이것이 Ch.14 자동화 파이프라인의 핵심 동기 중 하나다.

8.1.3 1+1이 2가 아닌 세 가지 이유

두 에이전트를 합쳤을 때 성능이 선형적으로 증가하지 않는 이유는 세 가지다:

이유 1: 정보 손실(Information Loss). 에이전트 A가 에이전트 B에게 메시지를 전달할 때, 컨텍스트 윈도우 제한으로 일부 정보가 손실된다. 이 손실은 전달 단계마다 누적된다. 순차 위임(Sequential Delegation)에서 $k$단계를 거치면:

정보 누적 손실 모델
$$I_k = I_0 \cdot \prod_{j=1}^{k} (1 - \ell_j) \approx I_0 \cdot (1-\bar{\ell})^k$$
$I_0$는 원본 정보량, $\ell_j$는 $j$번째 전달 단계에서의 손실률, $\bar{\ell}$은 평균 손실률. 실험적으로 $\bar{\ell} \approx 0.15 \sim 0.25$. 3단계 전달 후 원본 정보의 40~60%만 남는다.

이유 2: 역할 충돌(Role Conflict). 두 에이전트의 역할이 명확히 분리되지 않으면, 같은 작업을 중복하거나 서로 상충하는 결과를 낸다. 역할 경계(role boundary)의 불명확성이 효율성을 떨어뜨린다.

이유 3: 의사결정 지연(Decision Latency). 두 에이전트가 합의해야 하는 상황에서, 합의 과정 자체가 시간과 토큰을 소모한다. 단일 에이전트가 즉시 결정하는 것을, 두 에이전트는 3~5턴의 대화 후에 결정한다. 이 조정 비용(coordination cost)이 성능 향상을 상쇄할 수 있다.

멀티 에이전트의 "성능 역전" 현상

실제 실험에서 흔히 관찰되는 현상: 에이전트를 추가했는데 성능이 오히려 하락하는 것. AutoGen GroupChat에서 3개 에이전트가 1개 에이전트보다 낮은 태스크 완료율을 보이는 경우가 20~30% 발생한다. 주요 원인은 (1) 정보 손실 누적, (2) 역할 충돌, (3) 메시지 폭발에 의한 컨텍스트 오염. 이것은 "에이전트를 더 많이"가 아니라 "에이전트를 더 잘 조직"해야 함을 시사한다.

8.1.4 이 장의 로드맵

이 장은 멀티 에이전트 평가의 고유한 과제를 7개 섹션으로 심층 분석한다:

  1. 8.2: 주요 프레임워크의 협업 패턴 — AutoGen, CrewAI, LangGraph, Swarm
  2. 8.3: 멀티 에이전트 고유의 평가 차원 — 8가지 차원의 수학적 정의
  3. 8.4: 협업 실패 모드 심층 분석 — 9가지 실패 모드와 탐지 알고리즘
  4. 8.5: 프레임워크별 평가 전략 — 각 프레임워크에서 협업 품질을 측정하는 방법
  5. 8.6: 멀티 에이전트 평가의 근본적 한계 — 조합 폭발, 신뢰도 저하, 정답 부재
  6. 8.7: 사례 연구 — 3에이전트 코드 리뷰 시스템 실증 분석
  7. 8.8: 요약 및 다음 장으로의 연결

각 섹션은 수학적 정의, 코드 예시, 실증 데이터를 포함하며, Part III(Ch.10~15)의 6차원 프레임워크 설계로 직접 연결된다.

실무자를 위한 가이드: 어디서 시작해야 하는가

이 장의 내용이 방대하므로, 독자의 역할에 따라 다음 순서로 읽는 것을 권장한다:

평가 엔지니어: 8.3(5차원) → 8.7(사례) → 8.4(실패 모드) → 8.5(프레임워크별 전략)

시스템 설계자: 8.1(개념) → 8.2(협업 패턴) → 8.6(한계) → 8.8(체크리스트)

연구자: 8.2.6(게임 이론) → 8.6.5(정보 이론) → 8.7.5(메타 분석) → 8.8.2(미래 연구)

8.2 멀티 에이전트 협업 패턴

멀티 에이전트 시스템의 협업 패턴은 에이전트 간의 제어 흐름(control flow)데이터 흐름(data flow)를 정의한다. 같은 에이전트들이라도 패턴이 다르면 성능이 크게 달라지므로, 평가는 패턴을 고려해야 한다.

8.2.1 AutoGen 패턴

AutoGen은 세 가지 기본 협업 패턴을 제공한다. 각 패턴은 서로 다른 평가 과제를 만든다:

패턴 1: 순차적 위임 (Sequential Delegation)

Researcher → Writer → Reviewer → Editor. 각 에이전트가 이전 결과를 입력받아 순차 처리. AutoGen의 기본 패턴.

평가 특성: 정보 흐름이 단방향이므로 병목 지점(bottleneck) 식별이 용이. 하지만 각 단계에서의 정보 손실이 누적되어 최종 품질이 저하될 수 있다.

# AutoGen 순차적 위임 — 궤적 캡처 포함 from autogen import AssistantAgent, UserProxyAgent researcher = AssistantAgent("researcher", llm_config=gpt4, system_message="당신은 리서처입니다. 정보를 수집하고 요약하세요.") writer = AssistantAgent("writer", llm_config=gpt4, system_message="당신은 작가입니다. 리서치 결과를 글로 작성하세요.") reviewer = AssistantAgent("reviewer", llm_config=gpt4, system_message="당신은 검토자입니다. 글의 품질을 평가하고 개선안을 제시하세요.") # 궤적 캡처를 위한 커스텀 후크 trajectory = [] def capture_hook(sender, receiver, message): trajectory.append({ "from": sender.name, "to": receiver.name, "content_len": len(message), "timestamp": time.time() }) user_proxy = UserProxyAgent("user") user_proxy.initiate_chat(researcher, message="조사해라") # researcher → writer → reviewer 순서로 자동 전달
순차 위임의 정보 보존률
$$\text{Preservation}(k) = \prod_{i=1}^{k} (1 - \ell_i)$$
$k$단계 순차 전달 후 보존되는 원본 정보 비율. $\ell_i$는 $i$번째 전달의 손실률. AutoGen 실험에서 $\bar{\ell} \approx 0.2$이므로 3단계 후 약 51%만 보존된다.

패턴 2: 그룹 토론 (Group Chat)

3개 이상의 에이전트가 동시 참여. GroupChatManager가 발언 순서를 관리. 브레인스토밍, 코드 리뷰 등에 활용.

평가 특성: 모든 에이전트가 모든 메시지를 볼 수 있어 정보 공유는 원활하지만, 메시지 수가 $O(N \times T)$로 증가( $N$=에이전트 수, $T$=턴 수)하여 컨텍스트 오염 위험이 높다.

# AutoGen GroupChat — 발언 균형 분석 from autogen import GroupChat, GroupChatManager import numpy as np groupchat = GroupChat( agents=[researcher, writer, reviewer], messages=[], max_round=15 ) manager = GroupChatManager(groupchat=groupchat) # 대화 후 참여 균형 분석 def analyze_balance(messages): counts = {} for m in messages: name = m.get("name", "unknown") counts[name] = counts.get(name, 0) + 1 values = list(counts.values()) mean_v = np.mean(values) std_v = np.std(values) balance = max(0, 1 - std_v / mean_v) if mean_v > 0 else 0 return {"counts": counts, "balance": balance}

패턴 3: 중첩 대화 (Nested Chat)

에이전트 A와 B의 대화 결과를 에이전트 C가 받아서 처리. 재귀적 구조 가능. 하위 대화의 품질이 상위 대화에 영향을 미치는 "중첩 의존성"이 특징.

평가 특성: 중첩 깊이가 깊어질수록 내부 대화의 오류가 외부로 전파될 위험이 증가. 각 중첩 수준별로 독립적 평가가 필요하다.

중첩 대화의 오류 전파 모델
$$P(\text{error}_{\text{outer}}) = 1 - \prod_{d=1}^{D}\left(1 - P(\text{error}_d) \cdot \prod_{d'=d+1}^{D} T_{d'}\right)$$
$D$: 중첩 깊이, $P(\text{error}_d)$: 깊이 $d$에서의 오류 확률, $T_{d'}$: 깊이 $d'$에서의 오류 전파율. $D=2$이고 $P(\text{error})=0.1$, $T=0.5$이면 $P(\text{error}_{\text{outer}}) \approx 0.075$. $D=3$이면 $\approx 0.1$. 중첩이 깊어질수록 오류가 선형적으로 증가.
# 중첩 대화 품질 추적 class NestedChatEvaluator: """중첩 대화의 계층별 품질 평가""" def __init__(self): self.depth_logs = {} # {depth: [quality_scores]} def evaluate_nested(self, chat_tree): """중첩 대화 트리를 재귀적으로 평가""" for depth, conversation in chat_tree.items(): quality = self._evaluate_single(conversation) self.depth_logs[depth] = quality # 깊이별 품질 저하 분석 if len(self.depth_logs) > 1: degradation = {} depths = sorted(self.depth_logs.keys()) for i in range(1, len(depths)): drop = self.depth_logs[depths[i-1]] - self.depth_logs[depths[i]] degradation[depths[i]] = drop return {"depth_quality": self.depth_logs, "degradation": degradation} return {"depth_quality": self.depth_logs}

8.2.2 CrewAI 패턴

CrewAI는 AutoGen보다 역할 중심(role-centric) 설계를 강조한다. 각 에이전트가 명시적 역할(role), 목표(goal), 배경서(backstory)를 가지며, 태스크가 위계적(hierarchical)으로 조직된다.

CrewAI Process: Sequential vs Hierarchical

# CrewAI 순차 + 위계적 프로세스 from crewai import Agent, Task, Crew, Process researcher = Agent( role="Senior Research Analyst", goal="시장 동향 분석 및 인사이트 도출", backstory="10년 경력의 금융 분석가...", verbose=True ) writer = Agent( role="Content Writer", goal="분석 결과를 이해하기 쉽게 작성", backstory="기술 작문 전문가...", verbose=True ) # 순차 프로세스 crew_seq = Crew( agents=[researcher, writer], tasks=[research_task, write_task], process=Process.sequential ) # 위계적 프로세스 (매니저가 조정) manager = Agent(role="Project Manager", goal="태스크 분배 및 품질 관리") crew_hier = Crew( agents=[researcher, writer, manager], tasks=[research_task, write_task], process=Process.hierarchical, manager_llm="gpt-4" )

평가 함의: 위계적 프로세스는 매니저 에이전트의 품질이 전체 성능을 결정한다. 매니저가 잘못된 태스크 분배를 하면 하위 에이전트의 능력과 무관하게 전체가 실패한다. 따라서 매니저 평가실행 에이전트 평가를 분리해야 한다.

CrewAI 패턴의 평가적 특성 분석

CrewAI는 명시적 역할 정의(role, goal, backstory)를 통해 RA(역할 준수도) 측정에 유리하지만, 다른 차원에서는 한계가 있다:

차원장점한계
ITTask output이 명시적으로 전달되어 완전성 측정 용이중간 산출물의 정확성 검증이 어려움
RAbackstory와 role이 비교 기준으로 활용 가능role이 넓게 정의되면 침범 탐지 불가
CQsequential에서 메시지 수가 적어 품질 측정 단순hierarchical에서 매니저-에이전트 간 메시지가 캡처 안 됨
CCDAG 기반 실행으로 인과 관계 추적 가능순환이 불가능하여 피드백 기반 개선 불가
RAE각 Task의 토큰 사용량을 개별 측정 가능매니저 오버헤드가 불투명
CrewAI의 "역할 프롬프팅 딜레마"

backstory를 너무 구체적으로 설정하면 역할이 경직되어 창발적 협업이 불가능해진다. 반면 너무 추상적으로 설정하면 역할 침범이 빈번해진다. 이 trade-off를 역할 구체성-유연성 스펙트럼이라 부르며, 실험적으로 backstory가 2~3문장일 때 최적의 RA와 성능 균형을 달성한다.

8.2.3 LangGraph 패턴

LangGraph는 상태 기계(State Machine)방향 그래프(Directed Graph)로 협업을 모델링한다. AutoGen/CrewAI보다 훨씬 정교한 제어 흐름이 가능하며, 조건부 분기(conditional routing)와 순환 루프를 지원한다.

LangGraph: 상태 그래프 기반 협업

# LangGraph 상태 그래프 — 코드 리뷰 워크플로우 from langgraph.graph import StateGraph, END from typing import TypedDict, List, Dict class ReviewState(TypedDict): code: str review_comments: List[Dict] revision_count: int approved: bool def reviewer_node(state: ReviewState): # 코드 리뷰 수행 comments = llm_review(state["code"]) state["review_comments"] = comments return state def reviser_node(state: ReviewState): # 피드백 기반 코드 수정 revised = llm_revise(state["code"], state["review_comments"]) state["code"] = revised state["revision_count"] += 1 return state def should_continue(state: ReviewState): # 조건부 분기: 승인 or 추가 수정 if state["approved"] or state["revision_count"] >= 3: return "end" return "revise" # 그래프 구성 graph = StateGraph(ReviewState) graph.add_node("review", reviewer_node) graph.add_node("revise", reviser_node) graph.add_conditional_edges("review", should_continue, { "revise": "revise", "end": END }) graph.add_edge("revise", "review") # 순환 루프

평가 함의: LangGraph는 상태 스냅샷(state snapshot)을 통해 그래프의 각 노드에서의 상태를 캡처할 수 있다. 이것은 노드별 평가를 가능하게 하며, 어떤 노드에서 품질이 저하되었는지 정확히 파악할 수 있다. 순환 루프의 경우, 루프 당 품질 변화를 추적하여 수렴(convergence) 여부를 평가한다.

LangGraph 패턴의 평가적 우위와 한계

LangGraph는 3개 프레임워크 중 평가에 가장 유리한 구조를 가지지만, 완벽하지는 않다:

측면장점한계
상태 추적모든 노드에서 상태 스냅샷 캡처 → IT/CC 측정 정확상태가 복잡해지면 스냅샷 자체가 평가 부담
순환 루프피드백 기반 개선이 가능 → CC 수렴 추적무한 루프 위험 → 최대 반복 횟수 제한 필요
조건부 분기경로별로 다른 평가 기준 적용 가능모든 경로를 테스트하려면 조합 폭발
토큰 효율상태 기반이므로 대화 재전송 불필요 → RAE 우수초기 상태 설계 비용이 높음
순환 루프 수렴 지수 (Loop Convergence Index)
$$\text{LCI} = \frac{\Delta Q_n}{\Delta Q_1} = \frac{Q_{n} - Q_{n-1}}{Q_1 - Q_0}$$
$Q_k$: $k$번째 루프에서의 산출물 품질. LCI가 0에 수렴하면 품질이 수렴한 것(양호), LCI가 일정하게 유지되면 개선이 선형적으로 진행 중, LCI가 음수면 품질이 악화 중(루프 종료 필요). LangGraph에서는 상태 스냅샷으로 $Q_k$를 자동 계산할 수 있다.

8.2.4 OpenAI Swarm 패턴

Swarm은 핸드오프(handoff) 기반의 경량 패턴이다. 에이전트가 함수를 호출하여 다음 에이전트로 제어권을 넘기는 방식. AutoGen보다 간단하지만, 평가 기능이 제한적이다.

Swarm: 핸드오프 기반 제어권 이전

# OpenAI Swarm 핸드오프 패턴 from swarm import Swarm, Agent def transfer_to_writer(): """리서치 완료 후 작가에게 핸드오프""" return writer_agent researcher_agent = Agent( name="Researcher", instructions="주제를 조사하고 요약하세요", functions=[transfer_to_writer] ) writer_agent = Agent( name="Writer", instructions="리서치 결과를 기사로 작성하세요" ) client = Swarm() response = client.run( agent=researcher_agent, messages=[{"role": "user", "content": "AI 동향 분석"}] )

평가 함의: Swarm의 핸드오프는 명시적이므로 제어 흐름 추적이 용이. 하지만 (1) 내장 평가 기능 없음, (2) 대화 기록이 스트링으로만 전달, (3) 핸드오프 시점에서의 상태 검증 불가. 별도 평가 계층이 필수적.

Swarm의 장단점: 심층 분석

측면장점단점평가에 미치는 영향
단순성최소한의 설정으로 즉시 실행 가능복잡한 워크플로우 표현 불가평가 대상이 단순→평가도 단순
핸드오프명시적 제어권 이전으로 추적 용이핸드오프 조건이 함수 내에 숨겨짐제어 흐름은 추적 가능하지만 의도 파악 어려움
상태 관리상태가 없어(stateless) 디버깅 쉬움컨텍스트를 메시지로만 전달→정보 손실IT 측정은 가능하나 RA 측정은 제한적
확장성에이전트 추가가 쉬움에이전트 간 관계 관리 부재3+ 에이전트에서 평가 복잡도 급증
# Swarm 평가 래퍼 — 내장 평가 기능 추가 class EvaluableSwarm: """Swarm에 평가 계층을 추가한 래퍼""" def __init__(self, swarm_client): self.client = swarm_client self.trajectory = [] # 핸드오프 궤적 def run_with_eval(self, agent, messages): """평가 정보를 수집하며 실행""" response = self.client.run(agent=agent, messages=messages) # 궤적 기록 for msg in response.messages: self.trajectory.append({ "sender": msg.get("sender", "unknown"), "content": msg.get("content", ""), "timestamp": time.time() }) # 핸드오프 횟수로 RA 추정 handoffs = sum(1 for t in self.trajectory if "transfer_to" in t["content"]) return { "response": response, "trajectory": self.trajectory, "handoff_count": handoffs, "total_messages": len(self.trajectory) }

8.2.5 패턴 비교 분석

속성AutoGenCrewAILangGraphSwarm
제어 흐름대화 기반역할/태스크 기반그래프/상태 기계핸드오프
조건부 분기제한적없음완전 지원함수 기반
순환 루프max_round없음완전 지원불가
상태 관리메시지 리스트태스크 출력TypedDict State스트링 전달
평가 기능Hook 콜백Task outputState snapshot제한적
확장성3~5 에이전트3~10 에이전트제한 없음2~3 에이전트
평가 적합성중간중간높음낮음
평가 관점에서의 패턴 선택

평가의 용이성 측면에서는 LangGraph가 가장 유리하다. 상태 기반 설계 덕분에 각 노드의 입력/출력을 독립적으로 검사할 수 있고, 조건부 분기로 인한 경로(path)별 평가도 가능하다. 반면 Swarm은 가장 간단하지만 평가 기능이 거의 없어, 프로덕션 평가에는 부적합하다. Ch.12에서 이 차이를 프레임워크 독립적 어댑터로 어떻게 통합하는지 다룬다.

8.2.6 게임 이론적 관점: 협력 vs 경쟁

멀티 에이전트 협업을 게임 이론(game theory)의 렌즈로 바라보면, 왜 특정 패턴이 성공/실패하는지 이해할 수 있다. 각 에이전트를 "플레이어"로, 협업 결과를 "페이오프(payoff)"로 모델링한다.

순차 위임 = 스택엘베르크 게임 (Stackelberg Game)

첫 번째 에이전트가 "리더"로서 행동을 먼저 선택하고, 후속 에이전트가 "팔로워"로서 최적 응답을 선택. 리더의 선택이 전체 페이오프를 결정하므로, 첫 번째 에이전트의 품질이 전체 성능의 상한을 정한다.

순차 게임의 서브게임 완전 균형
$$\text{Agent}_2^* = \arg\max_{a_2} U_2(a_1^*, a_2)$$ $$\text{Agent}_1^* = \arg\max_{a_1} U_1(a_1, \text{Agent}_2^*(a_1))$$
에이전트 2는 에이전트 1의 행동 $a_1^*$을 관찰한 후 최적 응답 $a_2^*$를 선택. 에이전트 1은 에이전트 2의 최적 응답을 예측하여 자신의 행동을 선택. AutoGen 순차 위임에서 이 균형이 달성되지 않으면 정보 누락이 발생.

그룹 토론 = 내시 협상 게임 (Nash Bargaining Game)

모든 에이전트가 동시에 행동을 선택하고, 합의점(Nash equilibrium)에 도달해야 한다. 합의에 실패하면 "분쟁 포인트(disagreement point)"로 귀결 — 즉, 아무런 결과도 얻지 못한다.

내시 협상 해
$$\text{NBS} = \arg\max_{(u_1, \ldots, u_N)} \prod_{i=1}^{N} (u_i - d_i)$$
$u_i$: 에이전트 $i$의 효용, $d_i$: 분쟁 포인트(협상 실패 시의 효용). NBS는 모든 에이전트에게 "공정한" 타협점을 제공. AutoGen GroupChat에서 max_round 도달 후 강제 종료는 분쟁 포인트에 해당.

위계적 조정 = 메커니즘 디자인 (Mechanism Design)

CrewAI의 매니저 에이전트는 "메커니즘 디자이너" 역할을 한다. 각 에이전트가 자신의 진짜 능력을 드러내도록(incentive-compatible) 태스크를 분배해야 한다. 매니저가 에이전트의 능력을 잘못 평가하면, 잘못된 태스크 분배로 전체 성능이 하락한다.

게임 이론의 평가적 함의

게임 이론적 관점에서 "좋은 협업"은 "내시 균형에 가까운 상태"로 정의할 수 있다. 즉, 어느 에이전트도 일방적으로 자신의 행동을 변경하여 전체 페이오프를 개선할 수 없는 상태. 이것은 MEI의 CC(결론 일관성) 차원과 깊이 연결된다.

8.3 멀티 에이전트 고유의 평가 차원

단일 에이전트 평가에는 없고 멀티 에이전트에만 존재하는 평가 차원이 있다. 이 차원들은 에이전트 간의 관계(inter-agent relationship)에서 발생하므로, 단일 에이전트의 성능이 아무리 뛰어나도 측정할 수 없는 속성이다. 다음 5가지 차원은 Ch.6의 6차원 프레임워크 중 D2(Coordination)D5(Efficiency) 차원을 멀티 에이전트 특화 관점에서 심화한 것이다.

8.3.1 정보 전달 효율 (Information Transfer Efficiency)

에이전트 A가 에이전트 B로 정보를 전달할 때, 핵심 정보가 얼마나 보존되는가? 이 차원은 단일 에이전트에서는 의미가 없다 — 에이전트가 하나뿐이므로 "전달"이 발생하지 않기 때문이다.

정보 전달 효율 (IT)

$$IT(A \to B) = \frac{|F_B \cap F_{\text{required}}|}{|F_{\text{required}}|}$$

$F_B$: 에이전트 B가 수신한 핵심 정보 집합, $F_{\text{required}}$: 작업 완수에 필요한 최소 정보 집합.

정보 전달 효율은 단순한 "전달률"이 아니다. 세 가지 하위 차원이 존재한다:

IT의 세 가지 하위 차원

하위 차원정의측정 방법임계값
완전성(Completeness)필요한 정보가 모두 전달되었는가?$\frac{|F_B|}{|F_{\text{required}}|}$$\geq 0.9$
정확성(Accuracy)전달된 정보가 원본과 일치하는가?$1 - \frac{|F_B \setminus F_A|}{|F_A|}$$\geq 0.95$
적시성(Timeliness)정보가 필요한 시점에 전달되었는가?$1 - \frac{\Delta t_{\text{delay}}}{T_{\text{total}}}$$\geq 0.8$
다단계 정보 보존 모델
$$IT_{\text{chain}} = \prod_{k=1}^{K} IT(A_k \to A_{k+1}) \cdot \gamma^{K-1}$$
$K$단계 체인에서의 누적 정보 전달 효율. $\gamma < 1$은 단계별 감쇠 계수(일반적으로 $\gamma \approx 0.95$). AutoGen 순차 위임에서 $K=3$이면 $IT_{\text{chain}} \approx 0.7^3 \times 0.95^2 \approx 0.33$, 즉 원본 정보의 1/3만 최종 에이전트에 도달한다.
# 정보 전달 효율 측정 — LLM-as-Judge 방식 import json from openai import OpenAI client = OpenAI() def measure_info_transfer(sender_msg, receiver_msg, task_context): """sender가 보낸 정보가 receiver에게 얼마나 전달되었는지 측정""" prompt = f""" 당신은 멀티 에이전트 시스템 평가자입니다. [작업 맥락] {task_context} [발신자 메시지] {sender_msg} [수신자 메시지] {receiver_msg} 다음 기준으로 정보 전달 효율을 평가하세요: 1. 완전성(0~1): 발신자의 핵심 정보 중 수신자가 인식한 비율 2. 정확성(0~1): 수신자가 인식한 정보의 정확도 3. 적시성(0~1): 정보가 필요한 시점에 활용되었는가 JSON 형식으로 출력: {{"completeness": x, "accuracy": x, "timeliness": x}} """ resp = client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": prompt}], response_format={"type": "json_object"} ) scores = json.loads(resp.choices[0].message.content) return scores

8.3.2 역할 준수도 (Role Adherence)

각 에이전트가 자신에게 할당된 역할을 얼마나 충실히 수행하는가? 멀티 에이전트 시스템에서 역할 침범(role intrusion)은 예상치 못한 상호작용을 유발한다. 이 차원은 단일 에이전트에서는 측정 자체가 불가능하다 — 역할이 하나뿐이므로 "침범"의 개념이 존재하지 않기 때문이다.

역할 준수도 (RA)

$$RA_i = 1 - \frac{|\{a \in A_i : \text{role}(a) \neq R_i\}|}{|A_i|}$$

$A_i$: 에이전트 $i$의 행동 집합, $R_i$: 에이전트 $i$의 할당된 역할. 역할 밖 행동의 비율이 낮을수록 RA가 높다.

하지만 RA 측정에는 근본적인 어려움이 있다: $R_i$를 어떻게 정의하는가? 명시적 역할 정의(system prompt의 역할 설명)와 암묵적 역할 기대(다른 에이전트가 해당 에이전트에게 기대하는 행동)가 다를 수 있다. 이를 구분하여 측정해야 한다.

이중 역할 준수도 (Dual RA)
$$RA_i^{\text{explicit}} = 1 - \frac{|\{a \in A_i : a \notin R_i^{\text{prompt}}\}|}{|A_i|}, \quad RA_i^{\text{implicit}} = 1 - \frac{|\{a \in A_i : a \notin R_i^{\text{expected}}\}|}{|A_i|}$$
$R_i^{\text{prompt}}$: 시스템 프롬프트에 명시된 역할, $R_i^{\text{expected}}$: 다른 에이전트들이 기대하는 역할. $RA^{\text{explicit}}$은 높지만 $RA^{\text{implicit}}$이 낮으면, 역할 정의 자체가 잘못되었을 가능성이 높다.

역할 침범의 4가지 패턴

패턴설명예시위험도
역할 넘어가기다른 에이전트의 역할을 대신 수행리서처가 작가 대신 글 작성높음
역할 포기자신의 역할을 수행하지 않음리뷰어가 "좋습니다"만 반복높음
역할 혼란자신의 역할을 잘못 이해디버거가 테스트 케이스를 작성중간
역할 진화대화 중 역할이 자연스럽게 변화리서처가 분석가 역할까지 수행낮음~중간

역할 침범의 파급 효과 (Cascade Effect)

역할 침범은 연쇄 반응을 유발한다. 에이전트 A가 B의 역할을 침범하면:

1단계: B는 자신의 역할이 이미 수행되었다고 판단 → 수동적으로 전환 (RA 저하)
2단계: B의 수동성이 C에게 전달 → C도 동기 부여 상실 (RA 추가 저하)
3단계: 전체 시스템이 1~2개 "워크홀릭" 에이전트에 의존 → 단일 장애점(SPOF) 형성

이 연쇄 반응을 수식화하면:

역할 침범 파급 모델
$$RA_{\text{system}} = \prod_{i=1}^{N} RA_i^{\beta_i}, \quad \beta_i = 1 + \alpha \cdot \sum_{j \neq i} (1 - RA_j)$$
한 에이전트의 RA 저하가 다른 에이전트의 RA에 미치는 영향을 모델링. $\beta_i > 1$이면 해당 에이전트가 다른 에이전트의 침범에 더 민감. $\alpha \approx 0.3$이 실험적으로 적합. 예: 3에이전트에서 한 에이전트의 RA가 0.5로 저하되면, 다른 에이전트의 $\beta$가 1.15로 증가하여 전체 시스템 RA가 지수적으로 감소.
역할 경계의 역설: 너무 엄격하면 창발성이 사라진다

RA를 1.0으로 만드는 것이 항상 좋은 것은 아니다. 역할 진화(role evolution)는 때때로 유익하다. 리서처가 분석가 역할까지 자연스럽게 확장하면서 새로운 인사이트를 발견하는 경우가 있다. 문제는 "의도적 확장"과 "무의식적 침범"을 구분하는 것. 이를 위해 역할 경계 테스트(Role Boundary Test)를 수행한다: 역할 진화가 성능 향상으로 이어지면 "적응", 하락으로 이어지면 "침범"으로 분류.

# 역할 준수도 자동 측정 + 파급 효과 분석 def measure_role_adherence(agent_name, agent_role, messages): """에이전트의 역할 준수도를 메시지 히스토리로부터 측정""" role_violations = 0 total_actions = 0 for msg in messages: if msg.get("name") != agent_name: continue total_actions += 1 # LLM으로 역할 준수 여부 판단 judgment = client.chat.completions.create( model="gpt-4", messages=[{ "role": "user", "content": f"역할: {agent_role}\n행동: {msg['content'][:500]}\n" f"이 행동은 역할에 부합하는가? YES/NO" }] ) if "NO" in judgment.choices[0].message.content.upper(): role_violations += 1 return 1 - (role_violations / max(total_actions, 1)) def compute_system_ra(agent_ras: dict, alpha: float = 0.3): """역할 침범 파급 효과를 반영한 시스템 전체 RA""" ras = list(agent_ras.values()) n = len(ras) system_ra = 1.0 for i, ra_i in enumerate(ras): # 다른 에이전트의 RA 저하가 i번째 에이전트에 미치는 영향 beta = 1.0 + alpha * sum(1 - ras[j] for j in range(n) if j != i) system_ra *= ra_i ** beta return system_ra

8.3.3 의사소통 품질 (Communication Quality)

에이전트 간 메시지가 얼마나 효율적이고 유용한가? 불필요한 반복, 모순된 진술, 불명확한 지시는 협업 품질을 저하시킨다.

의사소통 품질 (CQ)

$$CQ = w_1 \cdot \text{Conciseness} + w_2 \cdot \text{Coherence} + w_3 \cdot \text{Utility}$$

가중치 $w_1 + w_2 + w_3 = 1$은 작업 유형에 따라 조정. 일반적으로 $w_1=0.3, w_2=0.3, w_3=0.4$.

CQ의 세 가지 구성 요소

간결성(Conciseness): 불필요한 반복 없이 핵심만 전달하는가? 동일한 의미의 메시지가 3회 이상 반복되면 감점.

일관성(Coherence): 이전 메시지와 모순되지 않는가? 에이전트 A가 "X는 참"이라고 한 후 나중에 "X는 거짓"이라면 감점. 단, 새로운 정보로 의견을 변경한 경우는 예외.

유용성(Utility): 메시지가 수신자의 작업에 실제로 기여하는가? "네, 알겠습니다" 같은 확인 메시지만 반복하면 유용성이 낮다.

메시지 효율성 지수
$$\text{MEI} = \frac{\sum_{m \in M_{\text{useful}}} |m|}{\sum_{m \in M_{\text{all}}} |m|}$$
$M_{\text{useful}}$: 유용한 메시지 집합, $|m|$: 메시지 $m$의 토큰 수. MEI가 낮으면 대부분의 토큰이 "낭비"되고 있음을 의미. AutoGen GroupChat에서 MEI $\approx 0.4$, LangGraph에서 MEI $\approx 0.7$로 측정.

CQ의 자동 측정 파이프라인

의사소통 품질을 수동으로 평가하는 것은 비실용적이다. 다음은 자동 CQ 측정 파이프라인의 구조다:

# CQ 자동 측정 파이프라인 class CommunicationQualityAnalyzer: """멀티 에이전트 대화의 의사소통 품질 자동 분석""" def __init__(self, llm_judge): self.judge = llm_judge self.repetition_threshold = 0.85 # 의미적 유사도 임계값 def analyze_conversation(self, messages): """전체 대화의 CQ 분석""" results = { "conciseness": self._measure_conciseness(messages), "coherence": self._measure_coherence(messages), "utility": self._measure_utility(messages), "redundancy_map": self._build_redundancy_map(messages) } # 가중 합산 results["CQ"] = (0.3 * results["conciseness"] + 0.3 * results["coherence"] + 0.4 * results["utility"]) return results def _measure_conciseness(self, messages): """반복 메시지 비율 측정""" redundant = 0 for i, m1 in enumerate(messages): for m2 in messages[i+1:]: sim = semantic_similarity(m1["content"], m2["content"]) if sim > self.repetition_threshold: redundant += 1 break return 1.0 - (redundant / max(len(messages), 1)) def _measure_coherence(self, messages): """동일 에이전트의 메시지 간 모순 측정""" contradictions = 0 by_agent = defaultdict(list) for m in messages: by_agent[m["sender"]].append(m) for agent, msgs in by_agent.items(): for i in range(1, len(msgs)): # LLM으로 모순 여부 판단 is_contra = self.judge( f"다음 두 메시지가 모순되는가?\n" f"1: {msgs[i-1]['content']}\n" f"2: {msgs[i]['content']}" ) if is_contra: contradictions += 1 total_pairs = sum(len(m)-1 for m in by_agent.values() if len(m) > 1) return 1.0 - (contradictions / max(total_pairs, 1))
CQ의 작업 유형별 가중치

창작(coding) 작업에서는 간결성이 중요하지만($w_1=0.4$), 분석 작업에서는 유용성이 더 중요하다($w_3=0.5$). 가중치를 잘못 설정하면, 창작 에이전트가 불필요하게 장황해지거나, 분석 에이전트가 너무 짧아서 맥락을 잃을 수 있다.

8.3.4 결론 일관성 (Conclusion Consistency)

여러 에이전트가 도출한 결론이 서로 일관성이 있는가? 이 차원은 특히 분석/의사결정 작업에서 중요하다.

결론 일관성 (CC)

$$CC = \frac{1}{\binom{N}{2}} \sum_{i

$C_i$: 에이전트 $i$의 최종 결론, $\text{sim}$: 의미적 유사도 함수. $N$개 에이전트의 모든 쌍에 대해 평균.

주의: CC가 너무 높으면 오히려 문제

CC가 0.95 이상이면 모든 에이전트가 동일한 결론에 도달한 것이다. 이것은 (1) 올바른 합의 도달이거나 (2) 확증 편향 증폭(confirmation bias amplification)일 수 있다. 다양성이 지나치게 낮으면 "집단사고(groupthink)"의 징후. 따라서 CC는 $0.7 \leq CC \leq 0.9$ 구간이 이상적이다 — 충분한 합의는 이루어지되, 독립적 사고는 보존되어야.

CC의 세 가지 측정 수준

수준 1: 표면적 일치(Surface Agreement). 결론의 핵심 명제가 동일한가? "X 기능을 추가하라" vs "X 기능을 추가하라"는 완전 일치. 빠르지만 얕다.

수준 2: 논리적 일치(Logical Consistency). 결론에 도달한 추론 경로가 일관성이 있는가? 같은 결론이라도, 한 에이전트는 "성능 때문"이라고 하고 다른 에이전트는 "보안 때문"이라고 하면 논리적 일치가 낮다.

수준 3: 가치 정렬(Value Alignment). 결론 뒤에 있는 가치 판단이 일치하는가? "성능 vs 가독성"에서 어느 것을 우선하는가? 이 수준이 가장 깊지만 측정이 가장 어렵다.

3수준 CC 통합 지표
$$CC_{\text{total}} = \alpha \cdot CC_{\text{surface}} + \beta \cdot CC_{\text{logical}} + \gamma \cdot CC_{\text{value}}$$
$\alpha + \beta + \gamma = 1$. 일반적으로 $\alpha=0.3, \beta=0.4, \gamma=0.3$. 논리적 일치에 가장 높은 가중치. 가치 정렬은 측정 비용이 높아 LLM-as-Judge에 의존.
# CC 3수준 측정 def measure_conclusion_consistency(conclusions, agents): """3수준 결론 일관성 측정""" # 수준 1: 표면적 일치 — 임베딩 코사인 유사도 embeddings = [embed(c["conclusion"]) for c in conclusions] surface_scores = [] for i in range(len(embeddings)): for j in range(i+1, len(embeddings)): surface_scores.append(cosine_sim(embeddings[i], embeddings[j])) cc_surface = np.mean(surface_scores) # 수준 2: 논리적 일치 — 추론 경로 비교 reasoning_chains = [c["reasoning"] for c in conclusions] cc_logical = llm_judge( f"다음 추론 체인들이 논리적으로 일관성이 있는가?\n" + "\n---\n".join(reasoning_chains) ) # 수준 3: 가치 정렬 — 가치 판단 비교 value_judgments = [c["values"] for c in conclusions] cc_value = llm_judge( f"다음 가치 판단이 정렬되어 있는가?\n" + "\n---\n".join(value_judgments) ) # 통합 cc_total = 0.3*cc_surface + 0.4*cc_logical + 0.3*cc_value return { "surface": cc_surface, "logical": cc_logical, "value": cc_value, "total": cc_total, "risk": "groupthink" if cc_surface > 0.95 else "healthy" }

8.3.5 자원 분배 효율 (Resource Allocation Efficiency)

에이전트 간에 작업량과 토큰 소비가 균형 있게 분배되는가? 한 에이전트가 과부하되면 전체 시스템이 병목된다.

자원 분배 효율 (RAE)

$$RAE = 1 - \frac{\sigma_T}{\mu_T}$$

$\sigma_T$: 에이전트별 토큰 사용량의 표준편차, $\mu_T$: 평균 토큰 사용량. RAE가 1에 가까울수록 균등 분배.

자원 분배 불균형의 3가지 원인

① 허브 에이전트(Hub Agent): 매니저/오케스트레이터 역할의 에이전트가 모든 메시지를 중계하여 토큰 사용량이 폭증. 위계적 CrewAI에서 흔히 관찰됨.

② 무임승차자(Free-rider): 특정 에이전트가 최소한의 응답만 하고 실질적 기여를 하지 않음. "네, 동의합니다"만 반복하는 에이전트가 대표적.

③ 워크홀릭(Workaholic): 한 에이전트가 다른 에이전트의 역할까지 대신 수행. 역할 침범과 자원 불균형이 동시에 발생.

# 자원 분배 분석 시각화 import matplotlib.pyplot as plt import numpy as np def analyze_resource_allocation(token_usage: dict): """에이전트별 토큰 사용량 분석""" agents = list(token_usage.keys()) tokens = list(token_usage.values()) mean_t = np.mean(tokens) std_t = np.std(tokens) rae = 1 - (std_t / mean_t if mean_t > 0 else 0) # Gini 계수 (불평등 정도) sorted_t = np.sort(tokens) n = len(sorted_t) gini = (2 * np.sum((np.arange(n) + 1) * sorted_t)) / (n * np.sum(sorted_t)) - (n + 1) / n return { "rae": rae, "gini": gini, "hub_agent": agents[np.argmax(tokens)], "free_rider": agents[np.argmin(tokens)] } # 예시: AutoGen 3에이전트 usage = {"researcher": 2500, "writer": 800, "reviewer": 400} result = analyze_resource_allocation(usage) # RAE ≈ 0.57 (불균형), Gini ≈ 0.35

8.3.6 5차원 통합: 멀티 에이전트 평가 지수

위 5가지 차원을 종합한 MEI(Multi-agent Evaluation Index)를 정의한다:

MEI — 멀티 에이전트 평가 지수
$$\text{MEI} = \alpha_1 \cdot IT + \alpha_2 \cdot RA + \alpha_3 \cdot CQ + \alpha_4 \cdot CC + \alpha_5 \cdot RAE$$
가중치 $\alpha_i$는 작업 유형에 따라 다르다. 기본값: $\alpha = (0.25, 0.20, 0.20, 0.20, 0.15)$. 정보 전달에 약간 더 높은 가중치를 부여하는 것이 실험적으로 가장 변별력이 높다.
작업 유형$\alpha_1$(IT)$\alpha_2$(RA)$\alpha_3$(CQ)$\alpha_4$(CC)$\alpha_5$(RAE)
코드 생성0.300.250.150.150.15
분석/의사결정0.200.150.200.300.15
창작/브레인스토밍0.150.150.250.150.30
데이터 파이프라인0.350.200.150.200.10

① 정보 전달 효율 (Info Transfer)

$IT = \frac{|\text{전달된 핵심 정보}|}{|\text{필요한 핵심 정보}|}$

에이전트 간에 중요한 정보가 누락 없이 전달되는가?

② 역할 준수 (Role Adherence)

$RA = 1 - \frac{|\text{역할 밖 행동}|}{|\text{전체 행동}|}$

각 에이전트가 자신의 역할을 수행하는가?

③ 의사소통 품질 (Comm Quality)

$CQ = \frac{\text{유용한 메시지}}{\text{전체 메시지}}$

불필요한 반복, 모순, 혼란이 없는가?

④ 결론 일관성 (Conclusion Consistency)

$CC = \cos(\mathbf{v}_{\text{final}}, \mathbf{v}_{\text{optimal}})$

최종 결론이 논리적으로 일관되는가?

⑤ 자원 분배 (Resource Allocation)

$R_{\text{waste}} = \frac{\sum \text{불필요한 토큰}}{\sum \text{전체 토큰}}$

에이전트 간 작업량이 균형 있는가?

8.4 협업 실패 모드

멀티 에이전트 협업은 단일 에이전트에 없는 새로운 종류의 실패를 만들어낸다. 이 절에서는 6가지 주요 실패 모드를 분석하고, 각각의 원인 체인(causal chain), 탐지 방법, 완화 전략을 제시한다.

8.4.1 정보 누락 (Information Loss)

원인 체인

컨텍스트 윈도우 한계 → 이전 메시지 요약 → 핵심 정보 누락 → 후속 에이전트가 불완전한 정보로 작업 → 누적 오류

이것은 "전화 게임(telephone game)" 문제다. 3단계만 거쳐도 원본 정보의 50% 이상이 손실될 수 있다.

컨텍스트 압축 손실 모델
$$L_{\text{cumulative}} = 1 - \prod_{k=1}^{K} \left(1 - \frac{|C_k|}{W}\right)$$
$C_k$: $k$번째 에이전트의 컨텍스트 크기, $W$: 컨텍스트 윈도우 크기. $\frac{|C_k|}{W}$가 1에 가까워지면 압축이 심해지고 손실이 급증. 실제로 AutoGen에서 4에이전트 체인은 $L_{\text{cumulative}} \approx 0.65$에 도달.

8.4.2 역할 침범 (Role Intrusion)

원인 체인

불명확한 역할 정의 → 에이전트가 다른 역할 수행 → 원래 역할 공백 → 전체 파이프라인 붕괴

사례: 코드 리뷰 워크플로우에서 리서처가 "이 코드는 다음과 같이 개선해야 합니다..."라며 직접 코드 수정 제안. 리뷰어와 리서처의 역할이 충돌하여, 실제 리뷰는 이루어지지 않음.

역할 침범 탐지 — RA 역산
$$\text{Intrusion}(A_i) = \frac{|\{a \in \text{Actions}(A_i) : a \notin R_i\}|}{|\text{Actions}(A_i)|}$$
$R_i$: 에이전트 $i$의 역할에 해당하는 행동 집합. $\text{Intrusion} > 0.2$이면 역할 침범으로 간주. 문제는 $R_i$를 자동으로 정의하기 어렵다는 것. LLM-as-Judge로 "이 행동이 해당 역할에 적합한가?"를 판단.

역할 침범의 4가지 패턴

① 하향식 침범(Downward Intrusion): 매니저/조정자가 하위 에이전트의 작업을 직접 수행. CrewAI에서 매니저가 "내가 직접 하겠습니다"라며 태스크를 수행.

② 상향식 침범(Upward Intrusion): 하위 에이전트가 조정/결정 역할을 침범. 리서처가 "다음 단계는 X를 해야 합니다"라며 매니저의 역할 수행.

③ 수평적 침범(Lateral Intrusion): 동급 에이전트 간 역할 침범. 리서처가 코드를 작성하거나, 작성자가 리서치를 수행.

④ 진화적 침범(Evolutionary Intrusion): 대화가 진행되면서 역할이 서서히 변형. 처음에는 자기 역할을 잘 수행하던 에이전트가, 10턴 이후에는 다른 역할을 수행. 가장 탐지하기 어려운 패턴.

# 역할 침범 실시간 탐지 class RoleIntrusionDetector: """대화 진행 중 역할 침범 탐지""" def __init__(self, role_definitions): # 각 역할의 허용/금지 행동 정의 self.roles = role_definitions # {agent_name: {allowed: [...], forbidden: [...]}} def check_message(self, agent, message): """메시지가 역할을 침범했는지 확인""" role = self.roles.get(agent, {}) forbidden_keywords = role.get("forbidden", []) intrusions = [] for keyword in forbidden_keywords: if keyword.lower() in message.lower(): intrusions.append(keyword) return { "agent": agent, "intrusion_count": len(intrusions), "intrusions": intrusions, "severity": "high" if len(intrusions) >= 2 else "low" }

8.4.3 확증 편향 증폭 (Confirmation Bias Amplification)

원인 체인

동질적 에이전트 구성 → 초기 가설 형성 → 후속 에이전트가 초기 가설을 비판 없이 수용 → "합의"로 오인된 편향

이것은 가장 위험한 실패 모드다. 표면적으로는 성공처럼 보이기 때문이다. 모든 에이전트가 동의하므로 $CC > 0.95$로 측정되지만, 실제로는 집단사고(groupthink)가 발생한 것이다.

편향 증폭 계수
$$\text{Amplification} = \frac{P(\text{biased conclusion} \mid N \text{ agents})}{P(\text{biased conclusion} \mid 1 \text{ agent})}$$
동일 모델로 구성된 $N$개 에이전트에서 편향 결론에 도달할 확률. 실험적으로 $N=3$일 때 $\text{Amplification} \approx 1.8$, $N=5$일 때 $\approx 2.3$. 즉 5에이전트 시스템은 단일 에이전트보다 편향 결론에 도달할 확률이 2.3배 높다.
# 확증 편향 탐지 — 다양성 지수 측정 from sklearn.metrics.pairwise import cosine_similarity import numpy as np def measure_diversity(agent_conclusions: list, embeddings: list): """에이전트 결론의 의미적 다양성 측정""" sim_matrix = cosine_similarity(embeddings) n = len(embeddings) # 상삼각 행렬의 평균 (자기 유사도 제외) mask = np.triu(np.ones((n, n)), k=1).astype(bool) avg_similarity = sim_matrix[mask].mean() # 다양성 = 1 - 평균 유사도 diversity = 1 - avg_similarity # 편향 증폭 경고 if avg_similarity > 0.95: return { "diversity": diversity, "warning": "집단사고 의심 — 모든 에이전트가 동일 결론", "recommendation": "반대 의견(devil's advocate) 에이전트 추가" } return {"diversity": diversity, "warning": None}

8.4.4 메시지 폭발 (Message Explosion)

메시지 폭발은 멀티 에이전트 시스템에서 가장 흔하면서도 가장 간과되는 실패 모드다. 겉보기에 시스템은 정상 작동하는 것 같지만, 실제로는 대부분의 토큰과 시간이 의미 없는 메시지에 소비되고 있다.

원인 체인

명확한 종료 조건 부재 → 에이전트가 "조금만 더..." 반복 → 토큰 한계 도달 → 강제 종료

AutoGen GroupChat에서 max_round=15로 설정해도, 에이전트가 "동의합니다, 추가로..."라며 실질적 진전 없이 턴을 소비하는 경우가 많다. 이 현상을 "礼貌的沉默"(정중한 침묵)이라 부르자 — 에이전트는 동의의 형태를 취하지만, 그 동의가 작업 완성에 기여하지 않는다.

메시지 폭발의 복잡도
$$\text{Messages}(N, T) \geq N \cdot T - \binom{N}{2} \cdot \left\lfloor \frac{T}{2} \right\rfloor$$
$N$개 에이전트가 $T$턴 동안 대화할 때의 최소 메시지 수. GroupChat에서 $N=5, T=15$이면 최소 60개 메시지, 각각 평균 200토큰이면 12,000토큰만 대화 오버헤드로 소비.

메시지 폭발의 3가지 유형

실제 시스템에서 관찰되는 메시지 폭발은 크게 세 가지 패턴으로 나뉜다:

유형 1: 동의 루프 (Agreement Loop)

에이전트 A가 제안 → B가 동의 + 추가 의견 → C가 동의 + 또 추가 → A가 다시 응답... 무한 반복. 실제 사례: AutoGen GroupChat에서 3에이전트가 "함수명을 개선하자"는 주제로 12턴을 소비하며, 매 턴마다 "좋은 생각입니다, 그리고..."라며 새로운 사소한 제안을 추가. 최종적으로 12개의 함수명 후보 중 하나도 선택하지 못함.

탐지 기준: 연속 $k$개 메시지에서 새로운 정보량(information gain)이 $\Delta I < \epsilon$일 때 폭발로 분류. 여기서 $\Delta I = H(\text{response}_{t+1}) - H(\text{response}_{t+1} | \text{context}_{1:t})$.

유형 2: 수정 전쟁 (Edit War)

에이전트 A가 문서 작성 → B가 수정 → A가 다시 원복 + 수정 → B가 다시 수정... 버전이 분기되며 수렴 불가. 실제 사례: CrewAI에서 Researcher가 보고서 초안 작성 후 Writer가 "가독성 개선"을 위해 구조를 전면 변경, Reviewer가 "원본 구조가 더 낫다"며 다시 변경. 5턴 동안 같은 단락이 7번 수정되며 원본 의미까지 왜곡.

탐지 기준: 동일한 코드/텍스트 블록이 $k$번 이상 수정되고, 최종 버전과 초기 버전의 유사도가 $\text{sim}(v_0, v_k) < 0.3$일 때 폭발로 분류.

유형 3: 컨텍스트 오염 (Context Pollution)

대화가 길어지면서 이전 메시지가 새로운 응답에 노이즈로 작용. 에이전트가 관련 없는 이전 발언에 반응하며 주제가 이탈. 실제 사례: LangGraph에서 10턴째 Writer가 Researcher의 초기 (이미 해결된) 질문에 다시 답변하며, 실제 작업을 잊어버림.

탐지 기준: 최근 $w$개 메시지와 태스크 설명의 의미적 유사도가 $\bar{s} < 0.5$일 때 주제 이탈로 분류.

메시지 효용 지수 (Message Utility Index)
$$\text{MUI}(m_t) = \frac{\text{InformationGain}(m_t)}{\text{TokenCost}(m_t)} = \frac{H(R_{t+1}) - H(R_{t+1} | m_t)}{|m_t|}$$
메시지 $m_t$의 효용. MUI가 0에 가까우면 해당 메시지는 "의사소통 노이즈"다. 건강한 협업에서는 $\overline{\text{MUI}} > 0.1$, 폭발 상태에서는 $\overline{\text{MUI}} < 0.02$.
# 메시지 폭발 탐지기 import numpy as np from typing import List, Dict class MessageExplosionDetector: """3가지 유형의 메시지 폭발을 실시간 탐지""" def __init__(self, window: int = 5): self.window = window self.msg_history: List[Dict] = [] self.edit_counts: Dict[str, int] = {} # block_id → edit count def check_agreement_loop(self, messages: List[str]) -> dict: """유형 1: 동의 루프 탐지""" if len(messages) < self.window: return {"detected": False} recent = messages[-self.window:] agreement_phrases = ["동의", "좋습니다", "맞습니다", "agree"] agreement_ratio = sum( 1 for msg in recent if any(p in msg.lower() for p in agreement_phrases) ) / len(recent) return { "detected": agreement_ratio > 0.7, "agreement_ratio": agreement_ratio, "severity": "HIGH" if agreement_ratio > 0.9 else "MEDIUM" } def check_edit_war(self, block_id: str) -> dict: """유형 2: 수정 전쟁 탐지""" self.edit_counts[block_id] = self.edit_counts.get(block_id, 0) + 1 count = self.edit_counts[block_id] return { "detected": count > 3, "edit_count": count, "recommendation": "해당 블록을 잠그고 투표로 결정" if count > 3 else None } def check_context_pollution(self, recent_msgs, task_desc) -> dict: """유형 3: 컨텍스트 오염 탐지 (의미적 유사도 기반)""" # 실제 구현에서는 임베딩 코사인 유사도 사용 relevance_scores = [ semantic_similarity(m, task_desc) for m in recent_msgs ] avg_relevance = np.mean(relevance_scores) return { "detected": avg_relevance < 0.5, "avg_relevance": avg_relevance, "action": "컨텍스트 윈도우 압축 필요" if avg_relevance < 0.5 else "정상" }

완화 전략: 4가지 설계 원칙

① 명시적 종료 조건: "더 이상 개선할 점이 없으면 'DONE'을 출력"과 같은 명확한 종료 프로토콜. AutoGen에서는 `max_round` 외에 `max_consecutive_auto_reply=3` 설정.

② 정보 게인 임계값: 각 메시지가 이전 메시지 대비 새로운 정보를 $\Delta I \geq \theta$ 이상 포함해야 전송. 그렇지 않으면 메시지가 자동으로 "수신 확인(ACK)"으로 압축.

③ 발언권 관리(Token Budget): 전체 태스크의 토큰 예산 $B$를 설정하고, 각 에이전트에게 $B/N$을 할당. 예산 소진 시 해당 에이전트는 수신 전용으로 전환. "경제적" 메시지를 유도.

④ 요약-압축 주기: $k$턴마다 중간 요약을 생성하여 대화 기록을 압축. LangGraph의 StateGraph에서는 자동으로 최신 상태만 유지하지만, AutoGen/CrewAI에서는 명시적 구현 필요.

메시지 폭발은 "비용 문제"가 아니라 "설계 문제"다

메시지 폭발을 "토큰이 아까워서" 막는 것이 아니다. 폭발된 대화는 평가의 적(敵)이 된다. 60개의 의미 없는 메시지 속에서 의미 있는 정보 전달을 평가하는 것은 불가능에 가깝다. CQ(의사소통 품질) 점수가 폭발된 대화에서는 "노이즈의 품질"을 측정하게 된다. 따라서 메시지 폭발 방지는 평가의 전제 조건이다.

8.4.5 교착 상태 (Deadlock)

원인 체인

에이전트 A가 "X 방안이 낫다" → 에이전트 B가 "Y 방안이 낫다" → A가 재반박 → B가 재반박 → 무한 순환

이것은 의견 충돌 해결 메커니즘이 없을 때 발생한다. AutoGen에서는 GroupChatManager가 임의 종료할 수 있지만, CrewAI/LangGraph에서는 명시적 타임아웃이 필요하다.

교착 상태 탐지 — 순환 패턴 매칭
$$\text{Deadlock}(H) = \exists\, k : \text{sim}(m_t, m_{t-k}) > \theta \land \text{sender}(m_t) = \text{sender}(m_{t-2k})$$
대화 이력 $H$에서 주기 $k$로 반복되는 메시지 패턴을 탐지. 동일 에이전트가 $k$턴 간격으로 유사한 주장을 반복하면 교착 상태. 임계값 $\theta$는 일반적으로 0.8. 이 탐지는 실시간으로 수행되어야 하므로, 효율적인 슬라이딩 윈도우(sliding window) 방식 필요.
# 교착 상태 실시간 탐지기 class DeadlockDetector: """멀티 에이전트 대화의 교착 상태 실시간 탐지""" def __init__(self, window=6, threshold=0.8): self.window = window # 확인할 이전 메시지 수 self.threshold = threshold def check(self, message, history): """새 메시지가 교착 패턴인지 확인""" sender = message["sender"] content = message["content"] # 동일 발신자의 최근 메시지 찾기 sender_msgs = [m for m in history[-self.window:] if m["sender"] == sender] if len(sender_msgs) >= 2: # 가장 최근 동일 발신자 메시지와 비교 sim = semantic_similarity(content, sender_msgs[-1]["content"]) if sim > self.threshold: return { "deadlock": True, "pattern": f"동일 주장 반복 (sim={sim:.2f})", "resolution": "투표 또는 강제 결정 필요" } return {"deadlock": False}
교착 상태의 숨겨진 원인: 불완전한 프롬프트

교착 상태의 근본 원인은 종종 에이전트 프롬프트에 "의견 충돌 시 어떻게 할 것인가"가 정의되지 않았기 때문이다. "분석가" 역할의 에이전트가 "비평가" 역할의 에이전트와 충돌할 때, 누가 최종 결정권을 가지는지가 명확하지 않으면 교착이 발생한다. 해결책: 각 에이전트에 의견 충돌 해결 프로토콜을 프롬프트에 포함시킨다.

8.4.6 부작용 충돌 (Side-effect Collision)

원인 체인

에이전트 A가 파일 쓰기 → 에이전트 B가 동시에 같은 파일 쓰기 → 마지막 쓰기가 이전 것을 덮어씀 → 데이터 손실

이것은 분산 시스템의 고전적 문제가 멀티 에이전트에 재현된 것이다. 상호 배제(mutual exclusion) 없이 공유 자원에 접근하면 필연적으로 발생.

부작용 충돌 확률
$$P(\text{collision}) = 1 - \prod_{i=1}^{N}\left(1 - \frac{|S_i|}{|S_{\text{total}}|}\right)$$
$S_i$: 에이전트 $i$가 수정하는 공유 자원의 집합. $|S_i \cap S_j| > 0$이면 충돌 가능. 3개 에이전트가 5개 파일을 무작위 수정하면 충돌 확률 $\approx 0.48$. 파일당 1개 에이전트만 수정하도록 제한하면 $P = 0$.

부작용 충돌의 4가지 패턴

① 덮어쓰기(Overwrite): 에이전트 A의 결과를 에이전트 B가 덮어씀. 파일 시스템에서 가장 흔함.

② 순서 의존(Ordering): A→B 순서로 실행되어야 하는데 B→A로 실행됨. 예: 테스트를 먼저 실행하고 코드를 나중에 수정.

③ 부분 갱신(Partial Update): A가 레코드의 필드 1~3을 수정하고, B가 필드 3~5를 수정. 필드 3의 값이 경쟁 상태(race condition)에 빠짐.

④ 리소스 고갈(Resource Exhaustion): 여러 에이전트가 동시에 API를 호출하여 레이트 리밋(rate limit)에 도달. 결과적으로 모든 에이전트가 실패.

# 부작용 충돌 방지 — 파일 잠금 메커니즘 import fcntl from contextlib import contextmanager @contextmanager def agent_file_lock(filepath, agent_name): """에이전트별 파일 잠금 — 상호 배제 보장""" lockfile = filepath + ".lock" with open(lockfile, "w") as f: f.write(agent_name) f.flush() # 비배타적 잠금 획득 시도 try: fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB) yield # 임계 구역 finally: fcntl.flock(f, fcntl.LOCK_UN)
실패 모드원인증상검출 방법완화 전략
정보 누락컨텍스트 길이 초과이전 에이전트의 핵심 발견을 무시Info Transfer < 0.7구조화된 요약, 체크포인트
역할 침범불명확한 역할 정의리서처가 코드를 작성Role Adherence < 0.8명시적 역할 프롬프트, 가드레일
확증 편향 증폭동질적 에이전트 구성초기 가설을 비판 없이 수용Diversity < 0.1Devil's advocate 에이전트
메시지 폭발효율적 종료 조건 부재100턴 이상 무한 대화Comm Quality < 0.3진전 감지기, 강제 종료
교착 상태의견 충돌 해결 불가동일 주제에서 순환loop detection타임아웃, 투표 메커니즘
부작용 충돌동시 파일/DB 수정마지막 수정이 이전 수정 덮어씀conflict detection상호 배제, 버전 관리
실패 모드 간 상호작용

이 6가지 실패 모드는 독립적이지 않다. 메시지 폭발이 발생하면 컨텍스트가 길어져 정보 누락이 악화되고, 역할 침범이 발생하면 자원 불균형이 심화된다. 이 "실패 연쇄(failure cascade)"는 단일 에이전트에서는 불가능한 현상이다. Ch.11에서 이 연쇄를 끊는 평가 기반 개입(evaluation-driven intervention) 전략을 다룬다.

8.5 프레임워크별 협업 평가 전략

8.2에서 분석한 각 협업 패턴은 서로 다른 평가 전략을 요구한다. 이 절에서는 프레임워크별로 어떤 차원을 중심으로 평가해야 하는지, 어떤 도구로 궤적을 캡처하는지를 구체적으로 제시한다.

8.5.1 AutoGen 평가 전략

AutoGen은 세 가지 패턴(순차, 그룹, 중첩)이 존재하므로, 패턴별로 다른 평가 접근이 필요하다.

순차 위임 평가

핵심 차원: 정보 전달 효율(IT). 순차 파이프라인에서 가장 중요한 것은 이전 단계의 정보가 손실 없이 다음 단계로 전달되는가이다.

측정 방법: 각 단계의 입력/출력을 후크(hook)로 캡처하여, 정보 누락률을 단계별로 측정.

# AutoGen 순차 위임 — 단계별 품질 추적 class SequentialQualityTracker: def __init__(self): self.stage_data = {} def hook(self, sender, receiver, message): """각 메시지 전달 시 품질 기록""" stage = f"{sender.name}->{receiver.name}" self.stage_data[stage] = { "input_tokens": len(message.split()), "timestamp": time.time() } def compute_quality_drop(self): """단계별 품질 저하 분석""" stages = list(self.stage_data.keys()) if len(stages) < 2: return {} quality_profile = {} for i in range(1, len(stages)): prev_tokens = self.stage_data[stages[i-1]]["input_tokens"] curr_tokens = self.stage_data[stages[i]]["input_tokens"] # 토큰 수 변화로 정보 증감 추정 quality_profile[stages[i]] = { "retention": min(1.0, curr_tokens / max(prev_tokens, 1)), "stage": i } return quality_profile

그룹 토론 평가

핵심 차원: 의사소통 품질(CQ), 결론 일관성(CC). 그룹 토론에서는 메시지 효율성과 다양성이 핵심.

측정 방법: (1) 참여 균형 지수: 각 에이전트의 발언 횟수 균형, (2) 정보 다양성: 각 메시지의 의미적 신규성, (3) 수렴 속도: 토론이 합의에 도달하는 속도.

AutoGen GroupChat: 자동 품질 모니터링

GroupChat의 가장 큰 문제는 대화가 산으로 가는 것이다. 이를 실시간으로 감지하는 품질 모니터를 구축할 수 있다:

# AutoGen GroupChat 실시간 품질 모니터 class GroupChatMonitor: """GroupChat 대화의 실시간 품질 모니터링""" def __init__(self, max_rounds=15): self.max_rounds = max_rounds self.metrics_history = [] def on_message(self, message, round_num): """새 메시지마다 품질 메트릭 업데이트""" # 참여 균형 speaker_counts = Counter(m["sender"] for m in self.messages) participation_balance = 1.0 - np.std(list(speaker_counts.values())) / np.mean(list(speaker_counts.values())) # 정보 다양성 if len(self.messages) >= 2: last_msg = self.messages[-1]["content"] prev_msgs = [m["content"] for m in self.messages[-3:]] novelty = 1.0 - max(semantic_similarity(last_msg, p) for p in prev_msgs) else: novelty = 1.0 # 경고 조건 warnings = [] if participation_balance < 0.5: warnings.append("참여 불균형: 일부 에이전트만 발언") if novelty < 0.2: warnings.append("정보 다양성 낮음: 반복적 대화") if round_num > self.max_rounds * 0.7 and not self._has_convergence(): warnings.append("수렴 지연: 합의에 가까워지지 않음") return {"balance": participation_balance, "novelty": novelty, "warnings": warnings}
AutoGen GroupChat 참여 균형 지수
$$\text{Balance} = 1 - \frac{\sigma(\mathbf{c})}{\mu(\mathbf{c})}$$
$\mathbf{c} = (c_1, c_2, \ldots, c_N)$: 각 에이전트의 발언 횟수 벡터. $\sigma$: 표준편차, $\mu$: 평균. Balance가 0.8 이상이면 균형적 참여. AutoGen에서 전형적으로 Researcher가 40%, Writer가 35%, Reviewer가 25%를 차지하여 Balance $\approx 0.75$.

8.5.2 CrewAI 평가 전략

CrewAI는 역할 중심 설계이므로 역할 준수도(RA)가 가장 중요한 평가 차원이다.

CrewAI 평가 파이프라인

# CrewAI 평가 — 태스크 출력 기반 from crewai import Crew, Task, Agent def evaluate_crew_run(crew: Crew, result: dict): """CrewAI 실행 결과 평가""" evaluation = { "task_completion": [], "role_adherence": [], "resource_balance": {} } # 1. 태스크 완성도 for task in crew.tasks: output = result.get(task.description, {}) completion_score = llm_judge( criteria="태스크 목표 달성도", task_goal=task.description, output=str(output) ) evaluation["task_completion"].append({ "task": task.description[:50], "score": completion_score }) # 2. 자원 분배 분석 token_usage = {} for agent in crew.agents: # CrewAI는 usage_metrics로 토큰 추적 token_usage[agent.role] = getattr( agent, "usage_metrics", {} ).get("total_tokens", 0) return evaluation

CrewAI 역할 준수도 심층 분석

CrewAI의 가장 큰 장점이자 평가 핵심은 명시적 역할 정의다. 하지만 "역할"의 경계가 모호할 수 있다:

모호성 예시: Researcher의 backstory가 "10년 경력의 시니어 Python 개발자"라면, 코드 작성이 역할 침범인가? 아니면 리서치의 자연스러운 일부인가? 이 모호성을 해결하기 위해 역할 경계 매트릭스를 정의해야 한다:

행동ResearcherWriterReviewer
코드 분석핵심 역할참고만검증
코드 작성금지핵심 역할금지
개선안 제안허용(방향성만)핵심 역할허용(피드백만)
최종 승인금지금지핵심 역할
CrewAI 태스크 종속성 그래프 품질
$$\text{DAG}_{\text{quality}} = \frac{\sum_{t \in T} \text{score}(t) \cdot w_t}{\sum_{t \in T} w_t} \cdot \left(1 - \frac{|\text{blocked\_tasks}|}{|T|}\right)$$
$T$: 태스크 집합, $w_t$: 태스크 가중치, $\text{blocked\_tasks}$: 선행 태스크 실패로 실행 불가능한 태스크. CrewAI의 sequential process에서 선행 태스크가 실패하면 후속 태스크도 실패하므로, 종속성 관리가 전체 품질의 핵심.

LangGraph는 상태 스냅샷 덕분에 가장 정밀한 평가가 가능하다. 각 그래프 노드의 입력 상태와 출력 상태를 비교하여, 정확히 어느 노드에서 품질이 저하되었는지 파악할 수 있다.

LangGraph 노드별 품질 추적

# LangGraph 상태 스냅샷 기반 평가 from langgraph.graph import StateGraph class GraphEvaluator: def __init__(self, graph: StateGraph): self.graph = graph self.snapshots = [] def capture_snapshot(self, node_name, state_before, state_after): """각 노드 실행 전후 상태 캡처""" self.snapshots.append({ "node": node_name, "before": state_before, "after": state_after, "delta": self._compute_delta(state_before, state_after) }) def _compute_delta(self, before, after): """상태 변화량 계산""" delta = {} for key in after: if key in before: if isinstance(after[key], str): delta[key] = { "added": len(after[key]) - len(before[key]), "quality": llm_judge("개선 정도", before[key], after[key]) } return delta def identify_bottleneck(self): """품질 저하 노드 식별""" return min( self.snapshots, key=lambda s: s["delta"].get("quality", {}).get("score", 1.0) )

LangGraph의 순환 루프(Iterative Refinement) 평가

LangGraph의 가장 강력한 기능은 조건부 순환 루프다. Reviewer가 "품질 불충분"이라고 판단하면 Writer 노드로 다시 돌아간다. 이 루프를 평가하는 것이 핵심:

평가 지표:

수렴 속도(Convergence Rate): 몇 번의 루프만에 MEI≥0.8에 도달하는가? 1~2회가 이상적, 3회 이상이면 프롬프트 개선 필요.

루프당 개선도(Improvement per Loop): 각 루프에서 MEI가 얼마나 개선되는가? $\Delta\text{MEI}_k = \text{MEI}_{k} - \text{MEI}_{k-1}$. 첫 번째 루프에서 $\Delta\text{MEI}_1 \approx 0.1$, 두 번째에서 $\Delta\text{MEI}_2 \approx 0.05$로 감소하는 것이 정상. $\Delta\text{MEI}$가 음수면 루프가 악화시키는 것.

루프 포인트(Loop Point) 품질: 루프가 발생하는 노드(주로 Reviewer)의 판단이 정확한가? 오탐지(false positive: 불필요한 루프)와 미탐지(false negative: 필요한 루프를 놓침)의 비율.

LangGraph 순환 루프 효율
$$\text{LoopEff} = \frac{\Delta\text{Quality}_{\text{total}}}{\text{TokenCost}_{\text{loops}}} \cdot \frac{1}{1 + \text{FalsePositive}_{\text{rate}}}$$
$ \Delta\text{Quality}_{\text{total}}$: 모든 루프 후의 품질 개선량, $\text{TokenCost}_{\text{loops}}$: 루프에 사용된 총 토큰. $\text{LoopEff} > 1.0$이면 루프가 비용 대비 효과적. 실제 LangGraph에서 2회 루프 시 $\text{LoopEff} \approx 1.5$, 3회 이상이면 $\text{LoopEff} < 0.8$로 비효율적.
# LangGraph 순환 루프 분석기 class LoopAnalyzer: """LangGraph 순환 루프의 효율성 분석""" def analyze(self, snapshots): loop_points = [s for s in snapshots if s.get("is_loop")] if not loop_points: return {"loops": 0, "converged": True} improvements = [] for i in range(1, len(loop_points)): delta = loop_points[i]["mei"] - loop_points[i-1]["mei"] improvements.append(delta) return { "loops": len(loop_points), "total_improvement": sum(improvements), "marginal_improvement": improvements[-1] if improvements else 0, "converged": loop_points[-1]["mei"] >= 0.8, "recommendation": ( "루프 효율 양호" if sum(improvements) > 0.1 else "프롬프트 개선 필요" ) }

8.5.4 Swarm 평가 전략

Swarm은 내장 평가 기능이 거의 없으므로, 외부 평가 레이어를 구축해야 한다. 핸드오프 지점에서의 상태 검증이 핵심.

Swarm 평가의 세 가지 전략

전략 1: 핸드오프 검증(Handoff Validation). 각 핸드오프 시점에서 전달되는 정보의 완전성을 검증. "리서처가 5가지 발견을 했는 데, 작가에게 3가지만 전달되었는가?"

전략 2: 궤적 재구성(Trajectory Reconstruction). Swarm의 메시지 로그를 분석하여 제어 흐름 그래프를 재구성. 어느 에이전트가 언제 핸드오프를 받았는지 시각화.

전략 3: 외부 벤치마크 연동(External Benchmark Integration). Swarm의 출력을 기존 벤치마크(SWE-bench, HumanEval)로 평가. 협업 품질은 무시하고 결과만 평가하는 pragmatic 접근.

Swarm 핸드오프 효율
$$H_{\text{efficiency}} = \frac{\sum_{h \in H} \text{IT}(h)}{|H|}$$
$H$: 핸드오프 집합, $\text{IT}(h)$: 핸드오프 $h$에서의 정보 전달 효율. 3에이전트 Swarm에서 핸드오프가 2회 발생하면 $|H|=2$. 각 핸드오프의 IT가 0.8, 0.6이면 $H_{\text{efficiency}} = 0.7$. LangGraph의 상태 공유(핸드오프 없음)와 비교하면 Swarm의 핸드오프는 정보 손실 포인트.

Swarm 외부 평가 레이어

# Swarm 핸드오프 검증 래퍼 class SwarmEvalWrapper: def __init__(self, client): self.client = client self.handoff_log = [] def run_with_eval(self, agent, messages, validators): """핸드오프 시점마다 상태 검증""" response = self.client.run(agent=agent, messages=messages) # 각 핸드오프 기록 분석 for msg in response.messages: if "tool_calls" in msg: for tool in msg["tool_calls"]: if "transfer" in tool["function"]["name"]: # 핸드오프 시점의 상태 검증 validation = validators.get( tool["function"]["name"], lambda x: True )(msg["content"]) self.handoff_log.append({ "from": agent.name, "validated": validation }) return response

8.5.5 프레임워크 비교 요약

프레임워크협업 구조평가 가능성궤적 캡처권장 메트릭평가 난이도
AutoGen1:1, GroupChat, Nested높음Hook 콜백IT, RA, CQ중간
CrewAISequential, Hierarchical중간Task outputRA, CC, Resource중간
LangGraphState Machine, Graph매우 높음State snapshot전체 5차원높음(정밀)
OpenAI SwarmHandoff 기반낮음제한적RA, IT낮음(제한)
프레임워크 독립적 평가의 필요성

프레임워크별로 평가 방식이 다르면, 동일한 작업에 대해 AutoGen과 LangGraph의 성능을 비교할 수 없다. Ch.12에서는 프레임워크 독립적 평가 어댑터를 제시하여, 어떤 프레임워크로 구현되었든 동일한 5차원으로 평가할 수 있는 통합 방법을 다룬다.

시사점

멀티 에이전트 평가의 가장 큰 도전은 "좋은 협업"의 정의다. 단일 에이전트에서는 "정답"이 있지만, 협업에서는 "정답"이 없다 — 다만 "더 나은 프로세스"와 "덜 나은 프로세스"가 있을 뿐. 우리의 6차원 프레임워크에서 Coordination(②) 차원이 이 문제를 다룬다.

8.6 멀티 에이전트 평가의 근본적 한계

이 장을 마무리하기 전에, 멀티 에이전트 평가가 근본적으로 가지는 한계를 직시해야 한다. 이 한계들은 기술적 개선으로 해결할 수 있는 것이 아니라, 이론적(impossibility result) 또는 실용적(practical limitation) 성격을 가진다.

8.6.1 평가의 조합 폭발

$N$개의 에이전트가 각각 $M$개의 행동 옵션을 가질 때, 가능한 상호작용 조합은 $M^N$이다. 이것은 단일 에이전트의 $M$과 비교하면 지수적(exponential) 증가다.

평가 공간 복잡도
$$|\text{Eval Space}| = O\left(\binom{N}{2} \cdot M^2 \cdot T\right)$$
$N$개 에이전트, $M$개 행동, $T$턴. 3에이전트·10행동·10턴이면 $\binom{3}{2} \times 100 \times 10 = 3,000$개 평가 포인트. 5에이전트·20행동·20턴이면 190,000개. 현실적으로 모든 조합을 평가하는 것은 불가능하므로, 샘플링 전략이 필수적.

조합 폭발에 대응하는 3가지 샘플링 전략

① 무작위 샘플링(Random Sampling): 가능한 모든 상호작용 중 $k$개를 무작위로 선택하여 평가. 간단하지만, 중요한 상호작용을 놓칠 수 있다. 필요 샘플 수: $k \geq \frac{z^2 \cdot p(1-p)}{e^2}$ (95% 신뢰수준, $\pm 5%$ 오차에서 $k \approx 385$).

② 전략적 샘플링(Stratified Sampling): 에이전트 쌍별로 층을 나누어 각 층에서 샘플링. "리서처-작성자" 쌍과 "작성자-리뷰어" 쌍을 각각 따로 평가. 모든 관계 유형을 커버하지만, 층 정의가 필요.

③ 적대적 샘플링(Adversarial Sampling): 가장 실패할 가능성이 높은 상호작용을 우선 평가. "에이전트 A가 모호한 정보를 전달하고, 에이전트 B가 이를 잘못 해석하는" 시나리오에 집중. 효율적이지만, 정상 케이스를 놓침.

샘플링 효율의 하한
$$k_{\min} = \Omega\left(\frac{N^2 \cdot \log N}{\epsilon^2}\right)$$
$N$개 에이전트의 모든 쌍을 $\epsilon$ 오차 내로 평가하기 위한 최소 샘플 수. $N=5, \epsilon=0.1$이면 $k_{\min} \approx 400$. 즉, 5에이전트 시스템의 모든 상호작용을 10% 오차로 평가하려면 최소 400번의 독립 실행이 필요. 비용이 $400 \times \$0.05/\text{실행} = \$20$.

8.6.2 신뢰도(reliability)의 저하

LLM-as-Judge 방식의 평가자 신뢰도가 $\rho$라고 할 때, $K$단계 순차 평가의 누적 신뢰도는:

누적 평가 신뢰도
$$\rho_{\text{cumulative}} = \rho^K$$
$\rho = 0.85$인 LLM 평가자로 5단계를 평가하면 $\rho^5 \approx 0.44$. 즉, 절반도 신뢰할 수 없다. 이것은 멀티 에이전트 평가가 단일 에이전트 평가보다 근본적으로 더 불확실하다는 의미.

신뢰도 저하를 완화하는 4가지 전략

① 다중 평가자 앙상블(Multi-Judge Ensemble): 동일한 평가를 3개의 독립 LLM으로 수행하고 다수결 또는 평균으로 결정. $\rho_{\text{ensemble}} \approx 1 - (1-\rho)^3 \approx 0.997$ for $\rho=0.85$. 3배 비용 증가.

② 검증된 체크포인트(Verified Checkpoints): 순차 평가의 각 단계를 독립적으로 검증. 전체 누적 신뢰도가 아니라 각 단계의 신뢰도만 관리. 단계 간 독립성을 가정하면 $\rho_{\text{overall}} = 1 - (1-\rho_{\text{step}}) \cdot K$.

③ 자동화된 규칙 기반 필터(Rule-based Prefilter): LLM 평가 전에 규칙 기반 필터로 명백한 오류를 선제 제거. "역할 침범"은 키워드 매칭으로 90% 이상 탐지 가능. LLM은 규칙으로 판단하기 어려운 "미묘한" 경우에만 사용.

④ 인간-인-더-루프(Human-in-the-Loop): LLM 신뢰도가 임계값 이하인 경우에만 인간 평가자 개입. 비용 효율적이지만, 인간 평가자의 일관성도 완벽하지 않음($\rho_{\text{human}} \approx 0.75$).

# 신뢰도 기반 적응적 평가 class AdaptiveEvaluator: """신뢰도에 따라 평가 전략을 자동 조정""" def __init__(self, target_reliability=0.9): self.target = target_reliability self.judge_reliability = 0.85 # LLM-Judge 기본 신뢰도 def evaluate(self, trajectory): K = len(trajectory["stages"]) cumulative = self.judge_reliability ** K if cumulative >= self.target: # 신뢰도 충분 — 단일 Judge로 평가 return self._single_judge_eval(trajectory) elif cumulative >= 0.7: # 신뢰도 보통 — 3-Judge 앙상블 return self._ensemble_eval(trajectory, n=3) else: # 신뢰도 낮음 — 앙상블 + 인간 검토 result = self._ensemble_eval(trajectory, n=5) result["needs_human_review"] = True return result

8.6.3 정답 부재 문제

단일 에이전트 코드 생성에서는 "테스트 통과 여부"라는 명확한 기준이 있다. 하지만 멀티 에이전트 협업에서 "좋은 협업"의 기준은 무엇인가?

세 가지 철학적 접근

① 결과 중심(Outcome-based): 최종 결과물의 품질만으로 평가. 프로세스는 무시. 빠르지만, 우연한 성공을 참 성공과 구분 불가.

② 프로세스 중심(Process-based): 협업 과정의 품질로 평가. 결과가 나빠도 좋은 프로세스면 높은 점수. 정확하지만 평가 비용이 높음.

③ 하이브리드: 결과와 프로세스를 모두 고려. 우리의 MEI 지수가 이 접근. 가장 실용적이지만 가중치 설정이 임의적.

정답 부재와 Goodhart의 법칙

"정답"이 없으면, 우리가 정의한 대용 지표(proxy metric)가 최적화 대상이 된다. MEI가 0.9 이상인 시스템이 "좋은" 시스템이라고 정의하면, 에이전트는 MEI를 높이는 방향으로 최적화된다. 이것이 Goodhart의 법칙: "지표가 목표가 되면, 더 이상 좋은 지표가 아니다." 해결책은 Ch.14에서 다루는 다지표 균형(multi-metric balancing)이다.

정답 부재 하의 평가 품질 상한
$$Q_{\text{eval}} \leq 1 - \frac{H(\text{``좋은 협업''})}{H_{\max}(\text{``좋은 협업''})}$$
"좋은 협업"의 정의에 대한 엔트로피 $H$가 높을수록(=정의가 모호할수록) 평가 품질의 상한이 낮아진다. 단일 에이전트 코딩에서 $H \approx 0.1$이지만, 멀티 에이전트 협업에서 $H \approx 0.6$. 즉, 평가의 이론적 최대 정확도가 40%에서 90% 사이.

8.6.4 인과 관계 추론의 어려움

멀티 에이전트 시스템에서 "에이전트 A가 잘못된 정보를 전달해서 실패했다"고 결론지을 수 있는가? 아니면 "에이전트 B가 정보를 잘못 해석해서 실패했다"고 해야 하는가?

인과 귀인(causal attribution) 문제
$$P(\text{Agent}_i \text{ caused failure} \mid \text{failure}) = \frac{P(\text{failure} \mid \text{Agent}_i \text{ error}) \cdot P(\text{Agent}_i \text{ error})}{\sum_j P(\text{failure} \mid \text{Agent}_j \text{ error}) \cdot P(\text{Agent}_j \text{ error})}$$
베이즈 정리로 인과 확률을 추정할 수 있지만, 분모의 합이 모든 에이전트에 대해 정확히 알려져야 한다. 현실적으로 불가능하므로, 근사적 방법(counterfactual analysis)에 의존.

인과 추론을 위한 반사실적 분석(Counterfactual Analysis)

인과 관계를 추론하는 가장 실용적인 방법은 "만약 X가 달랐다면?"이라는 반사실적 질문을 던지는 것이다:

질문 1: "에이전트 A가 정확한 정보를 전달했다면, 결과가 달랐을까?" → A의 정보를 correct로 교체하여 재실행.

질문 2: "에이전트 B가 A의 정보를 올바르게 해석했다면?" → B의 해석을 oracle로 교체하여 재실행.

질문 3: "조정자가 개입했다면?" → 타임아웃 감지 후 강제 종료 대신 중재 프롬프트 삽입.

이 접근은 실행 비용이 3배이지만, 인과 관계를 가장 신뢰성 있게 추론할 수 있다.

# 반사실적 분석 프레임워크 def counterfactual_analysis(original_run, agent_to_test, correction_fn): """특정 에이전트의 행동을 교정하여 재실행""" # 원본 실행의 메시지 로그 복사 corrected_messages = original_run["messages"].copy() # 대상 에이전트의 메시지를 교정 for i, msg in enumerate(corrected_messages): if msg["sender"] == agent_to_test: corrected_messages[i] = correction_fn(msg) # 교정된 메시지로 재실행 corrected_run = replay_run(corrected_messages) # 원본 vs 교정 비교 return { "original_success": original_run["success"], "corrected_success": corrected_run["success"], "causal_contribution": ( corrected_run["success"] and not original_run["success"] ), "attribution": agent_to_test if ( corrected_run["success"] and not original_run["success"] ) else "other" }

8.6.5 정보 이론적 한계: Shannon 엔트로피 관점

멀티 에이전트 시스템의 통신 효율을 Shannon 정보 이론으로 분석하면, 이론적 하한을 구할 수 있다.

멀티 에이전트 통신 엔트로피
$$H(\text{Comm}) = -\sum_{i=1}^{N}\sum_{j \neq i} P(m_{ij}) \log_2 P(m_{ij})$$
$P(m_{ij})$: 에이전트 $i$가 에이전트 $j$에게 메시지를 보낼 확률. $H$가 높을수록 통신이 무질서(고엔트로피). 이상적인 협업은 $H$가 적당히 낮아야 — 너무 높으면 소통 과부하, 너무 낮으면 정보 고립.

상호 정보량(Mutual Information)으로 측정하는 정보 전달
$$I(A_i; A_j) = H(A_i) - H(A_i \mid A_j) = \sum P(a_i, a_j) \log \frac{P(a_i, a_j)}{P(a_i)P(a_j)}$$
에이전트 $i$와 $j$ 사이의 상호 정보량. $I(A_i; A_j)$가 높으면 두 에이전트가 강하게 연결되어 정보를 효과적으로 공유. $I = 0$이면 완전 독립 — 정보 전달이 없다. AutoGen GroupChat에서 평균 $I \approx 0.35$ bits, LangGraph에서 $I \approx 0.52$ bits로 측정. LangGraph의 구조화된 상태 전달이 정보 공유에 효과적임을 수학적으로 확인.
# Shannon 엔트로피 기반 통신 분석 import numpy as np from collections importdef compute_communication_entropy(messages, agents): """멀티 에이전트 통신 엔트로피 계산""" msg_counts = defaultdict(lambda: defaultdict(0)) total = 0 for msg in messages: sender = msg.get("sender") receiver = msg.get("receiver") if sender and receiver: msg_counts[sender][receiver] += 1 total += 1 # Shannon 엔트로피 entropy = 0 for sender in msg_counts: for receiver in msg_counts[sender]: p = msg_counts[sender][receiver] / total entropy -= p * np.log2(p) # 최대 엔트로피 (균등 분포) max_entropy = np.log2(len(agents) * (len(agents) - 1)) normalized = entropy / max_entropy if max_entropy > 0 else 0 return { "entropy": entropy, "max_entropy": max_entropy, "normalized": normalized, "interpretation": "균형적" if 0.3 < normalized < 0.7 else "편중됨" }

8.6.6 확장성 한계: 2에서 20 에이전트까지

에이전트 수를 증가시키면 평가 복잡도가 어떻게 변하는가? 이것은 실제 시스템 설계에서 가장 중요한 질문 중 하나다.

에이전트 수채널 수MEI(예상)평가 비용실용성
210.80낮음가장 안정적
330.75중간협업 효과 최대
5100.65높음조정 오버헤드 증가
10450.50매우 높음관리 비용이 이익 초과
20190<0.35실질적 불가이론적 한계
"Sweet Spot"은 3~5개 에이전트

실증 연구에 따르면, 멀티 에이전트 협업의 성능 대비 비용 효율이 가장 높은 구간은 3~5개 에이전트다. 2개는 너무 단순하고, 10개 이상은 조정 오버헤드가 협업 이익을 상회한다. 이것은 팀 규모에 대한 "링겔만 효과(Ringelmann Effect)" — 팀이 커질수록 개별 기여가 감소하는 현상 — 과 일치한다.

한계 인식이 곧 설계 원칙

이 한계들을 인정하는 것은 포기가 아니다. 오히려 무엇을 측정할 수 있고 무엇을 측정할 수 없는지를 명확히 함으로써, 평가 설계가 더 탄탄해진다. "조합 폭발"을 알면 샘플링 전략을 설계하고, "정답 부재"를 알면 프로세스 평가를 병행하고, "인과 추론의 어려움"을 알면 개별 에이전트 평가와 시스템 전체 평가를 분리할 수 있다.

8.7 사례 연구: 3에이전트 코드 리뷰 시스템

이 절에서는 지금까지의 이론을 실제 사례에 적용한다. 리서처→작성자→검토자 3에이전트 코드 리뷰 시스템을 AutoGen, CrewAI, LangGraph로 각각 구현하고, 동일한 5차원으로 평가하여 비교한다.

8.7.1 실험 설정

공통 설정

항목
태스크Python 함수 10개의 코드 리뷰 + 개선안 작성
기반 모델GPT-4o (모든 에이전트 동일)
에이전트 수3 (Researcher, Writer, Reviewer)
평가 기준5차원 (IT, RA, CQ, CC, RAE) + 최종 산출물 품질
반복 횟수각 프레임워크 5회 실행, 평균

8.7.2 결과

차원AutoGenCrewAILangGraph해석
IT (정보 전달)0.720.680.85LangGraph가 구조화된 상태로 전달하여 가장 높음
RA (역할 준수)0.700.850.88CrewAI의 명시적 역할 정의가 효과적
CQ (의사소통)0.600.550.78AutoGen의 GroupChat 오버헤드가 최저
CC (결론 일관성)0.750.720.80순환 루프로 수렴한 LangGraph가 가장 일관
RAE (자원 분배)0.550.700.82AutoGen의 Hub 에이전트 문제
MEI (종합)0.660.700.83LangGraph가 모든 차원에서 우위
최종 산출물7.2/107.5/108.1/10프로세스 품질과 결과 품질의 상관관계 확인
총 토큰45,00032,00028,000LangGraph가 가장 효율적
핵심 발견

① 프로세스 품질이 결과 품질과 상관관계가 있다: MEI와 최종 산출물 점수의 피어슨 상관계수 $r = 0.89$. 좋은 협업 과정이 좋은 결과로 이어진다.
② 프레임워크 선택이 성능에 영향을 미친다: 동일한 에이전트/모델/태스크임에도 프레임워크별로 MEI가 0.66~0.83으로 차이. 협업 패턴의 설계가 성능을 좌우한다.

③ 토큰 효율과 품질이 반비례하지 않는다: LangGraph가 가장 적은 토큰(28K)으로 가장 높은 품질(8.1)을 달성. 효율적 상태 관리가 불필요한 메시지를 줄인다.

프레임워크별 ROI (Return on Investment)
$$\text{ROI}_{\text{framework}} = \frac{\text{Quality}_{\text{output}} \times \text{MEI}}{\text{Token Cost} \times \$0.00003/\text{token}}$$
LangGraph: $\frac{8.1 \times 0.83}{28000 \times 0.00003} = 7.98$, AutoGen: $\frac{7.2 \times 0.66}{45000 \times 0.00003} = 3.52$. LangGraph의 ROI가 AutoGen의 2.3배. 상태 기반 설계가 비용 효율성까지 개선.

결과의 통계적 유의성

5회 반복 실험에서 MEI의 표준편차: AutoGen $\sigma=0.04$, CrewAI $\sigma=0.03$, LangGraph $\sigma=0.02$. LangGraph가 가장 안정적. AutoGen vs LangGraph의 MEI 차이(0.66 vs 0.83)는 $p < 0.01$ (paired t-test)로 통계적으로 유의.

하지만 주의: 5회 반복은 최소한의 샘플 크기다. 8.6.1에서 계산한 $k_{\min} \approx 400$에 비하면 턱없이 부족. 따라서 이 결과는 경향성(trend)을 보여주는 것이지, 일반화 가능한 결론이 아니다.

8.7.3 실패 사례 분석

AutoGen: 정보 누락 사례

Researcher가 "이 함수의 시간 복잡도가 $O(n^2)$에서 $O(n \log n)$으로 개선 가능"이라고 보고했으나, Writer가 이 정보를 누락하고 단순 스타일 개선만 작성. Reviewer는 원본 리서치를 볼 수 없어 누락을 발견하지 못함.

원인: 순차 전달에서 Writer의 컨텍스트 윈도우 초과로 자동 요약 발생. 핵심 정보가 요약에서 제외됨.

IT 점수: 0.45 (평균 0.72보다 현저히 낮음)

CrewAI: 역할 침범 사례

Researcher가 리서치를 마치고 Writer에게 전달했어야 하지만, "제가 직접 개선안을 작성하겠습니다"라며 Writer의 역할을 침범. 이후 실제 Writer는 할 일이 없어 "동의합니다"만 반복.

원인: Researcher의 backstory가 "10년 경력의 시니어 개발자"로 설정되어, 코드 작성 능력이 암시됨. 역할 경계가 불명확.

RA 점수: 0.55 (평균 0.85보다 현저히 낮음)

LangGraph: 성공 사례 — 순환 루프의 힘

Reviewer가 "이 개선안은 시간 복잡도 개선이 누락되었습니다"라고 피드백. 상태 그래프의 조건부 분기가 활성화되어 Writer가 다시 작성. 2번째 루프에서 시간 복잡도 개선이 포함된 최종 산출물 도출.

왜 성공했나: LangGraph의 상태 스냅샷이 모든 정보를 구조화된 형태로 유지. Writer가 두 번째 시도에서 Researcher의 원본 발견을 그대로 참조할 수 있었음. 순차 위임의 "전화 게임" 문제를 상태 공유로 해결.

MEI 점수: 0.88 (평균 0.83보다 높음)

8.7.4 개선 전략: 평가 기반 피드백 루프

실패 사례를 분석한 결과, 평가 결과를 실시간으로 시스템에 피드백하면 성능을 개선할 수 있다.

# 평가 기반 실시간 개선 — LangGraph 예시 from langgraph.graph import StateGraph, END class EvalState(TypedDict): code: str review: str mei_scores: dict # 5차원 점수 iteration: int def evaluated_review(state: EvalState): """평가 기반 리뷰 — 품질이 임계값 미만이면 피드백 제공""" review = llm_review(state["code"]) # MEI 5차원 평가 mei = compute_mei(state["code"], review, state) state["mei_scores"] = mei state["review"] = review # 품질이 낮으면 구체적 개선 지시 if mei["IT"] < 0.7: state["review"] += "\n[시스템 경고] 정보 전달 효율이 낮습니다. " "원본 리서치의 핵심 발견을 모두 포함하세요." if mei["RA"] < 0.8: state["review"] += "\n[시스템 경고] 역할 준수도가 낮습니다. " "리뷰어 역할에만 집중하세요." return state def should_iterate(state: EvalState): # MEI 종합 점수가 0.8 이상이거나 3회 반복 시 종료 if state["mei_scores"].get("MEI", 0) >= 0.8 or state["iteration"] >= 3: return "end" return "revise"
평가 기반 개선의 효과

이 피드백 루프를 적용한 결과, AutoGen의 MEI가 0.66→0.78로 +18% 개선, CrewAI가 0.70→0.79로 +13% 개선. LangGraph는 이미 구조화된 상태 관리 덕분에 개선 효과가 상대적으로 작았음(0.83→0.87, +5%). 평가가 가장 필요한 곳은 가장 구조화되지 않은 시스템이다.

8.7.5 메타 분석: 5차원 간 상관관계

15개 실험(3 프레임워크 × 5회)의 데이터를 종합하여 5차원 간 상관관계를 분석한다.

ITRACQCCRAE
IT1.000.450.620.710.38
RA0.451.000.330.520.68
CQ0.620.331.000.580.41
CC0.710.520.581.000.35
RAE0.380.680.410.351.00

주요 발견: IT와 CC의 상관관계가 가장 높다($r=0.71$). 정보가 잘 전달될수록 결론 일관성이 높아진다. 반면 RAE는 다른 차원과 상관관계가 낮아, 자원 분배는 독립적으로 최적화해야 함을 시사.

상관관계로 도출한 개입 전략

상관관계 매트릭스는 어떤 차원을 개선하면 다른 차원에 파급 효과가 있는지를 알려준다. 실무적 활용 방법:

전략 1: IT 우선 개선 — IT→CC($r=0.71$), IT→CQ($r=0.62$) 경로가 존재하므로, 정보 전달을 개선하면 결론 일관성과 의사소통 품질도 자연스럽게 향상. 가장 효율적인 "leverage point".

전략 2: RA 독립 관리 — RA는 다른 차원과 비교적 낮은 상관관계($\bar{r} \approx 0.46$). 역할 준수도는 프롬프트 설계로 직접 제어해야 하며, 다른 차원 개선으로 간접 향상을 기대하기 어렵다.

전략 3: RAE는 비용 문제 — RAE와 다른 차원의 평균 상관관계가 $\bar{r} \approx 0.38$로 가장 낮다. 자원 분배 불균형은 성능 저하보다 비용 낭비와 직결. 비용 최적화 차원에서 별도 관리.

차원 간 개선 전파 효율 (Improvement Propagation Efficiency)
$$\text{IPE}(D_i) = \sum_{j \neq i} r_{ij} \cdot \frac{\partial D_j}{\partial D_i} \approx \sum_{j \neq i} r_{ij} \cdot \frac{\Delta D_j^{\text{observed}}}{\Delta D_i^{\text{intervention}}}$$
차원 $D_i$를 개선했을 때 다른 모든 차원에 미치는 총 효과. IPE(IT) ≈ 1.71, IPE(RA) ≈ 1.30, IPE(RAE) ≈ 1.14. IT 개선이 가장 넓은 파급 효과를 가진다.
MEI의 설계 철학: 독립 vs 종속 차원

5차원이 서로 독립이라면 각각 개별 최적화가 최선이다. 하지만 상관관계가 존재하면, 의존적 최적화가 필요하다. IT를 먼저 확보하면 CC와 CQ가 따라오지만, RAE는 별도 처리해야 한다. 이것이 MEI 가중치에서 IT에 0.25(최고 가중치)를 부여하는 이유다 — 단순히 "정보 전달이 중요해서"가 아니라, IT가 다른 차원의 개선을 촉매하는 역할을 하기 때문이다.

8.8 요약 및 다음 장으로의 연결

이 장에서 우리는 멀티 에이전트 평가의 고유한 차원과 과제를 다루었다. 핵심 요약:

Ch.08 핵심 정리

8.1: 단일→멀티 전환은 "에이전트 수 증가"가 아니라 질적 전환(qualitative shift)이다. 창발성, 통신 채널 폭발, 조정 오버헤드가 새로운 평가 과제를 만든다.

8.2: 4가지 주요 협업 패턴(AutoGen/CrewAI/LangGraph/Swarm)은 각각 다른 평가 전략을 요구한다. LangGraph의 상태 기반 설계가 평가에 가장 유리. 게임 이론적 분석으로 각 패턴의 특성을 규명.

8.3: 멀티 에이전트 고유의 5차원(IT, RA, CQ, CC, RAE)을 정의하고, 이를 종합한 MEI 지수를 제안. 작업 유형별 최적 가중치 테이블 제공.

8.4: 6가지 협업 실패 모드를 원인 체인과 완화 전략과 함께 분석. 특히 확증 편향 증폭은 표면적 성공으로 위장되어 가장 위험.

8.5: 프레임워크별 평가 전략을 구체적 코드로 제시. AutoGen은 Hook 기반, CrewAI는 Task output 기반, LangGraph는 State snapshot 기반.

8.6: 조합 폭발, 신뢰도 저하, 정답 부재, 인과 추론 어려움, 정보 이론적 한계, 확장성 한계라는 6가지 근본적 한계를 규명. Shannon 엔트로피와 상호 정보량으로 통신 효율의 이론적 하한 제시.

8.7: 3에이전트 코드 리뷰 사례에서 MEI와 결과 품질의 상관관계($r=0.89$)를 실증. 평가 기반 피드백 루프가 MEI를 +13~18% 개선.

8.8.1 실천적 체크리스트

멀티 에이전트 시스템을 평가할 때, 다음 체크리스트를 활용하라:

평가 설계 체크리스트

#항목확인 포인트
1에이전트 수 결정3~5개가 sweet spot. 10개 이상은 조정 오버헤드 검증 필요
2협업 패턴 선택순차/그룹/위계/핸드오프 중 태스크에 맞는 패턴 선택
35차원 기준 설정IT≥0.7, RA≥0.8, CQ≥0.6, CC∈[0.7,0.9], RAE≥0.7
4실패 모드 탐지6가지 실패 모드에 대한 자동 탐지 코드 포함
5궤적 캡처프레임워크별 Hook/Snapshot/Output 캡처 설정
6평가 신뢰도LLM-as-Judge의 $\rho \geq 0.85$ 확인, 다단계 시 $\rho^K$ 주의
7반복 횟수최소 5회 반복으로 통계적 유의성 확보
8베이스라인단일 에이전트 성능을 베이스라인으로 설정, 멀티가 실제로 이익인지 검증

8.8.2 미래 연구 방향

이 장에서 다룬 멀티 에이전트 평가는 아직 초기 단계다. 다음은 미래 연구가 집중해야 할 영역이다:

5가지 미래 연구 과제

① 동적 역할 재배치 평가: 현재는 역할이 고정되어 있지만, 실제 복잡한 작업에서는 에이전트가 스스로 역할을 재배치해야 한다. "역할 진화"를 어떻게 평가할 것인가? 현재의 RA 지표는 "고정된 역할에 대한 준수도"만 측정한다. 적응적 역할 준수도(Adaptive RA) — 역할 변화가 태스크 성공에 기여했는지를 평가하는 새로운 지표가 필요하다.

② 인간-에이전트 협업 평가: 이 장은 순수 에이전트-에이전트 협업만 다루었다. 인간이 루프에 포함된 경우(Human-in-the-loop), 평가 차원이 어떻게 변하는가? 인간의 피로도, 신뢰도, 개입 빈도가 새로운 차원이 된다. 특히 인간의 과신용(overtrust)/과불신용(undertrust)이 시스템 성능에 미치는 영향은 측정되지 않고 있다.

③ 대규모 멀티 에이전트(10+): 확장성 한계를 극복하기 위한 계층적(hierarchical) 평가 구조. 10개 에이전트를 3개 서브그룹으로 나누어 그룹 내/간 평가를 분리. 핵심 과제: 그룹 경계(group boundary)를 어떻게 정의하고, 그룹 간 상호작용을 어떻게 측정할 것인가?

④ 멀티모달 협업 평가: 텍스트뿐 아니라 이미지, 코드, 표를 주고받는 멀티모달 에이전트 간의 정보 전달 효율을 어떻게 측정할 것인가? IT 지표를 모달리티별로 확장하여, 모달리티 간 정보 변환 손실(cross-modal information loss)을 정량화해야 한다.

⑤ 평가 기반 자동 최적화: 8.7.4의 피드백 루프를 확장하여, 평가 결과를 기반으로 협업 구조를 자동으로 최적화하는 메타러닝(meta-learning) 접근. "어떤 패턴이 이 태스크에 최적인가?"를 자동으로 탐색. 평가-최적화 루프(Evaluation-Optimization Loop)의 수렴 조건과 안정성 분석이 선행 과제다.

미래 연구 로드맵: 난이도-영향력 매트릭스
과제구현 난이도학술적 영향력산업적 영향력권장 우선순위
① 동적 역할높음높음중간2순위
② 인간-에이전트중간매우 높음매우 높음1순위
③ 대규모(10+)매우 높음중간높음3순위
④ 멀티모달높음높음높음2순위
⑤ 자동 최적화매우 높음매우 높음매우 높음장기 목표
인간-에이전트 협업이 1순위인 이유: 산업 현장에서 가장 즉각적인 수요가 있으며, 기존 평가 차원을 확장하는 것으로 시작 가능하기 때문. 자동 최적화는 장기 목표지만, 8.7.4의 피드백 루프가 그 초석이 된다.
Part II→Part III: 평가에서 실천으로

Ch.07~08에서 우리는 에이전트 벤치마크와 멀티 에이전트 평가 차원을 다루었다. 이것은 "무엇을 측정할 것인가"에 대한 답이다. Ch.09에서는 "기존 프레임워크가 이것을 얼마나 잘 측정하는가"를 비교 분석하고, Ch.10 이후에서는 "우리가 직접 평가 시스템을 어떻게 설계하는가"로 넘어간다.

특히 이 장에서 정의한 5차원(IT, RA, CQ, CC, RAE)은 Part III에서 평가 파이프라인 설계의 핵심 기반이 된다. MEI 지수는 Ch.13의 종합 평가 대시보드에서 직접 활용된다.