하네스 엔지니어링, AI에 제약을 거는 것만은 아니랍니다

기술정리

#AI#에이전트#MCP#하네스#LLM

TL;DR

  • 은 코드가 아니다. **이름+설명+입력 스키마로 된 선언(인터페이스)**이다. 그 뒤엔 코드·API·다른 LLM·사람·서브에이전트 뭐든 올 수 있다.
  • MCP는 자율성 엔진이 아니다. 툴을 표준 방식으로 노출하는 배관(트랜스포트) 규격이다. 자율성은 MCP가 아니라 그걸 감싼 하네스 루프 설계에서 나온다.
  • 하네스는 제약 장치가 아니다. **모델을 실제로 굴러가게 하는 구동 골격(지시+툴+컨텍스트+루프)**이다. 제약(가드레일)은 그 안의 일부일 뿐이다.
  • 관통하는 축 하나: “결정권을 누가 쥐느냐.” 커맨드 → 툴 콜링 → 자율 에이전트는 단절된 세계가 아니라, 재량권을 조금씩 푼 연속체다.

들어가며 — 안다고 생각했는데, 까보니 달랐다

  • 나는 개발자가 아니다. 서비스 기획자다.
  • 그런데 일이 흘러가다 보니 멀티 에이전트 구조를 직접 설계하고, 툴을 붙이고, 라우터를 짜게 됐다.
  • 그 과정에서 “이미 안다”고 여겼던 개념 몇 개가, 막상 뜯어보니 내가 알던 것과 달랐다.
  • 이 글은 그 오해 세 개 — 툴, MCP, 하네스 — 를 바로잡은 기록이다.
  • 목적은 두 가지. 나 자신을 위한 정리이자, 나처럼 “개발자는 아닌데 실무로 파는” 사람에게 지도를 하나 남기는 것.

오해 1 — “툴은 결국 코드다”

  • 처음엔 툴을 그냥 “에이전트가 부르는 함수”라고 생각했다.
  • 그러다 문서를 보면 툴이 어떤 건 코드고, 어떤 건 API고, 어떤 건 그냥 LLM을 또 부르더라. 개념이 흐물흐물했다.
  • 원인은 하나였다. 업계가 “tool”이라는 한 단어를 서로 다른 세 층위에 다 갖다 쓴다.

층위를 나누면 안개가 걷힌다

  • 층위 1 — 인터페이스(계약): LLM 관점에서 툴의 진짜 정의. 이름 + 설명 + 입력 스키마(JSON Schema)로 된 선언. 그게 전부다.
    • 핵심: 모델은 툴을 “실행”하지 않는다. {"name": "get_quote", "input": {...}} 같은 **의도(구조화된 JSON)**를 뱉을 뿐, 실제 실행은 내 코드가 한다.
  • 층위 2 — 구현: 그 선언 뒤에 뭐가 붙느냐. 여기가 다양성의 정체.
    • 순수 함수/코드 (DB 쿼리 등)
    • 외부 API 래퍼 (날씨·결제·영상 생성)
    • 또 다른 LLM 호출 (“요약해줘” 툴 뒤에 실제론 모델이 돈다)
    • 사람 (승인 요청 툴 → 슬랙으로 사람에게 물어봄, human-in-the-loop)
    • 서브에이전트 (툴을 부르면 뒤에서 에이전트가 통째로 돈다)
  • 층위 3 — 트랜스포트: 그 선언이 모델에게 어떻게 전달되느냐. (→ 오해 2에서 다룸)

정리

  • 툴 = 인터페이스, 구현 = 아무거나.
  • 모델 입장에선 코드든 API든 LLM이든 사람이든 전부 동일하게 “이름+스키마 가진 호출 가능한 것”으로 보인다.
  • “툴이 코드냐 아니냐”가 헷갈렸던 건, 선언(모델이 보는 것)과 구현(뒤에서 도는 것)을 같은 단어로 불렀기 때문이다.
  • 실무 이점: 툴 뒤를 코드→사람 승인→LLM으로 모델 인터페이스는 안 건드리고 자유롭게 교체할 수 있다. (예: 위험한 확정 작업을 나중에 human-in-the-loop로 바꾸기)

오해 2 — “MCP가 자율성을 준다”

  • MCP를 붙인 에이전트를 보면 확실히 더 “자율적”으로 느껴졌다. 그래서 MCP가 자율성의 원천인 줄 알았다.
  • 아니었다. MCP는 자율성 엔진이 아니라 배관 규격이다.

MCP가 실제로 하는 일

  • MCP(Model Context Protocol)가 하는 건 하나. 툴/리소스를 표준화된 방식으로 노출하는 것.
  • 서버가 “나 이런 툴들 있어(tools/list)” 알려주고, 호출하면 결과 돌려준다. 끝이다.
  • MCP 자체는 루프를 타이트하게 돌릴지 느슨하게 돌릴지에 대해 아무 말도 하지 않는다. 그냥 트랜스포트다.

그럼 그 “자율성”은 어디서 왔나

  • 자율성은 MCP를 감싼 **하네스(에이전트 루프)**에서 나온다.
  • “툴 목록 받아 → 계획 → 호출 → 결과 관찰 → 반복”을 열린 루프로 도는 건 루프 쪽 설계지 MCP가 아니다.
  • 다만 MCP가 그 방향으로 유도하긴 한다:
    • 동적 발견 — 툴을 하드코딩하는 대신 런타임에 서버에 물어 받는다 → “정해진 3개 중 선택”이 아니라 “수십 개 중 알아서 골라”가 된다.
    • 큰 툴 가방 + 열린 루프 — 표준 인터페이스라 아무거나 꽂히니, 설계가 자연스럽게 “툴 잔뜩, 알아서 해”로 흐른다.

로컬 MCP vs 인라인 툴 — 근본은 같다

  • 둘 다 결국 내 컴퓨터에서 내 코드가 함수를 실행하는 것이다.
  • 차이는 프로세스 경계 하나뿐:
    • 인라인: 툴 핸들러가 하네스와 같은 프로세스. 그냥 함수 콜.
    • 로컬 MCP: 툴 핸들러가 별도 프로세스(서버). 하네스가 JSON-RPC로 말 걸어 실행.
  • “서버”가 원격이란 뜻이 아니다. python my_server.py로 띄운 로컬 프로세스도 완벽한 MCP 서버다.
  • 벽(프로세스 경계)을 세우는 값어치: 재사용·공유(여러 에이전트가 같은 서버에 붙음), 언어 독립, 격리, 동적 발견. 대가는 프로세스 관리·직렬화 오버헤드.

정리

  • MCP가 자율성을 주는 게 아니라, MCP가 툴 꽂기를 쉽게 만들어서 사람들이 자율적으로 설계하게 유도한다.
  • 트랜스포트(MCP)와 통제 정책(내 라우터)을 분리해 생각하면, “표준화는 취하되 타이트함은 유지”라는 좋은 자리를 잡을 수 있다.

오해 3 — “하네스는 제약이다”

  • 이게 가장 크게 틀렸던 지점이다. 나는 “하네스 엔지니어링 = 모델에 제약을 거는 일”로 알고 있었다.
  • harness의 일상적 뜻(마구·안전벨트, 뭔가를 묶는 것) 때문에 자연스러운 오해였다.

하네스의 진짜 정의

  • 소프트웨어에서 harness는 그 이미지에서 “묶어서 통제·구동하는 골격” 쪽으로 의미가 넘어갔다. (test harness가 코드를 감싸 돌려주는 것처럼)
  • 에이전트 맥락에서 하네스 = 날것의 LLM을 실제 작동하는 에이전트로 만드는, 모델을 감싼 구동 코드 전체.
  • 하는 일:
    • 지시 조립 — 시스템 프롬프트, md 파일들을 읽어 프롬프트로 묶음
    • 툴 선언·실행 — 툴 알려주고, tool_use 나오면 실행
    • 루프 — 호출 → 결과 관찰 → 재호출 → 반복
    • 컨텍스트/메모리 관리
    • 출력 파싱·라우팅
  • 지시(md) + 툴(코드) + 컨텍스트 + 루프를 한데 묶어 모델을 구동하는 껍데기.

“제약”이라는 직감의 한 톨의 진실

  • 하네스가 “쓸 수 있는 툴은 이것뿐”, “이렇게 행동해라”를 정의하니, 결과적으로 **모델의 행동 공간을 규정(=한정)**하긴 한다.
  • 하지만 그건 하네스가 “제약 장치”라서가 아니라 운영 환경을 정의하는 것의 부수 효과다.
  • 내가 헷갈린 진짜 원인은 따로 있었다:
    • 하네스가 가드레일을 담는 그릇이라서. 제약(“이 툴만 노출”, “이 액션은 승인”)을 구현하는 곳이 결국 하네스 안이다. 그래서 “하네스 짠다 = 모델 가둔다”로 체감된다.
    • 정의(구동)와 한정(제약)이 동전의 양면이라서.

비유

  • 하네스 = 자동차 전체 섀시.
  • 가드레일(제약) = 그중 브레이크·안전벨트.
  • “차 만드는 일(하네스 엔지니어링)“과 “브레이크 다는 일(제약)“은 같지 않다. 브레이크는 차의 일부일 뿐이다.

이건 나만의 오해가 아니었다 — 국내 담론의 기울기

  • 확인해보니, “하네스 = 제약/강제”는 내 개인 착각이 아니었다. 국내 소개글 다수가 그 프레임으로 하네스를 설명하고 있다.
  • 실제로 여러 국내 글이 하네스를 “출력을 원하는 방향으로 강제하는 시스템”, “안전하게 제어·운용하기 위한 설계 구조”, “길을 잃지 않도록 규칙을 만들어주는 일”로 정의한다.
  • 배경 추정: 2026년 2월 무렵 “하네스 엔지니어링”이라는 이름이 붙으며 개념이 국내에 빠르게 퍼졌고, 그 소개 과정에서 **“프롬프트만으론 강제가 안 되니 시스템으로 통제한다”**는 실무 동기가 전면에 부각됐다. 그 결과 “통제·강제” 측면이 정의의 얼굴이 됐다.
  • 다만 균형을 위해: 국내에도 원 정의(구동 골격)를 정확히 옮긴 글이 있다. 앤트로픽 표현을 빌려 “입력을 처리하고, 도구 호출을 조율하고, 결과를 반환하는 시스템”으로 소개하거나, “규칙·도구·스킬·메모리·피드백 루프를 감싸는 시스템”으로 설명하며 말·고삐·안장 비유를 쓰는 경우다.
  • 그래서 정확한 그림은 이렇다: 국내엔 “강제 프레임”이 흔하지만, 원 정의는 그보다 넓은 “구동 골격”이다. 제약은 그 골격이 담아내는 여러 기능 중 하나다.

용어를 대하는 태도

  • 영어권에선 harness가 여러 맥락의 일반명사인데, 한국선 음차(“하네스”)로 들어오며 고유명사/전문용어처럼 뭉쳐 정착했다.
  • 그 과정에서 의미 폭이 좁아지거나 살짝 틀어진다. (“에이전트”, “파이프라인”, “오케스트레이션”도 비슷)
  • 그래서 실체를 아는 쪽이 이긴다. 단어는 “이 맥락에선 이 뜻이겠네” 정도로 유연하게 받으면 된다.

세 오해를 관통하는 축 — “결정권을 누가 쥐느냐”

  • 세 오해를 풀고 보니, 결국 하나의 축으로 이어졌다.
  • 커맨드 → 툴 콜링 → 자율 에이전트는 단절된 세 세계가 아니라, 재량권을 조금씩 푼 연속체다.
단계 트리거 실행 경로 결정 LLM 역할
커맨드 사람 (/견적 X) 사람 없음
명령어의 자연어 껍데기 자연어 내가 깔아둔 레일 분류·매핑
자율 툴 콜링 자연어 LLM이 계획·연쇄·재시도 계획·실행
  • 겉보기엔 뒤 둘이 “자연어로 말하니 툴이 불린다”로 똑같아 보이지만, 결정권을 누가 쥐느냐가 완전히 다르다.
  • 그래서 “지금 우리 서비스는 자유로운 느낌이 아니다”는 한계가 아니라, 결정권을 안 넘긴 상태다.
  • 그리고 그건 프로덕션 서비스엔 옳은 선택이다. 결정권을 LLM에 넘기는 순간 예측 가능성·안전·감사 가능성이 같이 나간다.

트레이드오프

  • 타이트(통제): 고정 툴 레지스트리, 워크플로우가 언제 뭘 부를지 통제. 예측·테스트·안전·저비용. 단, 안 짜둔 경로는 못 함(브리틀).
  • 자율(유연): 동적 발견, 계획·연쇄·재시도. 안 짜둔 요청도 처리. 단, 예측 불가·고비용·보안 표면 넓음.
  • 어느 게 더 발전이냐가 아니라 통제↔유연 곡선 위 다른 점이다.
  • 성숙한 패턴: 위험·반복 핵심 경로는 꽉 잡고(커맨드/상태머신), 탐색적·저위험 주변부는 풀어준다(자율). 한 서비스 안에 층위로 공존시킬 수 있다.

마치며

  • 이 개념들은 알고리즘적으로 대단한 게 아니다. LLM + 툴 호출 루프 + 컨텍스트 관리 + 게이트웨이의 조립이다.
  • 대단한 건 코드가 아니라 채택·유지보수·생태계다. 각 조각은 단순한데, 다 붙여서 계속 돌아가게 유지하는 게 일이다.
  • 그러니 기술적 경외심에 눌릴 필요는 없다. 다만 “이걸 직접 만들 가치가 있나 / 빌려올까”는 별개의 판단이다.
  • 나는 개발자가 아니지만, 개념을 성분으로 분해해서 이해하는 방식으로 여기까지 왔다. 같은 자리에 선 누군가에게 이 지도가 쓸모 있길.

핵심 주장 3

  1. 툴·MCP·하네스의 혼란은 대부분 “층위 뭉개기”에서 온다 — 인터페이스/구현/트랜스포트를 분리하면 대부분 풀린다.
  2. 자율성의 원천은 MCP가 아니라 하네스 루프 설계다 — MCP는 트랜스포트일 뿐, 통제권은 여전히 내 손에 있다.
  3. 하네스는 구동 골격이고 제약은 그 일부 — “결정권을 누가 쥐느냐”가 통제↔유연을 가르는 진짜 축이다.

가장 큰 허점 3 + 예상 반박 3

  1. 허점: 층위 3분할이 실제 프레임워크마다 딱 안 맞을 수 있다.

    • 일부 도구는 인터페이스와 구현을 강하게 묶어 노출한다.
    • 예상 반박: “그럼 이 모델이 틀렸다” → 재반박: 3층위는 개념적 렌즈지 특정 구현의 파일 구조가 아니다. 렌즈로 보면 그 “묶인” 도구도 “인터페이스+구현을 함께 포장한 것”으로 해석돼 여전히 유효하다.
  2. 허점: “MCP는 트랜스포트일 뿐”이 MCP의 실질 효과를 과소평가한다.

    • 동적 발견·표준화가 설계를 자율 쪽으로 강하게 민다는 건 단순 배관 이상의 파급이다.
    • 예상 반박: “그럼 MCP가 자율성을 주는 게 맞다” → 재반박: 유도와 강제는 다르다. MCP는 자율 설계를 쉽게 만들 뿐, 타이트한 루프도 MCP로 얼마든지 구현된다. 인과의 주체는 여전히 루프 설계다.
  3. 허점: “타이트=프로덕션, 자율=탐색”이 지나친 이분법일 수 있다.

    • 실제로는 프로덕션에서도 부분 자율이 유효한 사례가 늘고 있다.
    • 예상 반박: “프로덕션도 자율로 가야 한다” → 재반박: 동의한다. 그래서 결론이 “둘 중 택일”이 아니라 **“경로별 층위 공존”**이다. 위험 경로는 잠그고 저위험은 푸는 다이얼 조절이 핵심이지, 전면 타이트가 정답이라는 주장이 아니다.

참고

이 글의 “국내 담론” 부분은 아래 소개글들을 살펴본 뒤 종합한 관찰이다. 표현은 모두 내 말로 정리했으며, 원문 확인은 각 출처에서.

  • 셀렉트스타 — 하네스 엔지니어링이란? (앤트로픽 정의 인용)
  • MadPlay — 프롬프트와 컨텍스트를 넘어, AI 에이전트를 위한 하네스 엔지니어링
  • 요즘IT(위시켓) — 하네스 엔지니어링으로 AI 에이전트를 길들여봤습니다
  • 패스트캠퍼스 — 2026 AI 필수 키워드: 하네스 엔지니어링 개념 정리
  • gpters — 하네스 엔지니어링 완벽 정리
  • 채널톡 — 하네스 엔지니어링이란?

원 개념 출처: OpenAI “Harness engineering: leveraging Codex in an agent-first world” (2026.02), Anthropic 엔지니어링 블로그.