AI 에이전트, MCP 자료
AI 에이전트 구성 & 메시지 프로토콜 v2.0
최종 업데이트: 2026-04-17 10:45
기준 버전: Mind-Log v5.0 (팟캐스트 전용 파이프라인)
원본 문서:
CLAUDE.md,docs/architecture/AGENT_ROLES.md
1. 에이전트 구성 — 팟캐스트 파이프라인 12개 에이전트 (Learning Agent 포함)
Mind-Log v5.0은 팟캐스트 모드 전용 파이프라인이다. 대화모드는 제거되었다.
팟캐스트 파이프라인 12개 에이전트(TIER 0~4: 9개 + 독립 2개 + Learning 1개 = 12개)로 구성된다.
| # | 에이전트명 | sender/receiver 식별자 | TIER | 담당 |
|---|---|---|---|---|
| 01 | Intent Classifier | intent_classifier | 0 | 개발자1 |
| 02 | Safety Agent | safety | 1 (병렬) | 개발자2 |
| 03 | Emotion Agent | emotion | 1 (병렬) | 개발자2 |
| 04 | Content Analyzer | content_analyzer | 1 (병렬) | 개발자3 |
| 05 | Podcast Reasoning | podcast_reasoning | 1 (병렬) | 개발자3 |
| 06 | Episode Memory | episode_memory | 독립 (Reasoning 조건부) | 개발자2 |
| 07 | Knowledge Agent | knowledge | 독립 (Reasoning 조건부) | 개발자1 |
| 08 | Script Generator | script_generator | 2 (병렬) | 개발자1 |
| 09 | Visualization | visualization | 2 (병렬) | 개발자2 |
| 10 | Batch Validator | batch_validator | 3 | 개발자3 |
| 11 | Script Personalizer | script_personalizer | 4 | 개발자1 |
| 부가 | Learning Agent | learning | 비동기 후처리 | 개발자3 |
2. TIER 기반 파이프라인
TIER 0: intent_classifier → 의도 분류, 1차 위기 감지
TIER 1 (병렬 Fan-out):
├── safety
├── emotion
├── content_analyzer
└── podcast_reasoning
├── episode_memory ← 조건부 호출
└── knowledge ← 조건부 호출
TIER 2 (병렬):
├── script_generator
└── visualization
TIER 3: batch_validator → PASS/FAIL 검증
TIER 4: script_personalizer → 최종 출력
비동기: learning (에피소드 완료 후)
3. 에이전트 간 통신 — 메시지 프로토콜 v2.0
통합 메시지 엔벨로프
{
"schema_version": "agents.protocol.v2",
"message_id": "msg_{uuid}",
"request_id": "req_{uuid}",
"timestamp": "2026-02-10T14:30:00.123Z",
"sender": "{agent_name}",
"receiver": "{agent_name}",
"message_type": "request | response | event | cancel | error",
"payload": {},
"metadata": {
"session_id": "sess_{uuid}",
"correlation_id": "corr_{uuid}",
"trace_id": "trace_{uuid}",
"mode": "podcast",
"interaction_unit": "episode",
"tier": 0,
"priority": 1,
"retry_count": 0
},
"audit": {
"agent_version": "1.0.0",
"processing_time_ms": 120,
"llm_calls": 1,
"status": "ok | error | partial"
},
"errors": []
}
현재 구현 상태:
BaseAgent.create_message()로 MessageEnvelope(v2.0) 생성이 가능하나, 에이전트 간 통신은 LangGraph AgentState 공유 + DI 패턴으로 구현되어 엔벨로프 미활성 상태. 백엔드 확장 시 활성화 검토.
priority 레벨
| priority | 의미 | 사용 사례 |
|---|---|---|
| 0 | CRITICAL | Safety CRISIS 취소 시그널 |
| 1 | HIGH | 일반 파이프라인 메시지 |
| 2 | NORMAL | 비동기 후처리, 보조 에이전트 |
| 3 | LOW | 학습/통계 수집 |
message_type
| message_type | 용도 |
|---|---|
| request | 에이전트에 작업 요청 |
| response | 작업 결과 전달 |
| event | 비동기 이벤트 (결과 기대 없음) |
| cancel | 실행 중 취소 (CRISIS) |
| error | 에이전트 실패 알림 |
4. CRISIS 선점 메커니즘
4.1 설계 원안 (Design)
Safety Agent가 L3~L4 위기를 감지하면 (설계상 의도):
Safety → asyncio.Event cancel_event 발행
↓
TIER 1 병렬 에이전트 (emotion, content_analyzer, podcast_reasoning) → 취소
↓
Safety가 직접 위기 응답 생성 (script_generator / batch_validator / script_personalizer 건너뜀)
↓
next_step = "crisis_response"
⚠️ 설계 vs 실제 코드 (PR #159 반영)
위 블록은 설계 원안이다. PR #159 이후 실제 코드(
src/graph/workflow.py:297, 334, 378)는 다음과 같이 동작한다:
- line 297:
cancel_event = asyncio.Event()객체는 생성되지만
- line 334: CRISIS 감지 시 cancel_event를 발행(set)하지 않는다 (주석: "CRISIS 감지 — 파이프라인 계속 진행 (cancel_event 미발행)")
- line 378:
cancel_event.set()호출은 TIMEOUT 경로 전용이다
- CRISIS는 TIER 1 병렬 작업을 취소하지 않고, TIER 2~4까지 하드코딩 폴백 출력으로 계속 진행된다 (즉시 취소 아님)
- 관련 테스트: CRISIS 폴백 단위 테스트 18건(#159), Task 2/3/4와 정합
4.2 실제 코드 흐름 (PR #159, Actual)
Safety → CRISIS 판정 (risk_level="crisis")
↓
TIER 1 병렬 에이전트 → 취소되지 않고 정상 완료 (cancel_event 미발행)
↓
TIER 2 (script_generator / visualization) → CRISIS 하드코딩 폴백 출력
↓
TIER 3 (batch_validator) → 폴백 유지
↓
TIER 4 (script_personalizer) → 위기 응답 톤으로 최종 출력
cancel_event는 TIMEOUT 전용 신호이며, CRISIS는 파이프라인 continuation + LLM 폴백 하드코딩 방식으로 처리된다.
5. 독립 에이전트 조건부 호출 패턴
Episode Memory와 Knowledge Agent는 StateGraph 노드가 아닌 독립 에이전트다.
Podcast Reasoning이 DI(의존성 주입) 패턴으로 조건부 호출한다:
class PodcastReasoningAgent:
def __init__(self, memory_agent, knowledge_agent):
self.memory_agent = memory_agent
self.knowledge_agent = knowledge_agent
async def run(self, ...):
# 조건부 Episode Memory 호출
if graph.needs_personal_context:
memory_result = await self.memory_agent.search(query=...)
# 조건부 Knowledge 호출
if graph.needs_expert_knowledge:
knowledge_result = await self.knowledge_agent.search(query=...)
6. 팟캐스트모드 메시지 흐름 (정상)
user → intent_classifier (request, T0)
intent_classifier → safety (request, T1, fan-out)
intent_classifier → emotion (request, T1, fan-out)
intent_classifier → content_analyzer (request, T1, fan-out)
intent_classifier → podcast_reasoning (request, T1, fan-out)
[조건부]
podcast_reasoning → episode_memory (request, T1)
episode_memory → podcast_reasoning (response, T1)
podcast_reasoning → knowledge (request, T1)
knowledge → podcast_reasoning (response, T1)
[TIER 1 Fan-in → Stories 대기]
AgentState → wait_for_stories_node (Stories 맥락 대기, PR #110)
│ asyncio.Event 기반 StoriesStore 대기
│ 기본 타임아웃 _STORIES_WAIT_TIMEOUT = 300s (workflow.py:657)
↓
[TIER 2 병렬]
AgentState → script_generator (TIER 2, Stories 수신 후)
AgentState → visualization (TIER 2, 병렬)
script_generator → batch_validator (response, T2→T3)
batch_validator → script_personalizer (response, T3→T4, PASS)
script_personalizer → user (response, T4, 최종 에피소드)
[비동기]
async_post → episode_memory (memory_write=True 시 저장)
async_post → learning (학습 이벤트)
7. 추적 ID 규칙
| ID 유형 | 형식 | 범위 |
|---|---|---|
| session_id | sess_{uuid} | 세션 전체 |
| correlation_id | corr_{uuid} | 동일 사용자 요청 내 모든 메시지 |
| trace_id | trace_{uuid} | 분산 추적 체인 전체 |
| request_id | req_{uuid} | 사용자 입력 1회 단위 |
| message_id | msg_{descriptive_id} | 개별 메시지 고유 |
버전: Mind-Log v5.0 | 프로토콜: v2.0 | 모드: 팟캐스트 전용
※ 참고: 본 프로젝트는 MCP(Model Context Protocol)를 사용하지 않는다. 에이전트 간 통신은 LangGraph AgentState 공유 + DI 패턴으로 구현되어 있다.