추적 파일(Trace File)의 형태가 갖춰지기 전까지는 다음 시도를 거부하라
요약
에이전트 시스템에서 다음 단계로 진행하기 전에 '추적 파일(Trace File)'의 구조적 완전성을 검증하는 것이 필수적입니다. 추적 파일을 단순한 실행 로그가 아닌, 라벨과 봉인이 갖춰진 포장 목록처럼 취급해야 합니다. 이 형태 검사(Shape Check)는 모델 호출 낭비를 막고 시스템 안정성을 높이는 핵심 방어 기제입니다.
핵심 포인트
- 추적 파일은 단순히 실행 결과가 아니라 구조화된 '포장 목록'으로 간주해야 함.
- 핵심 필드(Trace ID, Unique Span IDs, Parent Links 등)의 존재 여부가 필수적인 형태 검사 기준임.
- 누락된 필드는 경고가 아닌 시스템 종료 코드(Exit Code)로 처리되어야 함.
- 에이전트 시도는 추적 파일의 닫힌 형태(closed shape)가 갖춰질 때까지는 비용으로 간주해야 함.
두 번째 에이전트 시도는 진단이 아니라 비용이다. 첫 번째 추적 파일에 닫힌 형태(closed shape)가 갖춰질 때까지는 말이다. 요약 라인에서 실행이 완료되었다고 할 수 있지만, 그 문장만으로는 근본적인 범위(root span)가 존재하는지, 각 도구 호출(tool call)에 자식 요소(child)가 있는지, 또는 오류가 나중에 그룹화할 수 있는 유형(type)을 담고 있는지를 증명하지 못한다. 추적 파일을 포장 목록(packing list)으로 취급하라. 라벨이 없으면 다른 선적품을 주문해서는 안 된다.
디버그 루프는 아티팩트들이 ID를 공유하지 않으면 조용히 실패한다. 모델은 단락을 반환하고, 도구 로그에는 명령어가 표시되며, 작업 트리(working tree)가 변경될 수 있지만, 이 세 가지 중 어느 것도 범위(span)가 아니다. 다음 호출은 새로운 이야기를 시작하며, 당신은 그것이 동일한 도구를 재시도했는지, 건너뛰었는지, 아니면 세 번째 경로를 발명했는지 알 수 없다. 형태 검사(shape check)는 그 호출 앞에 위치한다: 이것은 패치(patch)가 올바른지 여부를 결정하는 것이 아니라, 단지 실행 자체가 비교 가능한지(comparable)만을 결정할 뿐이다.
형태(Shape)는 화물이 아니라 포장 목록이다. 창고 직원은 모든 품목을 열어보지 않고도 상자에 라벨과 무게, 봉인(seal)이 되어 있는지 확인할 수 있다. 추적 ID의 존재, 고유 범위 ID(unique span ids), 부모 링크(parent links), 음수가 아닌 지속 시간(non-negative duration), 도구 이름(tool name), 그리고 입력 해시(input hash)가 바로 그 봉인이 된다. 이 해시가 수정하려 했던 파일과 일치하는지는 나중의 질문이며, 이 둘을 혼동하는 것이 팀이 누락된 필드 때문에 모델 호출을 낭비하는 방식이다.
계약 조건을 한 가지 이유로 실패할 만큼 작게 유지하라: 파일 하나, 추적 ID 하나, 부모가 비어 있는 정확히 하나의 루트(root), 그리고 모든 다른 범위는 해당 파일에 존재하는 부모를 가리켜야 한다. 범위 ID는 반복되지 않으며, end_ns는 최소한 start_ns보다 커야 하는데, 이는 여러 기계 간의 순서를 확인하는 것이 아니라 단일 범위 자체의 시계 값만을 확인한다. tool. 접두사로 이름 붙여진 범위는 tool.name과 input.sha256을 포함하며, error 상태는 exception 이벤트나 error.type 속성을 포함하고, 루트는 run.id를 포함한다. 누락된 필드는 경고 메시지로 지나치는 것이 아니라 종료 코드(exit code)이다.
종료 코드 2는 실패한 테스트가 배포를 중단시키는 방식처럼 셸을 중지시켜야 합니다. 경고(warning)는 다음 단계가 실행되도록 허용하며, 그 다음 단계가 바로 보호하려 했던 모델 호출입니다. 종료 코드 0은 파일을 나중에 시도에 합칠 수 있다는 의미일 뿐입니다. 에이전트가 버그를 수정했다거나 원격 컬렉터가 동일한 바이트를 가지고 있다는 것을 의미하지 않습니다.
아래의 검사기는 제안된 로컬 도구입니다. 타이밍을 측정하거나 벤치마크는 아닙니다. OTLP protobuf 대신 간소화된 JSON 내보내기(export) 파일을 읽습니다. 만약 트레이서가 이미 OTLP JSON을 작성한다면, spanId, parentSpanId, 그리고 startTimeUnixNano를 짧은 어댑터에서 매핑한 다음, 게이트 자체는 단순하게 유지하세요. 실행당 하나의 실패 이유만 있으면 됩니다.
#!/usr/bin/env python3
"""제안된 트레이스 형태 게이트. 미실행 예시; 이름을 내보내기 도구(exporter)에 맞게 조정하세요."""
import hashlib, json, sys
...
스크립트 옆에 픽스처(fixture)를 커밋하여 에이전트 없이도 게이트를 테스트할 수 있게 하세요. 루트는 run.id가 필요하고, 도구 스팬은 16진수 형식의 input.sha256, 상태(status) error, 그리고 error.type을 timeout과 같은 값으로 설정해야 합니다. python3 trace_shape.py fixture.json은 하나의 shape_ok 줄을 출력하고 종료 코드 0으로 끝나야 하며, input.sha256를 복사하여 제거한 후에는 종료 코드 2가 나와야 합니다. 만약 손상된 사본이 여전히 0으로 종료된다면, 그 게이트는 장식적이며 어떤 모델 호출 앞에도 위치해서는 안 됩니다.
python3 trace_shape.py fixture.json; echo "pass:$?"
python3 - <<'PY'
import json
...
픽스처 자체는 30줄을 넘지 않게 유지할 수 있습니다. 루트 규칙과 도구 규칙을 증명하기에는 두 개의 스팬만 충분합니다. 세 번째 스팬은 나중에 두 번째 도구가 있을 때만 추가하세요. 파일이 진지해 보이도록 만들기 위해 존재하는 추가적인 스팬들은 검사기를 무시하도록 훈련시킬 것입니다.
{
"trace_id": "4f0c9a11c0de4b0a9c11aa00bb11cc22",
"spans": [
...
로컬 재현(local replay)을 위해 여전히 본문이 필요한 경우, 원시 도구 인자(raw tool argument)를 해당 해시로 키를 지정하여 스팬 외부(outside the span)에 저장하십시오. 이 게이트는 오직 해시 필드가 존재하는지 여부만 확인하며 재계산하지 않습니다. 왜냐하면 본문은 이 파일에 없기 때문입니다. 재계산은 다른 스크립트에서 수행되어야 하므로, 마스킹 변경(redaction change)을 에이전트 변경으로 오인해서는 안 됩니다. 성공 시 출력되는 id_hash는 파일 순서상의 스팬 ID의 지문(fingerprint)일 뿐이며, CI 로그에 유용합니다. 그리고 스팬을 다르게 정렬하면 이 값은 변경됩니다.
행동 차이 분석(behavioral diff)은 두 번째 단계이며, 두 파일 모두 통과할 때까지 기다려야 합니다. 이때 이름(names), 상태 코드(status codes), 그리고 input.sha256 값을 비교합니다. 두 번째 파일에만 존재하는 이름은 새로운 도구 호출(new tool call)을 의미하며, 동일한 도구 이름 아래에서 해시가 변경된 것은 새로운 인자(new argument)를 의미합니다. 게이트를 통과하지 못한 두 파일을 비교하면 부재 목록(table of absences)이 깔끔하게 생성되지만, 이는 분석처럼 느껴질 뿐 실제 분석은 아닙니다. 이 게이트는 의도적으로 그 비교보다 앞서 멈춥니다.
수집기(collector)가 이미 동일한 스키마를 강제하고 에이전트가 로컬 파일을 내보낼 수 없는 경우에는 이 접근 방식을 건너뛰십시오. 왜냐하면 더 약한 두 번째 게이트는 첫 번째 게이트와 벗어나게 될 것이기 때문입니다. 샘플링된 프로덕션 트래픽(sampled production traffic)의 경우에도 건너뛰십시오. 도구 자식 요소(tool children)를 누락시키는 샘플러는 검사기(checker)가 실패하는 실행을 만들 것이며, 종료 코드는 샘플링 결정에 대해 계측(instrumentation) 탓을 하게 될 것입니다. 만약 종료 코드 0이 작동 중인 작업 트리(working tree)가 정확하다는 증거로 누군가에게 보여질 수 없다면 건너뛰십시오. 왜냐하면 잘 구성된 추적 파일만으로도 잘못된 편집을 설명할 수 있기 때문입니다. 도구 인자의 해시조차 유지할 수 없다면 건너뛰십시오. 왜냐하면 그 해시는 여전히 조인 키(join key)이며, 조인 키는 소유자(owner)와 보존 규칙(retention rule)이 필요하기 때문입니다.
공개(Disclosure): 이 문서는 MonkeyCode의 제품 홍보 활동의 일환으로 작성되었습니다. 무료 모델 접근은 단지 형태가 없는 재시도(retry)가 낭비할 예산으로서만 중요하며, 무료 서버 옵션은 trace_shape.py가 이미 로컬 파일에 전달한 이후의 나중 내보내기 대상일 뿐이므로, 수집기 설정과 에이전트 동작은 같은 시간 안에 디버깅되지 않습니다. 모델 이름, 할당량(quota), 하드웨어 크기 또는 보존 기간은 언급하지 않았는데, 이는 이 초안에 대해 어느 것도 검증되지 않았기 때문입니다. 만약 그 서버가 연결할 수 없다면, JSON을 유지하십시오. 왜냐하면 결코 도착하지 않을 원격 배치(remote batch)는 로컬 패스(local pass)를 생성하거나 삭제하지 않기 때문입니다. 파일이 준비되면, 체크된 파일이 기록의 출처로 남아있는 한, 그 무료 접근은 다음 시도를 위한 합리적인 장소입니다.
루프는 의도적으로 짧게 유지됩니다: 하나의 JSON 파일을 방출하고, 형태 스크립트(shape script)를 실행하며, 깨진 고정 장치(fixture)가 2로 종료되고 실제 파일이 0으로 종료될 때까지 계측(instrumentation)을 수리합니다. 그런 다음, 그리고 오직 그때만, 또 다른 모델 호출에 자원을 사용하십시오. 요약 라인은 기다릴 수 있습니다. 패킹 리스트는 기다릴 수 없습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기