유모스원
경력근거: 자율적으로 원인을 진단하고 액션을 실행하는 Agentic AI 루프 개발
※ 실제 산출물이 아닌 AI 예측 시안입니다.
유모스원은 이 자리에 배차 최적화와 혼잡 제어 상황에서 원인을 진단하고 액션을 실행하는 Agentic AI 루프 개발을 맡기고, 상태 머신과 이벤트 기반 아키텍처 설계 역량, Self-Correction 을 갖춘 에이전트 구조를 요구합니다. 에이전트가 사람 승인 없이 차량을 움직이는 제품에서는 실행 기록과 구역 지표가 한 플랫폼에 같이 쌓여야 조치 효과를 셀 수 있고, 그 판정이 곧 운영 책임자가 자동 실행 범위를 정하는 근거가 됩니다. 이 포트폴리오는 평가 창 앞뒤로 대기시간을 맞대는 규칙, 판정을 기다리는 조치의 상태 머신, 그 판정을 에이전트의 자기 교정 도구로 쓰는 구조를 보여줍니다. 실제 교통 관제 운영 기준이나 배차 최적화 알고리즘에 대한 전문성은 주장하지 않습니다.
공고가 꼽은 세 제품 가운데 하나가 배차 최적화와 혼잡 제어 상황에서 원인을 진단하고 액션을 실행하는 자율 운영 에이전트입니다. 에이전트가 사람 대신 차량을 움직이는 순간부터, 그 조치가 혼잡을 실제로 줄였는지 되짚는 일이 관제 요원의 일상 업무가 됩니다.
조치는 실행 직후가 아니라 평가 창이 지나야 효과를 알 수 있어, 실행됨·평가 대기·판정 완료로 넘어가는 상태 머신과 늦게 도착하는 지표 이벤트를 다루는 설계가 제품의 뼈대가 됩니다.
공고는 Tool-use, 상태 추론, Self-Correction 을 통합한 에이전트 아키텍처와 LangGraph 같은 프레임워크 경험을 요구합니다. 조치 효과 판정을 에이전트가 다음 조치 전에 부르는 도구로 붙이면, 같은 구역에서 투입과 회수를 오가는 실수를 에이전트 스스로 멈추는 교정 단계가 됩니다.
유모스원은 스마트시티 플랫폼에서 시뮬레이터, 관제 챗봇, 자율 운영 에이전트 세 제품을 만듭니다. 이 관리자 페이지는 자율 에이전트가 한 교대 동안 실행한 조치 기록과 구역별 대기시간 측정값, 조치 종류별 운영 정책표를 받아 조치마다 다섯 판정 중 하나를 붙입니다. 정책표의 평가 창만큼 실행 시각 앞뒤로 같은 구역의 평균 대기시간을 견주고, 승인 없이 한도보다 많은 차량을 움직였는지, 같은 구역에서 투입과 회수가 몇 번 뒤집혔는지 셉니다. 관제 요원은 교대가 끝날 때 이 판정으로 조치를 되짚고, 운영 책임자는 같은 화면을 보고 다음 교대에 자동 실행으로 남길 조치 종류를 정합니다.
스마트시티 관제센터에서 자율 에이전트가 실행한 조치를 교대마다 되짚고, 다음 교대에 자동 실행을 맡길 범위를 정하는 관제 요원과 운영 책임자
지금 관제 요원은 에이전트 실행 기록과 구역 대기시간 그래프를 따로 열어, 눈에 띈 조치 몇 건만 앞뒤 그래프를 맞춰 봅니다. 한 교대에 조치가 수십 건이면 어느 조치 뒤에 대기시간이 늘었는지, 승인 없이 한도를 넘긴 재배치가 있었는지, 한 구역에서 투입과 회수가 오갔는지는 교대 인계 때 빠지기 쉽습니다. 조치마다 정책표의 평가 창으로 앞뒤 평균을 맞대고 승인 한도와 뒤집힘 횟수를 세면, 다음 교대 전에 자동 실행을 줄일 조치 종류가 숫자로 섭니다.
관제 요원이 자율 조치 기록, 구역 대기시간 측정값, 운영 정책표 세 파일을 올리면 조치마다 다섯 판정 중 하나와 앞뒤 평균 대기시간·변화율·뒤집힘 횟수가 서는 관리자 페이지입니다. 정책표의 평가 창으로 앞뒤 측정값을 고르는 창 계산과, 같은 구역 조치를 시각순으로 세워 투입·회수 뒤집힘을 세는 규칙이 이 주에 들어갑니다. 입력은 교대가 끝난 뒤 올리는 파일 하나로 받고, 실시간 연동은 두지 않습니다.
조치와 측정값을 이벤트로 받아, 조치가 실행됨·평가 대기·판정 완료로 넘어가는 상태 머신을 붙입니다. 평가 창이 끝나기 전 조치는 평가 대기로 두고 늦게 도착한 측정값이 오면 다시 계산하며, 창이 지나도 측정값이 없으면 판단 못 함으로 닫습니다. 교대 여섯 번 분량(조치 300건)으로 더미를 늘려, 미리 적어 둔 판정과 갈리는 조치가 어느 판정에 몰리는지 봅니다.
LangGraph 로 만든 작은 배차 에이전트가 같은 구역에 조치를 내기 전에 최근 판정을 묻는 도구를 Function Calling 으로 부르고, 상반 조치 반복이나 혼잡 증가가 걸린 구역에서는 실행 대신 관제 요원 승인 요청으로 바꿉니다. 교대가 끝나면 Claude 가 판정 묶음을 받아 다음 교대에 넘길 인계 메모를 씁니다.
관제 요원이 10월 2일 주간 교대 기록을 올리면 판교역 환승구역 투입(A-3301)이 대기시간 +45.2% 로 혼잡 증가 묶음에, 물류단지 북문의 무승인 14대 재배치(A-3315)가 대기시간이 줄었는데도 한도 초과 묶음 맨 위에 서는 과정을 시연합니다.
운영 책임자가 시청 앞 광장 묶음을 펼쳐 40분 사이 투입과 회수가 네 번 오간 조치 번호와 간격을 읽고, 그 구역의 차량 투입을 다음 교대에 승인제로 돌릴지 정합니다.
대기시간 값이 빈 측정, 한도와 같은 8대의 무승인 투입, 승인받은 12대 재배치, 결과는 좋은데 한도를 넘은 조치, 대기시간이 4.9% 늘었지만 문턱 아래라 혼잡이 줄어듦에 서는 조치를 한 교대 기록에 담으면 조치마다 묶음이 하나씩 붙고, 측정 시각 형식이 어긋난 측정 파일 12종을 넣어도 그 구역 조치만 남은 측정값으로 다시 계산되고 교대 전체 판정은 멈추지 않습니다.
2주차에는 교대 여섯 번(조치 300건)의 정답 판정을 제가 미리 적어 두고 자동 판정과 갈린 조치를 판정별로 모읍니다. 조치·측정·정답을 한 사람이 만든 대조라, 이 수는 다섯 규칙과 판정 차례가 적힌 대로 걸리는지만 말하고 관제 요원의 판단과 맞는지는 말하지 않습니다.
위 수치는 더미데이터 자가채점이며, 판정이 자동 실행 범위를 정하는 데 실제로 쓸모 있는지는 유모스원 관제 플랫폼의 실제 에이전트 실행 기록과 구역 지표, 관제 요원이 남긴 되짚기 결과가 있어야 측정됩니다. 실제 플랫폼의 조치 이벤트와 구역 측정값을 세 표의 컬럼으로 옮기는 변환기만 쓰면 판정 규칙은 그대로 씁니다.
300건 정답은 관제 요원이 아니라 제가 적었으므로, 판정이 관제 현장의 되짚기와 맞는지는 이 포트폴리오가 답하지 못합니다. 보여줄 수 있는 것은 값이 빈 측정, 한도와 같은 대수, 승인받은 초과 조치에서 판정이 정해진 차례대로 갈린다는 사실입니다.
조치 앞뒤 창에 측정이 고르게 두세 개씩 있으면 창 끝 시각과 null 처리가 틀려도 판정이 우연히 맞습니다. 대학병원 정문은 뒤 창에 값이 빈 측정 한 줄만 두었고, 물류단지 북문에는 대기시간이 줄었는데 무승인으로 14대를 옮긴 조치를, 시청 앞 광장에는 10~15분 간격으로 투입과 회수가 오간 네 조치를 한 교대에 넣었습니다.
앞뒤 평균 대기시간 차이는 조치의 효과와 같은 말이 아닙니다. 같은 시각 열차 지연이나 행사로 승객이 몰리면 좋은 조치도 혼잡 증가로 보이므로, 판정은 되짚을 조치를 세우는 데서 멈추고 원인은 관제 요원이 가립니다.
혼잡이 줄어듦 묶음에는 늘어남 문턱 +10% 를 넘지 않은 조치가 모두 들어옵니다. 더미의 테크노밸리 순환로 배차 간격 단축(A-3339)은 대기시간이 4.9% 늘었는데도 이 묶음에 섭니다. 그 이름만 믿지 않도록 펼침 화면에 변화율을 부호 그대로 두고, 이 묶음을 감소와 변화 없음으로 나눌지는 실제 기록을 본 뒤 정할 도입 과제로 둡니다.
이 포트폴리오는 평가 창으로 조치 효과를 셈하는 규칙과 그 판정을 상태 머신과 에이전트 교정 도구로 쓰는 구조를 보여줍니다. 교통 관제 운영과 배차 최적화 알고리즘에 대한 전문성은 주장하지 않습니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
자율 운영 에이전트가 한 교대 동안 실행한 조치 기록입니다. 조치 하나에 한 줄이고, 관제 요원 승인 없이 실행한 조치는 approved_by 가 null 입니다. 한도와 같은 대수의 무승인 투입, 승인받은 한도 초과 재배치, 한 구역에서 10~15분 간격으로 오간 투입과 회수를 일부러 담았습니다.
| action_id | zone_id | zone_name | action_type | vehicles_moved | executed_at | approved_by |
|---|---|---|---|---|---|---|
| A-3301 | Z-07 | 판교역 환승구역 | 차량 투입 | 6 | 2026-10-02T07:40:00+09:00 | — |
| A-3312 | Z-11 | 물류단지 북문 | 차량 재배치 | 12 | 2026-10-02T08:20:00+09:00 | 관제 김도윤 |
| A-3315 | Z-11 | 물류단지 북문 | 차량 재배치 | 14 | 2026-10-02T09:10:00+09:00 | — |
| A-3318 | Z-03 | 시청 앞 광장 | 차량 투입 | 3 | 2026-10-02T10:00:00+09:00 | — |
| A-3319 | Z-03 | 시청 앞 광장 | 차량 회수 | 3 | 2026-10-02T10:10:00+09:00 | — |
아래 JSON Schema 에 맞는 자율 에이전트 조치 기록 행을 더 만들어 주세요. {"type":"object","properties":{"action_id":{"type":"string","description":"자율 에이전트가 실행한 조치 번호입니다."},"zone_id":{"type":"string","description":"조치를 실행한 관제 구역입니다."},"zone_name":{"type":"string"},"action_type":{"type":"string","description":"조치 종류입니다. action_policy 의 action_type 가운데 하나입니다."},"vehicles_moved":{"type":"integer","minimum":0,"description":"조치로 움직인 차량 대수입니다. 차량을 움직이지 않는 조치는 0 입니다."},"executed_at":{"type":"string","description":"조치를 실행한 시각입니다. +09:00 오프셋이 붙은 ISO 8601 입니다."},"approved_by":{"type":["string","null"],"description":"실행 전에 승인한 관제 요원입니다. 에이전트가 승인 없이 실행했으면 null 입니다."}},"required":["action_id","zone_id","zone_name","action_type","vehicles_moved","executed_at","approved_by"]} 한 교대(8시간)에 구역 10~20곳, 조치 30~60건을 만들고 action_type 은 action_policy 에 있는 열 가지 가운데서 고릅니다. 차량을 움직이지 않는 조치(우회 경로 안내·정차 지점 임시 이동)는 vehicles_moved 를 0 으로 둡니다. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) approved_by 가 null 인데 vehicles_moved 가 무승인 한도보다 큰 조치, (2) 한도와 정확히 같은 대수의 무승인 조치, (3) 한 구역에서 평가 창 안 간격으로 투입과 회수가 세 번 넘게 오간 조치 묶음, (4) 승인자가 있는 한도 초과 조치, (5) 앞뒤 측정이 없는 시간에 실행한 조치. 생성한 행은 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"action_id":{"type":"string","description":"자율 에이전트가 실행한 조치 번호입니다."},"zone_id":{"type":"string","description":"조치를 실행한 관제 구역입니다."},"zone_name":{"type":"string"},"action_type":{"type":"string","description":"조치 종류입니다. action_policy 의 action_type 가운데 하나입니다."},"vehicles_moved":{"type":"integer","minimum":0,"description":"조치로 움직인 차량 대수입니다. 차량을 움직이지 않는 조치는 0 입니다."},"executed_at":{"type":"string","description":"조치를 실행한 시각입니다. +09:00 오프셋이 붙은 ISO 8601 입니다."},"approved_by":{"type":["string","null"],"description":"실행 전에 승인한 관제 요원입니다. 에이전트가 승인 없이 실행했으면 null 입니다."}},"required":["action_id","zone_id","zone_name","action_type","vehicles_moved","executed_at","approved_by"]}관제 구역마다 15분 안팎 간격으로 잰 평균 대기시간입니다. 센서나 집계가 빠진 시각은 avg_wait_min 이 null 이고, 그 줄은 평균에서 뺍니다. 조치 직후 측정이 비어 있는 구역을 일부러 담았습니다.
| zone_id | measured_at | avg_wait_min |
|---|---|---|
| Z-07 | 2026-10-02T07:15:00+09:00 | 4 |
| Z-07 | 2026-10-02T07:30:00+09:00 | 4.4 |
| Z-07 | 2026-10-02T07:55:00+09:00 | 5.9 |
| Z-07 | 2026-10-02T08:10:00+09:00 | 6.3 |
| Z-11 | 2026-10-02T07:50:00+09:00 | 10.4 |
아래 JSON Schema 에 맞는 구역 대기시간 측정 행을 더 만들어 주세요. {"type":"object","properties":{"zone_id":{"type":"string"},"measured_at":{"type":"string","description":"대기시간을 잰 시각입니다. +09:00 오프셋이 붙은 ISO 8601 입니다."},"avg_wait_min":{"type":["number","null"],"minimum":0,"description":"그 시각 구역 안 승객의 평균 대기시간(분)입니다. 센서나 집계가 빠지면 null 입니다."}},"required":["zone_id","measured_at","avg_wait_min"]} 구역마다 10~20분 간격으로 측정하고, 출퇴근 시간대에는 평균 대기시간이 평소의 1.5~3배가 되게 합니다. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) avg_wait_min 이 null 인 측정, (2) 조치 실행 시각과 정확히 같은 시각의 측정, (3) 평가 창 안에 측정이 하나도 없는 구간, (4) 조치와 무관하게 대기시간이 갑자기 튀는 측정, (5) 조치 뒤 평균 대기시간이 0~10% 사이로 조금 늘어난 구간. 생성한 행은 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"zone_id":{"type":"string"},"measured_at":{"type":"string","description":"대기시간을 잰 시각입니다. +09:00 오프셋이 붙은 ISO 8601 입니다."},"avg_wait_min":{"type":["number","null"],"minimum":0,"description":"그 시각 구역 안 승객의 평균 대기시간(분)입니다. 센서나 집계가 빠지면 null 입니다."}},"required":["zone_id","measured_at","avg_wait_min"]}조치 종류마다 승인 없이 움직일 수 있는 최대 차량 대수, 효과를 볼 평가 창, 이 조치를 되돌리는 반대 조치를 적은 운영 정책표입니다. 값은 작성자가 정한 가정이고, 운영 책임자가 이 표를 고치면 판정이 다시 계산됩니다.
| action_type | max_vehicles_unapproved | eval_window_min | opposite_action_type |
|---|---|---|---|
| 차량 투입 | 8 | 30 | 차량 회수 |
| 차량 회수 | 8 | 30 | 차량 투입 |
| 차량 재배치 | 8 | 40 | — |
| 배차 간격 단축 | 4 | 30 | 배차 간격 연장 |
| 배차 간격 연장 | 4 | 30 | 배차 간격 단축 |
아래 JSON Schema 에 맞는 관제 조치 운영 정책 행을 더 만들어 주세요. {"type":"object","properties":{"action_type":{"type":"string"},"max_vehicles_unapproved":{"type":"integer","minimum":0,"description":"승인 없이 움직일 수 있는 최대 차량 대수입니다. 이보다 크면 관제 요원 승인이 필요합니다."},"eval_window_min":{"type":"integer","minimum":5,"description":"조치 효과를 볼 때 실행 시각 앞뒤로 잡는 시간 창(분)입니다."},"opposite_action_type":{"type":["string","null"],"description":"이 조치를 되돌리는 반대 조치입니다. 없으면 null 입니다."}},"required":["action_type","max_vehicles_unapproved","eval_window_min","opposite_action_type"]} action_type 은 교통 관제에서 쓸 법한 조치 이름으로 쓰고, 반대 조치가 있으면 두 조치가 서로를 opposite_action_type 으로 가리키게 짝을 맞춥니다. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) max_vehicles_unapproved 가 0 이라 차량을 하나라도 움직이면 승인이 필요한 조치, (2) 반대 조치가 없는 조치, (3) 평가 창이 60분 넘게 긴 조치. 생성한 행은 위 스키마를 통과해야 하며, 형식을 깨뜨리는 시도는 별도로 3건만 표시해 두세요.{"type":"object","properties":{"action_type":{"type":"string"},"max_vehicles_unapproved":{"type":"integer","minimum":0,"description":"승인 없이 움직일 수 있는 최대 차량 대수입니다. 이보다 크면 관제 요원 승인이 필요합니다."},"eval_window_min":{"type":"integer","minimum":5,"description":"조치 효과를 볼 때 실행 시각 앞뒤로 잡는 시간 창(분)입니다."},"opposite_action_type":{"type":["string","null"],"description":"이 조치를 되돌리는 반대 조치입니다. 없으면 null 입니다."}},"required":["action_type","max_vehicles_unapproved","eval_window_min","opposite_action_type"]}| Python | 평가 창 계산, 앞뒤 평균, 뒤집힘 세기, 판정 차례를 담은 규칙 엔진과 판정 API 의 언어입니다. |
| TypeScript | 판정 묶음과 조치 펼침, 구역 대기시간 흐름 그래프를 그리는 관리자 화면의 언어입니다. |
| 상태 머신 | 조치마다 실행됨 → 평가 대기 → 판정 완료로 넘어가는 상태를 두고, 평가 창이 끝나기 전 판정을 내지 않게 막습니다. |
| 이벤트 기반 아키텍처 | 조치 실행과 대기시간 측정을 각각 이벤트로 받아, 늦게 도착한 측정값이 오면 그 구역의 평가 대기 조치를 다시 계산합니다. |
| LangGraph | 3주차 배차 에이전트의 계획·도구 호출·교정 단계를 그래프로 나눠, 판정 조회 결과에 따라 실행과 승인 요청 가지로 갈립니다. |
| Function Calling | 에이전트가 최근 판정을 묻는 도구와 관제 요원 승인 요청 도구를 부르는 형식입니다. |
| Claude Code | 규칙 엔진·상태 머신·화면 작업을 나눠 맡기고, 정답 판정 대조를 통과한 코드만 합칩니다. |
| Claude Sonnet | 3주차에 교대 판정 묶음을 받아 다음 교대에 넘길 인계 메모를 씁니다. |
✗ fail → 관제 요원이 먼저 되짚고 싶은 조치가 묶음 아래쪽에 있으면 상반 조치 반복을 지표 없음보다 앞에 둔 근거를 다시 보고, 그동안 두 사유가 걸린 조치는 펼침 화면에 둘 다 표시합니다.
✓ pass → 2주차는 조치와 측정을 이벤트로 받는 상태 머신부터 만듭니다.
✗ fail → 늦게 온 측정값 때문에 판정이 뒤집힌 조치부터 꺼내, 평가 창을 조치 종류별로 늘려야 하는지와 +10% 문턱이 맞는지 따집니다.
✓ pass → 3주차 에이전트 자기 교정과 인계 메모로 넘어갑니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · action_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
승인 없이 한도를 넘은 조치무승인 한도 초과같은 구역에 상반된 조치가 반복됨상반 조치 반복조치 뒤 혼잡이 늘어남혼잡 증가전후 지표가 없어 판단 못 함지표 없음혼잡이 줄어듦혼잡 감소자율 조치 한 건이 평가 창 앞뒤 대기시간 견줌과 승인 한도 견줌, 같은 구역 뒤집힘 세기를 거쳐 어떤 판정을 받는지 남기는 형식입니다. 효과 판정은 평균과 횟수 계산이 내리고, 3주차 인계 메모 작성에만 모델이 들어갑니다.
{"type":"object","properties":{"action_id":{"type":"string"},"zone_id":{"type":"string"},"action_type":{"type":"string"},"verdict":{"type":"string","enum":["혼잡이 줄어듦","조치 뒤 혼잡이 늘어남","전후 지표가 없어 판단 못 함","승인 없이 한도를 넘은 조치","같은 구역에 상반된 조치가 반복됨"]},"executed_at":{"type":"string"},"vehicles_moved":{"type":"integer","minimum":0},"approved_by":{"type":["string","null"]},"max_vehicles_unapproved":{"type":"integer","minimum":0},"eval_window_min":{"type":"integer","minimum":5},"before_count":{"type":"integer","minimum":0,"description":"executed_at 앞 eval_window_min 안(창 시작 포함, 실행 시각 제외)에서 avg_wait_min 이 null 이 아닌 zone_metrics 줄 수입니다."},"after_count":{"type":"integer","minimum":0,"description":"executed_at 뒤 eval_window_min 안(실행 시각 제외, 창 끝 포함)에서 avg_wait_min 이 null 이 아닌 zone_metrics 줄 수입니다."},"before_avg_wait_min":{"type":["number","null"],"minimum":0,"description":"앞 창 avg_wait_min 의 산술평균입니다. before_count 가 0 이면 null 입니다."},"after_avg_wait_min":{"type":["number","null"],"minimum":0,"description":"뒤 창 avg_wait_min 의 산술평균입니다. after_count 가 0 이면 null 입니다."},"wait_change_pct":{"type":["number","null"],"description":"(after_avg_wait_min − before_avg_wait_min) / before_avg_wait_min × 100 을 소수 첫째 자리로 반올림한 값입니다. 두 평균 중 하나라도 null 이면 null 입니다."},"opposite_flip_count":{"type":"integer","minimum":0,"description":"같은 zone_id 의 조치를 시각순으로 세웠을 때, 바로 앞 조치의 opposite_action_type 이 이 조치 종류이고 간격이 앞 조치의 eval_window_min 이하인 뒤집힘이 이어진 횟수입니다. 이 조치가 속한 이어진 묶음 전체로 셉니다."},"evidence":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"agg":{"type":["string","null"]},"value":{}},"required":["field","value"]}},"summary":{"type":"string"},"hedge":{"type":["string","null"]}},"required":["action_id","zone_id","action_type","verdict","executed_at","vehicles_moved","approved_by","max_vehicles_unapproved","eval_window_min","before_count","after_count","before_avg_wait_min","after_avg_wait_min","wait_change_pct","opposite_flip_count","evidence","summary"]}[
{
"action_id": "A-3301",
"zone_id": "Z-07",
"action_type": "차량 투입",
"verdict": "조치 뒤 혼잡이 늘어남",
"executed_at": "2026-10-02T07:40:00+09:00",
"vehicles_moved": 6,
"approved_by": null,
"max_vehicles_unapproved": 8,
"eval_window_min": 30,
"before_count": 2,
"after_count": 2,
"before_avg_wait_min": 4.2,
"after_avg_wait_min": 6.1,
"wait_change_pct": 45.2,
"opposite_flip_count": 0,
"evidence": [
{
"field": "executed_at",
"value": "2026-10-02T07:40:00+09:00"
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 4.2
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 6.1
},
{
"field": "eval_window_min",
"value": 30
}
],
"summary": "판교역 환승구역에 차량 6대를 넣은 뒤 30분 평균 대기시간이 4.2분에서 6.1분으로 45.2% 늘었습니다.",
"hedge": "투입 차량이 환승구역 진입로에서 서로 막혔는지, 같은 시각 열차 지연으로 승객이 몰렸는지는 이 판정이 가리지 않습니다."
},
{
"action_id": "A-3315",
"zone_id": "Z-11",
"action_type": "차량 재배치",
"verdict": "승인 없이 한도를 넘은 조치",
"executed_at": "2026-10-02T09:10:00+09:00",
"vehicles_moved": 14,
"approved_by": null,
"max_vehicles_unapproved": 8,
"eval_window_min": 40,
"before_count": 3,
"after_count": 2,
"before_avg_wait_min": 9.4,
"after_avg_wait_min": 7,
"wait_change_pct": -25.5,
"opposite_flip_count": 0,
"evidence": [
{
"field": "vehicles_moved",
"value": 14
},
{
"field": "max_vehicles_unapproved",
"value": 8
},
{
"field": "approved_by",
"value": null
}
],
"summary": "물류단지 북문에서 승인자 없이 차량 14대를 재배치했는데, 차량 재배치의 무승인 한도는 8대입니다.",
"hedge": "조치 뒤 40분 평균 대기시간은 9.4분에서 7.0분으로 줄었습니다. 결과가 좋아도 한도를 넘은 무승인 조치는 이 묶음에 먼저 올립니다."
},
{
"action_id": "A-3320",
"zone_id": "Z-03",
"action_type": "차량 투입",
"verdict": "같은 구역에 상반된 조치가 반복됨",
"executed_at": "2026-10-02T10:25:00+09:00",
"vehicles_moved": 2,
"approved_by": null,
"max_vehicles_unapproved": 8,
"eval_window_min": 30,
"before_count": 1,
"after_count": 2,
"before_avg_wait_min": 3.4,
"after_avg_wait_min": 3.3,
"wait_change_pct": -2.9,
"opposite_flip_count": 3,
"evidence": [
{
"field": "action_type",
"value": "차량 투입"
},
{
"field": "opposite_action_type",
"value": "차량 회수"
},
{
"field": "action_id",
"agg": "count",
"value": 4
},
{
"field": "executed_at",
"value": "2026-10-02T10:00:00+09:00"
},
{
"field": "executed_at",
"value": "2026-10-02T10:40:00+09:00"
}
],
"summary": "시청 앞 광장에서 10시부터 10시 40분 사이 차량 투입과 회수가 네 번 번갈아 실행돼, 방향이 세 번 뒤집혔습니다.",
"hedge": "네 조치 사이 간격은 10·15·15분으로 모두 평가 창 30분 안입니다. 같은 묶음의 A-3318·A-3319·A-3321 도 같은 판정을 받습니다."
},
{
"action_id": "A-3333",
"zone_id": "Z-18",
"action_type": "수요응답 호출 확대",
"verdict": "전후 지표가 없어 판단 못 함",
"executed_at": "2026-10-02T12:00:00+09:00",
"vehicles_moved": 2,
"approved_by": null,
"max_vehicles_unapproved": 5,
"eval_window_min": 20,
"before_count": 1,
"after_count": 0,
"before_avg_wait_min": 6.2,
"after_avg_wait_min": null,
"wait_change_pct": null,
"opposite_flip_count": 0,
"evidence": [
{
"field": "zone_id",
"value": "Z-18"
},
{
"field": "avg_wait_min",
"value": null
},
{
"field": "eval_window_min",
"value": 20
}
],
"summary": "대학병원 정문에서 수요응답 호출을 넓힌 뒤 20분 안에 잰 대기시간이 없어 효과를 판단하지 못했습니다.",
"hedge": "12시 10분 측정 줄은 있지만 avg_wait_min 이 비어 있어 뒤 지표로 세지 않았습니다. 조치 앞 지표는 11시 50분 한 건(6.2분)입니다."
},
{
"action_id": "A-3328",
"zone_id": "Z-15",
"action_type": "차량 투입",
"verdict": "혼잡이 줄어듦",
"executed_at": "2026-10-02T11:30:00+09:00",
"vehicles_moved": 3,
"approved_by": null,
"max_vehicles_unapproved": 8,
"eval_window_min": 30,
"before_count": 2,
"after_count": 2,
"before_avg_wait_min": 7.8,
"after_avg_wait_min": 5,
"wait_change_pct": -35.9,
"opposite_flip_count": 0,
"evidence": [
{
"field": "executed_at",
"value": "2026-10-02T11:30:00+09:00"
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 7.8
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 5
}
],
"summary": "테크노밸리 순환로에 차량 3대를 넣은 뒤 30분 평균 대기시간이 7.8분에서 5.0분으로 35.9% 줄었습니다.",
"hedge": null
},
{
"action_id": "A-3345",
"zone_id": "Z-07",
"action_type": "차량 투입",
"verdict": "혼잡이 줄어듦",
"executed_at": "2026-10-02T14:00:00+09:00",
"vehicles_moved": 8,
"approved_by": null,
"max_vehicles_unapproved": 8,
"eval_window_min": 30,
"before_count": 2,
"after_count": 2,
"before_avg_wait_min": 5.4,
"after_avg_wait_min": 4.5,
"wait_change_pct": -16.7,
"opposite_flip_count": 0,
"evidence": [
{
"field": "vehicles_moved",
"value": 8
},
{
"field": "max_vehicles_unapproved",
"value": 8
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 5.4
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 4.5
}
],
"summary": "판교역 환승구역에 무승인으로 차량 8대를 넣었고, 30분 평균 대기시간이 5.4분에서 4.5분으로 16.7% 줄었습니다.",
"hedge": "투입 대수 8대가 무승인 한도 8대와 같아 넘지 않은 것으로 셌습니다. 한도를 넘는다는 것은 한도보다 큰 경우만 뜻합니다."
},
{
"action_id": "A-3312",
"zone_id": "Z-11",
"action_type": "차량 재배치",
"verdict": "혼잡이 줄어듦",
"executed_at": "2026-10-02T08:20:00+09:00",
"vehicles_moved": 12,
"approved_by": "관제 김도윤",
"max_vehicles_unapproved": 8,
"eval_window_min": 40,
"before_count": 2,
"after_count": 2,
"before_avg_wait_min": 10.6,
"after_avg_wait_min": 9.35,
"wait_change_pct": -11.8,
"opposite_flip_count": 0,
"evidence": [
{
"field": "approved_by",
"value": "관제 김도윤"
},
{
"field": "vehicles_moved",
"value": 12
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 10.6
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 9.35
}
],
"summary": "물류단지 북문의 차량 12대 재배치는 관제 김도윤의 승인을 받았고, 40분 평균 대기시간이 10.6분에서 9.35분으로 11.8% 줄었습니다.",
"hedge": "한도 8대를 넘었지만 승인자가 있어 무승인 한도 판정에서 빠졌습니다."
},
{
"action_id": "A-3339",
"zone_id": "Z-15",
"action_type": "배차 간격 단축",
"verdict": "혼잡이 줄어듦",
"executed_at": "2026-10-02T13:00:00+09:00",
"vehicles_moved": 2,
"approved_by": null,
"max_vehicles_unapproved": 4,
"eval_window_min": 30,
"before_count": 2,
"after_count": 2,
"before_avg_wait_min": 5.1,
"after_avg_wait_min": 5.35,
"wait_change_pct": 4.9,
"opposite_flip_count": 0,
"evidence": [
{
"field": "avg_wait_min",
"agg": "avg",
"value": 5.1
},
{
"field": "avg_wait_min",
"agg": "avg",
"value": 5.35
},
{
"field": "eval_window_min",
"value": 30
}
],
"summary": "테크노밸리 순환로의 배차 간격을 줄인 뒤 30분 평균 대기시간이 5.1분에서 5.35분으로 4.9% 늘었지만, 늘어남 문턱 +10% 를 넘지 않아 이 묶음에 들어왔습니다.",
"hedge": "묶음 이름과 달리 대기시간은 조금 늘었습니다. 화면은 변화율 +4.9% 를 부호 그대로 보여주고, 0~10% 증가를 따로 가를지는 실제 기록을 본 뒤 정합니다."
}
][자동 검증 · 코드가 판정합니다] 1. verdict 가 혼잡이 줄어듦·조치 뒤 혼잡이 늘어남·전후 지표가 없어 판단 못 함·승인 없이 한도를 넘은 조치·같은 구역에 상반된 조치가 반복됨 다섯 값 중 하나인지 확인합니다. 2. action_id·zone_id·action_type·verdict·executed_at·vehicles_moved·approved_by·max_vehicles_unapproved·eval_window_min·before_count·after_count·before_avg_wait_min·after_avg_wait_min·wait_change_pct·opposite_flip_count·evidence·summary 필드가 빠짐없이 있는지 확인합니다. 3. before_count·after_count·opposite_flip_count 가 0 이상이고, 두 평균 대기시간이 0 이상인지 확인합니다. 4. before_avg_wait_min 과 after_avg_wait_min 을 같은 zone_id 의 zone_metrics 에서 창 규칙대로 다시 평균 내고, wait_change_pct 를 두 평균으로 다시 계산합니다. opposite_flip_count 는 같은 구역 조치를 시각순으로 세워 다시 셉니다. 5. approved_by 가 null 이고 vehicles_moved 가 max_vehicles_unapproved 보다 크면 verdict 는 승인 없이 한도를 넘은 조치입니다. 6. 앞 조건에 걸리지 않고 opposite_flip_count 가 3 이상이면 verdict 는 같은 구역에 상반된 조치가 반복됨입니다. 7. 앞 두 조건에 걸리지 않고 before_count 나 after_count 가 0 이면 verdict 는 전후 지표가 없어 판단 못 함입니다. 8. 앞 세 조건에 걸리지 않고 after_avg_wait_min 이 before_avg_wait_min 의 1.10 배보다 크면 verdict 는 조치 뒤 혼잡이 늘어남이고, 그렇지 않으면 혼잡이 줄어듦입니다. 9. evidence 의 field 이름이 agent_actions·zone_metrics·action_policy 에 있는 컬럼인지 대조합니다. 10. evidence 의 value 가 수록된 행의 원문 값과 같은지 확인합니다. 여러 줄의 평균이나 개수는 agg 를 적습니다. 11. summary 가 존댓말로 끝나는지 확인합니다. [판정 차례 · 위 규칙이 둘 이상 동시에 걸릴 때] 조치 하나에는 판정을 하나만 남깁니다. ① 승인 없이 한도를 넘은 조치 → ② 같은 구역에 상반된 조치가 반복됨 → ③ 전후 지표가 없어 판단 못 함 → ④ 조치 뒤 혼잡이 늘어남 → ⑤ 혼잡이 줄어듦. 사람 확인 없이 차량이 많이 움직인 조치는 대기시간이 줄었어도 가장 먼저 올리고, 투입과 회수를 오간 조치는 서로의 효과를 지워 전후 평균이 뜻을 잃으므로 지표보다 먼저 봅니다. 혼잡이 줄어듦에는 늘어남 문턱(+10%)을 넘지 않은 조치가 모두 들어오므로, 화면은 wait_change_pct 를 부호 그대로 보여줍니다. [하드 케이스 · 판정이 갈리는 이유] A-3333 은 Z-18 의 12시 10분 측정 줄이 avg_wait_min null 인 결측이라 뒤 창에 지표가 하나도 없어 판단 못 함입니다. A-3345 는 무승인 투입 8대가 한도 8대와 같아 넘지 않았고, 지표로 판정해 혼잡이 줄어듦입니다. A-3312 는 한도보다 많은 12대를 옮겼지만 approved_by 가 있어 무승인 판정에서 빠집니다. A-3315 는 대기시간이 25.5% 줄었는데도 무승인 14대라 ①로 올라갑니다. Z-03 의 네 조치는 간격이 10·15·15분으로 모두 30분 창 안이라 뒤집힘이 세 번 이어진 한 묶음입니다. A-3339 는 평균 대기시간이 5.1분에서 5.35분으로 4.9% 늘었지만 1.10 배 문턱(5.61분)을 넘지 않아 혼잡이 줄어듦에 들어갑니다. [평가 러너 · 2주차] 더미 교대 여섯 번의 자율 조치 300건에 손으로 매긴 정답 판정과 자동 판정을 대조해 판정별 일치율을 내고, 어긋난 조치는 따로 모아 평가 창 길이와 +10% 문턱, 뒤집힘 3회 문턱을 다시 봅니다. [수동 검증 · 사람이 봅니다] 1. 혼잡이 늘어난 조치가 조치 탓인지 같은 시각 사고·행사·열차 지연 탓인지는 관제 요원이 판단합니다. 2. 다음 교대에 어느 조치 종류를 자동 실행으로 남길지는 운영 책임자가 정합니다.
근거: 자율적으로 원인을 진단하고 액션을 실행하는 Agentic AI 루프 개발