Dual-Mode 실행
왜 모드를 분리하는가?
섹션 제목: “왜 모드를 분리하는가?”에이전트가 계획을 세우면서 동시에 파일을 수정하거나 명령을 실행하면 위험합니다. 탐색 중에 의도치 않은 부작용이 발생하고, 불완전한 계획이 즉시 실행될 수 있습니다.
Dual-Mode 실행은 에이전트의 상태를 명시적으로 두 가지로 구분합니다:
- Plan Mode: 읽기 전용. 정보를 수집하고 계획을 수립합니다.
- Normal Mode (Execute Mode): 전체 접근. 실제 변경을 수행합니다.
모드별 도구 접근
섹션 제목: “모드별 도구 접근”| 도구 | Plan Mode | Normal Mode |
|---|---|---|
read_file | 허용 | 허용 |
search_code | 허용 | 허용 |
list_directory | 허용 | 허용 |
write_file | 차단 | 허용 |
run_command | 차단 | 허용 |
delete_file | 차단 | 허용 |
call_api | 차단 | 허용 |
스키마 수준 강제
섹션 제목: “스키마 수준 강제”핵심은 “하지 말라”는 지시가 아니라 스키마 수준에서 물리적으로 불가능하게 만드는 것입니다.
from enum import Enumfrom typing import Callable
class AgentMode(Enum): PLAN = "plan" EXECUTE = "execute"
# 도구에 모드 메타데이터 부착TOOL_REGISTRY = { "read_file": {"fn": read_file, "modes": [AgentMode.PLAN, AgentMode.EXECUTE]}, "search_code": {"fn": search_code, "modes": [AgentMode.PLAN, AgentMode.EXECUTE]}, "list_directory": {"fn": list_directory, "modes": [AgentMode.PLAN, AgentMode.EXECUTE]}, "write_file": {"fn": write_file, "modes": [AgentMode.EXECUTE]}, "run_command": {"fn": run_command, "modes": [AgentMode.EXECUTE]}, "delete_file": {"fn": delete_file, "modes": [AgentMode.EXECUTE]},}
def get_available_tools(mode: AgentMode) -> list[dict]: """현재 모드에서 사용 가능한 도구만 LLM에 노출""" return [ {"name": name, "fn": tool["fn"]} for name, tool in TOOL_REGISTRY.items() if mode in tool["modes"] ]
def run_agent(goal: str): # Plan Mode: 읽기 전용 도구만 제공 plan_tools = get_available_tools(AgentMode.PLAN) plan = llm.complete(f"계획 수립: {goal}", tools=plan_tools)
# Execute Mode: 전체 도구 제공 exec_tools = get_available_tools(AgentMode.EXECUTE) result = llm.complete(f"실행: {plan}", tools=exec_tools)
return resultOpenDev의 6단계 실행 구조
섹션 제목: “OpenDev의 6단계 실행 구조”OpenDev 논문은 에이전트의 각 반복(iteration)이 다음 6단계로 구성됨을 제안합니다:
반복(iteration) N:
1. Pre-check & Compaction └── 컨텍스트 길이 확인, 오래된 히스토리 압축
2. Optional Thinking Phase └── 복잡한 태스크의 경우 extended thinking 활성화
3. Optional Self-Critique └── 이전 단계 출력 검토, Reflection 트리거 여부 결정
4. Action (LLM Call) └── 실제 LLM 호출, 도구 선택 및 파라미터 결정
5. Tool Execution with Approval └── 도구 실행, 필요시 인간 승인 요청
6. Post-processing & Termination Decision └── 결과 처리, 목표 달성 여부 판단단계별 상세
섹션 제목: “단계별 상세”1단계: Pre-check & Compaction
def pre_check(context: Context) -> Context: if context.token_count > COMPACTION_THRESHOLD: # 오래된 히스토리를 요약으로 교체 summary = llm.summarize(context.old_messages) return context.replace_old_with_summary(summary) return context5단계: Tool Execution with Approval
모든 도구 실행에 승인 레이어를 추가할 수 있습니다. 특히 파괴적 작업(파일 삭제, 배포 등)은 인간 승인이 권장됩니다.
APPROVAL_REQUIRED = {"delete_file", "deploy", "send_email"}
def execute_tool(tool_name: str, params: dict) -> str: if tool_name in APPROVAL_REQUIRED: approved = request_human_approval(tool_name, params) if not approved: return f"사용자가 {tool_name} 실행을 거부했습니다"
return TOOL_REGISTRY[tool_name]["fn"](**params)6단계: Termination Decision
def should_terminate(state: AgentState) -> bool: return ( state.goal_achieved or state.step_count >= MAX_STEPS or state.consecutive_failures >= MAX_FAILURES or state.explicitly_stopped )Plan Mode의 실제 적용
섹션 제목: “Plan Mode의 실제 적용”Claude Code, Cursor 등 실제 코딩 에이전트 도구들은 이미 이 패턴을 채택하고 있습니다.
| 도구 | Plan Mode 명칭 | 특징 |
|---|---|---|
| Claude Code | Plan Mode | /plan 명령으로 활성화, 읽기만 가능 |
| Cursor | Agent Preview | 변경 사항을 미리 보여주고 확인 요청 |
| GitHub Copilot Workspace | Planning Canvas | 계획을 시각화하고 편집 후 실행 |
Dual-Mode 실행은 계획과 실행을 명확히 분리하여 안전성과 예측 가능성을 높입니다. 스키마 수준에서 도구 접근을 제한하면 런타임 오류 없이 권한을 강제할 수 있습니다. OpenDev의 6단계 구조는 각 반복을 체계화하여 에이전트 루프의 신뢰성을 높입니다. 다음 챕터에서는 여러 에이전트를 조율하는 Multi-Agent 오케스트레이션을 다룹니다.