LLMOps 13

계약서 자동 분석 POC: 설계 문서 묶어보기

설계 문서가 따로따로 보이면 실제 POC에 어떻게 묶이는지 감이 오지 않는다.

근거 · 교안 p31-p35

계약서 자동 분석 POC: 설계 문서 묶어보기 대표 이미지

1장: 감독 에이전트: 전체 설계의 지휘자

솔라의 모니터 한구석에는 메모장 앱이 열려 있었다. 방금 막 원격 회의에서 받아 적은 듯한 짧은 목록이 깜박였다.

✓ POC 프로젝트 설계 문서

▪ Agent 정의서 ▪ Workflow Spec ▪ State 정의서 ▪ Decision Policy (조건 분기, 반복 정책) ▪ Prompt Spec

솔라는 마우스를 가져가 ‘Agent 정의서’ 줄을 블록 지정했다가, 다시 ‘Workflow Spec’ 줄을 드래그했다. 손가락이 까딱거릴 때마다 파란색 블록이 목록 위를 무의미하게 오갔다. 마치 각 항목이 서로 아무 관련 없는 섬처럼 보였다. 이 낱개의 문서들이 모여 어떻게 하나의 유기적인 ‘계약서 자동 분석 POC’라는 시스템이 되는지 도무지 그림이 그려지지 않았다.

“언니.”

거실 테이블에서 조용히 책을 읽던 루나가 고개를 들었다.

“이것 좀 봐. POC 설계에 필요한 문서 목록인데, 그냥 따로따로 할 일 목록 같아. Agent는 Agent대로, Workflow는 Workflow대로. 이게 다 어떻게 하나로 묶인다는 건지 감이 안 와.”

솔라의 목소리에는 선명한 막막함이 묻어났다. 그녀의 생각 속에서 ‘Agent 정의서’는 계약서에서 정보를 추출하는 똑똑한 AI 일꾼 하나를 설명하는 문서, 그 이상도 이하도 아니었다. 다른 문서들도 마찬가지였다. 각자의 역할에만 충실한, 서로를 모르는 전문가들 같았다.

루나는 솔라의 의자를 자기 쪽으로 살짝 돌렸다. 그리고는 테이블 위에 놓여 있던 깨끗한 빈 종이 한 장을 솔라 앞으로 밀어주었다. 정답을 알려주는 대신, 다른 질문을 던졌다.

“좋아. 그럼 이 POC 전체를 책임지는 감독이 딱 한 명 있다고 상상해 봐. 오케스트라 지휘자처럼.”

“감독?”

“응. 그 감독이 자기 일을 해줄 팀원들을 새로 뽑는 거야. 계약서를 분석하려면 어떤 전문가들이 필요할까? 그 감독이 어떤 팀원들을 만들어서, 무슨 일을 시킬지 한 문장으로 써볼래?”

솔라는 잠시 고민에 잠겼다. 낱개의 문서 목록을 볼 때와는 다른 관점이었다. 지휘자라. 솔라는 연필을 들고 종이 위에 작게 끄적이기 시작했다.

“음… ‘계약서 분석을 총괄하는 감독은…’”

솔라의 연필심이 종이를 스치는 소리만 들렸다. 몇 번 망설이던 연필 끝이 이내 망설임 없이 문장을 완성해나갔다.

“‘…문서가 계약서인지 아닌지 분류하는 분류 담당자, 계약서 종류에 맞춰 필요한 정보를 뽑아내는 추출 담당자, 그리고 추출 결과가 정확한지 검토하는 검토 담당자를 만들어 순서대로 일을 시킨다.’”

솔라는 자기가 쓴 문장을 소리 내어 읽어보았다. 제법 그럴듯한 팀의 모습이 그려졌다.

루나는 말없이 솔라가 쓴 문장을 가리켰다. 그리고는 한 박자 늦게, 솔라의 모니터에 떠 있는 문서 목록의 첫 번째 항목, ‘Agent 정의서’를 손끝으로 짚었다.

“솔라 네가 지금 쓴 그 문장. 그게 바로 ‘Agent 정의서’에서 가장 먼저 정의해야 할 내용이야.”

“어? 이게? 나는 Agent 정의서는 추출 담당자가 무슨 일을 하는지 같은, 개별 역할 설명서라고 생각했는데.”

“그것도 포함되지. 하지만 더 중요한 건 전체 그림을 그리는 거야. 방금 솔라 네가 한 것처럼, 어떤 개별 Agent들을 만들고 조율할지 결정하는 총감독, 즉 ‘Supervisor Agent’의 역할을 가장 먼저 정의하는 거지. 지휘자가 어떤 악기 연주자들이 필요한지 정하고, 언제 누가 연주할지 지휘하는 것처럼. 이 감독의 존재와 역할이 정의되어야 비로소 그 밑의 팀원들도 의미를 갖게 돼.”

솔라의 눈이 동그래졌다. 머릿속에 흩어져 있던 퍼즐 조각 하나가 제자리를 찾아 들어맞는 느낌이었다. ‘Agent 정의서’는 단순히 개별 일꾼들의 명세서가 아니었다. 전체 시스템을 지휘할 감독을 정하고, 그 감독이 어떤 팀을 꾸릴지 결정하는, 모든 설계의 출발점이었다. 이 첫 단추를 어떻게 끼우느냐에 따라 나머지 설계 문서들의 내용이 완전히 달라질 수밖에 없었다.

“아…! 알겠다. Agent 정의서가 그냥 각자 역할을 나열하는 게 아니라, 누가 이 모든 걸 지휘하는지, 그래서 어떤 팀 구조가 필요한지를 맨 처음에 그리는 설계도였구나. 이 감독을 어떻게 정의하느냐에 따라 필요한 팀원도, 그들이 일하는 방식도 전부 달라지겠네.”

솔라는 자신이 쓴 문장을 다시 들여다보았다. ‘분류 담당자’, ‘추출 담당자’, ‘검토 담당자’. 이들은 더 이상 외딴 섬이 아니었다. 하나의 감독 아래 모인 팀이었다. 이제야 비로소 낱개의 문서들이 연결될 첫 번째 고리가 보였다.

하지만 새로운 질문이 곧바로 고개를 들었다.

“좋아, 감독이 팀을 꾸렸어. 그런데 이 팀원들이 어떤 순서로 일하고, 한 사람이 끝낸 일은 다음 사람에게 어떻게 넘겨주는 거지? 분류 담당자가 일을 끝내면 저절로 추출 담당자에게 일이 넘어가는 건 아닐 거 아냐. 그 ‘흐름’은 어디에다 그려? 그리고 일을 주고받을 때, 각자 지금 어떤 ‘상태’인지는 어떻게 알고 움직이는 거야?”

2장: 워크플로우 & 상태: Agent들의 여정 지도

솔라는 어제 Supervisor Agent를 정의하며 사용했던 빈 종이를 다시 책상 위로 가져왔다. 종이 위에는 ‘감독은 분류, 추출, 검토 담당자를 만들어 순서대로 일을 시킨다’는 문장이 적혀 있었다. 그녀는 그 문장 아래에 어젯밤 내내 머릿속을 맴돌던 질문에 대한 답을 직접 그려 넣었다.

분류 담당자추출 담당자검토 담당자

단순한 화살표 세 개였지만, 흩어져 있던 Agent들이 드디어 하나의 길 위에서 만나는 것 같았다. 솔라는 만족스러운 미소를 지으며 자신의 그림을 들여다보았다. ‘흐름’을 그리라던데, 이게 바로 그 흐름이 아닌가.

하지만 그 만족감은 길지 않았다. 그녀의 시선이 모니터 속 설계 문서 목록으로 돌아갔을 때, 고개가 갸우뚱해졌다. 목록에는 ‘Workflow Spec’과 ‘State 정의서’라는 두 개의 항목이 나란히 있었다. 이 간단한 화살표를 설명하기 위해 굳이 두 종류의 문서가 필요할까? 그냥 순서도처럼 보일 뿐인데. 꼭 잘 닦인 길에 불필요한 교통 표지판을 세우는 것처럼 느껴졌다.

“언니, 내가 그린 이 흐름 말이야.”

솔라가 종이를 들어 보이자, 주방에서 물을 마시던 루나가 다가왔다.

“이게 Workflow 아니야? 그런데 왜 Workflow Spec이랑 State 정의서, 두 개나 필요하지? 그냥 이 순서대로 일한다고 적으면 끝나는 거 아닌가?”

루나는 솔라가 그린 그림을 조용히 들여다보았다. 정갈하게 그어진 화살표는 솔라의 생각처럼 명쾌해 보였다. 루나는 대답 대신, 솔라의 그림에서 ‘분류 담당자’와 ‘추출 담당자’를 잇는 첫 번째 화살표를 손가락으로 가리켰다.

“이 화살표 위에서 오고 가는 게 뭘까? ‘분류 담당자’가 일을 끝내고 ‘추출 담당자’에게 무언가 넘겨줘야 할 텐데.”

“음… ‘이 문서는 계약서다’라는 정보?”

솔라가 대답했다. 그러자 루나가 곧바로 질문을 이었다.

“좋아. 그럼 계약서가 아니라 세금계산서가 들어오면? 아니면 그냥 평범한 이메일이라면? 그때도 추출 담당자에게 똑같이 넘겨줘?”

“아니지. 세금계산서면 공급자나 금액을 뽑아야 하고, 계약서면 계약 기간이나 당사자를 뽑아야 하니까 추출 방식이 다를 거고… 이메일이면… 그냥 분석할 필요 없다고 알려줘야지.”

순간 솔라의 손이 멈칫했다. 그녀의 머릿속에서 하나의 화살표가 여러 갈래로 쪼개졌다. 하나의 길이 아니었다. 갈림길이었다. 그녀는 연필을 들어 기존의 화살표를 지우고, ‘분류 담당자’ 뒤에 다이아몬드 형태의 기호를 그린 뒤 세 갈래의 새로운 화살표를 그렸다. 각각 ‘계약서 처리’, ‘세금계산서 처리’, ‘처리 불가’라는 목적지를 향해서. 깔끔하던 직선도로가 복잡한 교차로로 변했다.

루나는 한 박자 늦게 입을 열었다.

“바로 그거야. 방금 솔라 네가 그린 그 갈림길이 포함된 지도가 바로 ‘워크플로우(Workflow)’야. Supervisor가 사용자 요청에 따라 동적으로 만들어내는 실행 계획이지. 고정된 공장 라인이 아니야.”

루나는 솔라의 연필 끝이 머물고 있는 다이아몬드 기호를 가리켰다.

“그리고 그 갈림길에서 어떤 길로 가야 할지 알려주는 신호등이 필요하겠지? ‘이 문서는 계약서다’ 혹은 ‘이 문서는 세금계산서다’ 같은 정보. 그게 바로 시스템의 현재 ‘상태(State)’야.”

솔라의 눈이 커졌다. Workflow Spec과 State 정의서가 왜 별도로 필요한지 단번에 이해됐다. Workflow Spec은 가능한 모든 경로와 갈림길을 그려놓은 전체 ‘지도’였다. 그리고 State 정의서는 그 지도의 각 지점에서 어떤 ‘상태’ 정보(예: document_type: 'contract')가 다음 경로를 결정하는지 정의하는 ‘범례’와 같았다. 이 둘은 떼려야 뗄 수 없는 한 쌍이었다.

“아…! 알겠다. Supervisor Agent가 이 ‘상태’를 보고 다음 단계를 결정하는 거구나! ‘문서 종류가 계약서’라는 상태를 확인하고, 워크플로우 지도에서 ‘계약서 추출’ 경로를 골라 추출 담당자에게 일을 시키는 거네. 그러니까 맨 처음 정의한 Agent들의 역할이 이 워크플로우와 상태 설계에 직접적으로 연결되는 거였어.”

솔라는 자신이 그린 복잡한 그림을 다시 보았다. 이제 이것은 더 이상 단순한 순서도가 아니었다. Supervisor Agent의 지휘 아래, 각 Agent들이 어떤 정보를 주고받으며 유연하게 협력하는지를 보여주는 살아있는 작전 지도였다. 개별적으로 보였던 Agent 정의서, Workflow Spec, State 정의서가 ‘감독-지도-범례’라는 하나의 세트로 묶이는 순간이었다.

문득, 솔라는 그림의 한 부분을 손가락으로 짚었다. ‘검토 담당자’가 ‘추출 담당자’의 작업 결과를 확인하는 지점이었다.

“그런데 언니, 만약에 검토 담당자가 결과를 보더니 ‘이거 품질이 너무 낮아서 못 쓰겠어. 다시 추출해 와’라고 하면 어떡해? 그럼 이 화살표가 거꾸로 가야 하잖아. 몇 번이나 다시 시도해야 하지? 실패하면 그냥 끝내는 거야, 아니면 사람이 확인하게 넘겨야 하는 거야? 그런 판단의 ‘기준’은 또 어디에다 정하는 거지?”

3장: 의사결정 정책: Agent의 판단 기준

솔라의 워크플로우 지도 위에 새로운 화살표가 그려졌다. 어지러운 고리 모양이었다. ‘검토 담당자’에서 나와 ‘추출 담당자’를 향해 거꾸로 돌아가는 화살표. 그 옆에는 작은 물음표와 함께 ‘품질 낮으면?’이라는 글씨가 쓰여 있었다. 어제 완성했다고 생각했던 지도가 순식간에 미완의 숙제처럼 보였다.

그녀는 모니터에 떠 있는 설계 문서 목록의 네 번째 항목, Decision Policy(조건 분기, 반복 정책)을 쳐다보았다. 저 고리 모양의 화살표, 즉 ‘반복’을 처리하는 규칙이 저기에 담기는 걸까. 솔라는 혼자 중얼거렸다. “간단하네. 만약 품질 점수가 80점 미만이면, 재실행. 그냥 이런 if-then 규칙들을 쭉 나열해 두는 문서인가?” 하지만 그렇게 생각하니 어딘가 허전했다. 그렇게 단순한 규칙 목록이라면, 굳이 ‘정책(Policy)’이라는 거창한 이름을 붙였을까? 마치 중요한 연결고리를 놓치고 있는 기분이었다.

“언니, 이 부분 말이야.”

솔라가 자신이 그린 다이어그램의 고리 부분을 가리켰다. 루나는 솔라의 옆으로 다가와 어지러운 화살표와 물음표를 들여다보았다.

“검토 담당자가 ‘이 결과는 별로야’라고 판단했을 때, 다시 추출 담당자에게 일을 시키는 이 반복 구간. 이 판단 기준을 ‘Decision Policy’ 문서에 적는 건 알겠어. 그런데 그게 그냥 ‘만약 조건이 A이면, B를 하라’ 같은 단순한 규칙들 목록이면, 전체 워크플로우랑 어떻게 연결되는지 모르겠어. 규칙은 규칙이고, 흐름은 흐름이고. 또다시 따로 노는 느낌이야.”

루나는 대답 대신, 깨끗한 빈 종이 한 장을 가져와 솔라의 지도 옆에 나란히 놓았다. 그리고는 그 위에 작은 표 하나를 그리기 시작했다. 표의 머리에는 각각 현재 상태 (State), 조건 (Condition), 판단 (Decision)이라고 적었다.

“좋아. 그 ‘판단’이 필요한 바로 그 순간으로 가보자. 검토 담당자가 추출 담당자로부터 결과를 막 넘겨받았어. 그게 이 표의 시작이야.”

루나는 현재 상태 칸에 ‘추출 결과 검토 대기’라고 썼다.

“자, 이제 솔라 네가 규칙을 만들어 봐. 이 상태에서 다음 단계로 넘어가려면, 어떤 ‘조건’을 확인해야 할까? 그리고 그 조건에 따라 Agent는 어떤 ‘판단’을 내리게 될까?”

솔라는 연필을 들고 잠시 고민했다. ‘품질이 낮으면’이라는 막연한 생각만으로는 표의 빈칸을 채울 수 없었다. 좀 더 구체적인 기준이 필요했다.

“음… 조건은… ‘추출 결과의 신뢰도 점수가 0.8 미만이다’ 같은 거?”

솔라가 조건 칸에 그렇게 적었다.

“좋아. 그럼 그럴 때 내리는 판단은?”

“‘재추출 요청’. 다시 하라고 시켜야지.”

솔라가 판단 칸을 채워 넣었다. 표의 첫 줄이 완성되었다.

현재 상태조건판단
추출 결과 검토 대기신뢰도 점수 < 0.8재추출 요청

루나는 한 박자 늦게, 완성된 첫 줄 아래에 새로운 줄을 그었다.

“그런데, 만약 계속 신뢰도 점수가 0.8 미만으로 나오면 어떡하지? 무한정 재추출을 요청할 수는 없잖아.”

솔라의 눈이 다시 표로 향했다. 맞다. 실패에 대한 처리도 정책에 포함되어야 했다. 그녀는 현재 상태 칸에 ‘재추출 요청 중’이라고 적고, 조건 칸에 ‘재시도 횟수가 3회를 초과한다’라고 썼다.

“그럴 땐… 포기하고 사람한테 넘겨야지. ‘수동 검토 요청’.”

솔라가 마지막 판단 칸을 채웠다.

현재 상태조건판단
추출 결과 검토 대기신뢰도 점수 < 0.8재추출 요청
재추출 요청 중재시도 횟수 >= 3수동 검토 요청
추출 결과 검토 대기신뢰도 점수 >= 0.8분석 완료

“아…”

솔라의 입에서 작은 감탄사가 흘러나왔다. 표를 채우고 나니 비로소 모든 것이 연결되었다. ‘Decision Policy’는 단순한 if-then 규칙의 나열이 아니었다. 워크플로우의 특정 상태(State)와 명확하게 연결되어 있었다. Supervisor Agent는 워크플로우 지도를 따라가다가 ‘추출 결과 검토 대기’라는 상태에 도달하면, 이 표, 즉 Decision Policy 문서를 펼쳐보는 것이었다. 그리고 현재 조건(신뢰도 점수, 재시도 횟수 등)에 맞는 판단을 찾아 다음 행동(재추출, 수동 검토, 완료)을 지시하는 구조였다.

“알겠다! Decision Policy는 워크플로우라는 지도의 갈림길이나 교차로마다 서 있는 교통경찰 같은 거였네! 어떤 상태에서, 어떤 조건을 보고, 누구를 어디로 보낼지 판단하는 역할. 그래서 Workflow Spec, State 정의서, 그리고 Decision Policy가 한 묶음으로 움직여야만 했던 거구나.”

솔라는 자신이 만든 작은 표를 자랑스럽게 바라봤다. 검토 Agent가 결과를 검증하고, 품질이 낮으면 자동으로 재실행을 요청하는 이 ‘품질 보증 메커니즘’이 바로 Decision Policy를 통해 구현되는 것이었다. 더 이상 설계 문서들이 외딴 섬으로 보이지 않았다.

그때, 솔라의 시선이 표의 ‘재추출 요청’이라는 판단에 머물렀다. 이 판단에 따라 Supervisor는 추출 담당자에게 다시 일을 시킬 것이다. 그런데…

“언니, 여기서 ‘재추출 요청’을 하기로 결정했어. 그러면 추출 담당자는 아까랑 똑같은 방식으로 또 추출을 시도할 거 아냐? 그럼 똑같이 낮은 품질의 결과가 나올 확률이 높은데. 재시도를 할 거면, 뭔가 다르게 지시를 내려야 의미가 있는 거 아니야? 그 ‘다른 지시’는 어디에다 적어두지?”

4장: 프롬프트 명세: LLM을 위한 정밀 지시

솔라는 어제 만들었던 작은 표를 책상 위에 펼쳐놓고 뚫어지게 바라보고 있었다. 그녀의 펜 끝이 표의 한 줄, ‘재추출 요청’이라는 단어 위를 불안하게 맴돌았다. Supervisor Agent가 이 판단을 내리는 것까지는 알겠다. 하지만 그 다음은?

솔라는 결심한 듯 표의 오른쪽에 새로운 열을 하나 추가했다. 그리고 맨 위에 실행 지시라고 썼다. 하지만 열은 텅 비어 있었다. 이 빈칸이 어제부터 그녀의 머릿속을 떠나지 않던 질문의 구체적인 형태였다. ‘재추출 요청’이라는 결정이 내려졌을 때, 추출 담당자에게 내릴 ‘다른 지시’는 대체 무엇이고, 어디에 적어야 하는가.

“이것 봐, 언니.”

솔라가 빈칸을 손가락으로 툭툭 쳤다.

“‘재추출 요청’을 하기로 결정했어. 근데 여기서 추출 담당자한테 뭘 시켜야 할지 모르겠어. 그냥 ‘다시 해봐’라고 하면 똑같은 실수만 반복할 거 아냐. 이 빈칸에 들어갈 말이 바로 Prompt Spec에 있는 내용인 건가? 그런데 그렇게 생각하면 또 이상해. Decision Policy는 정책 문서고, Prompt Spec은 프롬프트 모음집이고. 결국 또 서로 다른 서랍에 있는 문서 같단 말이지.”

솔라의 목소리에는 짜증 섞인 혼란함이 묻어났다. 그녀의 생각 속에서 Prompt Spec은 필요할 때마다 꺼내 쓰는, 잘 정리된 명령어 목록일 뿐이었다. 이전 단계의 설계 문서들과 어떤 유기적인 관계가 있는지 전혀 보이지 않았다.

루나는 말없이 솔라가 만든 표를 들여다봤다. 그리고는 ‘재추출 요청’이라고 적힌 바로 그 줄을 손끝으로 가리켰다.

“이 판단을 내리게 된 이유가 뭐였지?”

“추출 결과의 신뢰도 점수가 0.8 미만이라서.”

“맞아. 그럼 첫 번째 시도와 지금 이 두 번째 시도 사이에는 아주 중요한 차이가 생겼어. 우리는 이제 ‘첫 시도가 만족스럽지 못했다’는 사실을 알고 있지. 그 정보를 담아서 지시를 내려야 하지 않을까?”

루나는 빈 종이 한 장을 가져와 솔라 앞에 놓았다.

“여기에 딱 이 상황, 즉 ‘신뢰도 낮은 결과를 받은 뒤 재추출을 요청하는’ 상황을 위한 프롬프트 초안을 써보자. 추출 담당자인 LLM에게 무엇을 요구해야 할까? ‘목표’는 뭐고, 이번에는 특별히 주의해야 할 ‘제약 조건’은 뭘까?”

솔라는 연필을 들었다. 막연히 ‘다른 지시’라고 생각했을 때와는 느낌이 달랐다. ‘목표’와 ‘제약 조건’이라는 틀이 생기자 생각을 구체화하기 수월했다.

“음… 목표는 똑같겠지. ‘계약서 본문에서 계약 당사자, 계약 기간, 주요 금액을 추출한다.’”

솔라가 종이 위에 첫 줄을 썼다. 하지만 곧바로 펜을 멈췄다. 이것만으로는 처음 지시와 다를 게 없었다. 루나의 말처럼 ‘실패했다는 정보’가 빠져 있었다.

솔라는 잠시 고민하더니, ‘제약 조건’이라는 소제목 아래에 새로운 내용을 추가하기 시작했다.

“제약 조건: 이전 시도에서 ‘계약 기간’ 추출의 신뢰도가 낮게 평가되었음. 특히 ‘계약 체결일’과 ‘계약 효력 발생일’을 혼동하는 경향이 있으니, ‘효력’, ‘시작’, ‘발효’ 등의 키워드와 함께 명시된 날짜를 우선적으로 고려할 것. 문서의 머리말이나 꼬리말에 있는 날짜는 제외할 것.”

초안을 다 쓰고 나자, 솔라 자신도 놀랐다. 처음의 막연했던 ‘다시 해봐’와는 비교도 안 될 만큼 정밀하고 구체적인 지시가 만들어졌다.

루나는 한 박자 늦게, 솔라가 만든 Decision Policy 표와 방금 작성한 프롬프트 초안을 번갈아 가리켰다.

“이제 보여? Prompt Spec은 그냥 명령어 목록이 아니야. Decision Policy의 특정 판단이 내려졌을 때, 그 판단의 맥락을 LLM에게 전달하는 정밀한 지시서지. ‘신뢰도 점수가 낮다’는 조건이 있었기 때문에, ‘이전 시도의 문제점을 참고해서 재시도하라’는 구체적인 제약 조건이 프롬프트에 담길 수 있었던 거야.”

“아…!”

솔라의 눈이 커졌다. 흩어져 있던 두 개의 문서, Decision PolicyPrompt Spec이 눈앞에서 하나로 단단하게 연결되는 순간이었다. Decision Policy는 단순히 다음 행동을 ‘결정’하는 데서 그치는 게 아니었다. 그 결정이 내려진 이유와 맥락 자체가, Prompt Spec을 통해 LLM에게 전달될 가장 중요한 정보가 되는 것이었다.

“알겠다! 교통경찰이 그냥 ‘저쪽으로 가세요’라고 손짓하는 게 아니라, ‘저 앞에 사고가 나서 막히니, 이 골목으로 우회해서 조심히 가세요’라고 구체적인 상황과 지침을 함께 주는 거랑 똑같네. Decision Policy가 ‘우회하라’는 판단을 내리면, Prompt Spec은 ‘어떤 사고가 났고, 어느 골목으로, 어떻게 조심히 가야 하는지’를 알려주는 내비게이션 안내문이었어.”

솔라는 자신이 썼던 프롬프트 초안을 다시 들여다봤다. 계약서 종류에 따라, 또 이전 작업의 성공 여부에 따라 매번 다른 프롬프트가 필요하다는 사실을 깨달았다. 이것이 바로 ‘컨텍스트 기반 정보 추출’의 핵심이었다.

설계 문서들이 드디어 하나의 흐름으로 꿰어지는 느낌에 잠시 뿌듯함을 느끼던 솔라의 얼굴에 다시 새로운 물음표가 떠올랐다.

“좋아, 이제 Agent 정의서가 감독을 정하고, Workflow가 지도를 그리고, State가 현재 위치를 알리고, Decision Policy가 갈림길에서 판단을 내리고, Prompt Spec이 구체적인 길 안내를 한다는 건 알겠어. 이렇게 하나씩 따라가니 연결되는 건 알겠는데… 이 모든 걸 한눈에 볼 수는 없을까? 이 부품들이 다 모여서 완성된 ‘계약서 자동 분석기’라는 기계 전체는 어떻게 생겼는지, 그 전체 설계도가 보고 싶어.”

5장: POC 통합: 유기적인 설계의 완성

솔라의 책상 위에는 커다란 빈 종이 한 장이 펼쳐져 있었다. 하지만 더 이상 빈 종이가 아니었다. 지난 며칠간의 고민이 담긴 상자들과 화살표들이 어지럽게 뒤엉켜 있었다. ‘Agent 정의서’라는 상자에서 ‘Prompt Spec’이라는 상자로 기묘하게 구부러진 화살표가 그려져 있었고, ‘Workflow’와 ‘Decision Policy’는 서로를 밀어내는 듯 멀찍이 떨어져 있었다. 마치 억지로 부품들을 끼워 맞추려다 실패한 기계의 설계도 같았다.

솔라는 이 모든 것을 한눈에 보고 싶었다. 각 부품이 맞물려 돌아가는 전체 기계의 청사진을 그리고 싶었다. 하지만 머릿속에서 각 문서의 역할이 명확해질수록, 그것들을 하나의 그림으로 합치려는 시도는 번번이 실패로 돌아갔다. Agent, Workflow, State, Decision, Prompt. 이 다섯 개의 톱니바퀴는 서로 맞물리지 않고 제자리에서 헛돌기만 했다. 각 문서가 여전히 독립적인 조각으로 남아, 전체 시스템 설계도로서의 의미를 파악할 수 없었다.

“이게 아니야.”

솔라가 결국 연필을 내려놓으며 중얼거렸다. 그녀의 목소리를 들은 루나가 조용히 다가와 어지러운 다이어그램을 내려다보았다.

“전체 설계도를 그리려던 모양이네.”

“응. 그런데 완전히 엉망진창이야. Agent 정의서가 Workflow를 부르는 건지, Decision Policy가 State를 바꾸는 건지, 누가 언제 어떤 문서를 참조하는지 순서가 뒤죽박죽이야. 연결은 해야겠는데, 이 화살표들이 어디서 시작해서 어디로 가야 할지 모르겠어.”

솔라는 답답한 마음에 자신의 그림을 손바닥으로 가렸다. 낱개의 부품은 이해했지만, 조립 설명서를 잃어버린 기분이었다.

루나는 말없이 솔라의 모니터 화면을 가리켰다. 화면 한구석에는 이 모든 고민의 시작이었던 메모장 목록이 떠 있었다.

✓ POC 프로젝트 설계 문서

▪ Agent 정의서 ▪ Workflow Spec ▪ State 정의서 ▪ Decision Policy ▪ Prompt Spec

루나는 그 목록 옆에 있던, 솔라가 엉망으로 그려놓은 종이를 치우고 새로운 빈 종이 한 장을 깔았다. 그리고는 질문을 던졌다.

“좋아, 조립 설명서를 처음부터 다시 만들어보자. 딱 하나의 계약서 파일이 우리 시스템에 들어오는 순간부터 시작하는 거야. 가장 먼저 무슨 일이 일어나지?”

솔라는 잠시 생각에 잠겼다. 복잡한 그림 대신, 이야기의 시작점을 떠올리자 머릿속이 한결 단순해졌다.

“사용자가 계약서를 올리면… 그걸 처리할 총감독, Supervisor Agent가 호출돼.”

“바로 그거야. 그려봐.”

솔라는 종이의 맨 위에 ‘Supervisor Agent’라는 상자를 그렸다.

“그럼 그 Supervisor Agent는 자신이 누군지, 어떤 팀원(분류, 추출, 검토 담당자)을 만들 수 있는지 어떻게 알지? 어떤 문서를 봐야 할까?”

“아…!” 솔라는 모니터의 목록에서 ‘Agent 정의서’를 손가락으로 짚었다. 그리고는 Supervisor Agent 상자에서 ‘Agent 정의서’라는 또 다른 상자로 ‘참조’라고 적힌 점선을 그었다. 첫 번째 연결고리가 제자리를 찾았다.

루나는 한 박자 늦게 다음 질문을 던졌다.

“자, 감독이 팀을 꾸릴 준비를 마쳤어. 이제 계약서를 처리할 ‘계획’을 세워야지. 그 계획의 전체 지도, 즉 가능한 모든 경로가 담긴 문서는 뭐였지?”

“Workflow Spec!”

솔라는 Supervisor Agent가 ‘Workflow Spec’을 참조해서 ‘Workflow 인스턴스’라는 작은 길을 만들어내는 그림을 그렸다. 길이 생겼다.

“좋아, 이제 길이 생겼고 첫 번째 담당자인 ‘분류 담당자’가 일을 시작해. 그리고 ‘이 문서는 계약서임’이라는 결과를 내놓았어. 이 결과 정보는 뭐라고 불렀지? 그리고 그 정보의 형식을 정의하는 문서는?”

“State! 그리고 State 정의서!”

솔라는 ‘분류 담당자’가 일을 마친 뒤 화살표를 그리고, 그 위에 ‘State 업데이트’라고 적었다. 그리고 그 State는 ‘State 정의서’에 의해 규격이 정해져 있다는 참조선도 잊지 않았다. 이제 지도 위에 현재 위치를 표시하는 깃발이 꽂혔다.

“이제 Supervisor는 업데이트된 State(상태)를 봤어. ‘문서 종류 = 계약서’. 이 상태에서 다음 행동을 ‘판단’하기 위해 어떤 문서를 펼쳐봐야 할까? 교차로의 교통경찰 말이야.”

“Decision Policy!”

솔라의 손이 빨라졌다. Supervisor Agent가 State를 확인한 뒤, ‘Decision Policy’ 문서를 참조해 ‘추출 담당자 호출’이라는 판단을 내리는 과정을 망설임 없이 그려 넣었다.

“마지막이야.” 루나의 목소리가 차분하게 이어졌다. “Supervisor가 ‘추출 담당자 호출’이라는 판단을 내렸어. 그럼 추출 담당자인 LLM에게 내릴 구체적인 지시, 그 내비게이션 안내문은 어디에 있지?”

“Prompt Spec!”

솔라는 마지막 화살표를 그렸다. Supervisor Agent가 Decision Policy에서 얻은 판단을 근거로, Prompt Spec에서 적절한 프롬프트를 찾아내 추출 담당자에게 전달하는 그림이었다.

솔라는 연필을 내려놓고 자신이 완성한 다이어그램을 바라보았다. 처음 그렸던 어지러운 스파게티 코드 같던 그림과는 완전히 다른, 명확한 흐름을 가진 청사진이 눈앞에 있었다. 설계 문서들은 서로 무작위로 연결된 것이 아니었다. 모든 일의 중심인 Supervisor Agent가 작업의 각 단계마다 필요한 문서를 ‘순서대로’ 참조하는 구조였다.

“알겠다….” 솔라의 입에서 탄성이 터져 나왔다. “이 문서 목록은 그냥 체크리스트가 아니었어. Supervisor Agent라는 요리사가 요리를 하기 위해 순서대로 꺼내보는 레시피 북이었던 거야. 처음엔 팀원을 확인하고(Agent 정의서), 전체 요리 과정을 그리고(Workflow Spec), 각 단계의 결과물을 기록하고(State 정의서), 갈림길에서 다음 단계를 결정하고(Decision Policy), 마지막으로 실제 조리법(Prompt Spec)을 꺼내 드는 거였어.”

그녀는 처음 이 목록을 봤을 때의 막막함을 떠올렸다. 각 항목이 서로 아무 관련 없는 외딴 섬처럼 보였다. 하지만 이제 그 섬들을 잇는 항로가, 그리고 그 항로를 따라 움직이는 ‘Supervisor’라는 이름의 배가 선명하게 보였다.

솔라는 처음 그렸던, 실패한 설계도를 망설임 없이 구겨 쓰레기통에 던져버렸다. 그리고 방금 루나와 함께 완성한, 명확한 흐름이 담긴 새 다이어그램을 자신의 모니터 옆, 원래의 설계 문서 목록 바로 아래에 붙였다. 이제 그녀에게 ✓ POC 프로젝트 설계 문서 목록은 더 이상 단순한 할 일 목록이 아니었다. 하나의 견고하고 유기적인 AI Agent 시스템을 구축하기 위한, 살아있는 통합 설계 가이드라인이었다.