Self-Improving Agent Loop (Autoresearch)
본 루프는 self-hosted 오픈웨이트 모델(Qwen3, Llama 4, GLM-5 등) 전용이다. AgentCore의 Claude/Nova 등 관리형 폐쇄 모델은 자가 학습 불가이므로 스코프에서 제외한다.
실 운영 적용 전에 스코프·자동화 경계·데이터 거버넌스·롤백 기준에 대한 합의가 필요하다. 자세한 합의 대상은 ADR — Self-Improving Agent Loop 도입 의사결정을 참조.
Autoresearch 담론과 엔터프라이즈 해석
Karpathy의 핵심 주장
Andrej Karpathy는 2026년 3월 autoresearch 프로젝트를 통해 LLM이 단순한 "next token prediction" 기계를 넘어 자가 탐색(autoresearch) 시스템으로 진화할 것이라고 주장했다. 핵심 메커니즘:
- Tool-use Rollout: LLM이 도구(코드 실행, 웹 검색, 계산기 등)를 사용하며 여러 추론 경로를 탐색
- Success as Signal: 성공한 경로(정답 도달, 작업 완료)가 다음 학습의 시그널이 됨
- Self-Supervised Loop: 인간 라벨링 없이 자체 성공·실패 데이터를 축적하고 강화학습으로 재학습
- Compound Growth: 더 강해진 모델이 더 많은 성공 trace를 생성 → 더 강해지는 선순환
예시: 수학 문제 해결 Agent
- Rollout: "53 × 47 = ?"에 대해 5가지 접근(직접 계산, Python 실행, Wolfram Alpha, 근사 추정, 분해 계산)
- Success: Python 실행과 분해 계산이 정답 2491에 도달
- Training: 성공 경로를 preferred 샘플로, 실패 경로를 rejected 샘플로 DPO 학습
- Next Iteration: 모델이 복잡한 계산 시 Python 실행을 먼저 시도하도록 bias 증가
엔터프라이즈 환경의 제약
Karpathy의 이상론을 기업 환경에 적용하려면 다음 제약을 고려해야 한다:
| 제약 | 설명 | 해결 방향 |
|---|---|---|
| 데이터 거버넌스 | 프로덕션 trace에 PII, 기밀 정보 포함 가능 | Presidio PII 스캐너, k-anonymity, consent 추적 |
| 비용 | Rollout마다 LLM 호출 N배 증가 (N=탐색 경로 수) | 비용·품질 trade-off 최적화, 저비용 모델 우선 사용 |
| Reward 모델링 | "성공"의 정의가 모호(고객 만족? 정확도? latency?) | 복합 reward: LLM-as-judge + Ragas + 유저 피드백 |
| Mode Collapse | 특정 패턴만 반복 생성 (diversity 손실) | Entropy regularization, diverse sampling |
| Regulatory | 모델 변경마다 감사 로그, 모델 카드 업데이트 필요 | 버전 관리, audit trail, Agent 버전관리 연동 |
Self-improving loop는 **"완전 자동화"가 아니라 "인간 감독 하의 자동 강화"**로 해석해야 한다. 매 iteration마다 품질 게이트와 휴먼-인-루프 검증이 필수다.
5-Stage Loop 아키텍처
전체 아키텍처 다이어그램
Stage 1: Rollout — 프로덕션 트래픽 수집
목표: 실제 사용자 요청에 대한 Agent 실행 trace를 수집한다.
실행 주기: 연속(Real-time)
입력: 사용자 요청, 컨텍스트, Agent 상태
출력: Trace (프롬프트, 도구 호출, 중간 추론, 최종 응답, latency, 토큰 수)
수집 메커니즘:
from langfuse import Langfuse
langfuse = Langfuse()
@trace_agent_call # 데코레이터로 자동 trace
def execute_agent(user_query: str, context: dict):
trace = langfuse.trace(name="agent-execution", metadata={"user_id": context["user_id"]})
with trace.span(name="retrieval"):
docs = vector_db.search(user_query)
with trace.span(name="reasoning"):
response = llm.generate(prompt=build_prompt(user_query, docs))
with trace.span(name="tool-execution"):
if response.requires_tool:
tool_result = execute_tool(response.tool_name, response.tool_args)
trace.event(name="completion", metadata={"tokens": response.token_count})
return response
다양성 확보: 동일 요청에 대해 temperature 변화(0.7/0.9/1.1)로 3가지 응답 생성 → diversity 증가
실패 복구: Trace 수집 실패해도 사용자 응답은 정상 반환 (async logging)