Harness Engineering 101 — Agentic AI의 이면에 숨겨진 것들
요약
Agentic AI가 실제로 작동하기 위해 LLM을 감싸는 구조인 'Harness Engineering'의 개념과 중요성을 설명합니다. 도구 호출의 검증 과정과 토큰 예산 관리 등 에이전트의 안정성을 확보하기 위한 핵심 메커니즘을 다룹니다.
핵심 포인트
- Harness Engineering은 에이전트의 오류를 관리하는 프레임워크 구축 학문임
- 도구 호출 결과가 성공했더라도 실제 상태 변화를 검증하는 과정이 필수적임
- 컨텍스트 길이에 따른 비용, 망각, 속도 저하 문제를 토큰 예산 관리로 해결해야 함
Harness Engineering 101 — Agentic AI의 이면에 숨겨진 것들
이전 글에서는 "빈 LLM에서 → Agentic AI"로 가는 7개 레이어에 대해 이야기했습니다.
이번에는 각 레이어 내부에서 어떻게 작동하는지 — 그리고 무엇이 고장 날 수 있는지 살펴보겠습니다.
우리가 Claude Code, Cursor, 또는 Hermes를 사용할 때, 우리는 AI가 단계별로 작업하는 것을 봅:
생각 → 도구(tool) 호출 → 결과 확인 → 계속 생각 → 도구(tool) 호출 → 완료
우리가 보지 못하는 것은 그 과정 중에 발생하는 모든 오류이며 — 누군가(또는 코드)가 그 오류들을 끊임없이 관리하고 있다는 사실입니다.
그것이 바로 Harness Engineering입니다 — LLM을 감싸는 "프레임워크(structure)"를 구축하여, 완벽하지 않은 세상에서 에이전트(agent)가 실제로 작동할 수 있도록 모든 것을 관리하는 학문입니다.
1. The Loop — Harness의 핵심
이것은 모든 에이전트(agent)가 실행하는 루프(loop)입니다:
while not done and budget_ok:
response = llm.chat(messages, tools)
...
겉보기에는 평범한 while 루프처럼 보이지만 — 바로 이곳이 모든 것이 고장 날 수 있는 지점입니다.
실상: AI가 도구 호출(tool call)이 성공했다고 생각했을 때... 하지만 실제로는 그렇지 않은 경우
한번은 제가 Hermes에게 LED(법무부 강제집행국 자산 경매 사이트) 웹사이트에서 콘도를 찾아달라고 요청한 적이 있습니다.
AI의 계획: 웹사이트 접속 → 양식 작성 → 제출(submit) 클릭 → 결과 읽기
AI가 도구 browser_click(ref="submit_button")을 호출했습니다 — 도구는 "clicked"를 반환했습니다.
AI는 기뻐하며 — "완료! 결과를 얻었다"라고 생각하고 — 실제로 로드되지 않은 페이지에서 결과를 읽으려고 시도했습니다.
무슨 일이 일어난 걸까요? 도구는 "clicked"를 반환했지만, 웹 페이지는 아직 제출이 완료되지 않았습니다 — JavaScript가 여전히 실행 중이고, DOM이 아직 변경되지 않았으며, CAPTCHA가 아직 검증되지 않은 상태였습니다.
Harness가 처리해야 할 일: browser_click 이후에는 웹 페이지가 실제로 변경되었는지 확인하기 위한 browser_snapshot이 있어야 합니다 — 그리고 만약 페이지가 변하지 않았다면, 재시도(retry)하거나 전략을 변경해야 합니다.
이것이 harness가 하는 일입니다 — 도구 호출(tool call)을 즉시 믿지 않고, 검증(verify)하는 것입니다.
2. Token Budget — 주머니 속의 돈을 관리하는 것과 같음
AI가 도구를 호출할 때마다 — 다음 내용들을 저장해야 하므로 컨텍스트 윈도우(context window)가 길어집니다:
[사용자 메시지] → [어시스턴트 도구 호출(assistant tool_call)] → [도구 결과(tool result)] → [어시스턴트 도구 호출(assistant tool_call)] → [도구 결과(tool result)] → ...
만약 AI가 50번 작동한다면 — 컨텍스트는 100K+ 토큰(tokens)까지 길어질 수 있습니다.
문제:
- 💰 비용 발생 — Claude Sonnet $3/M input = 100K 토큰 사용 시 API 호출당 $0.30
- 🧠 LLM 망각 — 컨텍스트 (context)가 너무 길어지면 LLM이 초기 명령어를 잊기 시작함
- ⏱️ 속도 저하 — 컨텍스트가 길어질수록 추론 (inference) 시간이 길어짐
Harness가 처리해야 할 사항:
if token_count > threshold:
compress_context() # 오래된 도구(tool) 결과물을 제거하고 핵심 내용만 남김
사례: 한 에이전트(agent)를 관리하는 팀의 경험담 — AI가 50회 이상의 도구 호출 (tool calls)을 수행하며 컨텍스트가 150K 토큰까지 길어지자, 루프 (loop)에 빠지기 시작했습니다: 파일을 반복해서 읽고, 수정하고 또 수정하며, 자신이 무엇을 했는지 잊어버린 것입니다. 이때 Harness가 자동으로 컨텍스트를 압축 (compress context)하여 30K 토큰으로 줄였고, AI는 즉시 정신을 차리고 작업을 재개할 수 있었습니다.
3. Tool Error Recovery — 도구가 실패했을 때
도구 호출 (tool call)이 항상 성공하는 것은 아닙니다:
- terminal("git push"): Permission denied
- browser_click("submit"): Page did not change
- web_search("Go 1.27"): CAPTCHA blocked
...
AI는 도구 호출이 실패했다는 것을 인지해야 하며, 반드시 **복구 전략 (recovery strategy)**을 갖추고 있어야 합니다.
실제 사례: CAPTCHA를 통한 재시도 (retry) 학습
Hermes가 웹에서 자산을 검색해야 하는 상황 — 처음에는 정상적인 절차를 따랐습니다: 양식 작성 → 제출 (submit) 클릭 → CAPTCHA 차단 (CAPTCHA block)
실제 사용된 Harness 패턴:
시도 1: form.submit() → CAPTCHA 차단 ❌
시도 2: CAPTCHA를 먼저 읽기 → 제출 → 제출하는 동안 CAPTCHA가 변경됨 ❌
시도 3: 양식의 모든 필드에 조용히 데이터 입력 — 웹사이트가 입력 중임을 알지 못하도록 JavaScript를 사용하여 input field에 직접 값을 삽입 (onChange 이벤트를 트리거하지 않음. 해당 이벤트들은 AJAX를 호출하여 지역 데이터를 로드하게 만들고, 이는 제출 전 CAPTCHA를 새로고침하게 만들기 때문) → 마지막 단계로 CAPTCHA 읽기 → form.submit() 대신 button.click()을 사용하여 제출 버튼 클릭 → ✅ 성공!
Harness는 단순히
하지만 AI가 10번째 라운드에서 main.go의 500줄 전체를 "기억"할 필요는 없습니다. 단지 "main.go에는 RunServer를 호출하는 main 함수가 있다"는 사실만 알면 될 수도 있습니다.
Harness가 수행해야 할 작업:
📄 main.go (500 lines) — 1라운드: 전체 저장
📄 main.go (500 lines) — 10라운드: "main()을 정의하고 RunServer를 호출함"이라는 요약본만 저장
이 기술을 **컨텍스트 압축 (context compaction)**이라고 부릅니다. Harness는 작은 LLM을 사용하여 이전의 도구 결과 (tool result)를 읽고 → 요약한 뒤 → 요약본만 저장합니다.
실제 사례: Hermes의 설정(config)에는
compression.threshold가 있습니다. 기본값은 0.50 (컨텍스트 창의 50%)이며, 컨텍스트가 절반을 초과하면 자동으로 압축을 수행합니다. 예를 들어 100K 토큰이 20K 토큰으로 압축되어, API 호출당 $0.24를 절약할 수 있습니다.
5. 역할 교대 (Role Alternation) — 잘 알려지지 않은 규칙
LLM에는 엄격한 규칙이 있습니다: 대화(conversation) 내의 메시지는 반드시 역할(role)이 교대로 나타나야 합니다.
✅ user → assistant → user → assistant → user
❌ user → assistant → assistant → user ← 오류 발생!
단순해 보이지만, 에이전트 루프 (agent loop)에서는 결코 쉽지 않습니다:
[user: "API 생성해줘"]
[assistant: tool_call read_file] ← assistant
[tool result: "파일은 200줄입니다"] ← tool (user도 assistant도 아님)
...
Harness가 해결해야 할 문제: 연속되는 도구 호출 (tool calls)을 하나의 assistant 메시지로 통합해야 합니다.
# 도구 호출을 하나씩 보내는 대신 — harness는 보내기 전에 묶습니다
messages = [
{"role": "user", "content": "API 생성해줘"},
...
실제 사례: 이전 버전의 Hermes에는
/stop명령 시role alternation이 깨지는 버그가 있었습니다. AI가 도구를 호출하는 도중에 사용자가 중지(stop)를 눌렀을 때, harness가 남아있는 도구 호출들을 통합하지 못해 assistant 메시지가 연속으로 두 번 전송되었고, 이로 인해 API 에러가 발생했습니다. 이를 디버깅하는 데 3시간이 걸렸습니다.
6. 도구 스키마 (Tool Schema) — 코드를 "LLM 언어"로 변환하기
우리에겐 다음과 같은 Python 함수가 있습니다:
def read_file(path: str, offset: int = 1, limit: int = 500) -> dict:
"""줄 번호와 함께 텍스트 파일을 읽습니다."""
LLM은 Python을 이해하지 못합니다. 따라서 harness는 이를 JSON 스키마 (JSON schema)로 변환해야 합니다:
{
"name": "read_file",
"description": "줄 번호와 함께 텍스트 파일을 읽습니다.",
...
그리고 LLM이 다음과 같이 응답할 때:
{"name": "read_file", "arguments": {"path": "/home/user/main.go"}}
Harness는 이를 read_file(path="/home/user/main.go")로 변환한 뒤 실제로 호출해야 합니다.
사소해 보일 수 있지만, 50개의 도구(tools)가 있고 각 도구마다 5~10개의 파라미터(parameter)가 있는 상황에서 Harness는 우리가 고민할 필요 없이 이 모든 스키마(schema)를 관리해 줍니다.
7. Interrupts — 시스템을 망가뜨리지 않고 AI를 중단시키기
사용자가 도중에 마음을 바꿉니다: "멈춰! 그거 말고 다른 거 할래."
Harness가 해야 할 일:
- 루프(loop)를 즉시 중단
- 실행 중인 도구 호출(tool calls)을 취소 (예: 빌드를 실행 중인
terminal) - 역할 교대(role alternation)를 망가뜨리지 않음
- 새로운 명령을 받을 준비가 된 상태로 복귀
예시: AI가 대규모 레포지토리(repo)를 클론(clone)하는 중 사용자가
/stop을 명령함 —git clone이 80% 진행된 상태 — Harness는 프로세스를 종료(kill)하고, 일부 클론된 파일을 정리(cleanup)한 뒤, 다시 응답할 수 있는 상태로 돌아와야 합니다 — 이 모든 과정은 1초 미만(< 1 sec)에 이루어져야 합니다.
🧩 Harness = AI가 아닌 엔지니어링(Engineering)
요약: Harness Engineering은 **비범한 LLM을 관리하기 위해 설계된 평범한 소프트웨어 엔지니어링(software engineering)**입니다.
| 문제 | 해결책 | AI가 아닌 — 엔지니어링(Engineering) 영역 |
|---|---|---|
| 컨텍스트(Context)가 너무 김 | 압축 (Compaction) | 메모리(memory) 관리 |
| ... | ... | ... |
LLM이 뇌라면, Harness는 그 뇌를 감싸고 있는 신경계, 근육, 그리고 면역 체계입니다.
직접 만들기 — 최소 단위
자신만의 Harness를 만들어보고 싶으신가요?
# 최소 단위의 harness — 30줄
def run_agent(user_input, tools, max_rounds=10):
messages = [{"role": "user", "content": user_input}]
...
이 30줄의 코드로부터 — 여러분은 Kiro, Antigravity, Hermes가 겪었던 것과 동일한 문제에 직면하게 될 것이며, 그것이 바로 Harness Engineering의 시작입니다.
📚 더 읽어보기:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기