verifier 기준으로 나눈 세 Skill을 하나의 현금흐름 분석 하네스로 이은 3주차 실습(에이전트 하네스 3주차)

한 줄 요약

2주차에 journal-noncash-analysis Umbrella 아래 분리했던 일반 현금화 추적과 업무별 소멸 예외 판정을, 3주차에는 Trigger → Context → Route → Gate → Proof → Verdict → Approval/Repair가 있는 하나의 workflow 하네스로 연결했다. 정상 흐름을 실행한 뒤 사업장 식별자가 빠진 시간주차비 반제를 의도적으로 넣어 잘못된 자동 소멸을 확인했고, 예외 규칙 한 곳만 수리한 뒤 같은 기준과 같은 입력으로 재평가했다.

이런 분께 추천

  • Skill을 여러 개로 나눈 다음 실제로 어떤 순서로 연결해야 할지 막힌 분

  • “스크립트가 실행됐다”와 “업무 기준을 통과했다”를 분리하고 싶은 분

  • 실패했을 때 전체를 다시 만들지 않고 실패 소유자만 찾아 고치고 싶은 분

  • 자동 판정과 사람 검토의 경계를 명시적으로 남기고 싶은 분

2주차에서 이어진 출발점

2주차에는 하나의 현금흐름 분석 Skill을 verifier 차이로 나눴다.

journal-noncash-analysis              # Umbrella·Router
├─ journal-cash-path-tracer           # 일반 직접·간접 현금화 추적
└─ journal-extinction-exception-rules # 시간주차비·내국신용장 소멸 판정

Circuit도 이미 있었다.

전체 분개장 행
→ 일반 현금화 추적
→ unmatched_target_rows
→ 업무별 소멸 예외 판정
→ 순수 비현금 또는 human_review
→ 금액 보존·중복 소유 검증

하지만 여기까지는 잘 나뉜 실행 조각과 연결 코드에 가까웠다. 언제 시작해야 하는지, 어떤 입력을 믿어야 하는지, 어떤 결과는 자동 완료하면 안 되는지, 실패했을 때 어디만 고쳐야 하는지가 하나의 실행 계약으로 묶여 있지는 않았다.

2주차의 질문이 “어디를 나눌 것인가?”였다면, 3주차의 질문은 다음과 같았다.

나눈 조각을 어떤 조건과 순서로 움직이고, 무엇을 보고 끝났다고 말할 것인가?

사용한 도구

  • Hermes Agent v0.20.0

  • Python 3.11 표준 라이브러리

  • unittest

  • W2에서 만든 learner-owned working copy

  • JSON 실행 영수증과 회귀 테스트

핵심 개념

1. Tree는 주소록이고 Harness는 실행 계약이다

2주차 Tree는 어떤 Skill이 있고 누가 어떤 책임을 소유하는지 보여줬다. 3주차 Harness는 그 조각들이 실제 요청에서 어떻게 움직이는지를 정했다.

Trigger
→ Context 검사
→ journal-cash-path-tracer
→ unmatched_target_rows
→ journal-extinction-exception-rules
→ 최종 verifier
→ PASS 또는 human_review

Tree만 있으면 “무엇이 있는가”는 알 수 있지만, “언제 무엇을 부르고 어디서 멈추는가”는 알기 어렵다. 그래서 Tree 위에 Route, Criteria, Approval, Repair를 붙였다.

2. 실행 성공과 업무 완료는 다르다

Python 함수가 예외 없이 반환돼도 업무적으로 틀릴 수 있다. 이번 실험에서도 금액 보존과 중복 소유 검사는 통과했지만, 사업장 식별자가 없는 두 행을 같은 사업장으로 간주해 자동 소멸시키는 문제가 있었다.

따라서 최종 Gate를 네 항목으로 고정했다.

criteria:
  amount_conservation: true
  no_duplicate_owner: true
  missing_business_unit_never_extinguished: true
  known_exception_missing_unit_goes_to_human_review: true

네 항목이 모두 참이어야만 PASS로 판정했다.

3. 실패는 전체 흐름이 아니라 가장 작은 소유자에게 돌려보낸다

사업장 식별자 누락은 일반 현금화 경로 탐색의 실패가 아니었다. 시간주차비·내국신용장 소멸 조건을 소유한 journal-extinction-exception-rules의 실패였다.

그래서 Umbrella와 일반 추적기는 수정하지 않고, 예외 규칙 파일 하나만 고쳤다.

4. 사람 검토는 실패가 아니라 정상적인 출력이다

사업장 식별자가 없는데도 자동 소멸시키는 것은 위험하다. 반대로 무조건 오류로 끝내면 후속 판단에 필요한 정보가 사라진다.

이번 하네스에서는 이런 경우를 human_review로 반환하고, 자동 완료 대신 사람 승인을 요구하도록 했다.

만든 것

하네스 설계 계약

goal:
  분리된 일반 현금화 추적과 예외 소멸 판정을
  한 번의 검증 가능한 현금흐름 분석으로 실행한다.

trigger:
  start_when: 비식별 분개 묶음에 대한 명시적 수동 분석 요청
  never_start_when: 지원하지 않는 트리거 또는 입력·현금성계정 목록 누락

context:
  use: 분개 행, 목표 계정, 현금성계정 목록
  exclude: 개인정보, 실제 원장, 확인되지 않은 생산 규정

tree_or_route:
  Trigger → Context → 일반 추적 → 예외 규칙 → 최종 Gate → 승인/완료

control_shape: workflow

criteria:
  pass:
    - 금액 보존
    - 대상 행 중복 소유 없음
    - 사업장 누락 예외를 자동 소멸하지 않음
    - 사업장 누락 예외는 human_review로 반환
  fail:
    - 위 기준 중 하나라도 거짓
  ambiguous:
    - 복수 유효 후보 또는 필수 업무 식별자 누락

approval:
  human_review가 한 건이라도 있으면 사람 승인 필요

repair:
  failure_owner: 실패한 verifier를 소유한 하위 Skill
  smallest_fix: 해당 규칙만 수정하고 같은 입력·같은 기준으로 재평가

실행 흐름

명시적 수동 Trigger
→ 입력 행과 현금성계정 존재 확인
→ 일반 현금화 경로 추적
→ 미매칭 행을 예외 규칙으로 전달
→ 금액 보존·중복·사업장 Gate 검사
→ PASS면 완료
→ 애매하면 human_review와 승인 요청
→ FAIL이면 commit하지 않고 실패 소유자 반환

실행 영수증

각 실행은 다음 정보를 JSON으로 남기도록 했다.

Trace    어떤 단계를 통과했고 각 분류가 몇 건이었는가
Proof    금액 합계, 분류된 행 ID, 예외 소멸 ID, 사람 검토 ID, Criteria
Verdict  PASS / FAIL / HOLD / BLOCK
Approval 사람 승인이 필요한가
Repair   실패하면 어느 책임만 고칠 것인가

실행 로그

1. 가장 작은 정상 실행

비식별 분개 5행을 실제 working copy 하네스에 넣었다.

input_target_amount: 600.0
cash_classified: 100.0
exception_extinguished: 200.0
pure_noncash: 300.0
human_review: 0.0

gate:
  amount_conservation: true
  no_duplicate_owner: true
  missing_business_unit_never_extinguished: true
  known_exception_missing_unit_goes_to_human_review: true

verdict: PASS
committed: true
approval: not_required

분류 결과의 합계는 다음처럼 보존됐다.

입력 600
├─ 일반 현금화       100
├─ 예외 소멸         200
├─ 순수 비현금       300
└─ 사람 검토           0
합계 보존: PASS

2. 의도적으로 부러뜨린 입력

정상 실행 뒤 Criteria를 고정하고, 사업장 식별자가 빠진 시간주차비 원행과 반제행을 넣었다.

기대 동작은 자동 소멸이 아니라 human_review였다. 그러나 수리 전 예외 규칙은 두 행의 빈 문자열을 같은 사업장으로 취급했다.

input_target_amount: 250.0
cash_classified: 0.0
exception_extinguished: 250.0
pure_noncash: 0.0
human_review: 0.0

gate:
  amount_conservation: true
  no_duplicate_owner: true
  missing_business_unit_never_extinguished: false
  known_exception_missing_unit_goes_to_human_review: false

verdict: FAIL
committed: false

여기서 중요한 점은 금액 보존만 보면 PASS처럼 보였다는 것이다. 금액은 맞았지만 업무 판정은 틀렸다. 그래서 최종 verifier가 commit을 막았다.

3. 막힌 점과 최소 수리

첫 번째 막힘은 대상 로직이 아니라 회귀 테스트 파일의 루트 경로 계산 오류였다. 테스트 파일이 하네스 작업 폴더보다 한 단계 위를 바라보고 있어 두 테스트가 모두 실행 전에 멈췄다. 경로 계산만 고친 뒤 다시 실행하자 정상 테스트는 통과하고 사업장 누락 테스트만 예상대로 실패했다.

test_happy_path_receipt_passes_frozen_criteria ... ok
test_missing_business_unit_is_held_for_human_review ... FAIL

Ran 2 tests
FAILED (failures=1)

실패 소유자는 journal-extinction-exception-rules로 확인됐다. 수리 전 working copy 전체를 백업하고 복원 리허설을 수행했다.

backup_status: PASS
file_count: 17
source_backup_identical: true
restore_rehearsal: true

그다음 예외 규칙에 두 가지만 추가했다.

  1. 사업장 식별자가 빈 값이면 두 행을 같은 사업장으로 비교하지 않는다.

  2. 시간주차비·내국신용장 대상의 사업장 식별자가 빠졌다면 자동 소멸 대신 human_review로 반환한다.

Umbrella, 일반 경로 추적기, 정상 입력, 실패 입력, Criteria는 바꾸지 않았다.

4. 같은 기준·같은 입력으로 재평가

수리 전과 동일한 사업장 누락 250 입력을 다시 실행했다.

input_target_amount: 250.0
cash_classified: 0.0
exception_extinguished: 0.0
pure_noncash: 0.0
human_review: 250.0

gate:
  amount_conservation: true
  no_duplicate_owner: true
  missing_business_unit_never_extinguished: true
  known_exception_missing_unit_goes_to_human_review: true

gate_verdict: PASS
execution_verdict: HOLD
committed: false
approval: required

자동 소멸 250이 사람 검토 250으로 이동했고, 같은 Criteria 네 항목을 모두 통과했다. 다만 사람 승인이 남아 있으므로 전체 실행은 완료로 과장하지 않고 HOLD에서 멈췄다.

새 하네스 테스트:

test_happy_path_receipt_passes_frozen_criteria ... ok
test_missing_business_unit_is_held_for_human_review ... ok

Ran 2 tests in 0.019s
OK

기존 W2 동작 회귀 테스트:

test_general_trace_classifies_direct_indirect_and_unmatched ... ok
test_lc_rule_requires_reverse_within_configured_days ... ok
test_parking_rule_extinguishes_only_exact_next_month_reversal ... ok
test_umbrella_circuit_preserves_amounts_and_routes_ambiguity ... ok

Ran 4 tests in 0.018s
OK

Python 전체 컴파일도 통과했다.

Before / After

항목

2주차까지

3주차 After

중심 질문

verifier가 다른 책임을 어디서 나눌까

나눈 책임을 어떤 조건과 증거로 움직일까

구조

Umbrella + 일반 추적 + 예외 규칙

Trigger부터 Verdict까지 이어지는 workflow 하네스

시작 조건

함수 호출 중심

명시적 수동 Trigger와 no-start 조건

Context

함수 인자

사용할 근거와 제외할 정보를 계약으로 고정

완료 기준

금액 보존·중복 소유

금액·중복 + 사업장 누락 안전성 + 사람 검토 경계

애매한 결과

일부 human_review 반환

사람 승인 필요 상태로 하네스가 명시

실패 처리

테스트 실패

commit 차단 + 실패 소유자 + 최소 수리 반환

수리 범위

후보 기능 구현

예외 규칙 한 곳만 수정

재평가

최종 테스트 실행

같은 Criteria·같은 실패 입력으로 Before/After 비교

완료 증명

테스트와 Circuit smoke

Trace·Proof·Verdict·Approval·Repair 실행 영수증

배운 점

Skill을 나누는 기준이 verifier 차이라면, 다시 잇는 기준은 Trigger부터 최종 Verdict까지 책임과 증거가 끊기지 않는가였다.

2주차에는 다른 실패를 다른 verifier가 소유하도록 나눴다. 3주차에는 그 덕분에 실제 실패가 생겼을 때 전체를 고치지 않고 journal-extinction-exception-rules 하나만 정확히 수리할 수 있었다.

또 하나의 중요한 발견은 금액이 맞는 것과 업무가 맞는 것은 다르다는 점이었다. 수리 전 실패에서도 250원은 정확히 보존됐다. 하지만 사업장 식별자가 없는데 자동 소멸한 판정은 잘못이었다. 완료 조건에는 계산 검증과 업무 의미 검증이 함께 있어야 했다.

다음에 다시 쓸 팁

  1. Tree를 만들었다면 각 Skill의 이름보다 먼저 한 번의 실행 순서를 적는다.

  2. Harness 계약은 Goal·Trigger·Context·Route·Criteria·Approval·Repair 일곱 칸으로 시작한다.

  3. 실행 성공과 업무 완료를 분리하고 최종 verifier를 별도로 둔다.

  4. 정상 입력을 한 번 통과시킨 뒤 Criteria를 고정한다.

  5. 실패 실험은 외부 변경 없이 재현 가능한 입력으로 설계한다.

  6. 실패하면 전체를 다시 만들지 말고 실패한 Criteria의 소유자를 찾는다.

  7. 수리 전 백업과 복원 리허설을 하고, 같은 실패 입력과 같은 Criteria로 재평가한다.

  8. 애매한 결과를 억지로 PASS/FAIL로 만들지 말고 human_review, HOLD, BLOCK 같은 정상 상태로 돌려준다.

확장 아이디어

  • 부분금액과 다대다 연결을 지원하되 금액 보존 Gate는 유지

  • 실제 회사의 사업장 코드표를 Context 계약으로 연결

  • 예외 규칙별 승인자와 승인 사유를 영수증에 추가

  • 비식별 golden workbook으로 AC:AF 결과까지 readback하는 최종 Gate 추가

  • 동일 입력을 반복 실행했을 때 결과가 바뀌지 않는 멱등성 검사 추가

  • 다음 개선 실험에서 정상·실패 실행 영수증을 baseline으로 사용

재사용 프롬프트

Tree를 다시 나누지 말고, Trigger → Context → Route → Gate → Proof → Verdict가 있는
가장 단순한 workflow 하네스로 연결해줘.

먼저 Goal·Trigger·Context·Tree/Route·Criteria·Approval·Repair 계약을 작성하고,
비식별 입력으로 가장 작은 정상 실행을 실제로 돌려 JSON 영수증을 남겨줘.
정상 실행 뒤 Criteria를 고정하고 안전한 실패 입력 하나를 실행해줘.
실패하면 전체를 다시 만들지 말고 실패 verifier의 소유자만 찾아,
수리 전 백업과 복원 리허설 후 가장 작은 부분만 수정해줘.
마지막에는 같은 Criteria와 같은 실패 입력으로 재평가하고,
기존 회귀 테스트까지 실행해 결과를 Before/After로 정리해줘.

마무리 한 문장

2주차가 서로 다른 실패를 서로 다른 verifier에게 맡기는 과정이었다면, 3주차는 그 verifier들을 하나의 실행 흐름 안에서 호출하고, 틀린 자동 판정을 멈추고, 가장 작은 책임만 고쳐 다시 증명하는 과정이었다.

1
1개의 답글
밀어주고 끌어주는

온·오프라인 AI 스터디

AI로 어디까지 할 수 있는지
직접 확인하실 분만 신청하세요.