NVIDIA NeMo Relay로 에이전트 하네스 추적하기: 성공률 뒤에 숨은 호출을 트레이스로 읽는 법 (feat. Hermes Agent)

핵심 요약

  • NVIDIA가 NeMo Relay로 Hermes Agent 실행을 ATOF 이벤트, ATIF 궤적, OpenTelemetry 트레이스로 기록하고 과업 검증 결과와 함께 읽는 튜토리얼과 동반 저장소를 공개했습니다.
  • 실습에는 macOS 또는 Linux, Git, curl, Docker, NVIDIA Build API 키가 필요하고, 터미널 도구 과제와 웹 검색 과제 두 개를 Hermes 0.21.1, NeMo Relay 0.8.3으로 고정해 실행합니다.
  • Nous Research의 Hermes ToolPerf 재실행(108회)에서 도구 계층 수정 후 Qwen3 Coder 30B의 성공률은 70%에서 81%로 올랐지만, 평균 LLM 호출은 3.8회에서 4.9회로, 소요 시간은 27초에서 42초로 늘었습니다.
  • 공개된 실행별 기록을 확인해 보면 Qwen 기준선의 실패 8건 중 5건은 도구가 한 번도 실행되지 않은 채 제공자 쪽 템플릿 오류로 끝났고, 이를 빼면 성공률 차이는 86%와 88%로 좁혀집니다.

NeMo Relay와 Hermes Agent 트레이싱 튜토리얼 소개

NVIDIA 기술 블로그의 Tracing Agent Harness Behavior with NVIDIA NeMo Relay 는 에이전트가 과업을 맞혔는지뿐 아니라 어떤 경로로 맞혔는지를 트레이스로 확인하는 방법을 다루는 튜토리얼입니다. 2026년 9월 30일 공개되었고, 저자는 William Markito Oliveira, Maryam Najafian, Moon Chung, Teknium 네 명입니다. 실습 코드는 NVIDIA/nemoclaw-community 저장소의 hermes-relay-tracing 예제로 함께 공개되었습니다.

원문이 출발점으로 삼는 문제는 단순합니다. 에이전트가 최종 답을 맞히더라도 그 과정에서 실패한 검색을 다시 시도하거나, 잘린 파일을 읽은 뒤 같은 내용을 명령으로 다시 가져오는 식의 추가 단계를 밟을 수 있습니다. 정답 하나만 보면 이런 단계는 보이지 않지만, 지연 시간과 토큰을 소비하고 실패할 기회도 늘립니다. 그래서 원문은 "성공 여부 확인만으로는 에이전트가 도구 오류에서 왜 회복했는지, 왜 일찍 멈췄는지, 왜 모델 호출이 더 필요했는지 설명할 수 없다" 고 말합니다.

이 글에서 말하는 에이전트 하네스(Agent Harness) 는 모델을 감싸고 프롬프트 구성, 도구 정의와 실행, 재시도, 실행 한도 같은 루프를 담당하는 코드입니다. 같은 모델이라도 하네스가 도구 오류 메시지를 어떻게 돌려주는지, 출력이 잘렸을 때 무엇을 알려주는지에 따라 행동이 달라집니다. 원문 후반부는 바로 이 하네스 변경을 평가하는 사례로, Nous Research가 Hermes Agent의 도구 계층을 고친 뒤 NeMo Relay 트레이스로 전후를 비교한 Hermes ToolPerf 결과를 소개합니다.

이 글은 원문의 실습 흐름을 따라가되, 동반 저장소의 상세 튜토리얼과 ToolPerf 저장소에 공개된 원시 결과를 함께 읽어 원문이 생략한 조건을 보충했습니다. 특히 ToolPerf 사례는 공개된 실행별 기록을 직접 확인한 결과, 원문의 해석 일부를 그대로 받아들이기 어려운 부분이 있어 별도 절에서 다룹니다. 직접 실습을 실행해 본 것은 아니며, 수치는 모두 원문과 저장소에 기록된 값입니다. AI 에이전트 평가 지표 전반은 앞서 정리한 NVIDIA의 AI 에이전트 평가 글과 함께 읽으면 좋습니다.

NeMo Relay가 하는 일: 스코프, 생명주기 이벤트, 그리고 세 가지 출력

NeMo Relay 문서는 Relay를 기존 에이전트 스택을 다시 작성하지 않고 에이전트 실행 안에서 일어나는 일을 관찰하고 제어하게 해 주는 공통 런타임(Runtime)으로 소개합니다. 세션, 턴, LLM 호출, 도구 호출, 하위 에이전트 같은 작업 단위를 스코프(Scope) 로 감싸고, 각 스코프가 시작하고 끝날 때 생명주기 이벤트(Lifecycle Event) 를 남겨 시간과 부모 자식 관계를 보존합니다. 시작과 끝이 없는 순간적 사건(세션 시작, 컨텍스트 압축, 스킬 로드 등)은 마크(Mark) 로 기록합니다. Relay는 에이전트 프레임워크나 모델 제공자, 관측 백엔드를 대체하지 않고 그 사이를 같은 이벤트 계약으로 연결하는 역할을 합니다.

튜토리얼은 관측 기능만 쓰지만, 문서상 Relay에는 도구와 LLM 호출 앞뒤에서 실행을 차단, 정제, 변환, 재시도할 수 있는 미들웨어(Middleware) 와 가드레일, 적응형 최적화를 설정으로 켜는 플러그인 구조도 있습니다. 런타임 동작의 기준은 Rust 구현이고 Python과 Node.js 바인딩이 같은 모델을 노출하며, Go와 C FFI는 실험 단계입니다. 원문이 Relay를 보안 시스템이 정책을 평가하거나 보안 플러그인을 만드는 데 쓸 증거 계층이라고 부르는 것도 이 구조 때문입니다. 저장소는 NVIDIA/NeMo-Relay이며 Apache License 2.0으로 공개되어 있습니다.

Hermes Agent는 Relay를 내장하고 있어 별도 플러그인이나 Relay CLI 없이 세션, 턴, 모델 호출, 도구 호출이 Relay 스코프 계층으로 기록됩니다. 다른 환경에서는 연결 방식이 다릅니다. 지원 통합 문서 기준으로 LangChain, LangGraph, Deep Agents는 관측, 보안, 최적화를 모두 지원하고, OpenClaw는 훅 기반이라 관측은 지원하지만 보안은 부분 지원, 최적화는 미지원입니다. Codex와 Claude Code는 Relay CLI를 로컬 사이드카로 실행하는 방식으로 관찰합니다.

ATOF, ATIF, OpenTelemetry: 같은 실행을 보는 세 가지 형식

Relay는 같은 생명주기 이벤트 스트림에서 세 가지 출력을 만듭니다. 원문 표를 정리하면 다음과 같습니다.

형식 담는 내용 쓰는 때
ATOF (Agent Trajectory Observability Format) 스코프 시작, 스코프 종료, 순간 마크를 ID와 타임스탬프와 함께 한 줄씩 기록한 JSONL 개별 이벤트, 시간, 부모 자식 관계를 디버깅하거나 감사할 때
ATIF (Agent Trajectory Interchange Format) 생명주기 이벤트를 모아 에이전트 상호작용, 도구 호출, 관찰 결과를 단계별로 정리한 JSON 에이전트의 경로를 단계별로 검토, 분석, 평가할 때
OpenTelemetry + OpenInference 실행을 부모 자식 스팬 계층으로 표현하고, OpenInference가 에이전트, LLM, 도구 스팬의 라벨과 속성을 정의 Arize Phoenix 같은 OTel 호환 도구에서 호출, 시간, 토큰, 오류를 볼 때

원문이 강조하는 실무 포인트는 ATIF와 ATOF의 차이입니다. ATIF의 도구 요청은 모델이 무엇을 실행해 달라고 했는지를 보여줄 뿐, 실제로 실행되어 성공했는지는 확인해 주지 않습니다. 실행 여부는 ATOF에서 해당 도구의 시작과 종료 이벤트, 그리고 기록된 오류를 찾아 확인해야 합니다. 두 이벤트는 같은 uuid 로 짝지어지고, parent_uuid 가 도구 호출을 상위 스코프에 연결합니다. 동반 저장소 튜토리얼은 여기에 통합이 제공하는 경우 도구 호출 식별자(tool_call_id)가 모델의 요청과 실제 실행을 이어 준다고 덧붙입니다.

동반 저장소의 최소 예제 파일에서 터미널 도구의 시작과 종료 이벤트를 보면 이 구조가 바로 보입니다. 원래는 한 줄짜리 JSONL이지만 읽기 쉽게 줄을 나눴습니다.

{"atof_version":"0.1","category":"tool","kind":"scope","name":"terminal",
 "scope_category":"start","timestamp":"2026-01-01T00:00:02+00:00",
 "uuid":"00000000-0000-0000-0000-000000000003",
 "parent_uuid":"00000000-0000-0000-0000-000000000001",
 "data":{"command":"python3 /opt/nemo-relay-hermes-tutorial/sample.py","workdir":"[tutorial workspace]"},
 "metadata":{"tool_call_id":"example-terminal-call"}}
{"atof_version":"0.1","category":"tool","kind":"scope","name":"terminal",
 "scope_category":"end","timestamp":"2026-01-01T00:00:03+00:00",
 "uuid":"00000000-0000-0000-0000-000000000003",
 "parent_uuid":"00000000-0000-0000-0000-000000000001",
 "metadata":{"otel.status_code":"OK","tool_call_id":"example-terminal-call"}}

같은 작업이 ATIF에서는 사용자 단계와 에이전트 단계 두 개로 묶이고, 에이전트 단계 안에 tool_calls 와 observation 이 들어갑니다. 사람이 읽고 평가하기에는 ATIF가 편하지만, 위 otel.status_code 처럼 실행 결과를 확정하는 정보는 ATOF 쪽에 있다는 점이 두 형식을 함께 남기는 이유입니다.

트레이스에는 설정에 따라 프롬프트, 모델 응답, 도구 인자와 결과, 파일 경로 같은 애플리케이션 데이터가 그대로 들어갈 수 있습니다. 원문과 동반 저장소 모두 공유 전에 트레이스를 검토하라고 명시합니다. 동반 저장소가 만드는 Relay 설정은 enable_full_payloads = false 라서 반복되는 LLM 시작 이벤트에는 현재 사용자 턴만 남고, 문서에 따르면 이 값과 무관하게 자격 증명 제거와 sanitizer는 적용됩니다.

NeMo Relay 더 알아보기

NeMo Relay Documentation - 설치, 개념, 설정

NeMo Relay Observability Configuration - 익스포터와 전송 대상 설정

GitHub Repository

실습 1: 터미널 도구 과제 하나로 전체 설정 검증하기

준비물은 macOS 또는 Linux, Git과 curl, 실행 중인 Docker, 그리고 NVIDIA Nemotron 3.5 Lightning 모델 페이지에서 발급한 NVIDIA Build API 키입니다. 첫 실습은 웹 검색과 Phoenix를 붙이기 전에 설정 전체를 확인하려고 일부러 작게 만든 과제입니다. Hermes가 터미널 도구로 print("VALUE=42") 한 줄짜리 Python 스크립트를 격리된 Docker 컨테이너 안에서 실행하고, 실행기가 정확히 VALUE=42 가 돌아왔는지 확인합니다. 설정 파일(config/smoke.env)상 실행 한도는 최대 8턴, 180초입니다.

이 컨테이너는 네트워크, 저장소 체크아웃, NVIDIA API 키에 접근할 수 없고, Hermes가 호스트에서 터미널 명령을 대신 실행하는 경로도 막혀 있습니다. Hermes Agent와 NeMo Relay 프로세스 자체는 저장소의 로컬 환경에서 돌고, Docker는 터미널 도구 샌드박스와 Phoenix 서비스에만 쓰입니다. 설정 스크립트는 .tutorial-runtime/ 아래에 Python 3.11, Hermes 0.21.1(GitHub 릴리스 태그 v2026.9.7), NeMo Relay 0.8.3을 담은 별도 환경을 만들며, 기존 Python이나 Hermes 설치는 건드리지 않습니다.

# Clone the tutorial repository.
git clone https://github.com/NVIDIA/nemoclaw-community

# Enter the cloned repository.
cd nemoclaw-community/examples/tools/hermes-relay-tracing

# Create the isolated Hermes Agent and NeMo Relay runtime.
./scripts/setup_tutorial_runtime.sh

# Copy the API key template.
cp keys.env.example keys.env

# Add NVIDIA_API_KEY to keys.env before continuing.

# Verify that Docker is running.
docker version

# Build the Docker image for the terminal-tool task.
./scripts/build_tutorial_image.sh

# Run the task and generate the ATOF and ATIF traces.
./scripts/run_tutorial.sh

keys.env 는 저장소가 무시하도록 설정되어 있어, 키를 이 파일에 적으면 셸 기록에 남지 않습니다. 실행기는 터미널 명령이 성공했는지, ATOF에 토큰 사용량이 포함된 완료된 LLM 스코프가 있고 도구 오류가 없는지, 비어 있지 않은 ATIF 궤적이 만들어졌는지를 확인합니다. 원문에 실린 검증된 실행 한 건의 요약은 다음과 같습니다.

ATOF summary

events: 74
completed llm scopes: 2
llm scopes with usage: 2
prompt tokens: 7239
completion tokens: 96
total tokens: 7335
tool calls: 1
tool errors: 0
correlated events: 74

ATIF summary

agent: Hermes Agent
model: nvidia/nemotron-3.5-lightning-30b-a3b
steps: 3
llm calls: 2
requested tool calls: 1

Task verified: VALUE=42
Artifacts: .../artifacts/runs/<run-id>

스크립트 하나를 실행하는 과제에도 모델 호출 2회, 이벤트 74개, 프롬프트 토큰 7,239개가 기록됩니다. 출력 토큰은 96개뿐이라 이 과제의 비용 대부분은 입력, 즉 시스템 프롬프트와 도구 정의에서 나온다는 점을 숫자로 확인할 수 있습니다. 토큰 수와 식별자, 경로는 실행마다 달라집니다. 저장된 실행은 다음처럼 다시 요약할 수 있습니다.

HERMES_PYTHON=".tutorial-runtime/venv/bin/python"
RUN_DIRECTORY="artifacts/runs/<timestamp-pid>"
"$HERMES_PYTHON" scripts/summarize_atof.py \
  "$RUN_DIRECTORY/atof/run.jsonl" \
  --require-token-usage
"$HERMES_PYTHON" scripts/summarize_atif.py \
  "$RUN_DIRECTORY"/atif/trajectory-*.json

원문에는 3분 51초 길이의 워크스루 영상도 실려 있습니다. 영상 설명에 따르면 영상은 위 두 실습이 아니라 Hermes가 README와 Python 파일을 읽고 코드를 평가해 답하는 별도 워크플로를 Phoenix에서 따라가며, 트레이스가 기기를 떠나기 전에 sanitizer가 개인 식별 정보를 지우는 모습도 보여줍니다.

실습 2: 파일과 웹을 오가는 학회 찾기 과제를 Phoenix로 보기

두 번째 과제는 여러 도구를 쓰는 조사 과제입니다. 동반 저장소 튜토리얼의 설정에 따르면, 2026년 6월 29일부터 7월 3일까지 샌디에이고에 머물면서 머신러닝 이론 학회에 참석하고 싶은 상황입니다. 여행 계획 파일에는 날짜, 장소, 주제만 있고 학회 이름은 빠져 있습니다. Hermes는 read_file 로 계획을 읽고, web_search 와 web_extract 로 맞는 학회를 찾아 공식 웹사이트에서 날짜와 장소를 확인한 뒤, write_file 로 보고서를 저장하고 학회 이름을 답해야 합니다. 실행 한도는 최대 12턴, 300초입니다.

./scripts/run_conference_research_with_phoenix.sh

이 실습에서는 Relay의 OpenInference 익스포터가 OpenTelemetry 스팬을 OTLP(OpenTelemetry Protocol)로 로컬 Phoenix 컨테이너에 보냅니다. Phoenix는 저장된 ATOF나 ATIF 파일을 읽는 것이 아니라 OTLP로 트레이스를 직접 받습니다. 엔드포인트와 인증 설정만 바꾸면 LangSmith 같은 다른 OTLP 호환 백엔드로도 보낼 수 있습니다. 웹 검색은 Hermes에 내장된 키 없는 검색을 쓰므로 별도 검색 자격 증명은 필요 없지만, 공개 검색 서비스라 요청이 속도 제한에 걸리면 과제가 실패할 수 있습니다. Phoenix는 기본 6006 포트를 쓰고, 이미 쓰고 있다면 PHOENIX_UI_PORT=6007 처럼 바꿔 실행합니다.

실행기는 성공을 보고하기 전에 다음을 모두 확인합니다.

  • 최종 답이 COLT 2026 인지
  • 저장된 보고서에 COLT 2026, 2026년 6월 29일부터 7월 3일, 샌디에이고, 그리고 공식 learningtheory.org 출처가 들어 있는지
  • ATOF에 read_file, web_search, web_extract, write_file 호출이 성공으로 기록되었는지
  • 비어 있지 않은 ATIF 궤적이 만들어졌는지
  • Phoenix가 모델과 도구 스팬을 받았고 토큰 합계가 양수인지

원문 그림 1은 Nemotron 3.5 Lightning으로 실행한 트레이스입니다(아래 표의 46.3초 실행과는 다른 실행으로, 화면상 지연은 33.9초). 왼쪽 트리에서 hermes.session 아래 hermes.turn 이 있고, 그 안에 모델 호출 5회와 도구 호출 4회가 번갈아 나옵니다. 오른쪽은 첫 모델 호출로, 여행 기록을 읽고 웹에서 조건에 맞는 학회를 찾아 공식 사이트에서 확인한 뒤 보고서를 쓰라는 사용자 요청과, 모델이 그 응답으로 요청한 read_file 호출이 보입니다. 모델 호출 옆 토큰 수가 4,400에서 10,714까지 커지는 것은 도구 결과가 대화에 누적되기 때문으로 읽을 수 있습니다.

동반 저장소 튜토리얼은 Phoenix에서 트레이스를 읽는 순서도 제안합니다. 먼저 첫 모델 호출과 마지막 모델 호출을 보고, 그 사이 호출을 순서대로 엽니다. 모델 호출에서는 Hermes가 보낸 요청과 모델 응답, 요청된 도구 호출을 보고, 도구 호출에서는 모델이 만든 인자와 도구가 돌려준 결과를 봅니다. 실패한 실행이라면 마지막으로 완료된 스팬에서 오류, 빠진 도구 호출, 예상과 다른 결과를 찾습니다. 토큰이나 시간이 두드러지는 호출이 있으면 요청에 반복된 컨텍스트가 있는지, 앞뒤 도구 호출에 중복 작업이나 오류가 있는지 확인하되, "크거나 느린 호출은 조사할 가치가 있지만 자동으로 비효율인 것은 아니다" 라고 덧붙입니다.

다른 모델로 같은 과제를 돌려 보기

과제, 도구, 실행 한도, 검증기를 그대로 두고 모델만 바꿔 실행 경로가 어떻게 달라지는지 볼 수 있습니다. config/model_profile.env.example 을 model-profile.env 로 복사해 모델, 엔드포인트, API 모드, 키 환경 변수 이름을 적고 --model-profile model-profile.env 를 붙여 실행합니다. 지원하는 API 모드는 Hermes가 제공하는 chat_completions, anthropic_messages, codex_responses 이고, 엔드포인트가 도구 사용을 지원해야 합니다.

동반 저장소에는 두 모델의 검증된 실행 결과가 JSON으로 남아 있습니다.

항목 Nemotron 3.5 Lightning Claude Sonnet 5
검증 결과 통과 (COLT 2026) 통과 (COLT 2026)
모델 호출 / 도구 호출 / 도구 오류 5 / 4 / 0 5 / 5 / 0
총 토큰 31,554 60,059
소요 시간 46.3초 23.5초 (Phoenix 화면 기준)
Phoenix 추정 비용 가격 정보 없음 $0.053960
실행 환경 Hermes 0.21.1, Relay 0.8.3 (2026-09-11) Hermes 0.20.5, Relay 0.7.2 (2026-09-04)

Claude Sonnet 5 트레이스에서는 web_search 가 두 번 호출되어 도구 호출이 하나 더 많습니다. 다만 이 표를 모델 비교로 읽으면 안 됩니다. 원문도 실시간 웹 검색을 쓰는 실행이므로 모델 순위를 매기지 말고 행동을 탐색하는 데 쓰라고 하고, 통제된 비교에는 고정된 검색 응답과 반복 실행이 필요하다고 말합니다. 여기에 더해, 두 결과 파일을 열어 보면 Sonnet 5 실행은 Hermes 0.20.5와 Relay 0.7.2에서, Nemotron 실행은 Hermes 0.21.1과 Relay 0.8.3에서 기록되어 하네스 버전부터 다릅니다. 시스템 프롬프트와 도구 정의가 바뀌면 입력 토큰도 바뀌므로, 토큰 수 차이를 모델 차이로만 돌리기도 어렵습니다.

실습이 끝나면 ./scripts/stop_phoenix.sh 로 Phoenix 컨테이너를 정리합니다.

실습 도구 더 알아보기

Companion Tutorial Repository - 실행 가능한 과제, 검증기, Relay 설정, Phoenix 설정

Hermes Agent Documentation

Arize Phoenix

트레이스로 하네스 변경을 평가하는 여섯 단계

두 실습은 결과 하나를 검증하고 실행 하나를 살펴보는 방법입니다. 프롬프트, 도구, 설정, 하네스를 바꾼 것이 정말 개선인지 판단하려면 같은 검사를 통제된 조건에서 반복해야 합니다. 원문이 제시하는 절차는 다음과 같습니다.

  1. 정확하고 자동화된 성공 판정이 있는 고정 과제를 고릅니다.
  2. 기준선과, 프롬프트나 도구나 설정이나 하네스에 대한 하나의 집중된 변경을 정의합니다.
  3. 그 변경 외의 모든 것, 즉 모델 스냅샷, 제공자, 과제 입력, 실행 예산, 타임아웃을 고정합니다.
  4. 기준선과 후보를 NeMo Relay를 켠 상태로 같은 횟수만큼 반복 실행합니다.
  5. 먼저 검증된 과제 결과를 비교하고, 그다음 트레이스로 모델 호출, 도구 호출, 재시도, 오류, 소요 시간, 토큰, 비용을 살핍니다.
  6. 결과를 일반화하기 전에 그 변경이 지원해야 할 다른 모델이나 워크로드에서 평가를 반복합니다.

판정 기준도 명확합니다. 과제 완수율이 반복 가능하게 오르거나, 완수율을 유지하면서 목표로 한 신뢰성, 지연, 비용 지표가 개선될 때만 개선이라고 부릅니다. "한 번 더 빠른 실행이나 더 적은 호출은 결과를 설명하는 데 도움이 되지만, 그 자체로 최적화를 입증하지는 않는다" 는 것이 원문의 표현입니다. 동반 저장소는 여기에 공급자가 지원하면 시드와 샘플링 설정도 재사용하라고 덧붙이고, 실습 2를 A/B 테스트에 쓰려면 검색 응답을 캡처해 두 버전에 같은 응답을 주라고 말합니다. 바뀌지 않은 결과도 유용한데, 겉보기 개선이 특정 모델이나 환경, 표본에 기대고 있었음을 보여줄 수 있기 때문입니다.

Hermes ToolPerf 사례: 성공률은 오르고 호출은 늘었다

원문의 사례 연구는 Nous Research가 만든 Hermes ToolPerf 벤치마크입니다. 저장소 README에 따르면 운영 세션 DB 약 150만 개 메시지를 분석하고 도구 스키마의 토큰 비용을 감사한 뒤, NeMo Relay ATOF 트레이스를 턴 수 집계의 기준값으로 써서 만들었습니다. 운영 로그에서 찾은 실패 유형 9개를 각각 샌드박스와 결정적 성공 표식을 가진 벤치마크 과제로 바꿨고, 이를 Hermes Agent 도구 계층 수정 묶음(README 기준 15개 PR과 통합 수정 1건, 추적 이슈 #77056)의 전후 비교에 썼습니다.

재실행 조건과 전체 결과

원문이 인용하는 것은 2026년 8월 6일 재실행 결과입니다. 재실행 README에 적힌 조건은 원문보다 구체적입니다.

  • 기준선은 hermes-agent 5b4d20b524(수정 묶음 직전 커밋), 수정본은 f01c193be4(마지막 도구 수정 커밋)로 SHA를 고정했습니다.
  • 모델은 anthropic/claude-sonnet-4.5 와 qwen/qwen3-coder-30b-a3b-instruct 이고, 둘 다 OpenRouter를 거쳐 호출했습니다.
  • 과제 9개를 모델별, 버전별로 3회씩 돌려 총 108회이며, --max-turns 30, 타임아웃 600초를 적용했습니다.
모델 버전 과제 성공 평균 LLM 호출 평균 도구 호출 평균 도구 결과 데이터 평균 소요 시간
Claude Sonnet 4.5 기준선 24/27 (89%) 2.9 2.2 17 KB 16초
Claude Sonnet 4.5 수정본 23/27 (85%) 2.8 2.1 17 KB 22초
Qwen3 Coder 30B 기준선 19/27 (70%) 3.8 2.8 16 KB 27초
Qwen3 Coder 30B 수정본 22/27 (81%) 4.9 3.9 33 KB 42초

원문은 Sonnet에서는 실질적인 변화가 없었고(27회 중 한 번 차이), Qwen에서는 수정이 효과를 냈지만 대가가 따랐다고 해석합니다. 성공은 3건 늘었지만 LLM 호출, 도구 호출, 도구 결과 데이터, 소요 시간이 모두 늘어 더 느리고 호출이 많은 에이전트가 되었다는 것입니다. 원문은 과제별로 세 가지를 짚습니다.

  • 차단된 명령 과제(err_inline_script): 기준선 Qwen은 파서 차단에서 멈춰 33%였고, 차단된 명령 오류에 복구 방법을 덧붙인 수정(#77017) 덕분에 수정본은 100%가 되었다고 설명합니다. 원문은 복구에는 포기할 때보다 턴이 더 든다며 이것을 턴 수 증가의 이유로 듭니다.
  • 대소문자 무시 검색 과제(err_case_search): 일치 0건 안내 출력이 Qwen을 추가 탐색 검색으로 몰아, 3회 중 2회에서 턴이 3.3에서 9.3으로 늘어난 회귀입니다.
  • 숨김 파일 검색 과제(err_hidden_search): 두 모델, 두 버전 모두 0~33%에 머물러, 원래 실행에서 발견된 빈틈이 이 SHA에서도 열려 있습니다.

공개된 원시 기록으로 다시 읽은 결과

원문은 트레이스가 결과 디렉터리에 커밋되어 있어 누구나 원시 기록에서 표를 다시 만들 수 있다고 말합니다. 그래서 같은 디렉터리의 과제별 표(report.txt)와 실행별 기록(meta.jsonl)을 직접 열어 봤습니다. 같은 디렉터리의 ATOF 트레이스 압축본(약 28MB)도 풀어 실행별 도구 스코프를 셌습니다. 원문과 결론이 갈리는 지점이 두 군데 있습니다.

첫째, Qwen 성공률 상승의 대부분은 도구가 실행되기 전에 끝난 실행에서 나옵니다. 재실행 README는 Qwen 실행 중 기준선 5회와 수정본 2회가 최종 출력에 날것의 <function=...> XML을 남긴 채 끝났고, 이는 "OpenRouter의 채팅 템플릿 파손으로 어느 쪽 버전과도 무관하며, 양쪽 Qwen 성공률을 깎는다" 고 적어 두었습니다. meta.jsonl 에서 이 7회가 어느 과제인지 확인하면 다음과 같습니다.

과제 (Qwen) 기준선 성공 기준선 실패 중 XML 종료 수정본 성공 수정본 실패 중 XML 종료
err_inline_script 1/3 2 3/3 0
err_big_output 0/3 3 1/3 2
err_big_file_read 2/3 0 3/3 0
err_hidden_search 1/3 0 0/3 0
9개 과제 합계 19/27 5 22/27 2

err_inline_script 기준선의 실패 2회는 모두 모델이 python3 -c 한 줄 명령을 담은 도구 호출을 텍스트로 출력한 채 첫 응답에서 끝났습니다. 두 실행의 ATOF 트레이스에는 도구 스코프가 하나도 없고 LLM 호출도 1회뿐입니다. 즉 이 두 번의 실패에서는 명령이 실행되지 않았으므로 파서 차단도 일어나지 않았습니다. 수정본 3회는 ATOF 기준 각각 terminal 1회를 상태 OK로 실행하고 성공해, 차단 후 복구하는 경로를 탄 실행도 없습니다. err_big_output 기준선 3회도 ATOF에 도구 스코프가 없어, Nous Research가 재실행 README에서 설명한 잘린 출력에서 포기하는 상황보다 앞 단계에서 스크립트가 실행되지 않았습니다. 원문의 설명대로라면 기준선은 차단이나 잘림을 만나고 실패했어야 하지만, 기록은 그 단계에 도달하지 못했음을 보여줍니다.

108회 전체에서 도구 스코프가 0개인 실행은 정확히 이 XML 종료 7회뿐이었습니다. 재실행 README의 판단대로 이 7회를 버전과 무관한 제공자 잡음으로 보고 빼면, Qwen 성공률은 기준선 19/22(86%), 수정본 22/25(88%)로 차이가 거의 사라집니다. 반대로 수정본에 포함된 도구 스키마 축소가 템플릿 파손 빈도에 영향을 줬을 가능성도 이 기록만으로는 배제할 수 없습니다. 어느 쪽이든 공개 데이터가 지지하는 결론은 복구 레시피가 포기하던 과제를 완수로 바꿨다는 것보다는, 이 실행에서는 제공자 쪽 오류와 수정 효과를 구분할 수 없다는 것에 가깝습니다. 성공 여부만으로는 이유를 알 수 없다는 원문 앞부분의 주장이 원문 자신의 사례에도 그대로 적용되는 셈입니다.

둘째, 늘어난 턴의 가장 큰 몫은 회귀에서 나옵니다. 원문은 "Qwen의 추가 턴은 허둥댐이 아니라 복구였다" 고 쓰지만, 과제별 평균 LLM 호출의 변화를 더하면 9개 과제 합계 약 9.7회 증가(평균 3.8회에서 4.9회) 가운데 err_case_search 회귀 하나가 6.0회로 약 62%를 차지합니다. 그다음은 err_big_file_read 의 3.0회인데, 재실행 README도 이 과제에서 Qwen이 필요 이상으로 파일을 다시 읽는다고 적었습니다. 평균 소요 시간 증가(27초에서 42초) 역시 err_big_file_read 가 128초에서 212초로 늘어난 영향이 가장 큽니다. 아래 계산은 report.txt 의 과제별 평균 LLM 호출을 그대로 뺀 값입니다.

과제 (Qwen) 기준선 LLM 호출 수정본 LLM 호출 변화
err_case_search 3.3 9.3 +6.0
err_big_file_read 7.3 10.3 +3.0
err_big_output 1.0 3.0 +2.0
err_inline_script 1.3 2.0 +0.7
err_python_env 5.7 4.3 -1.4
나머지 4개 과제 -0.6
합계 약 +9.7

8월 2일 발표 수치와 재실행의 차이

한 가지 맥락을 더 알아 두면 좋습니다. ToolPerf 저장소 README 상단의 대표 수치는 지금도 약한 모델 기준 "LLM 턴 21% 감소, 도구 호출 29% 감소, 도구 오류와 오류 후 재시도 0, 컨텍스트로 들어가는 결과 바이트 33% 감소, 실제 소요 시간 23% 감소" 입니다. 이는 8월 2일 발표된 실행의 수치이고, 그 실행의 원시 트레이스는 /tmp 와 함께 사라졌다고 README에 적혀 있습니다. 8월 6일 재실행 README는 결과 해석 절의 제목부터 "이 재실행은 8월 2일 수치를 단순히 재현하지 않는다" 이고, 약한 모델이 더 빨라진 것이 아니라 더 많이 성공하면서 턴을 더 썼다고 정리합니다. 두 실행이 합의하는 것은 강한 모델은 차이가 없다는 점, 숨김 파일 검색의 빈틈이 실재한다는 점, 그리고 스키마 축소 같은 상시 개선은 이 벤치마크로 측정되지 않는다는 점입니다.

NVIDIA 원문은 재현 가능한 8월 6일 데이터를 인용했다는 점에서 올바른 선택을 했고, 원문이 앞에서 제시한 평가 절차를 그대로 적용하면 위의 질문들이 자연스럽게 나옵니다. 각 과제 3회, 모델 2개라는 표본 크기도 함께 고려해야 합니다. ToolPerf README도 n=3에서 몇 퍼센트 이하의 차이는 잡음으로 보라고 적고 있습니다.

자기 하네스에 적용할 때 확인할 것

이 튜토리얼이 실제로 주는 것은 Relay라는 도구보다 하네스 변경을 다루는 습관에 가깝습니다. 검증기로 결과를 먼저 판정하고, 트레이스로 그 결과가 나온 경로를 확인하며, 하나만 바꿔 같은 조건에서 반복하는 절차는 Relay가 아닌 다른 관측 도구를 쓰더라도 그대로 적용됩니다. Relay를 쓰면 ATOF, ATIF, OpenTelemetry를 같은 이벤트에서 얻을 수 있어 사람이 읽는 궤적과 실행을 확정하는 이벤트를 따로 맞출 필요가 없다는 점이 장점입니다.

다만 직접 적용할 때 몇 가지를 확인해야 합니다. 튜토리얼은 NeMo Relay 0.8.3에 고정되어 있지만, GitHub 릴리스 기준 최신 버전은 2026년 9월 28일의 0.9.3이므로 설정 형식이 문서와 다를 수 있습니다. Hermes Agent 외의 프레임워크는 지원 통합 표에서 관측, 보안, 최적화 지원 범위가 다릅니다. 트레이스에는 프롬프트와 도구 결과가 그대로 남을 수 있으니 저장과 공유 전에 내용을 검토해야 합니다. 그리고 ToolPerf 사례에서 본 것처럼, 공개 API 게이트웨이를 거쳐 모델을 호출하는 평가에서는 제공자 쪽 오류가 실패로 집계될 수 있으므로, 실패 실행이 실제로 어느 단계에서 끝났는지를 트레이스와 최종 출력으로 확인한 뒤 수정 효과를 판단하는 편이 안전합니다.

라이선스

동반 튜토리얼이 들어 있는 nemoclaw-community 저장소와 NeMo Relay는 Apache License 2.0으로 배포되어, 연구 목적은 물론 상업적 용도로도 자유롭게 사용 및 수정이 가능합니다. Hermes Agent 저장소는 MIT 라이선스입니다. Hermes ToolPerf 저장소에는 2026년 10월 1일 기준 라이선스 파일이 없으므로, 결과 데이터와 코드를 재사용하려면 저작권자에게 확인하는 것이 안전합니다.

:scroll: Tracing Agent Harness Behavior with NVIDIA NeMo Relay 소개 블로그

:tv: How to Trace and Evaluate a Hermes Agent with NVIDIA NeMo Relay and Phoenix YouTube 영상

:github: hermes-relay-tracing 동반 튜토리얼 GitHub 저장소

:github: NeMo Relay GitHub 저장소

:github: Hermes ToolPerf GitHub 저장소

더 읽어보기




이 글은 GPT 모델로 정리한 초안을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 댓글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:에서 이런 글들을 계속 정리하고 있습니다. 회원 가입으로 주요 글들을 이메일:love_letter:로, 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로 새 글 알림을 받아보세요! :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: