조사

에이전트 하네스를 지속적으로 개선하기

Stefan Heule & Jediah Katz읽는 데 9분

저희는 Cursor 에이전트 하네스를 다른 야심 찬 소프트웨어 제품을 만들 때와 같은 방식으로 접근합니다. 작업의 상당 부분은 비전이 주도하며, 이상적인 에이전트 경험이 어떤 모습이어야 하는지에 대한 관점에서 출발합니다.

그런 다음 그 비전에 더 가까워지기 위한 가설을 세우고, 이를 검증하는 실험을 실행하며, eval과 실제 사용량에서 얻은 정량적·정성적 신호를 바탕으로 반복적으로 개선합니다. 이 과정은 적절한 온라인 및 오프라인 계측에 달려 있습니다. 그래야 어떤 변화가 실제로 하네스를 더 낫게 만드는지 판단할 수 있기 때문입니다.

새로운 모델에 대한 Early Access를 받으면, 이런 접근 방식이 모두 한데 모입니다. 저희는 몇 주에 걸쳐 모델의 강점과 특성에 맞게 하네스를 맞춤 설정합니다. 그러면 특별히 튜닝된 하네스 안의 동일한 모델이 눈에 띄게 더 빠르고, 더 똑똑하고, 더 효율적으로 작동합니다.

때로는 도약적인 개선을 발견하기도 합니다. 하지만 대부분의 경우 하네스 개선은 작은 최적화를 집요하게 하나씩 쌓아 올리는 일에 가깝고, 이런 최적화들이 모여 에이전트가 소프트웨어를 더 잘 만들 수 있게 합니다.

컨텍스트 윈도우의 진화

대규모 언어 모델과 상호작용할 때 핵심이 되는 것은 컨텍스트 윈도우입니다. 에이전트에게 무언가를 만들도록 요청하면 컨텍스트 윈도우는 시스템 프롬프트와 도구 설명으로 시작해, 현재 대화 상태를 거친 뒤, 마지막에 사용자의 요청이 들어갑니다.

이 윈도우를 어떻게 구성하고 관리하는지는 Cursor의 역사 전반에 걸쳐 크게 발전해 왔습니다.

2024년 말 처음 코딩 에이전트를 개발했을 때는 모델이 스스로 적절한 컨텍스트를 고르는 능력이 훨씬 떨어졌습니다. 그래서 다양한 컨텍스트 엔지니어링 작업에 많은 공을 들여 가드레일을 마련했습니다. 예를 들어, 매번 수정이 이루어진 뒤 lint 및 타입 오류를 에이전트에 보여주고, 너무 적은 줄 수만 요청하면 파일 읽기 요청을 다시 구성했으며, 한 턴에서 호출할 수 있는 도구 수의 상한까지 두었습니다.

또한 각 세션이 시작될 때 에이전트가 항상 활용할 수 있도록 상당한 양의 정적 컨텍스트도 제공했습니다. 시기에 따라 여기에는 코드베이스의 폴더 레이아웃, 질의와 의미적으로 일치하는 코드 스니펫, 그리고 사용자가 수동으로 첨부한 파일의 압축 버전이 포함되기도 했습니다.

하지만 그런 방식은 이제 대부분 사라졌습니다.

지금도 일부 유용한 정적 컨텍스트(예: 운영 체제, git 상태, 현재 파일과 최근에 본 파일)는 포함합니다. 다만 모델 성능이 높아지면서 가드레일은 줄이고, 에이전트가 작업하는 동안 가져올 수 있는 더 많은 동적 컨텍스트를 제공하는 방향으로 바뀌었습니다. 이전 게시물에서는 동적 컨텍스트의 배경이 되는 몇 가지 기법을 깊이 있게 다뤘는데, 그중 상당수는 이후 다른 코딩 에이전트에도 도입되었습니다. 이제 저희는 에이전트가 동적으로 컨텍스트를 더 많이 가져오고 외부와 상호작용할 수 있는 방법을 더 많이 제공하는 데 주력하고 있습니다.

동적 컨텍스트를 사용하면 모델은 과거 대화, 활성 터미널 세션, 관련 도구와 같은 추가 정보를 언제 컨텍스트 윈도우로 가져올지 결정할 수 있습니다.동적 컨텍스트를 사용하면 모델은 과거 대화, 활성 터미널 세션, 관련 도구와 같은 추가 정보를 언제 컨텍스트 윈도우로 가져올지 결정할 수 있습니다.

하네스 변경을 평가하는 두 가지 방법

하네스와 모델은 함께 에이전트의 성능을 좌우하지만, 무엇이 "좋은지"를 딱 잘라 정의하기는 어렵습니다. 이를 파악하기 위해 저희는 여러 겹의 측정 체계를 구축했습니다.

저희는 공개 벤치마크와 자체 eval 스위트인 CursorBench를 함께 운영하고 있으며, 이를 통해 품질을 빠르고 표준화된 방식으로 파악하고 시간에 따른 변화를 비교할 수 있습니다. 하지만 아무리 뛰어난 벤치마크라도 실제 사용을 어디까지나 근사할 뿐이므로, 여기에만 전적으로 의존하면 중요한 신호를 놓치게 됩니다.

그래서 실제 사용 환경에서 두 개 이상의 하네스 변형을 나란히 배포해 A/B 테스트하는 온라인 실험도 진행합니다. 이 테스트에서는 다양한 지표를 통해 에이전트 품질을 측정합니다. 예를 들어 지연 시간, 토큰 효율, 도구 호출 횟수, 캐시 적중률처럼 비교적 명확한 지표가 있습니다. 이런 지표들은 방향성을 파악하는 데는 유용하지만, 에이전트가 실제로 일을 잘 해냈는지 같은 더 모호하지만 중요한 질문에는 여전히 충분히 답해주지 못합니다. 저희는 이를 두 가지 방식으로 측정합니다.

첫 번째는 에이전트가 생성한 코드의 "Keep Rate"입니다. 에이전트가 제안한 특정 코드 변경 집합에 대해, 일정 시간이 지난 뒤 그중 얼마만큼이 사용자의 코드베이스에 그대로 남아 있는지를 추적합니다. 이를 통해 사용자가 에이전트의 출력 결과를 수동으로 수정해야 했는지, 혹은 여러 번 반복하며 에이전트가 다시 고치도록 해야 했는지를 파악할 수 있고, 이는 에이전트의 초기 응답 품질이 낮았다는 신호가 됩니다.

두 번째로는 언어 모델을 사용해 에이전트의 초기 출력에 대한 사용자의 반응을 읽고, 사용자가 의미적으로 만족했는지를 포착합니다. 사용자가 다음 기능으로 넘어가는 것은 에이전트가 제 역할을 했다는 강력한 신호이고, 사용자가 스택 트레이스를 붙여 넣는 것은 그렇지 않았다는 신뢰할 수 있는 신호입니다.

이런 온라인 테스트를 통해 유망해 보이던 아이디어를 접어야 한다는 결론에 이를 때도 있습니다. 한 실험에서는 컨텍스트 요약을 위해 더 비싼 모델을 시도해 봤지만, 에이전트 품질에는 눈에 띄는 차이가 없었고 더 높은 요금을 감수할 만한 수준도 아니었습니다.

성능 저하 추적 및 복구

더 많은 모델과 기능을 추가할수록 하네스는 다른 소프트웨어와 마찬가지로 더 많은 잠재 상태를 갖게 되고, 그만큼 복잡성도 커집니다. 그러면 bug가 생길 수 있는 영역도 함께 넓어지며, 그중 상당수는 대규모 환경에서만 탐지할 수 있습니다.

에이전트의 도구는 bug가 발생하기 가장 쉬운 영역 중 하나이며, 도구 호출 오류는 Cursor의 세션에 매우 큰 악영향을 줄 수 있습니다. 에이전트가 스스로 바로잡는 경우도 많지만, 오류는 컨텍스트에 남아 토큰을 낭비하고, 누적된 실수가 이후 모델의 판단 품질을 떨어뜨리는 “컨텍스트 부패”를 일으킵니다.

경우에 따라서는 도구 호출 실패 이후 에이전트가 막히거나 완전히 엉뚱한 방향으로 벗어날 수도 있습니다. 도구 호출 volume이나 error rate 같은 지표은 에이전트가 일을 잘했는지를 직접 측정하지는 않지만, 더 큰 문제를 가리키는 신호로는 활용할 수 있습니다.

원인을 알 수 없는 오류는 모두 하네스의 bug로 간주하며, 실제로 그렇게 처리합니다. 하지만 많은 오류는 “예상된” 오류이기도 합니다. 예를 들어 모델이 가끔 잘못된 수정을 제안하거나, 존재하지 않는 파일을 읽으려고 할 수 있습니다. 저희는 이런 예상된 오류를 원인별로 분류합니다. InvalidArgumentsUnexpectedEnvironment는 모델의 실수와 컨텍스트 윈도우 내 모순을 포착하고, ProviderErrorGenerateImageWebSearch 같은 도구에서 발생한 벤더 장애를 포착합니다.

이 밖에도 UserAbortedTimeout 같은 여러 분류가 있으며, 이를 합치면 대부분의 예상된 오류를 포괄합니다.

올해 초 진행한 집중 스프린트에서, 모든 도구 호출의 reliability를 최소 99%, 많게는 99.9% 수준까지 끌어올렸습니다.올해 초 진행한 집중 스프린트에서, 모든 도구 호출의 reliability를 최소 99%, 많게는 99.9% 수준까지 끌어올렸습니다.

저희는 이러한 지표을 바탕으로 alert를 정의해 프로덕션에 반영된 중요한 regression을 포착합니다. 원인을 알 수 없는 오류는 언제나 bug이므로, 어떤 도구에서든 unknown error rate가 고정된 threshold를 넘으면 alert를 발생시킵니다. 다만 예상된 오류가 하네스의 bug를 뜻하는지, 아니면 예상 가능한 동작인지를 구분하는 일은 까다로울 수 있습니다.

예를 들어 grep 검색의 시간 초과는 도구의 성능 문제 때문일 수도 있고, 코드베이스가 너무 커서 모델이 비효율적인 query를 만든 탓일 수도 있습니다. 이를 해결하기 위해 저희는 예상된 오류가 기준선을 크게 웃돌 때 동작하는 anomaly detection alert를 운영합니다. 기준선은 도구별, 모델별로 계산하는데, 모델마다 도구 호출를 잘못 처리하는 비율이 다를 수 있기 때문입니다.

또한 저희는 모델이 로그를 검색하고, 새로 발생했거나 최근 급증한 문제를 찾아내고, 조사 내용을 담아 백로그 티켓을 만들거나 업데이트하는 방법을 가르치는 스킬을 갖춘 주간 자동화도 실행합니다. 저희는 한 번에 많은 문제의 수정 작업을 시작하기 위해 클라우드 Agent를 적극 활용하며, Linear에서 직접 이를 trigger할 수도 있습니다.

이 과정은 에이전트 하네스를 위한 자동화된 “소프트웨어 공장”을 구현하는 방식의 일부입니다. 올해 초 진행한 집중 스프린트 기간 동안, 저희는 예상치 못한 도구 호출 오류를 한 자릿수 규모만큼 줄였습니다.

다양한 모델에 맞게 하네스 맞춤 설정

저희의 모든 하네스 추상화는 특정 모델에 종속되지 않으며, 지원하는 각 모델에 맞게 폭넓게 맞춤 설정할 수 있습니다. 예를 들어, OpenAI의 모델은 패치 기반 형식으로 파일을 수정하도록 학습된 반면, Anthropic의 모델은 문자열 교체 방식으로 학습되었습니다. 두 모델 모두 어느 도구든 사용할 수는 있지만, 익숙하지 않은 도구를 쓰게 하면 추가 reasoning 토큰이 들고 실수도 더 많이 발생합니다. 그래서 저희 하네스에서는 각 모델이 학습 과정에서 사용했던 도구 형식을 제공하고 있습니다.

이러한 맞춤 설정은 매우 깊은 수준까지 이루어지며, 서로 다른 프로바이더는 물론 서로 다른 모델 버전에 맞춘 맞춤형 프롬프팅까지 포함됩니다. OpenAI의 모델은 지시를 따를 때 더 문자 그대로이고 정밀한 경향이 있는 반면, Claude는 조금 더 직관적이고 다소 불명확한 지시에도 더 유연하게 반응하는 편입니다.

출시 전에 새로운 모델에 대한 early access를 얻게 되면, 저희는 가장 비슷한 기존 모델의 하네스에서 출발해 반복적으로 개선해 나갑니다. 오프라인 eval을 실행해 모델이 어디에서 혼란을 겪는지 찾아내고, 저희 팀이 직접 사용해 보며 문제를 찾아낸 뒤, 그에 맞춰 하네스를 조정합니다. 이렇게 반복하면서, 배포해도 좋겠다고 판단되는 모델-하네스 조합이 나올 때까지 다듬습니다.

이 튜닝 과정의 상당 부분은 새로운 모델의 강점에 맞게 하네스를 맞춤 설정하는 일이지만, 때로는 하네스로 완화할 수 있는 모델 고유의 특성을 마주치기도 합니다. 예를 들어, 저희는 한 모델에서 저희가 context anxiety라고 부르게 된 현상을 관찰했습니다. 컨텍스트 윈도우가 차오를수록 그 모델은 작업을 거부하기 시작했고, 과제가 너무 커 보인다고 머뭇거리곤 했습니다. 저희는 프롬프트 조정을 통해 이런 behavior를 줄일 수 있었습니다.

채팅 도중 모델 전환 지원

대화 도중에 사용자가 모델을 전환할 수 있도록 하네스를 설계하는 일은 특히 까다롭습니다. 모델마다 동작 방식, 프롬프트, 도구의 형태가 서로 다르기 때문입니다.

사용자가 모델을 전환하면 Cursor는 해당 모델에 맞게 맞춤화된 프롬프트와 도구 세트가 포함된 적절한 하네스로 자동 전환합니다. 하지만 모델은 여전히 다른 모델이 만들어 낸 대화 기록, 즉 자신이 학습한 분포에서 벗어난 기록에 그 도구를 적용해야 합니다.

이를 해결하기 위해, 저희는 모델이 채팅 도중 다른 모델로부터 작업을 넘겨받는 상황임을 알려 주는 맞춤 지침을 추가합니다. 이 지침은 또 대화 기록에는 나타나지만 해당 모델의 자체 도구 세트에는 없는 도구를 호출하지 않도록 모델을 유도합니다.

모델이 자체 도구 세트에 없는 도구를 호출하지 않도록 방지모델이 자체 도구 세트에 없는 도구를 호출하지 않도록 방지

두 번째 과제는 캐시가 프로바이더별, 모델별로 달라진다는 점입니다. 따라서 전환이 일어나면 캐시 미스가 발생해 첫 번째 턴이 더 느려지고 비용도 더 많이 듭니다. 이를 완화하기 위해 전환 시점에 대화를 요약해 모델에 깔끔한 요약을 제공하고, 캐시 페널티를 줄입니다. 하지만 사용자가 복잡한 작업을 깊이 진행 중이라면 요약 과정에서 중요한 정보가 빠질 수 있습니다. 그래서 특별히 전환해야 할 이유가 없다면, 일반적으로는 대화가 끝날 때까지 같은 모델을 계속 사용하는 것을 권장합니다.

대화 도중 모델 전환의 어려움을 피하는 또 다른 방법은 새 컨텍스트 윈도우에서 시작하는 하위 에이전트를 대신 사용하는 것입니다. 최근에는 사용자가 특정 모델로 하위 에이전트를 직접 실행해 달라고 요청할 수 있는 기능을 하네스에 추가했습니다.

하네스와 소프트웨어 개발의 미래

AI 지원 소프트웨어 엔지니어링의 미래는 멀티 에이전트가 될 것입니다. 모든 하위 작업을 단일 에이전트 하나로 처리하는 대신, 시스템은 특화된 에이전트와 하위 에이전트에 작업을 적절히 위임하는 법을 익히게 됩니다. 하나는 계획을, 다른 하나는 빠른 수정을, 세 번째는 디버깅을 맡고, 각각 자신이 가장 잘하는 역할에 맞게 범위가 정해집니다.

이것이 제대로 작동하게 만드는 일은 본질적으로 하네스의 과제입니다. 시스템은 어떤 에이전트를 투입할지, 해당 에이전트의 강점에 맞게 작업을 어떻게 구성할지, 그리고 그 결과를 어떻게 하나의 일관된 워크플로우로 엮을지 알아야 합니다. 이런 조율을 오케스트레이션하는 능력은 어느 한 에이전트가 아니라 하네스에 있습니다. 즉, 하네스 엔지니어링은 원래부터 에이전트의 성공에 중요했지만, 앞으로는 그 중요성이 더욱 커질 것입니다.

분류: 조사

작성자s: Stefan Heule & Jediah Katz