에이전트 하네스 엔지니어링: LLM을 프로덕션급으로 만드는 법

Prompt Architect · 2026-06-17 · 8분

TL;DR — 비결정적인 LLM 주위를 감싸는 결정적 "껍질"을 설계하는 실무 가이드. 도구 표면, 권한·샌드박스, 컨텍스트 관리, 승인 게이트, 검증·로깅을 다룬다. 3개 AI 교차검증.

에이전트 하네스 엔지니어링이란 비결정적인 LLM을 감싸는 결정적(deterministic) "껍질"을 설계하는 일이다. 즉 도구 표면(tool surface), 권한·샌드박스, 컨텍스트 주입과 압축, 승인 게이트, 검증, 로깅·트레이싱, 서브에이전트 오케스트레이션을 엔지니어링하여 프로덕션에서 에이전트를 통제 가능하고 예측 가능하게 만드는 작업이다. 모델 자체는 갈아끼울 수 있어도, 이 껍질의 품질이 서비스의 신뢰성을 결정한다.

이 가이드는 Claude, OpenAI 계열, Google 계열 세 AI가 교차검증한 내용을 바탕으로 작성했으며, 특정 벤더에 종속되지 않는 일반 원칙을 다룬다. 다만 정확성을 위해 최신 사실을 짚어둔다. 현재 플래그십 모델은 Claude Opus 4.8 / GPT-5.5 / Gemini 3.5 Flash 세대다. Claude의 추론은 고정 budget_tokens(폐기됨)가 아니라 적응형 사고(adaptive thinking) + effort 레벨(low~`xhigh/max`)로 제어한다. 토큰 계산은 OpenAI용인 tiktoken이 아니라 count_tokens API를 써야 정확하다.

agent architecture diagram alt

핵심 개념: 하네스는 앱 설계다

LLM은 도구 호출을 "방출"할 뿐, 그것을 어떻게 처리할지는 전적으로 하네스가 결정한다. LLM은 당신 시스템의 보안 경계도, 승인 정책도, UX 표면도 모른다. 따라서 다음 다섯 가지가 하네스 엔지니어링의 골격이 된다.

  • 도구 표면: 모델이 무엇을 할 수 있는지의 형태
  • 권한·샌드박스: 부수효과(side effect)를 어디서 막는지
  • 컨텍스트 관리: 무엇을 넣고, 언제 압축·제거할지
  • 승인 게이트: 위험한 행동 앞에서 사람을 개입시키는 지점
  • 검증·트레이싱: 무슨 일이 일어났는지 재현·감사 가능한지

이 골격을 프레임워크가 자동으로 해결해 줄 것이라는 기대는 흔한 착각이다. 추적 가능한 프롬프트/도구/상태 경계는 여전히 당신의 앱 설계 책임이다.

베스트 프랙티스 체크리스트

1. 도구를 "에이전트-컴퓨터 인터페이스"로 설계하라

비즈니스 행동은 타입이 명시된 전용 도구로 만든다. refund_order, search_contracts처럼 의미가 분명한 도구는 하네스가 인터셉트하고, 게이팅하고, 렌더링하고, 감사할 수 있는 행동별 후크를 제공한다. 반면 탐색적 작업은 제한된 bash/샌드박스로 위임한다.

bash는 넓은 범위(breadth)를 주지만 하네스에는 불투명한 명령 문자열만 넘긴다 — 모든 행동이 같은 모양이라 권한·검증·병렬화를 구분할 수 없다. 승인이 필요한 행동, 가역성이 낮은 행동(외부 API 호출, 메시지 발송, 데이터 삭제)은 전용 도구로 승격하라. 각 도구 설명에는 다음을 명시한다.

항목 내용
언제 쓰는가 호출 트리거 조건을 서술적으로
입력 스키마 타입·필수 여부·enum
부수효과 무엇이 변경되는가
재시도 안전성 멱등(idempotent) 여부
에러 모드 실패 시 반환 형태

도구 설명에 "언제 호출하는지"를 처방적으로 적으면 최신 모델에서 호출 적중률이 측정 가능하게 올라간다.

2. 컨텍스트를 유한 자원으로 다뤄라

컨텍스트 창이 크다고 다 채우는 것은 비용·지연·집중력 손실을 부른다. 정적인 것(시스템 프롬프트, 도구 스키마)을 앞에, 동적인 것(사용자 데이터, 타임스탬프)을 뒤에 둔다. 이는 프롬프트 캐시 적중과도 직결된다 — 접두사(prefix)가 1바이트라도 바뀌면 그 뒤 캐시가 전부 무효화되므로, 안정적인 내용을 먼저 배치하는 것이 곧 비용 절감이다.

긴 실행에서는 압축(compaction), 도구 결과 비우기(tool-result clearing), 외부 메모리를 조합한다. 토큰 예산을 추정할 때는 모델별 토크나이저가 다르므로 count_tokens API로 실측해야 한다. 토큰 비용 자체를 더 깊게 다루는 형제 가이드는 LLM 토큰 비용 최적화 가이드를 참고하라.

모든 하네스 로직에는 유효기간이 있다. 모델이 강해질수록 어제 필요했던 스캐폴딩이 오늘은 과잉이 된다. 단순하고 조합 가능한 패턴을 선호하라.

human approval gate alt

3. 부수효과 경계마다 승인 루프를 둬라

삭제, 결제, 배포, 대량 파일 수정, 민감한 MCP 호출 — 이런 행동은 일시정지(pause)했다가 사람의 허가 후 재개(resume)하는 구조로 만든다. 수동 에이전트 루프에서는 stop_reason이 도구 호출을 가리킬 때 자동 실행하지 말고, 위험 도구라면 사용자 확인을 받은 뒤에야 결과를 피드백한다. 거부 시에는 "왜 거부했는지"를 모델에 돌려줘 다른 접근을 유도한다.

다음은 승인 게이트가 들어간 수동 루프의 골격이다.

# 적응형 사고 + effort로 제어 (budget_tokens 아님)
DANGEROUS = {"delete_file", "send_payment", "deploy"}

while True:
    resp = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=16000,
        thinking={"type": "adaptive"},
        output_config={"effort": "high"},  # low|medium|high|max
        tools=tools,
        messages=messages,
    )
    if resp.stop_reason == "end_turn":
        break

    messages.append({"role": "assistant", "content": resp.content})
    results = []
    for b in (x for x in resp.content if x.type == "tool_use"):
        if b.name in DANGEROUS and not human_approves(b):
            results.append({
                "type": "tool_result", "tool_use_id": b.id,
                "content": "사용자가 거부함. 다른 방법을 제안하라.",
                "is_error": True,
            })
            continue
        results.append({
            "type": "tool_result", "tool_use_id": b.id,
            "content": run_tool(b.name, b.input),
        })
    messages.append({"role": "user", "content": results})

4. 캐시를 의식한 프롬프트 순서를 지켜라

렌더 순서는 toolssystemmessages다. 안정적인 내용(고정된 시스템 프롬프트, 결정적으로 정렬된 도구 목록)을 앞에 두고, 변동 내용(타임스탬프, 요청별 ID)을 마지막 캐시 분기점 뒤에 둔다. 세션 도중 도구를 추가·제거하거나 모델을 바꾸면 캐시가 통째로 무효화되니 주의한다.

5. 서브에이전트는 진짜 필요할 때만

정책·도구·컨텍스트가 정말로 다를 때만 서브에이전트를 쓴다. 단순 작업이라면 단일 에이전트가 더 싸고 디버깅하기 쉽다. 모든 것을 멀티에이전트로 쪼개면 프롬프트·승인·트레이스 표면이 늘어나 복잡도만 커진다. 도구가 많아 스키마를 다 올리기 부담스럽다면, 멀티에이전트 대신 **도구 검색(tool search)**으로 관련 스키마만 동적으로 불러오는 편이 캐시도 보존하고 단순하다. 스킬 기반 점진적 공개 패턴은 AI 에이전트 스킬 가이드에서 더 자세히 다룬다.

흔한 오해와 실수

"bash 도구 하나면 충분하다." bash는 강력하지만 감사·권한·검증·재현성이 약하다. 가역성 낮은 행동은 전용 도구로 승격해야 통제권이 생긴다.

"프레임워크가 하네스를 알아서 처리한다." 아니다. 추적 가능한 프롬프트/도구/상태 경계는 당신의 앱 설계 몫이다. 프레임워크는 루프를 돌려줄 뿐이다.

"컨텍스트가 크니 다 넣자." 비용·지연이 늘고 모델의 집중이 흐려진다. 필요한 것만 넣고 나머지는 외부 메모리·압축으로 미룬다.

"모든 걸 멀티에이전트로 분할하자." 승인·트레이스·프롬프트 표면이 폭증한다. 단일 에이전트로 풀 수 있으면 그게 정답이다.

압축 중 결정적 정보 유실. 가장 치명적인 실수다. 압축 과정에서 확정된 결정, 리소스 ID, 미해결 블로커(open blocker), 검증 결과를 잃으면 에이전트는 같은 일을 반복하거나 거짓 진행 보고를 한다. 압축은 요약이지 폐기가 아니다 — 압축 블록을 다음 요청에 반드시 되돌려 넣어야(append response.content) 상태가 유지된다.

logging and observability alt

검증과 로깅: 재현 가능성이 신뢰의 근거다

모든 도구 호출(명령·입력·결과·승인 여부)을 트레이스로 남긴다. 토큰 사용량은 usage에서, 캐시 적중은 cache_read_input_tokens에서 확인한다. 장시간 에이전트라면 진행 주장을 도구 결과와 대조해 감사하도록 강제하면 허위 보고를 거의 없앨 수 있다. 검증 단계는 별도 컨텍스트를 가진 검증자 서브에이전트가 자기비판보다 대체로 낫다.

마무리

에이전트 하네스 엔지니어링의 핵심은 한 문장으로 압축된다. 비결정적 모델 주위를 결정적 껍질로 감싸라. 도구는 행동별로 타입을 명시해 게이팅·렌더링·감사가 가능하게 만들고, 컨텍스트는 유한 자원으로 다뤄 정적·동적을 분리하고, 부수효과 경계마다 승인 루프를 두고, 캐시를 의식해 프롬프트를 정렬하고, 서브에이전트는 정말 필요할 때만 쓴다. 그리고 압축 중에도 결정·ID·블로커·검증 결과를 결코 잃지 마라.

기억할 원칙 하나 더 — 모든 하네스 로직에는 유효기간이 있다. 모델 세대가 올라가면(현재 Claude Opus 4.8 / GPT-5.5 / Gemini 3.5 Flash) 과거의 방어적 스캐폴딩은 오히려 품질을 떨어뜨린다. 단순하고 조합 가능한 패턴을 선호하고, 마이그레이션 때마다 과잉 지시를 덜어내라. 정확성을 위해 다시 강조하면, Claude 추론은 적응형 사고 + effort로 제어하고(고정 budget_tokens 아님), 토큰은 count_tokens API로 계산한다(tiktoken 아님).

이 가이드는 Claude·OpenAI 계열·Google 계열 세 AI의 교차검증을 거쳐 벤더 중립적으로 정리했다. 다음 단계로, 스킬 기반 도구 확장은 AI 에이전트 스킬 가이드를, 토큰 비용 통제는 LLM 토큰 비용 최적화 가이드를 이어서 읽어보길 권한다. 당신의 다음 에이전트에서, 도구 하나를 골라 전용 도구로 승격하고 그 앞에 승인 게이트를 다는 것부터 시작해 보라.