대규모 언어 모델(LLM)을 이메일을 통한 인간의 승인이 필요한 워크플로우에 연결할 때, 정작 문제가 되는 것은 모델인 경우가 드뭅니다. 문제는 코드가 끝나고 편지함이 시작되는 지점에서 발생합니다. 한 번의 자율 실행이 요청을 발송합니다. 그런데 첫 번째 실행이 완료되기도 전에 또 다른 실행이 시작됩니다. 공유 편지함에는 서로 다른 프로세스에서 온 스레드들이 쌓입니다. 누군가 12시간이나 늦게 도착한 메시지에 '승인'을 클릭합니다. 이제 출력물도 있고 결정도 내려졌습니다. 하지만 어떤 실행이 무엇을 생성했는지, 혹은 그 승인이 과연 이번 생성 건에 대한 것이었는지조차 증명할 수 없습니다. 저는 수많은 내부 자동화 파이프라인을 정리해 오면서 이러한 패턴을 익혔습니다. 이는 대부분의 팀이 예상하는 것보다 훨씬 빠르게 혼란에서 사고로 번집니다.
운영의 경계 (The Operational Boundary)
오케스트레이터와 이메일 제공업체 사이의 경계는 단순한 네트워크 홉(hop)이 아닙니다. 그것은 상태의 경계입니다. LLM이 초안 작성을 마치더라도 해당 실행(run)은 여전히 살아있습니다. 대기 중인 상태입니다. 만약 시스템이 이메일 발송을 단순히 '발송 후 방치(fire-and-forget)'하는 이벤트로 취급한다면, 당신은 이미 흐름을 놓친 것입니다.
재시도 정책이 너무 공격적이어서 단일 실행이 두 개의 별도 승인 요청을 생성하는 파이프라인을 본 적이 있습니다. 또 다른 실행이 지난주 메시지가 여전히 남아 있는 메일함을 재사용하는 것도 보았습니다. 인간 승인자는 실행 ID(run ID)를 보지 않습니다. 그들은 제목과 버튼을 볼 뿐입니다. 구조가 없다면, 그들은 마케팅 뉴스레터와 모니터링 알림이 뒤섞여 있는 똑같은 편지함에서 추측에 의존하게 됩니다.
간과된 단계 (The Neglected Step)
팀들은 프롬프트를 튜닝하고, 가드레일을 추가하고, 출력물을 벤치마킹하는 데 몇 주를 보낼 것입니다. 그러고 나서 승인 단계를 Slack 채널이나 공유 지원 편지함에 연결하고는 작업이 끝났다고 생각합니다. 이는 세 가지 예측 가능한 문제를 야기합니다.
- 공유 편지함이 여러 실행에서 발생한 이벤트의 쓰레기통이 됩니다. 컨텍스트가 붕괴됩니다. 스레드를 일일이 열어 타임스탬프를 수동으로 분석하지 않고서는 어떤 메시지가 어떤 비즈니스 트랜잭션에 속하는지 재구성할 수 없습니다.
- 재시도가 증거를 덮어씁니다. 실행이 승인 요청을 재전송하면, 원래 메시지는 너무 의욕적인 이메일 클라이언트에 의해 묻히거나, 삭제되거나, 중복으로 표시될 수 있습니다. 감사 추적(audit trail)이 끊어집니다.
- 인간의 결정이 시스템 외부에 떠돕니다. 누군가 티켓이나 다이렉트 메시지(DM)로 "좋아 보이네요"라고 답장합니다. 그 의견은 워크플로우 내부의 구조화된 데이터로 전환되지 않습니다. 에이전트는 누가, 언제, 무엇을 말했는지 확인할 방법이 없습니다.
문제가 발생하여 조사해야 할 때, 당신은 전언(hearsay)에 의존하게 됩니다. "그게 맞는 이메일이었던 것 같아요." 기억은 추적 가능성이 아닙니다. 감사 로그는 짐작을 소화할 수 없습니다.
전달 상세 정보에서 체크포인트로 (From Delivery Detail to Checkpoint)
이를 해결하려면 설계 방식의 전환이 필요합니다. 이메일을 단순한 전달 수단으로 생각하는 것을 멈추십시오. 대신 시스템 체크포인트로 취급하기 시작하십시오. 이는 모든 메시지가 상태 전이(state transition)이며, 모든 상태 전이에는 신원, 권한 부여, 그리고 증거가 필요함을 의미합니다.
이러한 사고방식을 채택하면 질문이 달라집니다. 이메일이 성공적으로 발송되었는지를 묻는 대신, 어떤 실행이 이메일을 보냈는지, 어떤 증거를 남겼는지, 그리고 어떤 규칙이 워크플로우의 지속을 승인했는지를 묻기 시작합니다. 에이전트는 이메일 본문을 작성할 수 있습니다. 하지만 플랫폼은 신원 확인 및 검증 경로를 강제해야 합니다. LLM은 작가이고, 인프라는 공증인입니다.
최소 설계 (A Minimum Design)
이를 구축하는 데 큰 비용이 들지는 않습니다. 제가 제안하는 최소 기능 버전은 다섯 가지 의도적인 요소로 구성됩니다.
- 오케스트레이터는 워크플로우가 시작되는 정확한 순간에
run_id를 생성합니다. 이 식별자는 이후 모든 작업의 중추가 됩니다. 이는 절대 변하지 않으며 재사용되지도 않습니다. - 모든 이메일 작업은 세 가지 필드를 포함합니다:
run_id, "approval_request" 또는 "evidence_notification"과 같은message_type라벨, 그리고 어떤 거버넌스 규칙이 활성화되어 있는지 식별하는policy_version문자열입니다. 이를 통해 일반 메시지는 타입이 지정된 이벤트(typed event)로 변합니다. - 증거는 실행별로 격리된 편지함에 보관됩니다. 이것이 반드시 모든 실행마다 별도의 이메일 계정을 가져야 한다는 뜻은 아닙니다. 전용 라벨, 하위 폴더, 또는 한 실행의 통신이 다른 실행과 엉키지 않도록 스레드를 분리하는 라우팅 규칙을 의미할 수 있습니다.
- 승인 응답은 자유 형식의 "ok"가 아닌 구조화된 이벤트여야 합니다. 인간은 여전히 클릭하거나 답장을 하지만, 시스템은 해당 동작을
run_id, 결정 사항, 타임스탬프를 포함하는 기계 판독 가능한 페이로드(payload)로 변환합니다. - 증거와 결정 사항이 일치할 때만 흐름이 계속됩니다. 워크플로우는 승인 자체를 단독으로 신뢰하지 않습니다. LLM의 출력이 프로덕션에 도달하기 전에 원래 요청과 승인 페이로드를 대조하여 검증합니다.
유용한 체크포인트가 검증하는 것들
유용한 체크포인트는 인간의 결정을 수락하기 전에 네 가지 조건을 강제합니다.
- 수신자는 실행 컨텍스트(run context)에 속해야 합니다. 승인자가 이 특정 워크플로 인스턴스에 할당된 검토자가 아니라면, 시스템은 신호를 거부합니다.
- 대상 또는 라우팅 메타데이터가 현재 흐름 상태와 일치해야 합니다. 3단계에 대한 승인이 2단계를 건너뛸 수는 없습니다.
- 타임스탬프는 예상된 시간 범위 내에 있어야 합니다. 타임아웃 이후에 도착한 결정은 자동 통과가 아니라 새로운 검토를 트리거해야 합니다.
- 증거가 다른 실행에서 재사용되지 않아야 합니다. 동일한 메시지 ID 또는 토큰이 두 개의 별도 승인 요청에 나타나면 이는 충돌(collision)이며, 시스템은 중단되어야 합니다.
실제 비용
이 패턴은 공짜가 아닙니다. 더 많은 메타데이터를 저장해야 합니다. 누군가 유지 관리해야 하는 정책 계층이 추가됩니다. 팀이 인간의 결정을 단순한 코멘트가 아닌 구조화된 데이터로 기록하도록 강제해야 합니다. 관료주의처럼 보일 수 있지만, 실제로는 매우 훌륭한 거래입니다.
명확성을 위해 속도를 맞바꾸는 것입니다.
