이 프로세스의 게이트웨이에는 이런 이름이 붙어 있다. “ConfDecay over_trust_gap 0.2 초과 OR final 4.5 이상 OR 런타임 경보?” 조건이 다이어그램에 문자열로 박혀 있다는 게 이 배치의 전부다. AI 워크플로를 진단하는 도구 자체를 BPMN 프로세스로 그리고, 코드 에이전트를 그 안의 노드 하나로 넣었다. 프로세스 엔진을 에이전트를 감싸는 껍데기로 쓰는 것과 판단의 축으로 쓰는 것이 어떻게 다른지, 그리고 그 위에서 실제로 걸린 문제 셋을 적는다.
3편은 사람 개입 게이트를 담당자 판단이 아니라 계산이 발화시키게 만든 설계로 끝났다. 남은 질문은 그 게이트를 어디에 거느냐다.
진단을 프로세스로 그리면 이렇게 된다
프로세스 정의 파일을 열어 요소를 세면 시작 이벤트 1개, 종료 이벤트 2개, 배타 게이트웨이 3개, 병렬 게이트웨이 2개, 서비스 태스크 9개, 사람 태스크 1개다. 합쳐서 흐름 객체 18개, 이들을 잇는 흐름 20개.

읽는 순서는 왼쪽부터다. 워크플로 다이어그램이 올라오면 문서 이해 기능을 쓰는 파서 태스크가 받고, 첫 배타 게이트웨이가 “AI 개입 노드가 하나 이상인가”를 판정한다. 아니면 진단 없이 종료된다.
맞으면 병렬 게이트웨이가 세 갈래로 벌린다. 일반 실패, 보안, 핸드오프. 세 축이 각각 서비스 태스크로 그려져 있고 다시 병렬 게이트웨이에서 합쳐진다. 그다음 사고 사례 검색과 완화안 정리가 붙고, 두 번째 배타 게이트웨이가 사람 검토 여부를 가른다.

배포된 실행에서 이 진단 구간은 코드 에이전트 하나가 맡는다. 진입점은 coded_agent_wrapper.py의 run()이고, 안에서 도는 순서는 이렇다.
| 단계 | 하는 일 | 성격 |
|---|---|---|
| 파싱 | 노드 인벤토리 표를 읽어 노드 목록으로 | 결정적 |
| 후보 선별 | 온톨로지에 셀이 있는 노드만 채점 대상으로 | 결정적 |
| 근거 검색 | 사고 사례 코퍼스에서 노드별 선례 조회 | 검색 기반 |
| 핸드오프 지표 | 노드 쌍마다 IPS·확신도 감쇠·판정 계산 | 병렬 실행 |
| 합산과 게이트 판정 | 축 가중합, 색 판정, 게이트 조건 평가 | 결정적 |
전체가 약 33초다. 반환값은 셋이다. 노드별 진단 목록, 최고 점수, 그리고 사람 검토 필요 여부.
이 셋 중 프로세스가 실제로 읽는 것은 마지막 하나다. 게이트웨이는 불리언 하나만 본다. 판정 로직은 에이전트 안에 있고 프로세스는 결과만 소비하기 때문에, 임계값이 바뀌어도 프로세스 정의는 그대로다.
조건이 다이어그램에 적혀 있다
두 번째 게이트웨이의 이름은 이렇게 돼 있다.
ConfDecay over_trust_gap > 0.2 OR final ≥ 4.5 OR runtime alert?
이게 이 배치의 핵심이다. 게이트가 무슨 조건으로 열리는지가 프로세스 그림 위에 문자열로 있다. 규제 담당자가 저장소를 열지 않아도, 파이썬을 읽지 않아도, 다이어그램만 보고 “과신 격차 0.2를 넘으면 사람에게 온다”를 확인할 수 있다.
같은 조건이 코드에도 있다. evaluate_hitl()이 최종 점수, 과신 격차, 의도 보존 점수, 판정 점수를 차례로 보고 걸리는 이유를 문자열로 쌓아 반환한다. 다이어그램의 이름은 그 함수의 사람이 읽는 판이다. 둘이 어긋나면 안 되니 임계값은 코드 한 곳에 모아 뒀고, 계약 객체에 박혀 있어서 다른 실행 경로들도 같은 값을 읽는다.
입력은 어디까지 물려 있나
프로세스 맨 앞의 파서 태스크는 문서 이해 기능을 쓴다. 다만 코드 에이전트가 실제로 파싱하는 것은 마크다운 노드 인벤토리 표다. 노드 아이디, 기능, AI 개입 방식이 열로 들어 있는 표.
저장소에는 BPMN XML 파서, 머메이드 파서, 이미지를 멀티모달 모델로 읽어 머메이드로 바꾸는 모듈이 각각 들어 있다. 이미지 경로는 그림을 머메이드 텍스트로 옮긴 뒤 머메이드 파서를 재사용하는 구조다. 세 파서 모두 동작하지만 UiPath 경로의 코드 에이전트에는 아직 안 물려 있고, 엔진 쪽에도 “raw BPMN XML은 아직 자동 변환되지 않는다”는 주석이 그대로 남아 있다.
입력 형식을 넓게 열어야 하는 이유는 실무 사정이다. 배포 전 점검이 필요한 시점에 워크플로가 표준 형식 파일로 관리되는 경우는 드물다. 설계 회의에서 그린 화이트보드 사진이거나, 슬라이드에 붙은 도형 묶음이거나, 문서 안의 다이어그램이다. 입력을 BPMN 파일로 좁히면 점검 전에 워크플로를 다시 그리는 작업이 먼저 붙고, 그 순간 이 도구는 다시 프로젝트가 된다.
다만 지금 상태를 있는 그대로 적으면, 넓게 여는 설계는 있고 배선은 절반이다.
래퍼로 쓰는 것과 축으로 쓰는 것
프로세스 엔진 위에 에이전트를 올리는 방법은 둘이다. 겉으로는 비슷한데 판단이 어디 있느냐가 다르다.
| 구분 | 래퍼로 쓸 때 | 축으로 쓸 때 |
|---|---|---|
| 게이트 위치 | 에이전트 코드 안 조건문 | 프로세스 정의의 게이트웨이 |
| 상태 소유 | 에이전트 프로세스 | 프로세스 엔진 |
| 사람 개입 | 에이전트가 알림을 보냄 | 프로세스가 사람 태스크에서 대기 |
| 감사 기록 | 로그 파일 | 실행 이력 자체 |
| 규칙 변경 | 코드 수정과 배포 | 프로세스 정의 편집 |
| 비개발자 열람 | 코드를 읽어야 함 | 다이어그램으로 읽힘 |
마지막 두 줄이 이 프로젝트에서 결정적이었다. 자동 승인 노드에 사람 검토를 걸었다는 사실을 증명할 때, 코드 저장소의 조건문을 캡처해 제출하는 것과 프로세스 다이어그램의 게이트웨이를 가리키는 것은 받아들여지는 무게가 다르다.
상태 소유도 같은 얘기다. 사람 검토 태스크는 며칠씩 대기할 수 있다. 에이전트 프로세스가 상태를 들고 있으면 재시작과 배포와 장애가 전부 위험이 되고, 대기 중인 건이 여러 개면 각각을 추적할 장치를 따로 만들어야 한다. 프로세스 엔진의 지속 실행에 맡기면 대기 중인 인스턴스가 목록으로 관리되고 누가 언제 승인했는지가 실행 이력에 남는다.
3편에서 자동 승인 노드의 필수 완화안으로 판단 근거 추적의 영구 보존을 꼽았는데, 그 보존을 별도 기능으로 만들지 않고 실행 이력에 얹을 수 있는 것도 이 배치 덕분이다. 자동 승인된 건을 되짚을 때 필요한 것은 그 시점의 진단 결과, 게이트 판정, 승인자인데 셋 다 이력 안에 있다.
---
config:
look: handDrawn
theme: neutral
---
flowchart TD
subgraph W["래퍼 배치"]
W1["프로세스 엔진"] --> W2["에이전트<br/>판단 · 게이트 · 알림"]
W2 --> W3["로그 파일"]
end
subgraph S["축 배치"]
S1["프로세스 정의<br/>게이트웨이 · 사람 태스크"] --> S2["에이전트<br/>채점만"]
S2 --> S1
S1 --> S3["실행 이력 = 감사 기록"]
end이 배치가 공짜는 아니다
축으로 쓰는 대가는 유연성이다. 게이트 조건을 프로세스 정의에 적어 두면 조건을 바꿀 때 프로세스를 수정하고 다시 배포해야 한다. 코드 안 조건문이면 설정 값 하나로 끝날 일이 다이어그램 편집이 된다.
에이전트가 할 수 있는 일도 좁아진다. 진단 도중에 “이건 사람에게 물어봐야겠다”고 스스로 판단해 흐름을 바꾸는 설계는 이 배치에서 안 된다. 에이전트는 값을 돌려줄 뿐이고 분기는 밖에서 일어난다.
그래서 이 선택은 용도에 달렸다. 탐색적으로 도는 에이전트라면 래퍼 쪽이 맞다. 산출물이 규제 대응 자료로 쓰이고 게이트의 존재 자체를 증명해야 하면 축 쪽이 맞다. 유연성과 증명 가능성 중 무엇이 필요한지가 먼저 정해져야 배치가 정해진다.
왜 BPMN이었나
에이전트 여러 개를 엮는 방법은 여러 갈래다. 감독자 에이전트를 두거나, 그래프로 엮거나, 상태 기계로 짜거나, 코드에 순서를 박거나. 멀티 에이전트 워크플로 6 패턴에서 정리했듯 선택지는 넉넉하다.
BPMN을 고른 기준은 표현력이 아니라 둘이었다. 사람 태스크가 표기법 안에 1급 요소로 들어 있다는 것, 그리고 이 표기법이 20년 넘게 업무 프로세스를 그리는 표준으로 쓰였다는 것.
앞의 것은 기능 문제다. 감독자나 그래프 방식에서 사람 승인 대기를 넣으려면 대기 상태와 재개 지점을 직접 만들어야 한다. BPMN에서는 사람 태스크가 이미 있고 대기와 재개가 엔진의 기본 동작이다.
뒤의 것은 사람 문제다. 규제 담당자와 감사 인력은 프로세스 다이어그램을 읽어 왔다. 새 표기법을 배우게 하지 않아도 게이트가 어디 있는지 짚을 수 있다. 노코드는 잡아먹힐까, 더 귀해질까에서 다룬 결정적 스캐폴드 논지가 여기서 실물로 나온다. 언어 모델의 판단을 감싸는 뼈대는 결정적이어야 하고, 그 뼈대가 조직이 이미 읽을 줄 아는 표기법이면 설득 비용이 한 번 더 줄어든다.
세 축을 병렬로 벌린 이유
캔버스에서 파서 뒤에 병렬 분기가 있고 세 축이 갈라진다. 이 분기를 프로세스 정의에 노출한 것도 의도한 선택이다.
한 덩어리로 채점하고 결과만 세 축으로 나눠 보여줄 수도 있었다. 그러면 축 하나가 실패했을 때 진단 전체가 실패한다. 병렬로 두면 축 하나가 외부 참조 문제로 막혀도 나머지 결과는 남고, 어느 축이 빠진 채 나온 진단인지가 산출물에 표시된다.
이 성질이 실제로 쓰였다. 임베딩 모델이 없는 환경에서 돌리면 핸드오프 런타임 지표가 계산되지 않는다. 엔진은 그때 축소 모드 표시를 붙이고 “임베딩 모델이 없어 핸드오프 지표를 건너뜀”이라는 메모를 결과에 남긴 뒤 온톨로지 조회만으로 채점을 끝낸다. 3편에서 본 최고 4.76에 RED 세 개가 그 상태의 결과이고, 지표까지 켜면 4.88에 RED 네 개가 된다. 온톨로지를 갱신할 때마다 이 축소 모드 결과로 회귀를 확인한다. 근거와 참조가 두꺼워져도 판정이 그대로인지 보는 것인데, 8월 갱신에서도 법무 RED 세 개와 신용 심사 RED 세 개가 이전과 같았다. 전부 아니면 전무로 만들지 않은 덕에 축소라는 상태가 존재할 수 있었다.
플랫폼 위에서 실제로 걸린 것들
설계대로 도는 데까지 걸린 문제가 셋이다. 둘은 플랫폼 쪽 문제로 확인돼 공개 포럼에 등록했고 하나는 패키징 문제였다.
| 문제 | 증상 | 처리 |
|---|---|---|
| 솔루션 게시 | Maestro 흐름이 포함된 솔루션 배포 시 도구 팩토리를 찾지 못함 | 디버그 실행 경로로 우회 |
| 사람 태스크 자동 생성 | 케이스 폴더와 앱 폴더 바인딩이 어긋나 태스크 조회 실패 | 사람 검토를 분리해 시연 |
| 서버리스 패키징 | 에이전트 실행 시 환경 준비 단계에서 실패 | 휠 파일 선택 명시와 의존성 분리 |
세 번째가 가장 오래 걸렸다. 원인이 두 겹이었다. 패키징 설정에 어떤 파일을 담을지 지정돼 있지 않아 빌드가 대상을 결정하지 못했고, 검색과 임베딩에 쓰는 무거운 라이브러리가 하드 의존성으로 잡혀 설치 용량이 1.5GB에 달했다.
고친 방법도 둘이다. 빌드 설정에 포함할 경로를 명시하고, 무거운 라이브러리를 선택 의존성으로 옮겨 하드 의존성을 둘만 남겼다. 가능했던 이유는 무거운 것들의 임포트가 전부 지연 로딩이고, 임베딩이 없을 때 해시 기반 대체 경로가 준비돼 있었기 때문이다. 라이브러리가 하나도 없는 깨끗한 가상 환경에서 신용 심사 샘플을 돌려 사람 검토 필요 판정이 정상적으로 나오는 것까지 확인한 뒤 버전을 올렸다.

앞의 두 문제는 우회했다. 솔루션 게시가 막히니 디버그 실행 경로로 프로세스를 돌렸고, 사람 태스크 자동 생성이 막히니 진단 실행과 승인 화면을 나눠서 보여줬다. 우회 자체는 중요하지 않은데 우회한 뒤에도 검증하려던 게 검증됐는지는 중요하다. 확인하려던 것은 수정한 패키징으로 에이전트가 실행 환경 안에서 도는가였고, 그건 디버그 경로에서도 확인된다.
여기서 나온 것은 기술적 교훈이라기보다 일정 감각이다. 프로세스 엔진을 축으로 쓰기로 하면 그 엔진의 배포 경로, 폴더 구조, 패키징 규칙을 전부 통과해야 한다. 로컬에서 도는 진단 코드가 있다는 것과 그 코드가 플랫폼 안에서 도는 것은 다른 단계이고, 후자에 드는 시간이 전자보다 길 수 있다. 대신 상태 관리, 대기와 재개, 사람 태스크, 실행 이력을 직접 만들지 않아도 된다.
무엇이 검증됐고 무엇이 안 됐나
발표와 제출에서 지킨 기준은 화면으로 보여줄 수 있는 것만 수치로 말하는 것이었다.
검증된 것은 이렇다. 수정한 패키징으로 코드 에이전트가 실행 환경 안에서 오류 없이 약 33초에 완료되고, 반환값이 게이트웨이에 전달돼 경로가 갈리고, 사람 검토 경로에서 승인 후 프로세스가 재개된다. 신용 심사 샘플에서 지표를 켜면 임계 초과 노드 넷이 잡힌다.
안 된 것도 적는다. 판정 지표는 기본 백엔드가 모의값이라 실제 판정을 돌리려면 백엔드를 지정해야 한다. 관측 도구 연동은 미결이다. 별도 모델이 진단을 다시 훑는 동료 검토 모듈은 파일로 존재하지만 진단 엔진이 호출하지 않는다. 그래프 기반 검색의 성능 수치는 철회했다. 정답 집합과 검색기의 필터가 같은 원본에서 파생돼 필터가 정답을 자명하게 맞히는 구조였고, 독립적인 검색 품질 측정이 아니었다. 그래프 자체는 노드 8,287개와 간선 12,317개로 유효하지만 성능 수치는 재측정 대기다.
제출물과 발표 자료에서 이 수치들을 뺀 이유는 간단하다. 화면 증거가 없는 숫자를 넣으면 나머지 숫자도 같이 의심받는다.
마무리 - 게이트를 그림으로 두면
이 시리즈는 배포 전 점검이 컨설팅 계약 안에만 있다는 관찰에서 시작해, 그 점검을 채점표와 게이트로 나눈 뒤, 게이트를 프로세스 정의에 얹는 데까지 왔다.
네 편을 관통하는 것은 하나다. 판단을 사람 머릿속에서 표로 옮기고, 표를 코드가 아니라 데이터로 두고, 게이트 조건을 코드가 아니라 그림 위의 문장으로 두는 것. 각 단계에서 옮긴 방향은 같다. 판단을 밖으로 꺼내 읽을 수 있는 자리에 두면 재실행과 증명이 함께 따라온다.
컨설팅 진단이 비쌌던 이유는 사람이 판단해서가 아니라 그 판단이 밖으로 나온 적이 없어서였다. 표로 나오면 다시 돌릴 수 있고, 게이트웨이 이름으로 나오면 규제 담당자가 읽을 수 있다. 남은 값은 표를 계속 갱신하는 일에 붙는다.
출처
- 프로세스 정의
scripts/uipath/bpmn_diagnosis_workflow.bpmn(흐름 객체 18, 흐름 20), 에이전트 진입점scripts/uipath/coded_agent_wrapper.py(공개 저장소) - 게이트 조건
scripts/core/tools.py의evaluate_hitl(), 임계scripts/core/contracts.py의HitlThresholds - 제출 페이지: FDE Agent, Devpost
- 플랫폼 이슈 2건은 UiPath 공식 커뮤니티 포럼에 등록돼 있다 (솔루션 배포 이슈, 케이스 플랜 디버깅 중 사람 태스크 조회 실패)
관련 글

가장 위험한 노드는 자동 승인이었다 - 조용한 과신을 뺄셈으로 잡는 법
도메인이 다른 두 워크플로를 같은 채점표로 돌렸더니 최고점 노드의 성격이 같았다. 사람 손을 떼는 노드다. 확신도 뺄셈 하나로 조용한 과신을 잡는 방법, 3.6점 노드가 4.9로 올라가는 계산, 그리고 색이 빨간 것과 사람에게 가는 것이 왜 다른지 정리한다.

공개 데이터셋에 없는 축에 가장 큰 가중치를 줬다 - 36셀 리스크 온톨로지
AI 워크플로를 노드 단위로 채점하려면 채점표가 먼저 필요하다. 일반 실패와 보안 축은 OWASP·MITRE ATLAS·MIT 자료로 채웠지만 노드 사이를 보는 세 번째 축은 어느 공개 체계에도 없었다. 그 축에 0.4를 준 이유와, 점수가 실행 중에 올라가는 구조를 정리한다.

출시하고 나서야 어디서 깨지는지 안다 - 배포 전 점검을 프로세스로 옮긴 이유
AI 워크플로의 배포 전 위험 점검은 지금 컨설팅 계약서 안에만 있다. 워크플로 하나에 시니어 1~2주, 재실행 불가. 이 점검이 왜 비어 있는 사분면인지, 규제 시한이 실제로 언제인지, 그리고 그것을 한 번의 실행으로 옮기면 무엇이 남는지 정리한다.