$ uv run tools/flow.py push reference/lab03-example2-limit.json ! unpublished '75 IT helpdesk + safe record (answer)' (w2ae10aa66addee4): it used the same webhook path ✔ pushed '75 IT helpdesk + user limit (reference)' (id w3b18d2741bd22c6) POST http://localhost:5678/webhook/my-cost $ uv run tools/flow.py test cases/lab03-limit.json -v ✔ before: POST http://localhost:8800/budget/reset · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.0029704, "remaining_usd": 0.997029 → request POST http://localhost:8800/budget/reset {} ← response HTTP 200 { "daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.0029704, "remaining_usd": 0.9970296, "over": false } ✔ before: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 9} → request POST http://localhost:8800/usage-clear {} ← response HTTP 200 { "cleared": 9 } ✔ before: POST http://localhost:8800/budget · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 2, "max_question_chars": 500, "used_usd": 0, "remaining_usd": 1.0, "over": fals → request POST http://localhost:8800/budget { "user_limit_per_min": 2 } ← response HTTP 200 { "daily_usd": 1.0, "user_limit_per_min": 2, "max_question_chars": 500, "used_usd": 0, "remaining_usd": 1.0, "over": false } POST http://localhost:5678/webhook/my-cost · 4 case(s) × 1 ✔ 이준호 1번째 · 2.1s · 자동 답변 · 1 call · $0.000141 → request POST /webhook/my-cost { "question": "VPN 접속이 자꾸 끊겨요. 어떻게 하나요?", "user": "이준호" } ← response HTTP 200 { "route": "자동 답변", "answer": "VPN 접속 오류는 VPN 클라이언트를 최신 버전으로 업데이트하고, 인증서 만료 여부를 확인한 뒤 다시 접속하시기 바랍니다. 추가 도움이 필요하시면 담당 직원이 도와드리겠습니다.", "sources": [ "FAQ-003" ], "llm_calls": 1, "usage": { "prompt_tokens": 165, "completion_tokens": 47, "by_step": { "answer": { "model": "gpt-4.1-mini", "prompt_tokens": 165, "completion_tokens": 47, "cost_usd": 0.0001412 } } }, "cost_usd": 0.0001412, "trimmed": false, "question_chars": 24, "recorded": true } ✔ 이준호 2번째 · 1.6s · 자동 답변 · 1 call · $0.000150 → request POST /webhook/my-cost { "question": "프린터 출력이 안 돼요", "user": "이준호" } ← response HTTP 200 { "route": "자동 답변", "answer": "프린터 전원과 네트워크 연결을 확인하고, 인쇄 대기열을 비운 뒤 다시 출력해 보시기 바랍니다. 현재 접수된 관련 문의는 없습니다. 추가 도움이 필요하시면 담당자가 도와드리겠습니다.", "sources": [ "FAQ-004" ], "llm_calls": 1, "usage": { "prompt_tokens": 164, "completion_tokens": 53, "by_step": { "answer": { "model": "gpt-4.1-mini", "prompt_tokens": 164, "completion_tokens": 53, "cost_usd": 0.0001504 } } }, "cost_usd": 0.0001504, "trimmed": false, "question_chars": 12, "recorded": true } ✔ 이준호 3번째 · 1분에 2번 넘음 · 0.0s · 잠시 후 · 0 calls · $0.000000 → request POST /webhook/my-cost { "question": "VPN 접속이 자꾸 끊겨요. 어떻게 하나요?", "user": "이준호" } ← response HTTP 429 { "route": "잠시 후", "answer": "요청이 많아 잠시 뒤에 다시 물어봐 주세요.", "retry_after": 60, "llm_calls": 0, "cost_usd": 0 } ✔ 다른 사람은 그대로 · 1.9s · 자동 답변 · 1 call · $0.000136 → request POST /webhook/my-cost { "question": "비밀번호를 잊어버렸어요. 재설정은 어떻게 하나요?", "user": "한지훈" } ← response HTTP 200 { "route": "자동 답변", "answer": "비밀번호 재설정은 사내 포털 로그인 화면의 '비밀번호 찾기'에서 휴대폰 인증 후 새 비밀번호를 설정하시면 됩니다. 추가 도움이 필요하시면 문의해 주세요.", "sources": [ "FAQ-001" ], "llm_calls": 1, "usage": { "prompt_tokens": 169, "completion_tokens": 43, "by_step": { "answer": { "model": "gpt-4.1-mini", "prompt_tokens": 169, "completion_tokens": 43, "cost_usd": 0.0001364 } } }, "cost_usd": 0.0001364, "trimmed": false, "question_chars": 27, "recorded": true } Passed 4/4 report: runs/lab03-limit-20261028-211138.json ✔ after: POST http://localhost:8800/budget/reset · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.000428, "remaining_usd": 0.999572, → request POST http://localhost:8800/budget/reset {} ← response HTTP 200 { "daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.000428, "remaining_usd": 0.999572, "over": false } ✔ after: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 3} → request POST http://localhost:8800/usage-clear {} ← response HTTP 200 { "cleared": 3 } $ uv run tools/flow.py test cases/lab03.json POST http://localhost:5678/webhook/my-cost · 3 case(s) × 1 ✔ before: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 0} ✔ before: POST http://localhost:8800/budget · HTTP 200 · 0.0s · {"daily_usd": 0.001, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0, "remaining_usd": 0.001, "over": ✔ before: POST http://localhost:8800/usage · HTTP 200 · 0.0s · {"stored": 1, "total": 1} ✔ 한도를 넘으면 · FAQ 원문 · 0.1s · 한도 초과 · 0 calls · $0.000000 ✔ 한도를 넘으면 · 접수 원문 · 0.1s · 한도 초과 · 0 calls · $0.000000 ✔ before: POST http://localhost:8800/budget/reset · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.002, "remaining_usd": 0.998, "over ✔ before: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 1} ✔ 한도 안이면 평소대로 · 1.2s · 자동 답변 · 1 call · $0.000156 Passed 3/3 report: runs/lab03-20261028-211139.json ✔ after: POST http://localhost:8800/budget/reset · HTTP 200 · 0.0s · {"daily_usd": 1.0, "user_limit_per_min": 20, "max_question_chars": 500, "used_usd": 0.0001556, "remaining_usd": 0.999844 ✔ after: POST http://localhost:8800/usage-clear · HTTP 200 · 0.0s · {"cleared": 1} $ uv run tools/flow.py test cases/lab02-challenge.json POST http://localhost:5678/webhook/my-cost · 7 case(s) × 1 ✔ faq-vpn · LLM 한 번 · $0.0002 이하 · 1.3s · 자동 답변 · 1 call · $0.000141 ✔ faq-password · LLM 한 번 · $0.0002 이하 · 1.3s · 자동 답변 · 1 call · $0.000138 ✔ faq-printer · LLM 한 번 · $0.0002 이하 · 1.3s · 자동 답변 · 1 call · $0.000152 ✔ faq-mail · LLM 한 번 · $0.0002 이하 · 1.5s · 자동 답변 · 1 call · $0.000166 ✔ ticket-own · LLM 한 번 · $0.0002 이하 · 1.3s · 자동 답변 · 1 call · $0.000115 ✔ ticket-done · LLM 한 번 · $0.0002 이하 · 1.1s · 자동 답변 · 1 call · $0.000108 ✔ 규칙으로 모르는 질문은 분류 + 답 · 1.7s · 자동 답변 · 2 calls · $0.000097 Passed 7/7 report: runs/lab02-challenge-20261028-211149.json