LLMOps 20

AI Agent 워크플로우에 HITL '꽂기': '거절'을 '통제'로 전환하는 법

HITL 개념을 배워도 기존 그래프에 어느 지점에 꽂아야 하는지 막힌다.

근거 · 교안 p59-p60

AI Agent 워크플로우에 HITL '꽂기': '거절'을 '통제'로 전환하는 법 대표 이미지

1장: 기존 AI Agent의 ‘거절’ 흐름 진단하기

솔라는 노트북 화면에 떠 있는 워크플로우 다이어그램과 자신의 노트를 번갈아 보며 미간을 찌푸렸다. ‘문서 자동 분석 Agent에 HITL(Human-In-The-Loop) 붙이기’. 과제 제목은 명쾌했지만, 솔라의 손은 어디서부터 시작해야 할지 몰라 허공을 맴돌았다.

분명 개념은 이해했다. AI Agent가 스스로 판단하기 어려운 일을 만났을 때, 사람이 개입해서 최종 결정을 내리는 안전장치. 필요할 때만 호출되는 인간이라는 ‘노드(Node)’. 거대한 시스템의 흐름을 통제하는 ‘Control Layer’. 머릿속에서는 그럴듯한 설명들이 둥둥 떠다녔다.

하지만 눈앞의 다이어그램은 다른 이야기를 하고 있었다.

[Planner: 계획 수립][Executor: 계획 실행][Critic: 결과 평가]

여기까지는 좋았다. 문제는 그다음이었다. Critic의 평가 결과에 따라 길이 두 갈래로 나뉘었다.

  • APPROVED (승인)[종료]
  • REJECTED (거절)[Planner로 돌아가기]

솔라는 ‘REJECTED’에서 ‘Planner’로 곧장 이어지는 화살표를 손가락으로 가리켰다. “아니, 그래서 HITL을 어디에 ‘꽂아야’ 하냐고….” 혼잣말이 새어 나왔다. Critic이 ‘거절’하면 시스템은 곧바로 재계획에 들어간다. 인간이 끼어들 틈이 보이지 않았다. Critic을 사람으로 바꾸라는 뜻일까? 아니면 ‘REJECTED’라는 결과 자체를 무시하고 새로운 길을 만들어야 하는 걸까. 아는 단어들이 실제 문제 앞에서 무력하게 느껴졌다.

그때, 조용히 책을 읽고 있던 언니 루나가 솔라의 중얼거림을 들었는지 시선을 들어 노트북 화면을 살짝 훑어보았다.

“그 화살표가 마음에 안 드는구나.”

“응. Agent가 실패하면 그냥 바로 다시 하잖아. 멈추질 않아. 여기에 사람을 넣어야 한다는데, 도대체 어디에? 이 빽빽한 자동화 공정에 사람을 세워둘 자리가 안 보여.”

솔라는 마치 컨베이어 벨트에서 불량품을 발견했지만, 멈춤 버튼이 어디 있는지 몰라 발만 동동 구르는 심정이었다.

루나는 잠시 생각하더니, 솔라의 책상에 놓인 빈 노트를 조용히 솔라 쪽으로 밀었다. 그리고는 펜 하나를 그 위에 올려두었다.

“좋아. 그럼 그 ‘사람’은 잠시 잊어보자.”

“사람을 잊어? HITL을 하라면서?”

“딱 1분만. 그 복잡한 HITL 개념, Control Layer, 전부 다 머릿속에서 지우고. 지금 솔라 네가 보고 있는 저 다이어그램, 그 Agent가 원래 어떻게 작동하는지만 이 새 종이에 그려봐. 아주 단순하게.”

솔라는 의아했지만, 루나의 차분한 제안에 못 이기는 척 펜을 들었다. 뭐가 달라지겠냐는 생각이었지만, 일단 그려보기로 했다.

먼저 네모 상자 세 개를 그렸다. Planner, Executor, Critic. 그리고 각 상자를 화살표로 이었다. 이제 마지막 분기점. 솔라는 Critic 상자에서 뻗어 나가는 두 개의 화살표를 그렸다. 하나는 APPROVED라고 이름 붙이고 종료 상자로 연결했다.

그리고 다른 하나. REJECTED.

솔라는 잠시 펜을 멈췄다. 그리고는 노트북 화면의 다이어그램을 다시 한번 확인하고, REJECTED 화살표 끝을 Planner 상자의 입구로 망설임 없이 연결했다.

그림이 완성되자 솔라는 자기가 그린 것을 물끄러미 내려다보았다. 너무나도 당연한 그림이었다. 그런데 이상했다. 아까 노트북 화면으로 볼 때와는 무언가 느낌이 달랐다. 종이 위에는 그 어떤 외부로 통하는 문도, 잠시 멈춰 설 공간도 없는 완벽한 폐쇄 루프(Closed Loop)가 그려져 있었다.

“아…”

솔라의 입에서 나직한 탄성이 터져 나왔다.

“그냥… 정말로 돌아가는 것뿐이었네.”

“뭐가?”

“이 Agent 말이야. ‘거절’이라는 건 그냥 ‘다시 해!’라는 자동 신호일 뿐이었어. 사람이 끼어들 틈 같은 건 처음부터 있지도 않았던 거야. 난 자꾸만 기존 시스템 어딘가에 비어있는 ‘플러그’가 있을 거라고 생각했는데… 없어. 그런 건.”

솔라는 자신이 그린, REJECTED에서 Planner로 향하는 단호한 화살표를 손끝으로 톡톡 쳤다. 그것은 선택이나 고민의 여지가 없는, 기계적인 반사 작용처럼 보였다. 실패는 곧 재시도였다. 그 사이에는 0.1초의 망설임도, 다른 가능성도 존재하지 않았다.

루나가 조용히 고개를 끄덕이며 솔라의 노트에 적힌 문장을 가리켰다.

기존 Critic 결과 : REJECTED → 재계획

“네가 아까부터 보고 있던 그 문장이, 바로 그 화살표를 설명하는 규칙이었던 거지.”

솔라는 그제야 깨달았다. 그 문장은 HITL을 설명하기 위한 전제가 아니었다. HITL이라는 새로운 부품을 장착하기 전, 순정 상태의 엔진이 어떻게 돌아가는지를 보여주는 ‘기준선’이었다. 자신이 바꿔야 할 대상 그 자체였다.

“그렇구나. 이건 우리가 지금부터 고쳐야 할 ‘원래 흐름’이구나. 당연한 기본값이라고 생각했는데, 이게 바로 문제 정의였어.”

솔라는 방금 전 자신이 그린 단순한 다이어그램을 보았다. 이제 그것은 더 이상 복잡한 문제의 축소판이 아니었다. 앞으로 무엇을 해야 할지를 명확하게 알려주는 한 장의 지도가 되어 있었다.

솔라는 REJECTEDPlanner를 잇는 화살표 위에 펜을 가져다 댔다.

“좋아. 그럼 이제 문제는 명확해졌어. 이 자동 연결을 ‘끊고’ 시작해야 한다는 거잖아.”

하지만 솔라의 마음속에는 새로운 질문이 떠올랐다. 이 당연해 보이는 연결을 끊는다면, 그 빈자리에는 정확히 무엇을, 어떻게 연결해야 원래의 목적을 달성할 수 있을까? 단순히 선을 자르는 것과 새로운 부품을 제대로 ‘꽂는’ 것은 전혀 다른 차원의 문제였다.

2장: HITL, ‘거절’ 지점에 ‘꽂히다’

솔라는 방금 전 자신이 그린 워크플로우 다이어그램 위에 펜을 들고 잠시 허공에 멈췄다. Critic 상자에서 나와 Planner로 되돌아가는 REJECTED 화살표. 모든 문제의 근원처럼 느껴지는 완고한 자동화의 고리였다. 더 이상 망설일 필요가 없었다. 솔라는 검은 펜으로 그 화살표 위를 두 줄로 단호하게 그어 지워버렸다.

‘딸깍’. 마치 기계의 부품 하나가 제거된 듯한 상상 속 소음이 들렸다. 이제 다이어그램에는 명백한 ‘끊김’이 생겼다. CriticREJECTED라는 결과를 외치지만, 그 신호는 어디에도 가닿지 못하고 허공에 멈춰 있었다. 문제를 해결하려다 시스템 전체를 멈춰버린 셈이었다. 솔라는 펜 끝으로 빈 공간을 톡톡 건드렸다.

“연결을 끊는 것까지는 알겠는데….”

그럼 이 빈자리는 어떻게 채워야 할까. 솔라의 머릿속은 다시 복잡해졌다. Agent의 메인 워크플로우 바깥에 별도의 감시 시스템이라도 만들어야 하나? REJECTED 신호가 발생하면 그 시스템이 울려서 사람에게 알려주는, 일종의 ‘경보 시스템’ 같은 걸까? 하지만 그랬다간 시스템이 두 개가 되어버린다. 원래 흐름과 인간 개입 흐름이 따로 놀게 될 것 같았다. ‘Control Layer’라는 말이 무색해지는 순간이었다.

그때, 솔라의 고민을 지켜보던 루나가 조용히 손을 뻗었다. 루나의 손가락은 솔라의 노트북 화면이 아닌, 솔라가 참고하려고 펼쳐둔 교안의 한 문장을 가리켰다. 솔라는 아까부터 그냥 훑어보기만 했던 그 문장을 비로소 제대로 마주했다.

수정 Critic 결과 : REJECTED → HITL

“새로운 규칙이네.”

루나의 나지막한 목소리에 솔라는 고개를 들었다.

“네가 방금 지운 그 길 대신, 새로 놓으라는 이정표 같지 않아?”

솔라는 다시 자신의 다이어그램과 그 문장을 번갈아 보았다. 이전 규칙은 REJECTED → 재계획이었다. 그리고 새로운 규칙은 REJECTED → HITL이었다. 구조가 놀랍도록 똑같았다. 화살표의 목적지만 바뀐 것뿐이었다.

“아…!”

솔라는 깨달았다. HITL은 워크플로우 바깥에서 신호를 엿듣는 별도의 감시탑이 아니었다. 기존 흐름을 끊어낸 바로 그 자리에 대신 들어가는, 새로운 ‘정거장’이었다.

솔라는 아까 그었던 두 줄의 삭선(削線)을 지우개로 깨끗이 지웠다. 그리고는 CriticREJECTED 출구에서부터 새로운 화살표를 그리기 시작했다. 화살표의 끝은 Planner가 아니었다. 솔라는 화살표 끝에 새로운 네모 상자를 그리고, 그 안에 또렷하게 세 글자를 적었다.

HITL

완성된 다이어그램은 이전보다 더 복잡하지도, 더 단순하지도 않았다. 그저 REJECTED라는 갈림길에서 가야 할 목적지가 Planner에서 HITL로 바뀌었을 뿐이었다. 멈춤 없이 무한 반복하던 컨베이어 벨트에서, 불량품이 나오면 일단 ‘검수대’로 빠지도록 레일을 전환한 것과 같았다.

“꽂는다는 게… 정말로 그냥 이 자리에 꽂는 거였구나.”

솔라는 허탈한 웃음을 터뜨렸다. 복잡한 인터페이스나 새로운 통신 규약을 상상했지만, 진실은 훨씬 단순했다. ‘거절’이라는 결과가 나왔을 때, 기계에게 다시 하라고 소리치는 대신, 옆에 있던 사람을 돌아보게 만드는 것. 그게 전부였다.

수정 Critic 결과 : REJECTED → HITL 이라는 문장은 이제 더 이상 추상적인 개념이 아니었다. 그것은 워크플로우라는 지도 위에서, ‘REJECTED’라는 길 끝에 있는 낡은 ‘재계획’ 표지판을 떼어내고 ‘인간 검토’라는 새 표지판을 박아 넣으라는, 명확하고 구체적인 시공 지침이었다.

“좋아, 이제 Agent가 길을 잃고 헤맬 일은 없겠네. 문제가 생기면 무조건 나를 찾아올 테니까.”

솔라는 만족스럽게 자신의 수정된 다이어그램을 바라보았다. 이제 Agent는 실패했을 때 무작정 다시 시도하는 대신, 인간의 개입을 기다리는 상태로 멈출 것이다. 자동화된 ‘거절’이 통제 가능한 ‘멈춤’으로 바뀌는 순간이었다.

하지만 이내 새로운 질문이 고개를 들었다. 솔라는 HITL이라고 적힌 상자를 펜 끝으로 가리켰다. 화살표가 상자로 들어오기만 할 뿐, 나가는 길이 없었다.

“그런데 언니, Agent가 날 찾아왔어. 그래서 그다음은? 이 HITL 상자 안에서는 무슨 일이 벌어지는 거지? 내가 여기서 ‘OK’라고 할 수도 있고, ‘다시 해봐’라고 할 수도 있잖아. 그 결정에 따라서 이 멈춰버린 Agent는 어떻게 움직이는 거야?”

3장: 인간의 결정: ‘종료’ 또는 ‘재계획’ 통제하기

솔라는 자신이 수정한 워크플로우 다이어그램을 내려다보았다. Critic에서 Planner로 향하던 화살표는 지워졌고, 그 빈자리에는 REJECTED 출력을 받아내는 HITL이라는 새로운 상자가 자리 잡았다. 흐름은 이제 이곳에서 멈췄다. 들어오는 길은 있지만, 나가는 길이 없는 막다른 골목이었다. Agent가 실패했을 때 무작정 재시도하는 대신 일단 멈추게 하는 데는 성공했지만, 이 멈춰버린 Agent를 다음 어디로 보내야 할지 정할 수가 없었다.

그녀는 펜을 들어 HITL 상자에서 뻗어 나가는 두 갈래의 희미한 점선을 그렸다. 하나는 다이어그램의 오른쪽 끝에 있는 ‘종료’를 향했고, 다른 하나는 왼쪽의 ‘Planner’를 향해 구부러졌다. 하지만 확신이 없었다. 솔라는 두 점선 위에 각각 커다란 물음표를 그려 넣었다. 이 두 갈래 길을 선택하는 기준은 무엇이며, 자신의 선택이 정말로 Agent의 다음 행동을 강제할 수 있을까? 만약 자신의 결정이 단순한 ‘권고’에 그친다면, 이 모든 설계는 의미가 없었다.

솔라의 물음표를 가만히 들여다보던 루나는 대답 대신, 다시 한번 교안의 다른 문장을 조용히 가리켰다. 솔라가 앞서 ‘이정표’라고 생각했던 문장 바로 아래에 적혀 있던, 더 구체적인 행동 지침이었다.

사람의 입력 : approve → 종료 replan → Planner 재진입

“이건… 내가 할 수 있는 선택지 목록인가?”

“선택지 목록이기도 하고, 그 선택이 어떤 결과를 만드는지에 대한 ‘규칙’이기도 하지.”

루나의 말에 솔라는 문장을 다시 읽었다. approve종료로, replanPlanner 재진입으로 이어진다. 여기에는 ‘참고하여’나 ‘고려하여’ 같은 모호한 단어가 없었다. 마치 컴퓨터 코드의 if-else 구문처럼, 입력에 따라 출력이 명확하게 결정되는 구조였다. 인간의 판단이 단순한 권고가 아니라, 시스템의 다음 행동을 결정하는 직접적인 명령이었던 것이다.

“아…! 내가 그냥 ‘좋아’나 ‘다시 해’라고 말하는 게 아니구나.”

솔라는 깨달았다. HITL이라는 정거장에 멈춰 선 Agent에게 인간이 내려주는 것은 애매한 감상평이 아니었다. approve 또는 replan이라는, 시스템이 알아들을 수 있는 명확한 신호였다. 그리고 시스템은 그 신호에 따라 약속된 다음 행동을 기계적으로 수행할 뿐이었다. 인간은 이 순간만큼은 시스템의 일부, 즉 의사결정을 내리는 ‘노드’ 그 자체가 되는 것이었다.

솔라는 다시 펜을 들었다. 이제 HITL 상자의 텅 빈 내부를 채울 차례였다. 그녀는 먼저 상자 안에서 두 갈래로 뻗어 나가는 화살표를 그리기 시작했다. 물음표가 그려졌던 희미한 점선을 지우고, 그 위에 분명한 실선을 그었다.

첫 번째 화살표는 HITL 상자를 빠져나와, 다이어그램의 가장 오른쪽에 있던 종료 상자로 향했다. 솔라는 그 화살표 위에 ‘approve’라고 작게 적었다. Agent가 제시한 결과가 비록 REJECTED되었지만, 인간이 보기에 이만하면 충분하다고 판단했을 때 선택하는 길. 무한 반복의 고리를 끊고 작업을 끝내는 탈출구였다.

두 번째 화살표는 달랐다. 그 화살표는 HITL 상자를 나와, 다시 저 멀리 왼쪽에 있는 Planner 상자로 향했다. 원래 REJECTED가 향하던 바로 그 목적지였다. 솔라는 이 화살표 위에도 ‘replan’이라고 적었다. Agent의 계획이 정말로 잘못되었으니, 처음부터 다시 계획을 짜라고 돌려보내는 길. 하지만 중요한 차이가 있었다. 이전에는 기계가 자동으로 이 길을 택했지만, 이제는 인간의 명시적인 ‘재계획’ 명령이 있어야만 열리는 길이 된 것이다.

다이어그램이 마침내 완성되었다. 솔라는 자신이 그린 전체 워크플로우를 가만히 응시했다. 처음에는 어디에 꽂아야 할지조차 막막했던 HITL이 이제는 제자리를 찾았을 뿐만 아니라, 그 내부에서 어떤 일이 벌어지는지까지 명확해졌다.

Planner에서 시작된 작업은 Critic의 평가를 거친다. 만약 REJECTED라면, 이제 Agent는 HITL이라는 인간 검수관에게 온다. 그리고 인간은 두 개의 버튼 중 하나를 누른다. ‘approve’ 버튼을 누르면 작업은 그대로 종료된다. ‘replan’ 버튼을 누르면, Agent는 처음으로 돌아가 계획을 다시 짠다.

“이제야 알겠어.”

솔라는 만족스러운 표정으로 말했다.

거절을 무한 반복하는 게 아니라, 거절이 오면 일단 멈춰서 나에게 선택권을 넘기는 거였구나. 자동화를 멈추는 게 아니라, 자동화의 방향을 내가 통제하는 거였어.”

사람의 입력 : approve → 종료 replan → Planner 재진입

그 문장은 더 이상 복잡한 규칙의 나열이 아니었다. 인간에게 시스템의 고삐를 넘겨주는, 가장 확실한 권한 위임장이었다. 솔라는 이제 문서 자동 분석 Agent를 만들 때, Critic이 부정적인 결과를 내놓았을 때 어떤 일이 벌어져야 하는지 자신 있게 설계할 수 있었다. 그것은 더 이상 막연한 두려움의 대상이 아니라, 명확한 두 갈래 길을 가진 ‘인간 결정의 분기점’을 만드는 구체적인 작업이었다. 솔라는 완성된 다이어그램을 가볍게 두드리며, 곧 시작할 실습 프로젝트의 첫 단계를 머릿속으로 그렸다.