목차 열기
07. LLM 코디네이터
스웜 수준 전략 조정을 담당하는 컴포넌트. "선발 에이전트 결과 기반 후발 에이전트 전략 동적 조정"이라는 공격 패턴을 구현합니다.
역할
| 책임 | 내용 |
|---|---|
| 이벤트 수신 | 이벤트 버스의 구독자로 에이전트 이벤트 수집 |
| 버퍼링 | 이벤트를 버퍼에 쌓아두고 조건 충족 시 처리 |
| LLM 호출 | 현재 전략 스냅샷 + 최근 이벤트 윈도우를 입력으로 JSON 응답 요청 |
| 전략 갱신 | 응답 받은 업데이트를 공유 전략 저장소에 반영 |
| 감사 | 결정과 에러를 로그에 기록 |
모델 선정
| 항목 | 값 |
|---|---|
| 기본 모델 | gpt-4.1-nano |
| 교체 방법 | 환경변수로 변경 가능 |
| 응답 지연 | 2~3초 |
| 응답 포맷 | JSON 스키마 강제 |
| 호출 비용 | 대형 모델 대비 크게 낮음 |
왜 경량 모델인가
| 모델 특성 | 트레이드오프 |
|---|---|
| 대형 모델 (GPT-4o 급) | 응답 지연 수 초 → "결정 지점 즉시 읽기" 이점 희석 |
| 경량 모델 | 응답 2~3초 + JSON 스키마 강제 가능 + 호출 비용 낮음 |
- 스웜 코디네이션 판단은 "이 구역 막혔으니 다른 구역으로?" 수준 → 복잡한 추론 불필요
- 매 배치마다 호출되므로 작은 모델이 누적 비용 크게 감소
트리거 정책
코디네이터는 두 종류의 트리거 조건으로 LLM을 호출합니다.
즉시 처리 (Immediate Flush)
"지금 당장 판단해야 하는" 이벤트가 들어왔을 때 즉시 LLM 호출.
| 트리거 이벤트 | 의미 |
|---|---|
PAYMENT_PAGE_REACHED | 좌석 확보 성공 → 후발 에이전트 전략 반영 필요 |
SECTION_BLOCKED | 구역 차단 → 다른 구역으로 전환 고려 |
BLOCKED | 에이전트 차단 종료 → 패턴 분석 필요 |
동일 에이전트 CHALLENGE_FAILED 3회 연속 | 챌린지 반복 실패 → 전략 재조정 |
배치 처리 (Batched Flush)
일반 이벤트는 버퍼에 모아서 한 번에 처리.
| 조건 | 기본값 |
|---|---|
| 버퍼 크기 임계 | 5 이벤트 |
| 타임아웃 | 10초 |
| 둘 중 먼저 도달하는 조건으로 처리 | — |
의도 — 대부분 이벤트는 배치로 충분. 비용·처리량 효율 확보. 결정적 상황만 즉시 처리.
LLM 호출 구조
입력
| 요소 | 내용 |
|---|---|
| 시스템 프롬프트 | 역할·제약 조건 (아래 참조) |
| 사용자 메시지 | 현재 전략 스냅샷 + 최근 이벤트 윈도우 |
| 응답 스키마 | {reason, updates: [...]} JSON 형식 강제 |
시스템 프롬프트 원칙
| 원칙 | 내용 |
|---|---|
| 보수성 | 명확한 증거 있을 때만 변경 |
| 구역 변경 조건 | SECTION_BLOCKED의 명확한 증거에만 |
| 인원수 감소 조건 | SEAT_ADJACENT_NOT_FOUND 대응 시에만 |
| 자동 배정 에이전트 제외 | 좌석 추천 모드 에이전트(zone="RANDOM")의 구역은 건드리지 않음 |
중요 — LLM의 창의성은 잘못된 방향으로도 창의적입니다. 스웜 수준 자동화에서 LLM은 "제한된 결정권자"로 설계해야 안전합니다.
응답 스키마
{
"reason": "<한국어 설명>",
"updates": [
{
"agent_id": 2,
"zone": "익사이팅존", // 선택적
"party_size": 4, // 선택적
"seat_order": "front_left", // 선택적
"zone_blacklist": [...], // 선택적
"excluded_seats": [...] // 선택적
},
...
]
}
응답 처리
LLM 응답 수신
↓
JSON 파싱 + 스키마 검증
↓
공유 전략 저장소에 잠금 획득 후 원자적 업데이트
↓
감사 로그에 COORDINATOR_DECISION 기록
↓
이벤트 버스로 COORDINATOR_DECISION 발행 (모니터가 표시)
좌석 확보 성공의 특수 처리 (결정론 사이드 이펙트)
PAYMENT_PAGE_REACHED 이벤트는 LLM 호출 전에 결정론 사이드 이펙트를 즉시 실행합니다.
좌석 확보 성공 수신
↓
[결정론 사이드 이펙트 — LLM 호출 전]
• 확보된 좌석 라벨을 다른 모든 에이전트의 excluded_seats에 추가
↓
[LLM 호출]
• 구역 블랙리스트 갱신 같은 넓은 판단만
왜 LLM 전에 먼저 처리하나
- LLM 응답을 기다리는 1~수 초 동안 다른 에이전트가 같은 좌석 시도 → 충돌(409) 발생
- "LLM이 판단할 만한 것"과 "결정론으로 즉시 처리할 것"을 분리
- 지연 최소화로 이선좌 사고 방지
코디네이터 동작 상태도
[idle]
↓ 이벤트 수신
[buffering]
├─ 즉시 트리거 이벤트? → [llm_calling]
├─ 버퍼 임계 도달? → [llm_calling]
└─ 타임아웃 도달? → [llm_calling]
[llm_calling]
↓ 응답 수신 (성공)
[applying_updates]
├─ 전략 저장소 업데이트
├─ 감사 로그 기록
└─ 모니터에 통보
↓
[idle]
[llm_calling]
↓ 응답 실패 (타임아웃·오류)
[error_logged]
↓
[idle]
감사 로그
코디네이터 관련 이벤트는 별도 JSON Lines 파일에 기록됩니다.
| 이벤트 | 내용 |
|---|---|
COORDINATOR_DECISION | LLM 결정 완료. reason, updates, trigger, ts_ms 포함 |
COORDINATOR_ERROR | LLM 호출 실패. 에러 타입·시점 포함 |
경로: logs/attack/<env>/<run_id>/swarm_<ID>_coordinator_<ts>.jsonl
KPI로 산출되는 코디네이터 지표
| 지표 | 계산 |
|---|---|
| 총 결정 수 | COORDINATOR_DECISION 건수 |
| 유지 vs 변경 비율 | updates 배열 비어있으면 유지, 아니면 변경 |
| 에러율 | COORDINATOR_ERROR / (결정 + 에러) |
| 변경 지시 반영률 | 결정 이후 에이전트가 실제로 해당 전략을 따랐는지 (검증 가능한 범위) |
| 정책 반영 지연 | 결정 시각 ↔ 에이전트 반영 시각 차이의 중앙값 |
| 트리거 분포 | 트리거 종류별 발생 빈도 |
자세한 내용은 09-kpi-evaluation 참조.
비활성화
| 플래그 | 효과 |
|---|---|
--no-coordinator | 코디네이터 자체를 생성하지 않음 |
비활성 시 공유 전략 저장소는 초기 구성값을 유지. 에이전트 간 좌석 충돌 방지를 위한 결정론 사이드 이펙트(PAYMENT_PAGE_REACHED 반영)도 비활성됨.
참조
- 06-swarm-infrastructure — 이벤트 버스·전략 저장소
- 09-kpi-evaluation — 코디네이터 KPI 계산
- 11-events-reference — 코디네이터 이벤트 상세