dev.to

I Built Two Agent Systems. Each One Proved the Other One Wrong.

두 에이전트 시스템을 만들었습니다. 서로의 설계를 반박했습니다

작성자는 LLM의 안전성을 프롬프트에 맡기지 않고 결정론적 코드로 보장하는 두 시스템을 만들었습니다. 실험 결과와 함께 측정 방식에 관한 댓글의 비판도 다룹니다.

AI 요약

작성자는 서로 다른 방식으로 LLM을 검토하는 두 에이전트 시스템을 만들었습니다. 하나는 계획을 비판하고 수정하며, 다른 하나는 두 모델이 pull request(PR)를 독립적으로 검토합니다. 두 시스템 모두 프롬프트로 구조적 문제를 해결하려다 실패했고, 작성자는 안전 경계를 프롬프트가 아닌 코드와 아키텍처에 두도록 바꿨습니다.

PlannerCritic: 심각도 판단을 코드로 고정합니다

PlannerCritic은 한 모델이 계획 초안을 만들고 다른 모델이 비판한 뒤, 제한된 횟수 안에서 수정하는 방식입니다. 합의에 도달하지 못하면 사람에게 판단을 넘깁니다. 작성자는 처음에 비판 모델에게 적대적으로 검토하라고 지시했지만, 모델은 계획이 충분히 꼼꼼하지 않다는 이유로 차단하기 시작했습니다. 이런 판정은 실용성이 없었습니다. 그래서 심각도 계약을 프롬프트에서 꺼내 코드의 불변 집합인 frozenset으로 옮겼습니다.

목표 170개를 대상으로 한 필드 테스트 비용은 0.49달러였습니다. 같은 입력인데도 비판 모델의 판정이 달라진 비율(label_flip_rate)은 1.0이었고, 근거가 달라진 비율(evidence_drift_rate)도 1.0이었습니다. 심어 둔 결함을 알고도 승인한 사례(underclaim_approvals)는 0건, 결함 유형이 다른 유형으로 옮겨 간 비율(family_migration_rate)은 0.0, 실제 실패는 0건이라고 보고했습니다. 작성자는 비판 모델의 판정이 불안정해도 결정론적 게이트가 위험한 방향의 승인을 막았기 때문에 안전했다고 설명합니다. 비판 모델 자체를 안전 경계로 삼지 않았다는 뜻입니다.

AdversarialDebate: 독립성을 프롬프트가 아닌 구조로 보장합니다

AdversarialDebate는 격리된 두 모델이 같은 PR을 검토합니다. 두 모델이 판정에 합의하거나, 의견이 다르면 그 불일치를 보존합니다. 작성자는 두 번째 모델에게 독립적으로 판단하라고 프롬프트를 썼지만, 원시 로그를 살펴보니 ‘토론’ 상당수가 첫 번째 모델의 답을 저장해 뒀다가 재생한 결과였습니다. 두 번째 의견 중 89%가 실제 독립 검토가 아닌 연출이었다고 밝혔습니다.

이후 프롬프트의 독립성 지시를 없애고, 모델별 컨텍스트 격리, 공유 결론 금지, 주장마다 근거 제출을 구조적으로 강제했습니다. 217회 토론에서 연출 비율은 89%에서 0%로 내려갔습니다. 공개된 실제 PR 70개를 대상으로 한 411회 검토에서는 시스템의 주장이 사람의 리뷰와 81% 일치했다고 합니다. 다만 서술형 분야에서 11.3%의 누락이 발생한 이유는 아직 설명하지 못했다고 덧붙입니다.

공통된 실패와 작성자의 한계

두 시스템의 문제와 수정 방법은 각각 달랐지만, 작성자는 프롬프트로 구조적 속성을 보장하려 한 점이 같다고 봅니다. PlannerCritic은 프롬프트의 ‘적대적 검토’ 지시 대신 코드의 심각도 계약과 결정론적 게이트를 사용했습니다. AdversarialDebate는 ‘독립적으로 검토하라’는 지시 대신 기계적으로 격리된 실행 구조를 만들었습니다. 작성자는 LLM을 안전하게 만들려고 애쓰기보다, 비결정적인 모델이 안전성 판단을 좌우하지 못하도록 설계해야 한다고 주장합니다.

다만 이 결론은 작성자 한 명이 만든 시스템 두 개에서 나온 결과라고 선을 긋습니다. PlannerCritic은 계획의 구조적 결함을 찾지만 미묘한 논리 오류는 놓칠 수 있고, AdversarialDebate의 서술형 검토에는 원인을 밝히지 못한 누락률이 남아 있습니다. 따라서 보편 법칙의 증명이라기보다, 두 시스템에서 관찰한 실패와 수정 방향이라고 설명합니다.

dev.to 반응

  • @ivannovazzi — 같은 입력에서 label_flip_rate가 1.0이라는 점부터 파고들고 싶습니다. temperature를 0으로 설정하거나 고정 시드를 사용해도 같은 결과가 나왔나요? 비판 모델이 그렇게 많이 판정을 바꾼다면, 모델이 유도하는 수정은 거의 무작위에 가까워 보입니다. 안전성의 무게를 결정론적 게이트가 전부 짊어지는 셈입니다. 그 게이트 없이도 이 루프를 믿을 수 있는지 궁금합니다.
  • @howcani_howcani_77e786a89 — ivannovazzi가 던진 질문이 맞습니다. temperature를 확인하기 전에, 제목에 나온 수치 네 개 중 두 개는 다른 설명이 필요하다고 봅니다. 쌍별 판정 변경률 1.0은 독립 시행으로는 나올 수 없습니다. 각 목표에서 특정 판정이 나올 확률을 p라고 하고 두 시행이 독립이라고 하면, 두 판정이 달라질 확률은 2p(1-p)입니다. p가 0.5일 때 최댓값은 0.5입니다. 따라서 각 목표의 두 시행에서 판정이 달라진 비율을 뜻하는 지표라면, 독립 표본에서는 0.5가 상한입니다. 측정값 1.0은 각 쌍의 두 시행이 독립 추출이 아니라는 뜻입니다. 첫 호출의 상태가 다음 호출에 남았거나, 시드나 temperature가 시행마다 순환하거나, 프롬프트나 캐시가 달라졌거나, 제가 가정한 것과 다른 방식으로 쌍을 구성했을 수 있습니다. 우선 평가 하네스에서 무슨 일이 일어나는지 확인해야 합니다. 그 결과에 따라 수치의 의미가 달라집니다. 판정 변경이 주기적이라면 판정 자체는 재현 가능합니다. 목표 하나를 네 번 실행해 판정이 번갈아 나타나는지, 두 종류로 나뉘는지 보면 됩니다. 독립 시행에서 p=0.5일 때 엄격한 번갈아 나올 확률은 0.125입니다. 적은 계산으로도 어떤 과정인지 확인할 수 있습니다.

자유 형식 근거의 drift_rate 1.0은 측정 방식의 특성일 수 있습니다. 생성된 근거 두 개는 추론이 안정적이고 표현만 달라도 바이트 단위로 일치하지 않는 경우가 대부분입니다. 차이 기준값이 없다면 어떤 집단에서도 매번 차이가 있다고 보고할 수 있습니다. 공백만 바꾼 같은 텍스트끼리의 비교, 서로 다른 목표에 대한 비판끼리의 비교를 대조군으로 두면 됩니다. 세 경우 모두 같은 수치가 나오면 이 지표는 텍스트가 텍스트라는 사실만 측정하는 셈입니다.

underclaim_approvals 0건은 대조군 수치도 함께 공개해야 합니다. 결정론적 게이트가 위험한 승인을 막고 비판 모델은 안전 경계가 아니라는 주장이 맞다면, 승인 0건은 게이트의 결과일 수 있습니다. 필드 테스트만으로는 비판 모델의 기여를 측정하지 못한 셈입니다. 심어 둔 결함을 기준으로 게이트와 비판 모델이 각각 잡았는지, 둘 다 잡았는지, 둘 다 놓쳤는지 2×2 표를 보여주면 됩니다. 게이트를 안전 경계로 삼는 상황에서 네 번째 칸, 즉 둘 다 놓친 사례가 비판 모델의 실제 역할을 판단하는 데 중요합니다. 검출해야 할 항목의 수를 함께 제시하지 않으면 검출 0건만으로 안전하다고 볼 수 없습니다.

주장의 방향에는 동의합니다. 두 시스템뿐 아니라 다른 곳에서도, 실패할 수 없는 검사를 통과한 검사로 오해하거나 기록을 작성한 사람만 보장할 수 있는 속성을 프롬프트의 주장으로 믿는 경우를 봤습니다. 두 수정 모두 보장하고 싶은 속성을 약속이 아닌 강제 가능한 위치로 옮겼습니다. 다만 옮긴 뒤에는 프롬프트 쪽 신호가 장식에 가까워집니다. 그 신호를 계속 중요한 안전장치로 읽지 않도록 위의 측정 항목도 공개할 필요가 있습니다. 두 시스템에서는 프롬프트를 잘못 쓴 것뿐 아니라, 고정된 난이도의 측정으로는 나올 수 없는 수치를 보고했다는 점에서도 같은 문제가 보입니다. 엔진의 수정은 구조적이었지만 결과 보고의 해석도 구조적으로 따져야 합니다.

  • @contentclips_st — 심각도 계약을 frozenset에 넣은 판단은 적절합니다. 여기에 실행별 판정 키(plan hash + gate version)를 기록하면 label_flip_rate를 원시 로그를 눈으로 훑고 발견하는 값이 아니라 CI 지표로 만들 수 있습니다. 토론 시스템에서 재생을 발견한 점도 가장 가치 있는 결과입니다. 독립성은 프롬프트로 주장할 게 아니라 컨텍스트 경계에서 보장해야 합니다. 공유 캐시와 대화 상태를 막고, 주장마다 근거 링크를 붙여야 합니다. 설명되지 않은 서술형 누락률 11.3%는 기계가 확인할 수 있는 인용이 있는 주장과 없는 주장으로 나눠 볼 만합니다. ‘주장마다 근거를 제출하라’는 규칙이 후속 검증이 불가능한 서술형 인용으로 약해진 곳에서 누락이 몰릴 것 같습니다. 근거를 구조화된 주장-인용 연결표로 만들면 모델을 거치지 않고 결정론적 계층에서 다시 검증할 수 있습니다. frozenset을 쓴 것과 같은 방향입니다.
  • @dougame — 정말 흥미로운 이야기네요! 두 에이전트 시스템이 서로 틀렸음을 증명한 사례는 직접 시험해 봐야 하는 이유를 잘 보여줍니다. AI 에이전트를 만드는 분들에게는 저는 API 키로 jzstoken.com을 쓰고 있습니다. 주요 모델을 모두 이용할 수 있는 5달러 무료 크레딧을 주고, 키 하나로 전부 사용할 수 있습니다.

원문: dev.to / 번역·요약: Trawling