13 KiB
에이전트 루프 아키텍처 — 워크플로우 비교 분석
대상: 기술 임원 · 개발 리더 초점: 에이전트 코딩 서비스의 핵심 워크플로우 구조와 품질 보증 전략 작성일: 2026-03-31
1. 에이전트 루프란?
AI 코딩/문서 생성 서비스의 핵심 엔진은 에이전트 루프입니다.
사용자 요청 → [LLM 판단] → [도구 실행] → [결과 관찰] → [LLM 재판단] → ... → 최종 응답
이 반복(iteration)을 얼마나 지능적으로, 얼마나 품질 있게 수행하느냐가 서비스 경쟁력을 결정합니다.
2. 업계 주요 서비스 워크플로우 비교
2-1. OpenHands (오픈소스, ICLR 2025)
OpenHands는 CodeAct 논문 기반의 에이전트 프레임워크입니다.
┌─────────────────────────────────────────────────┐
│ AgentController │
│ │
│ while budget > 0: │
│ action = agent.step(state) ← 1 LLM 호출 │
│ observation = runtime.run(action) ← 도구 실행│
│ state.update(action, observation) │
│ if action == AgentFinishAction: │
│ break ← LLM이 "끝"이라 판단하면 종료 │
│ │
│ ⚠ 검증/검수 단계: 없음 │
│ ⚠ 계획 생성: 없음 (LLM 자율 판단) │
└─────────────────────────────────────────────────┘
핵심 특징:
- 1 반복 = 1 LLM 호출 + 1 도구 실행 (고정)
- 계획(Plan) 없음 — LLM의 chain-of-thought에 의존
- 검증(Review) 없음 — LLM이 알아서 다음 반복에서 확인할지 결정
- 종료는
AgentFinishAction반환으로 결정 (LLM 자율) - SecurityAnalyzer: 실행 전 위험도 평가 (LOW/MEDIUM/HIGH) — 품질 검증이 아닌 안전 게이트
장점: 단순, 빠름, 모델 무관 약점: 문서 생성 후 검수 보장 없음, LLM이 "충분하다"고 판단하면 미완성 상태로 종료
2-2. Claude Code (Anthropic)
┌─────────────────────────────────────────────────┐
│ Claude Code Agent Loop │
│ │
│ while true: │
│ response = llm.call(messages) ← 1 LLM 호출 │
│ if no tool_calls: │
│ break ← 텍스트만 반환하면 종료 │
│ for tool in tool_calls: │
│ result = execute(tool) │
│ messages.append(result) │
│ │
│ ⚠ 검증 단계: 없음 (시스템 프롬프트 권고만) │
│ ⚠ 계획: SKILL.md 프롬프트로 유도 │
└─────────────────────────────────────────────────┘
핵심 특징:
- OpenHands와 동일한 구조 (1 반복 = 1 LLM 호출)
- 종료: 도구 호출이 없으면 종료 (OpenHands의 AgentFinishAction과 유사)
- 검증: 시스템 프롬프트에 "확인하라"고 작성 가능하나, LLM이 무시할 수 있음
- 차별점: SKILL.md 표준으로 도메인별 프롬프트 커스터마이징
2-3. Cursor / Windsurf / GitHub Copilot
모두 동일한 단일 LLM 호출 루프 패턴:
- Cursor: Tab → Apply 기반, 에이전트 모드에서도 1호출/반복
- Windsurf (Cascade): Flow 기반이지만 루프 구조는 동일
- GitHub Copilot: 코드 완성 특화, 에이전트 모드는 Claude Code와 유사
공통 약점: 문서/코드 생성 후 "읽어서 확인"하는 아키텍처가 없음
3. 왜 검증 단계가 없을까?
3-1. AgentFinishAction 문제
OpenHands는 LLM이 AgentFinishAction을 반환하면 루프가 종료됩니다.
# OpenHands의 종료 판단
if isinstance(action, AgentFinishAction):
return # LLM이 "끝"이라고 하면 끝
문제: LLM이 "파일을 생성했으니 끝"이라고 판단하면, 내용이 불완전해도 종료됩니다.
우리는 왜 AgentFinishAction을 사용하지 않는가?
| 항목 | AgentFinishAction (OpenHands) | 도구 호출 없음 종료 (AX Copilot) |
|---|---|---|
| 종료 판단 | LLM이 명시적으로 "finish" 액션 반환 | LLM이 텍스트만 반환 (도구 미호출) |
| 장점 | 명시적, 종료 이유 포함 가능 | 별도 액션 정의 불필요, 자연스러운 대화 흐름 |
| 단점 | finish 호출을 잊거나 잘못 호출 가능 | LLM이 도구를 부르지 않으면 의도치 않게 종료 |
| 검증 타이밍 | finish 전에 검증 삽입 가능 (미구현) | 도구 실행 후 즉시 검증 삽입 (구현 완료) |
핵심: 둘 다 "LLM이 알아서 끝내라"는 구조이므로, 검증을 LLM에게 맡기면 생략될 수밖에 없습니다.
3-2. 시스템 프롬프트만으로는 부족
시스템 프롬프트: "문서 작성 후 반드시 file_read로 결과물을 검토하세요"
이 지시를 LLM이 따를 확률:
- GPT-4/Claude: ~60-70% (복잡한 작업에서 무시 경향)
- Gemini Flash: ~40-50% (무료 모델에서 더 자주 생략)
- 로컬 모델 (Ollama): ~30% (컨텍스트 길어지면 초기 지시 희석)
→ 아키텍처 수준에서 강제해야 신뢰성 확보 가능
4. 검증 강제 아키텍처 (AX Copilot 구현)
4-1. 기존 구조 (v1.7.0)
반복 1: LLM 호출 → "file_read로 현재 파일 확인하겠습니다"
도구 실행: file_read → 파일 내용 반환
반복 2: LLM 호출 → "html_create로 보고서를 생성하겠습니다"
도구 실행: html_create → "보고서.html 생성 완료"
반복 3: LLM 호출 → "보고서가 완성되었습니다." (텍스트만 = 루프 종료)
⚠ 생성된 파일을 읽어서 확인하지 않음!
4-2. 개선 구조 (v1.7.1 — 검증 강제)
반복 1: LLM 호출 → "file_read로 현재 파일 확인하겠습니다"
도구 실행: file_read → 파일 내용 반환
반복 2: LLM 호출 → "html_create로 보고서를 생성하겠습니다"
도구 실행: html_create → "보고서.html 생성 완료"
┌──────────────────────────────────────────────┐
│ ★ 검증 강제 (자동 삽입) │
│ │
│ 시스템: "생성된 파일을 file_read로 읽고 │
│ 내용 완전성, 구조, 맞춤법을 확인하세요" │
│ │
│ LLM 호출 (검증 전용) │
│ → file_read 실행 → 내용 확인 │
│ → 문제 있으면 수정 도구 호출 │
│ → 문제 없으면 "검증 완료" 보고 │
└──────────────────────────────────────────────┘
반복 3: LLM 호출 → "보고서가 완성되었습니다." (검증 통과 후 종료)
4-3. 코드 흐름 (의사코드)
while (iteration < maxIterations)
{
var blocks = await llm.SendWithToolsAsync(messages, tools);
foreach (var call in toolCalls)
{
var result = await tool.ExecuteAsync(call);
messages.Add(CreateToolResult(result));
// ★ 검증 강제: 문서 생성 도구 실행 후 자동 삽입
if (settings.EnablePostToolVerification
&& IsDocumentCreationTool(call.ToolName)
&& result.Success)
{
// 검증 전용 LLM 호출 (file_read 유도)
await RunPostToolVerificationAsync(messages, call, result);
iteration++; // 검증도 반복 횟수에 포함
}
}
if (no tool calls) break; // 텍스트만 = 종료
}
5. 부족한 부분과 향후 개발 방향
5-1. 현재 부족한 영역
| 영역 | 현재 상태 | OpenHands 비교 | 개선 필요성 |
|---|---|---|---|
| Multi-Agent 위임 | ❌ 미구현 | ✅ AgentDelegateAction | 높음 — 복잡한 작업을 하위 에이전트에 분할 |
| Event-Sourced State | 부분 구현 (Events 컬렉션) | ✅ 불변 이벤트 스트림 | 중간 — 재실행/디버깅에 유용 |
| SecurityAnalyzer | Ask 모드 권한 확인 | ✅ 위험도 자동 분류 | 낮음 — 사내 환경에서 우선순위 낮음 |
| CodeAct 통합 액션 | 도구별 분리 | ✅ bash+Python 통합 | 낮음 — 현재 도구 체계로 충분 |
| 검증 깊이 | 단일 검증 호출 | 해당 없음 | 중간 — 복수 기준별 검증 가능 |
| 검증 대상 확대 | 문서 생성 도구만 | 해당 없음 | 중간 — 코드 생성 후에도 검증 필요 |
5-2. 향후 개발 계획
Phase A: 검증 고도화 (단기)
| 기능 | 설명 | 예상 공수 |
|---|---|---|
| 검증 기준 커스터마이징 | 설정에서 검증 체크리스트를 사용자가 편집 | 낮음 |
| 코드 검증 확대 | script_create, file_edit 후에도 검증 (구문 오류 검사) |
낮음 |
| 검증 결과 UI 표시 | 워크플로우 타임라인에 "✅ 검증 통과" / "⚠ 수정 발생" 배지 | 낮음 |
| 검증 통계 | 검증에서 문제 발견/수정된 비율 추적 | 낮음 |
Phase B: 멀티에이전트 위임 (중기)
OpenHands의 AgentDelegateAction 패턴을 참고하되, 사내 환경에 맞게:
[메인 에이전트]
├── [리서치 에이전트] ← file_read, grep, folder_map 전담
├── [문서 에이전트] ← html_create, docx_create 전담
└── [검증 에이전트] ← file_read + 품질 평가 전담 ← 검증 분리!
| 기능 | 설명 | 예상 공수 |
|---|---|---|
| AgentDelegateAction | 하위 에이전트 위임 액션 정의 | 중간 |
| 에이전트별 도구 제한 | 리서치=읽기만, 문서=쓰기만 등 | 낮음 |
| 검증 에이전트 분리 | 생성과 검증을 다른 에이전트로 | 중간 |
Phase C: Reflexion 패턴 (장기)
Reflexion 논문(Shinn et al., 2023)의 자기 반성 패턴 강화:
실행 → 결과 → 자기 평가 → 반성 메모리 저장 → 다음 시도에 반영
현재 Self-Reflection은 오류 발생 시에만 동작. 이를 성공 시에도 적용:
- "이 문서는 사용자 요구를 80% 충족. 미흡 점: 표가 누락됨"
- 반성 결과를 AgentMemory에 저장 → 같은 유형 작업 시 참고
6. 정리
핵심 메시지
┌─────────────────────────────────────────────────────┐
│ │
│ 업계 모든 에이전트 루프는 "1반복 = 1 LLM 호출" │
│ 검증(Review)을 강제하는 아키텍처는 어디에도 없었음 │
│ │
│ AX Copilot은 "검증 강제"를 아키텍처 수준에서 구현 │
│ → 문서 품질 보증의 차별화 포인트 │
│ │
└─────────────────────────────────────────────────────┘
비교 요약
| 항목 | OpenHands | Claude Code | AX Copilot |
|---|---|---|---|
| 반복당 LLM 호출 | 1회 | 1회 | 1회 + 검증 1회 |
| 계획 생성 | ❌ | ❌ | ✅ PlanMode |
| 검증 강제 | ❌ | ❌ | ✅ PostToolVerification |
| 자기 반성 | ❌ | ❌ | ✅ Self-Reflection |
| 컨텍스트 압축 | ❌ | ❌ | ✅ ContextCondenser |
| 사용자 승인 | SecurityAnalyzer | 권한 프롬프트 | UserDecisionCallback |
| 진행률 추적 | ❌ | ❌ | ✅ TaskDecomposer |
| 피드백 학습 | ❌ | ❌ | ✅ FeedbackContext |
워크플로우 전체 비교도
OpenHands:
요청 → [LLM] → [도구] → [LLM] → [도구] → [LLM: "끝"] → 응답
↑ 검증 없음
Claude Code:
요청 → [LLM] → [도구] → [LLM] → [도구] → [LLM: 텍스트만] → 응답
↑ 검증 없음
AX Copilot (v1.7.1):
요청 → [계획 LLM] → 승인 → [LLM] → [도구] → [★검증 LLM★] → [LLM] → 응답
↑ PlanMode ↑ 실행 ↑ 생성 ↑ 강제 확인 ↑ 완료
작성: AX Copilot 개발팀 · 2026-03-31