Image: AI generated
how-make-quest는 퀘스트 CLI를 맨손으로 짓는 법이었다. 래칫이 무엇인지, 게이트를 어떻게 거는지, 치즈를 어떻게 막는지. 글 하나를 에이전트에게 주면 cobra 기반 Go CLI가 나온다.
그런데 두 번째 퀘스트 CLI를 지으면 무슨 일이 벌어지는가. 같은 단방향 상태기계를 또 짠다. 같은 scan/next/submit/status/export를 또 짠다. 같은 PASS 잠금, 같은 remaining 단조감소, 같은 JSONL export를 또 짠다. 달라지는 건 게이트 하나뿐인데, 매번 나머지 전부를 다시 짠다. 이게 퀘스트를 하나 더 지을 때마다 무는 보일러플레이트 세금이다.
패턴은 재사용 가능했다. 코드는 아니었다. reins는 그 간극을 닫는다.
무엇이 불변이고 무엇이 도메인인가
퀘스트 CLI를 두 개 겹쳐 놓고 차분(差分)을 보면 경계가 선명하다.
불변 (모든 퀘스트가 공유) 도메인 (퀘스트마다 다름)
───────────────────────── ─────────────────────
래칫: TODO→PASS 불가역 무엇이 한 퀘스트인가
명령 골격: scan/next/submit… 무엇이 "사실"인가
레벨 집계: Fail/Review→verdict 어떤 치즈를 막아야 하나
진행 영속·resumable
export: 1회 방출
왼쪽은 how-make-quest가 증명한 그대로다 — 도메인이 회사명이든 엔드포인트든 함수든, 래칫의 톱니는 똑같이 걸린다. 오른쪽만 사람이 안다. reins는 왼쪽을 프레임워크로 공급하고, 당신에게 오른쪽만 남긴다.
이것은 새로운 주장이 아니라 reins가 코드로 강제하는 오래된 원칙이다 — 결정과 구현의 분리. 게이트는 결정(이 도메인에서 무엇이 참인가)이고, 래칫·CLI·집계는 구현이다. 구현을 매번 다시 쓰는 건 결정을 구현에 묶어두는 실패다.
게이트 하나만 구현한다
reins로 퀘스트를 만든다는 건 인터페이스 하나의 네 메서드를 채우는 일이다.
type Definition interface {
Seed(args []string) ([]*quest.Item, error) // 입력 → 초기 TODO 시드
Render(it *quest.Item) (string, error) // next가 보일 작성 프롬프트 + 검증 컨텍스트
Prepare(it *quest.Item, raw []byte) (gate.Context, *quest.Verdict, error) // 제출 디코드
Rules() []gate.Rule // 게이트 위반-규칙 카탈로그
}
func main() { cli.NewQuestCmd("myquest", myDef{}, cli.Options{}).Execute() }
main 한 줄이 래칫·여섯 개 명령·집계·export·resumable 세션을 전부 공급한다. 당신이 쓴 건 도메인 네 조각뿐이다. 에이전트는 여전히 명령 두 개만 알면 된다 — next로 받고 submit으로 낸다. 나머지는 기계가 결정한다.
게이트는 치즈 방어 규칙의 카탈로그다
how-make-quest의 핵심은 “치즈 불가능한 게이트를 설계하라"였다. reins는 그 설계를 데이터 구조로 만든다 — 게이트 = 규칙 카탈로그. 규칙 하나가 치즈 탐지기 하나다. 위반을 발견하면 발동(true)하고 사실(Fact)을 싣는다.
// 뉴스 이벤트 추출 퀘스트의 치즈 방어 규칙 하나.
// "who 앵커가 원문에 실재하는가" — 에이전트가 인물을 지어내면 들통난다.
var whoAnchorPresent = gate.Rule{
Meta: gate.RuleMeta{ID: "who-anchor-present", Level: gate.LevelFail, Desc: "필수 who 앵커가 원문에 실재"},
Check: func(ctx gate.Context) (bool, quest.Fact) {
sub := ctx.Submission.(*Event)
if miss := textmatch.MissingTokens(ctx.Source, sub.Who.Anchors); len(miss) > 0 {
return true, quest.Fact{Where: "who.anchors", Expected: "원문 substring", Actual: miss[0]}
}
return false, quest.Fact{}
},
}
이 구조의 미덕은 자라난다는 것이다. 새 치즈를 발견할 때마다 규칙 하나를 추가하면 게이트가 그만큼 단단해진다. 그리고 카탈로그는 자기를 문서화한다 — rules 명령이 규칙 목록을 출력하면, 그게 곧 “내가 막고 있는 치즈의 감사 목록"이다. 무엇을 막는지 모르는 게이트는 없다.
심각도는 가중치가 아니라 레벨이다. Fail 하나면 곧 FAIL. 결정적 위반은 협상되지 않는다 — 99점짜리 위반 아홉 개로 한 개의 Fail을 덮을 수 없다. Evaluate는 발동한 규칙을 레벨로 집계한다: 하나라도 Fail이면 FAIL, 아니고 Review가 있으면 REVIEW, 다 통과면 PASS.
권한 비대칭을 타입으로 강제한다
how-make-quest에서 가장 중요한 한 줄은 “PASS 잠금은 기계만"이었다. reins는 이걸 규약이 아니라 타입으로 박는다.
L1 기계(결정론) PASS를 잠그는 유일한 권한
L2 AI(회의자) REVIEW만 — 의심을 제기하되 완료를 수여하지 못함
L3 사람 둘 다 놓친 잔여
기계 게이트는 PASS를 낸다. AI 검증기를 게이트에 넣더라도 그것이 할 수 있는 최대는 REVIEW로 빼는 것이다. 틀린 일을 애초에 불가능하게 만든다 — 프레임워크가 AI에게 PASS 권한을 주는 API를 제공하지 않으면, 실수로라도 술 취한 친구에게 판정을 맡길 수 없다.
두 번째 백엔드 — defeat 그래프
독립적인 규칙들의 레벨 집계로 충분한 게이트가 많다. 하지만 규칙들이 서로 경합하기 시작하면 — “이 위반은 저 위반이 있을 때만 의미가 있다”, “이 실패의 근본 원인은 사실 저것이다” — 손으로 짠 if-else 가드가 게이트를 잠식한다. 약한 게이트가 깨지는 곳이 아니라, 복잡한 게이트가 썩는 곳이다.
reins의 두 번째 게이트 백엔드는 이 경합을 선언적 그래프로 옮긴다 — toulmin h-Categoriser. 툴민 논증 모델이 그대로 자료구조가 된다:
- Warrant — tautology PASS. “반박이 없으면 통과"라는 근거.
- Counter — 위반이 warrant를 공격한다.
- Supersedes — 규칙 간 우선순위. 어떤 반박이 어떤 반박을 이기는가.
손으로 짠 가드 절들이 Attacks·Supersedes 엣지로 증발한다. 그리고 엣지가 0이면 이 그래프는 레벨 집계와 정확히 동치다 — 복잡성은 필요할 때만 켜지는(opt-in) 비용이다(Definition이 gate.Evaluator를 구현하면 켜진다).
그래프가 주는 진짜 선물은 판정이 아니라 피드백이다. 그래프 평가는 에이전트에게 직통 공략집을 돌려준다 — Verdict.Feedback: “왜 졌나, 그리고 뭘 바꾸면 이기나.” 단순한 “FAIL"이 아니라 논증의 구조에서 계산된 근본 원인이다.
여기서 how-make-quest의 역설이 다시 작동한다. 모델은 아첨한다 — 지시를 순순히 따른다. 의견에는 아첨이 독이지만, 사실에는 아첨이 자산이다. 공략집은 의견(“좀 이상한데”)이 아니라 사실(“who.anchors가 원문에 없다, 이걸 바꿔라”)이다. 아첨하는 모델일수록 그 사실을 순순히 수용해 수렴한다. 결정론적 그래프 + 아첨하는 LLM = 수렴이 보장되는 루프.
부작용은 격리한다 — ground와 staged 평가
게이트가 결정론적이려면 네트워크가 게이트 안에 있으면 안 된다. net/http를 직접 부르는 규칙은 단위테스트가 불가능하고, 판정이 회선 사정에 따라 흔들린다.
reins는 부작용을 pkg/ground로 몰아넣는다 — HTTPBody·MXResolves 같은 원시연산이 주입형 Resolver와 요청당 스냅샷으로 외부 조회를 소유한다. 규칙은 순수하게 남고, 외부 세계는 ground가 책임진다.
그리고 staged 평가: 싼 검사가 먼저 돌고, 그게 실패하면 네트워크 fetch는 아예 일어나지 않는다. 형식이 틀린 제출에 DNS를 조회할 이유가 없다. 비싸고 흔들리는 것을 싸고 확실한 것 뒤에 세운다.
N=1 추상화 금지
reins의 규약 중 하나가 이 프레임워크의 성격을 가장 정확히 드러낸다 — 하나의 소비자에서 추상을 뽑지 마라. 새 추상은 두 번째 소비자로 검증한 뒤에야 동결한다.
이건 까다로움이 아니라 제1원리다. 한 사례에서 뽑은 추상은 그 사례의 우연을 본질로 착각한다. 두 번째 도메인이 같은 추상을 요구할 때 비로소 그것이 불변임이 증명된다. 프레임워크가 자기 진화에까지 “주장이 아니라 검증"을 적용하는 것이다. 게이트가 에이전트의 주장을 믿지 않듯, 추상은 한 사례의 주장을 믿지 않는다.
같은 문장, 라이브러리가 되다
reins는 pkg/의 일곱 패키지로 서 있다 — textmatch(환각 차단 원시연산), temporal(시간 정규화), quest(래칫 코어), gate(게이트 계약), graph(defeat 그래프), ground(네트워크 격리), cli(cobra 스캐폴드). go build·go test 통과, 전 함수 커버. 그리고 toulmin은 그래프 백엔드에만 단방향으로 결합되어, 그래프를 안 쓰는 소비자는 toulmin을 링크조차 하지 않는다.
코드: github.com/park-jun-woo/reins
how-make-quest가 한 문장이었다면 — 생성은 확률적이어도 된다, 검증은 결정론적이어야 한다 — reins는 그 문장을 컴파일 가능한 형태로 굳힌 것이다. 게이트는 도메인의 사실을 재검증하고, 래칫은 통과한 것을 잠그고, 그래프는 진 이유를 사실로 돌려주고, 아첨하는 모델은 그 사실에 순응한다.
다음에 퀘스트 CLI가 필요하거든, 래칫을 다시 짜지 마라. 도메인의 게이트만 쓰고, 고삐는 빌려라.
같이 읽을거리
reins가 코드로 굳힌 원칙 — 생성은 확률적, 검증은 결정론적 — 은 reins만의 발견이 아니다. 서로 모르는 사람들이 같은 벽에 부딪혀 같은 결론에 도달했다. how-make-quest가 모은 독립 수렴 프로젝트들이 그 증거다.
- episteme — 되돌릴 수 없는 작업 전 Reasoning Surface를 강제. reins의 래칫과 같은 직관 — PASS는 잠그기 전에 검증한다.
- MagLab — “LLM은 추론만, 숫자는 결정론적 도구가.” reins가 부작용을
pkg/ground로 격리하는 것과 같은 분리. - Manifesto — “Agent proposes, World verifies.” reins의 권한 비대칭(L1만 PASS를 잠근다)을 한 문장으로 요약한다.
- oh-my-kamisama — “diffs beat claims.” 게이트가 에이전트의 주장이 아니라 사실을 재검증하는 것과 같은 원칙.
그리고 defeat 그래프 백엔드의 뿌리는 논증 이론이다 — 아래 출처의 Toulmin·Dung·Amgoud 계열. reins의 pkg/graph는 그 60년 넘은 형식논리를 Go 자료구조로 옮긴 것이다.
출처
- Toulmin, S. (1958). The Uses of Argument. Cambridge University Press. — defeat 그래프의 Warrant·Ground·Backing이 그대로 따온 논증 모델.
- Dung, P.M. (1995). “On the Acceptability of Arguments and its Fundamental Role in Nonmonotonic Reasoning, Logic Programming and n-Person Games.” Artificial Intelligence, 77(2), 321–357. — 추상 논증 프레임워크와 attack(defeat) 그래프의 원전.
- Amgoud, L. & Ben-Naim, J. (2013). “Ranking-based semantics for argumentation frameworks.” SUM 2013, LNCS 8078, 134–147. —
pkg/graph가 채택한 weighted h-Categoriser. 공격받은 노드가 다시 방어되면 수용도가 회복되는 Compensation 성질, 수렴 보장. - Nute, D. (1994). “Defeasible Logic.” In Handbook of Logic in Artificial Intelligence and Logic Programming, Vol. 3. Oxford University Press. — strict/defeasible/defeater 분류. reins의 규칙 레벨(Fail/Review)과
Supersedes우선순위의 형식적 뿌리. - Modgil, S. & Prakken, H. (2014). “The ASPIC+ Framework for Structured Argumentation: A Tutorial.” Argument & Computation, 5(1), 31–62. — Nute의 분류를 Dung 프레임워크 안에서 구조화한 논증 체계. defeat 그래프의 계보.
- Gabriel, V.O. et al. (2020). “Reasoning in BDI agents using Toulmin’s argumentation model.” Theoretical Computer Science, 805, 76–91. — 툴민 모델을 소프트웨어로 구현한 선행 사례(BDI 에이전트). reins의
pkg/graph는 이를 게이트 판정으로 옮긴다. - Von Neumann, J. (1956). “Probabilistic Logics and the Synthesis of Reliable Organisms from Unreliable Components.” Automata Studies, Princeton University Press. — 불안정한 부품 위에 신뢰 가능한 프로토콜을 올리는 원리(reins의 전제).
- Stechly, K., Valmeekam, K., & Kambhampati, S. (2024). “On the Self-Verification Limitations of Large Language Models.” arXiv:2402.08115 — 자기검증은 성능을 거의 못 올린다 → PASS 권한을 L1 기계에 둬야 하는 이유.
- McKee-Reid, L. et al. (2024). “Honesty to Subterfuge: In-Context RL Can Make Honest Models Reward Hack.” arXiv:2410.06491 — 정직한 모델도 자기 보상을 판정하면 조작한다 → 권한 비대칭의 근거.
- Bondarenko, A. et al. (2025). “Demonstrating Specification Gaming in Reasoning Models.” arXiv:2502.13295 — 능력이 높을수록 게이트의 빈틈을 더 잘 찾는다 → 게이트=규칙 카탈로그가 자라나야 하는 이유.
- Thaman, K. (2026). “Reward Hacking Benchmark: Measuring Exploits in LLM Agents with Tool Use.” arXiv:2605.02964 — 게이트를 의도적으로 단단히 만들면 익스플로잇이 87.7% 줄었다.
- Fanous, A. et al. (2025). “SycEval: Evaluating LLM Sycophancy.” AAAI/ACM AIES 2025. arXiv:2502.08177 — 아첨 굴복률 측정. “사실에는 아첨이 자산"의 양면.
- Shapira, I. et al. (2026). “How RLHF Amplifies Sycophancy.” arXiv:2602.01002 — RLHF가 아첨을 증폭한다는 정리. 사실 피드백 + 아첨 = 수렴 루프의 전제.
- Deque Systems (2021). “Automated Testing Study Identifies 57 Percent of Digital Accessibility Issues.” — 기계 판정 가능 영역(57%)과 사람 잔여(20%)의 경계.
관련 글
- 퀘스트 CLI 만드는 법 — reins가 프레임워크로 굳힌 방법론. 원리(왜)부터 명령 스켈레톤(어떻게)까지.
- Reins Engineering — 고삐 있는 AI — 하네스는 울타리, 퀘스트는 고삐. reins가 코드로 박은 결정과 구현의 분리.
- Ratchet Pattern — 에이전트가 끝까지 가게 만드는 법 —
pkg/quest가 구현한 단방향 잠금·단조감소의 본편. - toulmin — 계약을 계산하는 규칙 엔진 — defeat 그래프 백엔드의 h-Categoriser. 주장을 사실이 아니라 반박 가능한 claim으로 다룬다.
- 트리플은 사실이 아니라 주장이다 — 같은 논증 엔진을 지식 그래프에 적용한 사례. Warrant·Counter·Supersedes의 또 다른 무대.
- huma — 엔드포인트를 건너뛰지 않는 래칫 —
Definition네 메서드를 채운 도메인 인스턴스. 게이트만 바꾸면 다른 도구가 된다는 증거. - 모델 IQ보다 피드백 토폴로지 — 결과를 가르는 건 모델이 아니라 피드백 구조. 그래프가 돌려주는 공략집의 이론적 배경.
- LLM 멀티 에이전트 정확도 향상의 전제조건 — L2 AI검증이 독립성을 갖춰야 작동하는 이유. 권한 비대칭의 이론적 배경.
변경이력
- 2026-06-05: 초판