기본 단위
core/agent/loop.py:162 class AgenticLoop에 정의된 AgenticLoop는 매 턴을 구동하는 엔진입니다. 의도적으로 단순하게 유지되어 있습니다.
response = call_llm(messages, tools)
while response.has_tool_use:
for tool_call in response.tool_calls:
result = execute(tool_call)
messages.append(result)
response = call_llm(messages, tools)
return response.text복잡성은 다른 곳에 있습니다. 프롬프트 어셈블러, 도구 레지스트리, 검증 가드레일, 훅 시스템이 그것입니다. 루프 자체는 얇게 유지됩니다.
세 가지 컨트롤러
루프는 세 가지 책임을 전용 클래스에 위임합니다.
- ToolCallProcessor. 도구 호출 순서를 정하고, 중복을 제거하며, 도구별 pre/post 훅을 적용합니다.
- ErrorRecoveryStrategy. 도구가 실패했을 때 재시도 또는 명시적 종료 신호 (
model_action_required,user_clarification_needed) 로 분기합니다. v0.90.0에서 auto-escalation이 제거되었습니다. 모델이 직접 종료 신호를 emit해야 루프가 빠져나갑니다. - ConvergenceDetector. 진전 없이 동일 도구를 동일 인자로 N번 반복하는 루프를 감지하여 중단시킵니다.
멀티 인텐트 분해
루프는 "X를 분석하고 Y와 비교해줘"같은 복합 사용자 요청을 받습니다. 디컴포저(decomposer.md)는 첫 라운드 전에 요청을 도구 호출 시퀀스로 분해합니다.
시스템 프롬프트 구성
루프 시작 전에 core/agent/system_prompt.py의 build_system_prompt()가 STATIC/DYNAMIC 경계 마커(__GEODE_PROMPT_CACHE_BOUNDARY__)와 함께 시스템 프롬프트를 조립합니다. Anthropic 어댑터는 이 마커를 기준으로 프롬프트 캐싱을 위해 분할합니다. 프롬프트 캐싱을 참고하세요.
훅 통합
루프는 의미 있는 경계마다 라이프사이클 이벤트를 발화합니다.
SESSION_START,SESSION_ENDTURN_COMPLETELLM_CALL_START,LLM_CALL_END,LLM_CALL_FAILED,LLM_CALL_RETRYTOOL_EXEC_START,TOOL_EXEC_END,TOOL_EXEC_FAILEDTOOL_APPROVAL_REQUEST,TOOL_APPROVAL_GRANTED,TOOL_APPROVAL_DENIEDCONTEXT_OVERFLOW,CONTEXT_RESET
왜 얇은 루프인가
루프의 얇음은 의도적입니다. 시스템에서 가장 많이 테스트되고 가장 적게 바뀌는 코드입니다. 새로운 동작은 루프 안이 아니라 도구, 훅, 가드레일로 들어갑니다. 이렇게 해야 핵심 실행 경로가 예측 가능하고 테스트 가능한 상태로 유지됩니다.