A/B 테스트와 반복 개선
Harness는 소프트웨어다
섹션 제목: “Harness는 소프트웨어다”Harness를 “설정 파일” 처럼 다루면 개선이 느려집니다. Harness는 소프트웨어이며, 버전 관리, 테스트, 배포 주기 가 필요합니다. Harness 변경 하나가 전체 에이전트 성능을 수 십 퍼센트 바꿀 수 있기 때문입니다.
Manus의 SGD 접근법
섹션 제목: “Manus의 SGD 접근법”Manus(AI 에이전트 플랫폼)는 harness 최적화에 SGD(Stochastic Gradient Descent) 에 비유한 접근법을 사용합니다. 수학적 SGD가 아니라, 철학적 유사성을 차용한 것입니다.
Manus SGD 접근법:1. 현재 harness로 벤치마크 실행 → 기준 점수 측정2. 실패한 케이스를 수동으로 분석 → 개선 가설 도출3. 한 번에 하나의 harness 변수만 변경4. 동일 벤치마크 재실행 → 점수 변화 측정5. 개선되면 유지, 악화되면 롤백6. 1로 돌아가 반복핵심 원칙은 한 번에 하나의 변수만 변경 하는 것입니다. 여러 변경을 동시에 적용하면 어떤 변경이 성능을 개선하고 악화시켰는지 알 수 없습니다.
Harness 버전 관리
섹션 제목: “Harness 버전 관리”interface HarnessVersion { id: string; // 예: 'v2.3.1' description: string; // 이 버전의 변경 내용 config: HarnessConfig; createdAt: string; benchmarkResults?: BenchmarkResult[];}
interface HarnessConfig { systemPromptVersion: string; // 프롬프트 파일 해시 maxTurns: number; compactionThreshold: number; allowedTools: string[]; modelRoles: ModelRoles; reminderRules: ReminderRule[]; fuzzyMatchPasses: number;}
class HarnessVersionStore { async save(version: HarnessVersion): Promise<void> { const path = `.agent/versions/${version.id}.json`; await fs.writeFile(path, JSON.stringify(version, null, 2), 'utf-8'); }
async load(id: string): Promise<HarnessVersion> { const path = `.agent/versions/${id}.json`; const raw = await fs.readFile(path, 'utf-8'); return JSON.parse(raw); }
async list(): Promise<Pick<HarnessVersion, 'id' | 'description' | 'createdAt'>[]> { // ... }}A/B 실험 설계
섹션 제목: “A/B 실험 설계”interface Experiment { id: string; hypothesis: string; // "컨텍스트 리마인더를 5턴마다 추가하면 성공률이 높아진다" controlVersion: string; // 기준 harness 버전 ID treatmentVersion: string; // 실험 harness 버전 ID taskSample: string[]; // 실험에 사용할 작업 ID 목록 primaryMetric: keyof HarnessMetrics; // 주요 측정 지표 minSampleSize: number; // 통계적 유의성을 위한 최소 샘플 수}
async function runExperiment(experiment: Experiment): Promise<ExperimentResult> { const [controlHarness, treatmentHarness] = await Promise.all([ buildHarness(experiment.controlVersion), buildHarness(experiment.treatmentVersion), ]);
const controlMetrics = new MetricsCollector(); const treatmentMetrics = new MetricsCollector();
// 순서 편향 방지: 인터리빙 실행 for (let i = 0; i < experiment.taskSample.length; i++) { const task = await loadTask(experiment.taskSample[i]);
if (i % 2 === 0) { await runAndRecord(task, controlHarness, controlMetrics); await runAndRecord(task, treatmentHarness, treatmentMetrics); } else { await runAndRecord(task, treatmentHarness, treatmentMetrics); await runAndRecord(task, controlHarness, controlMetrics); } }
const control = controlMetrics.summarize(); const treatment = treatmentMetrics.summarize(); const diff = treatment[experiment.primaryMetric] - control[experiment.primaryMetric];
return { experimentId: experiment.id, hypothesis: experiment.hypothesis, control, treatment, primaryMetricDiff: diff, recommendation: diff > 0.02 ? 'adopt' : diff < -0.02 ? 'reject' : 'inconclusive', };}메트릭 기반 개선 주기
섹션 제목: “메트릭 기반 개선 주기”개선 주기 (2주 스프린트 권장):
Week 1: Day 1-2: 트레이스 데이터 분석 → 실패 패턴 발견 Day 3-4: 개선 가설 수립 → Harness 변경 구현 Day 5: 50개 샘플 빠른 실험 실행
Week 2: Day 1: 실험 결과 분석 → 채택/거부 결정 Day 2-3: 채택된 경우: 200개 샘플 검증 실험 Day 4: 프로덕션 배포 또는 다음 가설로 전환 Day 5: 회고: 무엇을 배웠는가?실패 분석 패턴
섹션 제목: “실패 분석 패턴”트레이스 데이터에서 개선 기회를 찾는 체계적 방법입니다.
async function analyzeFailures(traces: TraceEvent[][]): Promise<ImprovementOpportunity[]> { const opportunities: ImprovementOpportunity[] = [];
// 패턴 1: 특정 툴에서 반복 실패 const toolFailures = groupBy( traces.flatMap(t => t.filter(e => e.type === 'tool_result' && !e.success)), e => (e as ToolResultEvent).toolName ); for (const [toolName, failures] of Object.entries(toolFailures)) { if (failures.length > 5) { opportunities.push({ type: 'tool_reliability', description: `${toolName} 툴이 ${failures.length}번 실패함`, hypothesis: `${toolName} 의 에러 메시지를 더 명확하게 만들면 재시도 성공률이 높아진다`, priority: failures.length, }); } }
// 패턴 2: maxTurns 직전에 실패하는 작업 const nearMaxTurns = traces.filter(t => { const end = t.find(e => e.type === 'agent_end') as AgentEndEvent | undefined; return end && !end.success && end.turns >= MAX_TURNS * 0.9; }); if (nearMaxTurns.length > traces.length * 0.1) { opportunities.push({ type: 'max_turns', description: `${nearMaxTurns.length}개 작업이 maxTurns 근처에서 실패`, hypothesis: `maxTurns를 현재 값의 1.5배로 늘리면 성공률이 개선된다`, priority: nearMaxTurns.length, }); }
return opportunities.sort((a, b) => b.priority - a.priority);}개선 이력 관리
섹션 제목: “개선 이력 관리”.agent/ versions/ v2.0.0.json # 기준 harness v2.1.0.json # 컨텍스트 압축 임계값 조정 v2.2.0.json # 퍼지 매칭 9-pass 도입 v2.3.0.json # 이벤트 리마인더 추가 experiments/ exp-001.json # v2.0 vs v2.1: 성공률 +3.2pp exp-002.json # v2.1 vs v2.2: 성공률 +4.8pp exp-003.json # v2.2 vs v2.3: 성공률 +6.0pp (채택) exp-004.json # v2.3 vs v2.3+리마인더: +1.1pp (inconclusive)버전과 실험 이력을 관리하면 “왜 이 설계를 선택했는가” 를 나중에 추적할 수 있습니다. 팀 협업에서도 동일한 실험을 반복하는 낭비를 줄입니다.