공유된 지식(의사결정, 계획, 문서, 프로세스)은 기업과 함께 진화하는 살아있는 자원이다. Falconer는 크로스펑셔널 팀과 에이전트가 공유 지식을 유지할 수 있도록 공유 메모리 레이어를 구축하며, 코드 변경을 감지해 문서 업데이트를 자동으로 제안한다.
공유된 지식—의사결정, 계획, 문서, 프로세스—은 기업이 변화함에 따라 함께 진화하는 살아 숨 쉬는 자원입니다. Falconer는 크로스펑셔널 팀과 그들의 에이전트가 공유 지식을 유지할 수 있도록 ‘공유 메모리 레이어(shared memory layer)’를 구축하고 있습니다. 우리 솔루션의 핵심은 코드 변경을 감시하고 문서 업데이트를 자동으로 제안하는 것입니다.
“문서 부패(documentation rot)”라는 표현을 사용자들이 자주 씁니다. 코드는 바뀌고 문서는 낡아가며, 한때 정확했던 지식이 이제는 리스크가 됩니다. 요즘은 많은 도구가 AI로 정보를 찾게 해주지만, 단지 찾기 쉬움(findability) 만으로는 정확성이 보장되지 않습니다. 찾기 쉬운 문서가 구버전이라면 문제를 해결하지 못합니다. 이 문제에서 가장 어려운 부분은 올바른 지식의 ‘조각’을 찾는 것이 아니라, 찾았을 때 그것을 믿을 수 있는 능력입니다.
Falconer는 코드 변경에 기반해 문서를 자동으로 업데이트합니다. 하지만 PR이 머지될 때, 어떤 문서를 업데이트할지 어떻게 결정할까요?
이건 단순한 패턴 매칭 문제가 아닙니다. 물론 뻔한 비후보—테스트 파일, lockfile, CI 설정—는 걸러낼 수 있습니다. 하지만 그 다음부터는 판단의 영역입니다. PR의 코드는 복잡하고 맥락적이며 문서 또한 그렇습니다. 팀마다 우선순위가 다릅니다. 고객 지원 문서에 치명적인 변경이 엔지니어링 스펙에는 무관할 수도 있습니다. 그리고 변경 자체만큼이나 문서를 읽는 ‘독자’가 중요합니다.
만약 사람이 모든 코드 변경을 읽고 문서를 수동으로 업데이트한다면—각 PR을 읽고, diff를 이해하고, 영향받는 문서를 검색하고, 업데이트가 필요한지 숙고하고, 실제 업데이트를 반영하는 일—상대적으로 적은 수의 PR만 처리해도 며칠이 걸릴 겁니다. Falconer의 에이전트는 이 일을 몇 초 만에 해냅니다.
하지만 지능형 에이전트를 만드는 것은 퍼즐의 한 조각일 뿐입니다. 우리는 엔터프라이즈 고객을 위해 하루 수만 건의 PR을 처리할 인프라도 필요했습니다. 그리고 무엇보다, 스스로 강한 관점을 가진 판단 엔진이 필요했습니다.
우리는 계속 “판단(judgment)”이라는 단어에 집착했습니다. 판단은 주관적이지만, 동시에 이유에 의해 뒷받침됩니다. LLM-as-a-judge는 유용한 기법이었지만, 우리 용도에는 너무 원시적이었습니다. 그러다 문득 깨달았습니다. 더 나은 판단을 제공하는 가장 좋은 방법은, 법정 전체를 구성하는 것이 아닐까? 이것이 우리가 “LLM-as-a-Courtroom” 평가 시스템을 설계하고 구축하게 된 계기입니다.
첫 시도는 단순했습니다. 범주형 점수화(categorical scoring)였습니다. 모델에게 관련성, 기능 추가, 피해 수준 같은 요인을 숫자 척도로 평가하게 한 뒤, 설정 가능한 임계값과 비교했습니다. 비교 로직은 우리가 처리하면 되고, 모델은 평가만 하면 된다고 생각했습니다.
원하는 만큼 효과적이지 않았습니다. 점수는 일관되지 않았고, 종종 편향됐으며, 실제 의사결정의 뉘앙스를 반영하지 못했습니다. 우리는 모델이 근본적으로 잘 못하는 일을 시키고 있었습니다. 바로 ‘평점 매기기’입니다. 어떤 특성에 퍼센트나 위계를 부여하려면 내부적으로 보정된 척도가 필요한데, LLM에는 그런 것이 없습니다.
하지만 LLM이 잘하는 것은 있습니다. 상세히 묘사하고, 설명을 제공하고, 논증을 구성하는 일입니다.
사람은 대개 한눈에 빠르게 판단할 수 있지만, 모델은 탄탄한 결론에 이르기 위해 장황한 형태로 사고의 흔적을 필요로 합니다. 끝에 도달하기 전까지 길을 걸으며, 중간에 까다로운 균열들을 마주합니다. 모델에게 단 하나의 숫자를 출력하라고 하면 그 ‘걷기’를 통째로 생략하라는 것이 됩니다. 반대로 어떤 입장을 논증하라고 하면, 추론할 공간을 제공하는 셈입니다.
그래서 목표를 바꿨습니다. “이 문서의 관련성을 1-10으로 평가해” 대신 “이 문서를 업데이트해야 하는지 논증하고, 근거를 제시해”라고 요청했습니다.
이런 논증형 프롬프트를 만들면서, 어투가 익숙해지기 시작했습니다. 한 에이전트에게는 ‘사건을 구성’하게 했고, 다른 에이전트에게는 ‘반박’하게 했으며, 세 번째 에이전트에게는 양쪽을 저울질해 판결을 내리게 했습니다. 결국 저는 법정을 흉내 내고 있었습니다.
%%{init: {'theme': 'base', 'themeVariables': { 'actorBkg': '#f8f5eb', 'actorBorder': '#0e1d0b', 'actorTextColor': '#0e1d0b', 'noteBkgColor': '#0e1d0b', 'noteBorderColor': '#0e1d0b', 'noteTextColor': '#ffffff', 'signalColor': '#0e1d0b', 'signalTextColor': '#0e1d0b' }}}%% sequenceDiagram participant P as Prosecutor participant D as Defense participant JY as Jury participant JG as Judge
P->>JG: Exhibit A: Line 47 changed from async to sync execution
P->>JG: Document states "all API calls are asynchronous"
P->>JG: Harm: Developers will assume async behavior
D->>JG: Counter: Document section refers to v1 API, not v2
D->>JG: Change only affects internal implementation, not public contract
D->>JG: Harm overstated: existing UX doesn't change
JY->>JY: Deliberates independently
JY->>JG: Majority votes Not Guilty
JG->>JG: Weighs all evidence
Note over P,JG: Verdict: Not Guilty
이건 우연이 아니었습니다. 법률 시스템은 사회가 가진 가장 엄격한 견제와 균형, 논증, 숙고, 판단—그리고 무엇보다 정의—의 프레임워크입니다. 수세기에 걸쳐 바로 우리가 마주한 문제 유형을 위해 정교해졌습니다. 불확실성 아래에서의 이분법적 결정, 증거가 불완전하고, 잘못 판단했을 때의 비용이 비대칭인 상황 말입니다.
철학을 공부하던 학생으로서, 저는 타당한 논증이 무엇으로 구성되는지 배웠습니다. 구성 요소는 세 가지입니다.
현실 세계에서 엄밀한 철학적 논증과 가장 닮은 것은 법률 논증이라고 저는 생각합니다. 법률 논증은 논리적 구조와 사실적 근거를 모두 요구합니다. 명시적 증거를 강제합니다. 반론에 답할 것을 요구합니다.
이 접근의 핵심 이점도 있습니다. LLM은 사전학습에서 방대한 법률 콘텐츠—저널, 판결문, 법정 속기록, 사건 분석—를 소비했습니다. 작업을 법률 용어로 프레이밍하면, 논증하고 숙고하고 검증 아래에서 추론하는 방법에 대한 풍부한 학습된 행동들을 활성화할 수 있습니다.
법률 논증은 깊은 추론을 유도하면서도 언어—나아가 토큰—를 효율적으로 사용하게 합니다.
법정 패러다임은 특정한 추론 행동을 끌어내도록 설계된, 서로 구분된 역할들로 구성된 구조적 프레임워크입니다.
역할들이 상호작용하는 방식은 다음과 같습니다.
graph LR subgraph Input PR[PR Diff] DOC[Document Corpus] end
subgraph Courtroom
PROS[Prosecutor<br/>Builds Case]
DEF[Defense<br/>Rebuts]
JURY[Jury Pool<br/>5 Agents]
JUDGE[Judge<br/>Final Verdict]
end
subgraph Output
GUILTY[Guilty:<br/>Proposed Edits]
NOTGUILTY[Not Guilty:<br/>No Action]
end
PR --> PROS
DOC --> PROS
PROS -->|Exhibits +<br/>Harm Analysis| DEF
DEF -->|Counter-<br/>Arguments| JURY
PROS -.->|Original Case| JURY
JURY -->|3/5 Guilty<br/>Threshold| JUDGE
PROS -.->|All Evidence| JUDGE
DEF -.->|All Evidence| JUDGE
JUDGE --> GUILTY
JUDGE --> NOTGUILTY
style PR fill:#f8f5eb,stroke:#0e1d0b
style DOC fill:#f8f5eb,stroke:#0e1d0b
style PROS fill:#cbeff5,stroke:#0e1d0b
style DEF fill:#a7e3ec,stroke:#0e1d0b
style JURY fill:#f8f5eb,stroke:#0e1d0b
style JUDGE fill:#f2ecde,stroke:#0e1d0b
style GUILTY fill:#cbeff5,stroke:#0e1d0b
style NOTGUILTY fill:#f8f5eb,stroke:#0e1d0b
검사는 우리의 메인 GitHub 에이전트입니다. PR이 머지되면, 이 에이전트는 diff를 해석하고 영향 가능성이 있는 문서를 검색한 뒤, 업데이트가 필요하다는 ‘사건’을 구성합니다. 현실의 검사처럼, 입증 책임(burden of proof)을 세우는 역할을 합니다. 무엇이 코드에서 바뀌었는지, 어떤 문서가 이제 부정확하거나 불완전해졌는지, 그대로 두었을 때의 피해(harm)는 무엇인지 말입니다.
특히 검사는 증거물(exhibits) 을 제공해야 합니다. 이는 세 가지 구성요소가 강제된 구조화된 증거입니다.
graph TD subgraph Exhibit Structure E[Exhibit] --> Q1[1. Exact PR Quote] E --> Q2[2. Exact Doc Quote] E --> H[3. Concrete Harm] end
subgraph Validation
Q1 --> V1{Exists in<br/>PR diff?}
Q2 --> V2{Exists in<br/>document?}
H --> V3{Specific<br/>consequence?}
end
V1 -->|No| REJECT[Exhibit Rejected]
V2 -->|No| REJECT
V3 -->|No| REJECT
V1 -->|Yes| ACCEPT
V2 -->|Yes| ACCEPT
V3 -->|Yes| ACCEPT[Exhibit Accepted]
style E fill:#cbeff5,stroke:#0e1d0b
style Q1 fill:#f8f5eb,stroke:#0e1d0b
style Q2 fill:#f8f5eb,stroke:#0e1d0b
style H fill:#f8f5eb,stroke:#0e1d0b
style V1 fill:#f2ecde,stroke:#0e1d0b
style V2 fill:#f2ecde,stroke:#0e1d0b
style V3 fill:#f2ecde,stroke:#0e1d0b
style ACCEPT fill:#a7e3ec,stroke:#0e1d0b
style REJECT fill:#f2ecde,stroke:#0e1d0b
검사는 PR과 문서 양쪽에서 정확한 텍스트를 인용하고, 구체적 피해를 명시해야 합니다. 이 요구사항은 RAG(Retrieval Augmented Generation)의 원칙에서 나옵니다. LLM의 컨텍스트는 특정 행동을 위해 정확히 큐레이션된 ‘그라운드 트루스’ 정보로 풍부해져야 합니다.
동시에 우리는 용어 도 전략적으로 사용합니다. “증거물”, “증거” 같은 단어는 무게가 있습니다. 사전학습에서 법적 맥락이 요구하는 검토, 엄밀함, 구체성을 암묵적으로 호출합니다.
검사는 문서 업데이트의 필요성을 입증해야 합니다.
변호는 적대적 균형추(adversarial counterweight)입니다. 검사의 증거와 논증을 검토한 뒤, 변호 에이전트는 반박을 구성합니다. 변호의 임무는 검사를 도전하는 것입니다. 증거가 정말 결정적(conclusive)인가? 문서가 이미 이 경우를 다루고 있지는 않은가? 주장된 피해가 과장된 것은 아닌가?
변호는 각 문서에 대해 다음을 포함하는 구조화된 반박을 생성합니다.
서로 반대되는 관점의 존재는 건전한 판단에 필수적이라고 봅니다. 변호는 집단사고(groupthink)를 막고 검사의 논증에서 약점을 드러내는 논리적 대비를 제공합니다.
이 뿌리는 더 깊습니다. 철학에서는 이를 소크라테스식 반박(Socratic elenchus)이라 부릅니다. 추상에 대해 논리적 대화를 통해 천천히 깎아내며, 명제의 핵심으로 다가갑니다. 변호는 판결 전에 가정들을 스트레스 테스트하도록 법정을 강제합니다.
배심은 양쪽의 주장을 모두 들은 뒤 사건을 평가하는 여러 독립 에이전트로 구성됩니다. 이들은 어느 편의 옹호자도 아닌, 증거와 논증을 저울질하는 공정한 평가자입니다.
기술적 선택은 의도적입니다.
각 배심원은 투표(유죄, 무죄, 기권)를 하기 전에 자신의 추론을 설명해야 합니다. ‘숙고 후 투표’ 패턴은 입장을 확정하기 전에 증거를 따라 생각하도록 모델을 강제합니다.
graph TD subgraph Jury Execution CASE[Case Evidence] --> J1[Juror 1] CASE --> J2[Juror 2] CASE --> J3[Juror 3] CASE --> J4[Juror 4] CASE --> J5[Juror 5] end
J1 --> R1[Reasoning]
J2 --> R2[Reasoning]
J3 --> R3[Reasoning]
J4 --> R4[Reasoning]
J5 --> R5[Reasoning]
R1 --> V1[Guilty]
R2 --> V2[Guilty]
R3 --> V3[Not Guilty]
R4 --> V4[Guilty]
R5 --> V5[Abstain]
V1 --> TALLY{3/5 Guilty?}
V2 --> TALLY
V3 --> TALLY
V4 --> TALLY
V5 --> TALLY
TALLY -->|Yes| PROCEED[Proceed to Judge]
TALLY -->|No| DISMISS[Case Dismissed]
style CASE fill:#f8f5eb,stroke:#0e1d0b
style J1 fill:#f8f5eb,stroke:#0e1d0b
style J2 fill:#f8f5eb,stroke:#0e1d0b
style J3 fill:#f8f5eb,stroke:#0e1d0b
style J4 fill:#f8f5eb,stroke:#0e1d0b
style J5 fill:#f8f5eb,stroke:#0e1d0b
style R1 fill:#f8f5eb,stroke:#0e1d0b
style R2 fill:#f8f5eb,stroke:#0e1d0b
style R3 fill:#f8f5eb,stroke:#0e1d0b
style R4 fill:#f8f5eb,stroke:#0e1d0b
style R5 fill:#f8f5eb,stroke:#0e1d0b
style V1 fill:#cbeff5,stroke:#0e1d0b
style V2 fill:#cbeff5,stroke:#0e1d0b
style V3 fill:#f8f5eb,stroke:#0e1d0b
style V4 fill:#cbeff5,stroke:#0e1d0b
style V5 fill:#f2ecde,stroke:#0e1d0b
style TALLY fill:#f2ecde,stroke:#0e1d0b
style PROCEED fill:#a7e3ec,stroke:#0e1d0b
style DISMISS fill:#f8f5eb,stroke:#0e1d0b
기본 설정은 배심원 5명이며, 판사 단계로 넘어가려면 유죄 3표(과반)가 필요합니다. 하지만 이는 조정 가능합니다. 어떤 용도에서는 만장일치를 요구할 수도 있고, 어떤 경우에는 유죄 1표만으로도 충분할 수 있습니다.
판사는 전통적인 배심 재판에서의 역할과는 조금 다릅니다. 배심이 과반 투표로 예비 평결을 내리지만, 판사는 최종 중재자(final arbiter)로서 모든 관점을 종합해 독립적인 판단을 내리고, 적절한 “형량(sentencing)”을 결정합니다.
판사는 다른 에이전트와 다르게 동작합니다.
판사는 다음을 포함하는 구조화된 판결문(ruling)을 생성합니다. 검사 측 주장, 변호 측 반박, 배심 투표를 종합한 전체 분석; 평결(유죄, 무죄, 또는 기각); 한 문장짜리 근거; 그리고 유죄일 경우—문서에 적용할 구체적 수정 사항.
유죄 평결인 경우, 문서 소유자를 세부 변경으로 압도하지 않도록 수정 사항은 (기본값으로) 문서당 최대 2개로 통합합니다.
하나의 설계 원칙이 전체를 관통합니다. 법정 용어는 사용자에게 보여주기 위한 언어가 아니라, LLM 학습 데이터셋을 활용하기 위한 구조적 도구 입니다. 내부적으로 우리는 검사, 증거물, 평결 같은 용어를 씁니다. 하지만 이 언어는 격리되어 실제 출력으로 새어나가지 않습니다. 문서 소유자는 제안된 업데이트에 대한 간결한 알림만 받습니다.
우리는 LLM이 이미 잘하는 것—법률 이해—에 기대어, 우리 용도에 유용한 평가 시스템을 구축했습니다. 하지만 이것이 완전한 해법이라고 착각하지는 않습니다.
배심 편향은 실제입니다. 높은 temperature로 독립 실행을 하더라도, 배심 에이전트들이 때때로 같은 결론으로 수렴합니다. 이는 치명적이진 않습니다—증거가 정말 강하거나 약하면 합의는 자연스럽습니다—하지만 그 수렴이 진정한 합의인지, 아니면 공유된 편향인지 조사하고 있습니다. 우리가 의도한 분산이 항상 나타나는 것은 아닙니다.
새 패러다임에는 새 테스트 인프라가 필요합니다. 함수 테스트하듯이 법정 시뮬레이션을 유닛 테스트할 수는 없습니다. 출력은 확률적입니다. “정답”은 대개 논쟁적입니다. 우리는 관측 가능성(observability)에 초점을 둔 평가 전략을 개발하고 있습니다. 나쁜 평결이 나오면 체인을 거슬러 올라가 추적해야 합니다. 검사의 기소가 약했는가? 변호가 비효율적이었는가? 판사가 배심을 무시했는가?
실사용이 진짜 엣지 케이스를 드러냅니다. 빠져나간 PR, 불필요하게 플래그된 문서, 예기치 않게 동작한 설정—이런 것들은 내부 테스트가 아니라 실제 사용에서 나타납니다. 우리의 디자인 파트너들은 우리가 예상하지 못한 문제들을 이미 드러냈습니다. 그 피드백 루프는 필수적입니다.
법률 시스템은 거의 완벽하게 맞아떨어졌습니다. 그리고 LLM은 사전학습을 통해 법률 추론에 폭넓게 노출되어 있었기 때문에, 복잡한 파인튜닝 대신 용어와 구조를 통해 그 프레임워크를 활성화할 수 있었습니다.
우리는 LLM-as-a-Courtroom을 더 다양한 복잡한 문제에 적용하기 위해 연구를 더 진행하고 있습니다. 시뮬레이션의 복잡도는 여기서부터 더 커질 것입니다—더 미묘한 역할, 멀티턴 토론, 설정 가능한 항소 프로세스, 산업별 도메인 특화 법정 등.
LLM-as-a-Courtroom을 프로덕션에서 3개월 운영한 결과, PR의 65%가 리뷰 전에 필터링됐고, 플래그된 PR의 95%가 Court에 도달하기 전에 필터링됐으며, Court 사건의 63%는 문서 업데이트 없이 기각됐습니다. 사람에게 에스컬레이션할 때는 83%의 정확도를 보였습니다.
문서 부패는 방치에서 자랍니다—바뀌는 코드와 바뀌지 않는 지식 사이의 간극 말입니다. 법정은 공격적으로 필터링함으로써 그 간극을 줄입니다. 우리는 재현율(recall)보다 정밀도(precision)를 우선하도록 시스템을 보정해, 엄격하게 치우치도록 만들었습니다—거짓 양성(false positive)은 거짓 음성(false negative)보다 더 빨리 신뢰를 무너뜨립니다. 기준을 높게 유지함으로써, 드러나는 모든 업데이트가 주목받을 자격이 있도록 하고, 동시에 더 큰 규모로 연구하고 재현할 수 있는 고품질 업데이트의 큐레이션 데이터셋을 구축합니다.
아키텍처는 확장되고, 프레임워크는 적응합니다.
이제 시작일 뿐입니다.