에이전트와 하네스, 실제로 어떻게 움직이나

ai-agentllmharness

안녕하세요! 재니미입니다.

지난 글에서 하네스는 실체가 있는 소프트웨어이고, 에이전트는 그 위에서 모델이 스스로 판단하는 동작 방식이라고 정리했습니다. 이번엔 실제로 하네스가 모델을 어떤 순서로 부르는지, 같은 하네스가 워크플로우와 에이전트 중 뭘로 쓰이는지 예시로 따라가 보겠습니다.

하네스 루프, 한 단계씩 따라가보면

코딩 작업을 맡기는 하네스에 “이 버그 좀 고쳐줘”라고 요청하는 상황을 가정해봅시다. 실제로는 대략 이런 순서로 돌아갑니다.

  1. 하네스가 사용자 메시지, 시스템 프롬프트, 지금 쓸 수 있는 도구 목록(파일 읽기, 파일 쓰기, 명령 실행 등)을 묶어서 모델에 보냅니다.
  2. 모델은 아직 버그가 어디 있는지 모르니, “관련 파일부터 찾아야겠다”고 판단하고 파일 검색 도구를 호출하겠다는 응답을 내놓습니다.
  3. 하네스가 그 도구 호출을 받아서 실제로 파일 시스템을 뒤지고, 검색 결과를 다시 모델에 넣어줍니다.
  4. 모델은 검색 결과를 보고 이번엔 “이 파일을 고치고 테스트를 돌려야겠다”고 판단해서 파일 쓰기 도구, 명령 실행 도구를 순서대로 호출합니다.
  5. 하네스는 매번 그 호출을 실행하고 결과를 모델에 되먹입니다. 이 주고받기를 몇 차례 반복하다가 모델이 “이제 끝났다”고 판단하면 하네스가 루프를 멈추고 최종 응답을 사용자에게 보여줍니다.

이 사이클 전체, 즉 프롬프트를 조립하고 모델을 부르고 응답에서 도구 호출을 뽑아 실행하고 결과를 다시 넣어주는 반복을 실제로 돌리는 쪽이 하네스입니다. 그리고 그 반복 안에서 “다음에 뭘 할지”를 매번 모델이 스스로 고른다는 점이 에이전트적으로 동작하고 있다는 뜻입니다.

에이전트 관점에서 보면

방금 본 루프에서 하네스는 도구를 실제로 실행하고 결과를 넘겨주는 배관 역할만 합니다. 그 배관 안에서 모델이 실제로 하는 일은 네 가지로 나뉘는데, 전부 “모델이 정한다”로 끝나긴 해도 성격이 조금씩 다릅니다.

  • 정보가 없는 상태에서 첫 행동을 만들어냅니다. “버그를 고쳐라”는 목표만 있을 뿐 어디부터 봐야 하는지는 안 주어졌습니다. 에러 메시지나 최근 변경 이력 같은 단서를 종합해서 “일단 여기부터 보자”는 첫 가설을 모델이 세워줘야 합니다.
  • 애매한 결과 중에서 고릅니다. 검색 결과가 여러 개 나왔을 때 어느 게 진짜 원인인지는 정답표가 없습니다. 이름이 비슷한 함수가 세 파일에 있다면, 그중 최근에 고친 파일이나 에러 줄 번호에 가까운 쪽으로 모델이 후보를 좁혀줘야 합니다.
  • 실패를 보고 계획을 바꿉니다. 고친 코드로 테스트가 실패했다면 하네스는 “실패했다”는 사실만 돌려줄 뿐, 왜 실패했는지는 알려주지 않습니다. 원인을 다시 추론해서 다른 파일을 볼지 같은 파일을 다르게 고칠지 모델이 정해줘야 합니다.
  • 끝났다는 기준 자체를 정합니다. “완료”라는 상태는 하네스에 정의돼 있지 않습니다. 테스트가 몇 번 통과해야 끝인지 기준을 모델이 세워줘야 루프가 멈춥니다.

없는 정보로 첫 행동 만들기, 여럿 중 고르기, 실패를 되짚기, 끝을 스스로 정의하기. 이렇게 성격이 다른 판단들을 그때그때 채워 넣는 게 에이전트로 동작한다는 것의 실체입니다.

같은 하네스, 워크플로우로 쓸 수도 에이전트로 쓸 수도

여기서 워크플로우는 정해진 순서를 코드로 못박아둔 것을, 에이전트는 그 순서를 모델이 상황 봐가며 스스로 정하는 것을 말합니다(지난 글에서 다룬 구분입니다). 이번엔 PR(Pull Request, 코드 변경 사항을 저장소에 반영하기 전에 검토받는 단위)을 검토하는 하네스를 가정해봅시다. 쓸 수 있는 도구는 린트 실행, 테스트 실행, 커버리지 확인, 코멘트 작성, 이렇게 넷입니다.

워크플로우로 짜면 이렇게 됩니다. PR이 열리면 코드가 “린트 실행 → 테스트 실행 → 커버리지 확인 → 결과를 코멘트로 남기기” 순서를 그대로 못박아둡니다. 모델은 각 단계 결과를 요약하는 역할만 하고, 다음에 뭘 실행할지는 모델이 아니라 코드가 정합니다. 문서만 고친 PR이든 핵심 로직을 고친 PR이든 똑같은 네 단계를 다 거칩니다.

에이전트로 열어두면 다릅니다. 하네스는 “이 PR을 검토해줘”라는 요청과 같은 도구 넷만 모델에 쥐여줍니다. 모델이 PR 내용을 보고 “이건 문서만 고쳤으니 테스트는 건너뛰고 린트만 돌리면 되겠다”거나 “핵심 로직이 바뀌었으니 넷 다 순서대로 돌려야겠다”처럼 상황에 따라 다음 행동과 순서를 스스로 정합니다.

도구 넷과 코드베이스는 완전히 같습니다. 그 위에서 순서를 코드가 정하면 워크플로우, 모델이 정하면 에이전트라는 차이만 있습니다.

왜 이 구분이 쓸모 있나

뭔가 잘못됐을 때 어디를 들여다봐야 하는지가 이 구분에 따라 갈립니다. 하네스가 도구를 실행하다 에러를 던졌다면 코드나 로그를 보면 됩니다. 원인이 뻔히 코드 안에 있으니까요. 반면 모델이 매번 다른 도구를 고르다가 이상한 순서로 실행했다면, 그건 코드의 버그가 아니라 그 앞뒤에 있던 프롬프트나 도구 설명이 모델의 판단을 어떻게 이끌었는지를 봐야 하는 문제입니다. 하네스와 에이전트를 구분해두면 “코드를 고칠 문제”와 “프롬프트·도구 설계를 고칠 문제”를 헷갈리지 않게 됩니다.

감사합니다.


참고 자료