System Prompt
추상적 지시를 버리고 Planning & Discovery → Build → Verify → Fix의 강제된 작업 순서를 넣는다.
더 강한 모델을 찾기 전에 같은 모델이 어떤 환경에서 일하고 있는지 본다. LangChain의 사례는 그 질문을 숫자로 밀어붙인다. 모델은 그대로였지만 결과는 달라졌다. 차이를 만든 것은 두뇌가 아니라 두뇌가 움직이는 순서·도구·경계였다.
Terminal Bench 2.0은 89개의 복잡한 coding-agent 과제로 구성된 표준 벤치마크다. ML, debugging, 생물학, 보안, 게임 등 여러 영역을 포함하고, 일부 과제는 실행 시간이 10분에 가깝고 도구 호출도 100회를 넘는다고 원문은 설명한다.
Terminal Bench 2.0 점수 상승폭.
Top 30에서 Top 5로 상승.
원문 기준 모델은 전후 동일.
Agent Harness에는 바꿀 수 있는 것이 너무 많다. System Prompt, tools, hooks, middleware, skills, subagent delegation, memory까지 한꺼번에 움직이면 어떤 변화가 효과를 냈는지 알 수 없다. LangChain은 변수 세 개만 남겼다.
추상적 지시를 버리고 Planning & Discovery → Build → Verify → Fix의 강제된 작업 순서를 넣는다.
작업 환경을 자동 주입하고, 종료 직전에는 사양과 테스트를 다시 확인하는 완료 검사를 강제한다.
Doom loop 탐지, history trimming, PII filtering, caching, retry, tool access, human-in-the-loop 같은 횡단 관심사를 Agent 핵심 로직에서 분리한다.
첫 번째 변화는 문장의 화려함이 아니라 작업 순서의 강제다. 코드를 곧바로 쓰기 시작하지 않고, 계획·구현·검증·수정이라는 순서를 Harness가 외부에서 잡아준다.
Agent가 자신이 어디에 있는지 파악하는 데 시간을 낭비하고, 코드를 다시 읽은 뒤 “괜찮아 보인다”고 스스로 승인한 채 테스트 없이 멈추는 실패가 반복됐다.
시작 시 작업 디렉터리와 하위 구조를 매핑하고 bash 명령을 실행해 Python 버전과 사용 가능한 명령 등 설치 환경을 파악한다.
Agent가 종료하려는 순간을 가로막고 작업 사양을 기준으로 다시 검증하게 한다. 자기 코드를 다시 읽고 “그럴듯하다”고 판단하는 것은 완료의 근거가 되지 않는다.
Agent는 한 방향에 커밋한 뒤 같은 잘못된 접근을 조금씩 변형하며 반복할 수 있다. LangChain은 이를 doom loop로 보고 동일 파일의 반복 편집을 추적한다.
잘못된 방향을 포기하지 못한 채 같은 파일을 여러 번 조금씩 수정한다. 매번 거의 됐다고 느끼지만 문제의 축은 바뀌지 않는다.
특정 파일이 N회 편집되면 “다른 방법을 고려하라”는 개입을 넣는다. 수정 자체를 금지하지 않고, 반복 횟수라는 단단한 조건에서만 방향을 다시 생각하게 한다.
| Hook | 실행 시점 | 대표 용도 |
|---|---|---|
| before_agent | 호출 시작 시 1회 | 메모리 로딩, 리소스 연결 |
| before_model | 각 모델 호출 전 | 히스토리 절단, PII 필터링 |
| wrap_model_call | 모델 호출 전체 | 캐시, 재시도, 동적 도구 가용성 |
| wrap_tool_call | 도구 실행 전체 | 컨텍스트 주입, 도구 접근 제어 |
| after_model | 모델 응답 후 | human-in-the-loop 개입 |
| after_agent | 완료 시 1회 | 결과 저장, 리소스 정리 |
전 구간을 최고 추론 강도인 xhigh로 실행한 구성은 전 구간 high보다 크게 낮았다. 이유는 품질이 아니라 시간이었다.
처음에 깊게 생각해 방향과 검증 계획을 세운다.
실행에서는 충분한 수준으로 낮춰 시간과 token을 아낀다.
마지막 검증에서 다시 깊은 추론을 쓴다.
LangChain의 개선은 한 번의 영감이 아니었다. 기준선을 세우고 실패를 읽고 특정 원인만 겨냥해 바꾸고 다시 회귀 검증하는 반복 방법론이었다.
LangSmith에서 실험 데이터를 가져와 각 실패 사례의 실행 궤적을 분석한다. 최종 답만 보는 것이 아니라 어떤 도구를 언제 호출했고 어느 순간 잘못된 방향에 고착됐는지를 본다.
전체 최적화 과정에서 발견된 문제는 막연한 “모델이 부족하다”가 아니었다. 반복되는 실패에는 이름이 있었고 이름이 붙은 실패마다 대응 장치가 있었다.
코드를 쓴 뒤 다시 읽고 괜찮다고 판단하지만 테스트를 실행하지 않는다.
같은 파일을 10회 이상 수정하며 동일한 잘못된 접근의 작은 변형을 반복한다.
낯선 디렉터리 구조와 설치 환경을 이해하는 데 많은 시간을 소모한다.
모든 단계에서 과도한 추론을 사용해 제한 시간 안에 작업을 끝내지 못한다.
52.8에서 66.5로 오른 사실보다 더 중요한 것은 우리가 “모델이 부족하다”고 부르던 문제의 일부가 실제로는 환경이 부족한 문제일 수 있다는 점이다. 좋은 개발자도 준비되지 않은 컴퓨터에서는 제 능력을 다 쓰지 못한다. Agent 역시 다르지 않다.
현재 성능을 먼저 숫자로 고정한다.
최종 실패보다 실패가 만들어진 과정을 본다.
효과를 식별할 수 있도록 수정 범위를 제한한다.
한 과제 개선이 전체를 해치지 않는지 본다.
Harness를 완성품이 아니라 실험의 누적으로 다룬다.
같은 말이라도 길이 다르면 달리는 모습이 달라진다.
같은 사람이라도 도구와 규칙과 시간이 다르면 일의 결과가 달라진다.
LangChain의 숫자가 보여주는 것은
지능의 한계보다 환경의 책임이다.
실패를 모델 탓으로 돌리기 전에
어디에서 헤맸는지, 왜 멈췄는지,
무엇을 보지 못했고 무엇을 검증하지 않았는지 본다.
그리고 그 실패가 다시 일어나지 않도록
환경에 한 줄을 더한다.
좋은 Harness는 더 많이 명령하는 구조가 아니라, 실패를 더 정확히 기억하는 구조다.